(
request: Request,
task: Task,
parent:
| {+[propertyName: string | number]: ReactClientValue}
| $ReadOnlyArray<ReactClientValue>,
parentPropertyName: string,
value: ReactClientValue,
)
| 3322 | } |
| 3323 | |
| 3324 | function renderModelDestructive( |
| 3325 | request: Request, |
| 3326 | task: Task, |
| 3327 | parent: |
| 3328 | | {+[propertyName: string | number]: ReactClientValue} |
| 3329 | | $ReadOnlyArray<ReactClientValue>, |
| 3330 | parentPropertyName: string, |
| 3331 | value: ReactClientValue, |
| 3332 | ): ReactJSONValue { |
| 3333 | // Set the currently rendering model |
| 3334 | task.model = value; |
| 3335 | |
| 3336 | if (__DEV__) { |
| 3337 | if (parentPropertyName === __PROTO__) { |
| 3338 | callWithDebugContextInDEV(request, task, () => { |
| 3339 | console.error( |
| 3340 | 'Expected not to serialize an object with own property `__proto__`. When parsed this property will be omitted.%s', |
| 3341 | describeObjectForErrorMessage(parent, parentPropertyName), |
| 3342 | ); |
| 3343 | }); |
| 3344 | } |
| 3345 | } |
| 3346 | |
| 3347 | // Special Symbol, that's very common. |
| 3348 | if (value === REACT_ELEMENT_TYPE) { |
| 3349 | return '$'; |
| 3350 | } |
| 3351 | |
| 3352 | if (value === null) { |
| 3353 | return null; |
| 3354 | } |
| 3355 | |
| 3356 | if (typeof value === 'object') { |
| 3357 | switch ((value: any).$$typeof) { |
| 3358 | case REACT_ELEMENT_TYPE: { |
| 3359 | let elementReference = null; |
| 3360 | const writtenObjects = request.writtenObjects; |
| 3361 | if (task.keyPath !== null || task.implicitSlot) { |
| 3362 | // If we're in some kind of context we can't reuse the result of this render or |
| 3363 | // previous renders of this element. We only reuse elements if they're not wrapped |
| 3364 | // by another Server Component. |
| 3365 | } else { |
| 3366 | const existingReference = writtenObjects.get(value); |
| 3367 | if (existingReference !== undefined) { |
| 3368 | if (modelRoot === value) { |
| 3369 | // This is the ID we're currently emitting so we need to write it |
| 3370 | // once but if we discover it again, we refer to it by id. |
| 3371 | modelRoot = null; |
| 3372 | } else { |
| 3373 | // We've already emitted this as an outlined object, so we can refer to that by its |
| 3374 | // existing ID. TODO: We should use a lazy reference since, unlike plain objects, |
| 3375 | // elements might suspend so it might not have emitted yet even if we have the ID for |
| 3376 | // it. However, this creates an extra wrapper when it's not needed. We should really |
| 3377 | // detect whether this already was emitted and synchronously available. In that |
| 3378 | // case we can refer to it synchronously and only make it lazy otherwise. |
| 3379 | // We currently don't have a data structure that lets us see that though. |
| 3380 | return existingReference; |
| 3381 | } |
no test coverage detected