92
const PROMISE_PROTOTYPE = Promise.prototype;
93
94
const deepProxyHandlers = {
95
- get: function (target: Function, name: string, receiver: Proxy<Function>) {
95
+ get: function (
96
+ target: Function,
97
+ name: string | symbol,
98
+ receiver: Proxy<Function>,
99
+ ) {
100
switch (name) {
101
// These names are read by the Flight runtime if you end up using the exports object.
102
case '$$typeof':
121
case Symbol.toPrimitive:
122
// $FlowFixMe[prop-missing]
123
return Object.prototype[Symbol.toPrimitive];
124
+ case Symbol.toStringTag:
125
+ // $FlowFixMe[prop-missing]
126
+ return Object.prototype[Symbol.toStringTag];
127
case 'Provider':
128
throw new Error(
129
`Cannot render a Client Context Provider on the Server. ` +
144
},
145
};
146
140
-const proxyHandlers = {
141
- get: function (
142
- target: Function,
143
- name: string,
144
- receiver: Proxy<Function>,
145
- ): $FlowFixMe {
146
- switch (name) {
147
- // These names are read by the Flight runtime if you end up using the exports object.
148
- case '$$typeof':
149
- return target.$$typeof;
150
- case '$$id':
151
- return target.$$id;
152
- case '$$async':
153
- return target.$$async;
154
- case 'name':
155
- return target.name;
156
- // We need to special case this because createElement reads it if we pass this
157
- // reference.
158
- case 'defaultProps':
159
- return undefined;
160
- // Avoid this attempting to be serialized.
161
- case 'toJSON':
162
- return undefined;
163
- case Symbol.toPrimitive:
164
- // $FlowFixMe[prop-missing]
165
- return Object.prototype[Symbol.toPrimitive];
166
- case '__esModule':
167
- // Something is conditionally checking which export to use. We'll pretend to be
168
- // an ESM compat module but then we'll check again on the client.
169
- const moduleId = target.$$id;
170
- target.default = registerClientReferenceImpl(
171
- (function () {
172
- throw new Error(
173
- `Attempted to call the default export of ${moduleId} from the server ` +
174
- `but it's on the client. It's not possible to invoke a client function from ` +
175
- `the server, it can only be rendered as a Component or passed to props of a ` +
176
- `Client Component.`,
177
- );
178
- }: any),
179
- target.$$id + '#',
180
- target.$$async,
181
- );
182
- return true;
183
- case 'then':
184
- if (target.then) {
185
- // Use a cached value
186
- return target.then;
187
- }
188
- if (!target.$$async) {
189
- // If this module is expected to return a Promise (such as an AsyncModule) then
190
- // we should resolve that with a client reference that unwraps the Promise on
191
- // the client.
192
-
193
- const clientReference: ClientReference<any> =
194
- registerClientReferenceImpl(({}: any), target.$$id, true);
195
- const proxy = new Proxy(clientReference, proxyHandlers);
196
-
197
- // Treat this as a resolved Promise for React's use()
198
- target.status = 'fulfilled';
199
- target.value = proxy;
200
-
201
- const then = (target.then = registerClientReferenceImpl(
202
- (function then(resolve, reject: any) {
203
- // Expose to React.
204
- return Promise.resolve(resolve(proxy));
205
- }: any),
206
- // If this is not used as a Promise but is treated as a reference to a `.then`
207
- // export then we should treat it as a reference to that name.
208
- target.$$id + '#then',
209
- false,
210
- ));
211
- return then;
212
- } else {
213
- // Since typeof .then === 'function' is a feature test we'd continue recursing
214
- // indefinitely if we return a function. Instead, we return an object reference
215
- // if we check further.
216
- return undefined;
217
- }
218
- }
219
- let cachedReference = target[name];
220
- if (!cachedReference) {
221
- const reference: ClientReference<any> = registerClientReferenceImpl(
147
+function getReference(target: Function, name: string | symbol): $FlowFixMe {
148
+ switch (name) {
149
+ // These names are read by the Flight runtime if you end up using the exports object.
150
+ case '$$typeof':
151
+ return target.$$typeof;
152
+ case '$$id':
153
+ return target.$$id;
154
+ case '$$async':
155
+ return target.$$async;
156
+ case 'name':
157
+ return target.name;
158
+ // We need to special case this because createElement reads it if we pass this
159
+ // reference.
160
+ case 'defaultProps':
161
+ return undefined;
162
+ // Avoid this attempting to be serialized.
163
+ case 'toJSON':
164
+ return undefined;
165
+ case Symbol.toPrimitive:
166
+ // $FlowFixMe[prop-missing]
167
+ return Object.prototype[Symbol.toPrimitive];
168
+ case Symbol.toStringTag:
169
+ // $FlowFixMe[prop-missing]
170
+ return Object.prototype[Symbol.toStringTag];
171
+ case '__esModule':
172
+ // Something is conditionally checking which export to use. We'll pretend to be
173
+ // an ESM compat module but then we'll check again on the client.
174
+ const moduleId = target.$$id;
175
+ target.default = registerClientReferenceImpl(
176
(function () {
177
throw new Error(
224
- // eslint-disable-next-line react-internal/safe-string-coercion
225
- `Attempted to call ${String(name)}() from the server but ${String(
226
- name,
227
- )} is on the client. ` +
228
- `It's not possible to invoke a client function from the server, it can ` +
229
- `only be rendered as a Component or passed to props of a Client Component.`,
178
+ `Attempted to call the default export of ${moduleId} from the server ` +
179
+ `but it's on the client. It's not possible to invoke a client function from ` +
180
+ `the server, it can only be rendered as a Component or passed to props of a ` +
181
+ `Client Component.`,
182
);
183
}: any),
232
- target.$$id + '#' + name,
184
+ target.$$id + '#',
185
target.$$async,
186
);
235
- Object.defineProperty((reference: any), 'name', {value: name});
236
- cachedReference = target[name] = new Proxy(reference, deepProxyHandlers);
187
+ return true;
188
+ case 'then':
189
+ if (target.then) {
190
+ // Use a cached value
191
+ return target.then;
192
+ }
193
+ if (!target.$$async) {
194
+ // If this module is expected to return a Promise (such as an AsyncModule) then
195
+ // we should resolve that with a client reference that unwraps the Promise on
196
+ // the client.
197
+
198
+ const clientReference: ClientReference<any> =
199
+ registerClientReferenceImpl(({}: any), target.$$id, true);
200
+ const proxy = new Proxy(clientReference, proxyHandlers);
201
+
202
+ // Treat this as a resolved Promise for React's use()
203
+ target.status = 'fulfilled';
204
+ target.value = proxy;
205
+
206
+ const then = (target.then = registerClientReferenceImpl(
207
+ (function then(resolve, reject: any) {
208
+ // Expose to React.
209
+ return Promise.resolve(resolve(proxy));
210
+ }: any),
211
+ // If this is not used as a Promise but is treated as a reference to a `.then`
212
+ // export then we should treat it as a reference to that name.
213
+ target.$$id + '#then',
214
+ false,
215
+ ));
216
+ return then;
217
+ } else {
218
+ // Since typeof .then === 'function' is a feature test we'd continue recursing
219
+ // indefinitely if we return a function. Instead, we return an object reference
220
+ // if we check further.
221
+ return undefined;
222
+ }
223
+ }
224
+ if (typeof name === 'symbol') {
225
+ throw new Error(
226
+ 'Cannot read Symbol exports. Only named exports are supported on a client module ' +
227
+ 'imported on the server.',
228
+ );
229
+ }
230
+ let cachedReference = target[name];
231
+ if (!cachedReference) {
232
+ const reference: ClientReference<any> = registerClientReferenceImpl(
233
+ (function () {
234
+ throw new Error(
235
+ // eslint-disable-next-line react-internal/safe-string-coercion
236
+ `Attempted to call ${String(name)}() from the server but ${String(
237
+ name,
238
+ )} is on the client. ` +
239
+ `It's not possible to invoke a client function from the server, it can ` +
240
+ `only be rendered as a Component or passed to props of a Client Component.`,
241
+ );
242
+ }: any),
243
+ target.$$id + '#' + name,
244
+ target.$$async,
245
+ );
246
+ Object.defineProperty((reference: any), 'name', {value: name});
247
+ cachedReference = target[name] = new Proxy(reference, deepProxyHandlers);
248
+ }
249
+ return cachedReference;
250
+}
251
+
252
+const proxyHandlers = {
253
+ get: function (
254
+ target: Function,
255
+ name: string | symbol,
256
+ receiver: Proxy<Function>,
257
+ ): $FlowFixMe {
258
+ return getReference(target, name);
259
+ },
260
+ getOwnPropertyDescriptor: function (
261
+ target: Function,
262
+ name: string | symbol,
263
+ ): $FlowFixMe {
264
+ let descriptor = Object.getOwnPropertyDescriptor(target, name);
265
+ if (!descriptor) {
266
+ descriptor = {
267
+ value: getReference(target, name),
268
+ writable: false,
269
+ configurable: false,
270
+ enumerable: false,
271
+ };
272
+ Object.defineProperty(target, name, descriptor);
273
}
238
- return cachedReference;
274
+ return descriptor;
275
},
276
getPrototypeOf(target: Function): Object {
277
// Pretend to be a Promise in case anyone asks.