mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-27 06:43:19 +08:00
Refuse JSON and dynamic copies of object literals with accessors (#1490)
This commit is contained in:
@@ -3891,6 +3891,9 @@ function isJsonSafeAt(
|
||||
const shape = getRecord(t.shapeId);
|
||||
if (!shape) return false;
|
||||
if (recordTextCodecClass(shape) !== null) return false;
|
||||
// Accessor slots are not function-valued properties: Node's
|
||||
// JSON.stringify invokes the getter (see accessorSlotProp).
|
||||
if (shapeHasAccessorSlots(shape)) return false;
|
||||
// The recursive knot: answer true and let the rest of the graph
|
||||
// decide (any unsafe constituent ends the traversal immediately).
|
||||
if (visiting.has(t.shapeId)) return true;
|
||||
@@ -4228,6 +4231,9 @@ function canBoxDynCompositeAt(
|
||||
const shape = getRecord(t.shapeId);
|
||||
if (!shape) return false;
|
||||
if (recordTextCodecClass(shape) !== null) return false;
|
||||
// Accessor slots hold the getter and setter closures, not property
|
||||
// values (see accessorSlotProp).
|
||||
if (shapeHasAccessorSlots(shape)) return false;
|
||||
// Recursive shapes answer coinductively, like isJsonSafeType.
|
||||
if (visiting.has(t.shapeId)) return true;
|
||||
visiting.add(t.shapeId);
|
||||
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"order": [
|
||||
"<repo>/tests/diagnostics/object-literal-accessor-values.ts"
|
||||
],
|
||||
"diags": []
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// Object literals with get/set accessors keep their closures in reserved
|
||||
// slots, so their typed values have no JSON or checked-dynamic form: Node's
|
||||
// JSON.stringify and dynamic reads invoke the getter, which neither a typed
|
||||
// serializer nor a converted copy could do.
|
||||
|
||||
function hold(value: unknown): unknown {
|
||||
return value;
|
||||
}
|
||||
|
||||
const counter = {
|
||||
count: 1,
|
||||
get doubled(): number {
|
||||
return 2;
|
||||
},
|
||||
};
|
||||
|
||||
// JSON.stringify of the typed value would omit the getter's property.
|
||||
console.log(JSON.stringify(counter));
|
||||
|
||||
// Converting the typed value to `unknown` or `any` would lose the getter.
|
||||
hold(counter);
|
||||
const viaAny: any = counter;
|
||||
console.log(viaAny);
|
||||
|
||||
// A literal written into an `any` slot directly keeps its accessor.
|
||||
const direct: any = {
|
||||
get value(): number {
|
||||
return 3;
|
||||
},
|
||||
};
|
||||
console.log(direct.value);
|
||||
@@ -0,0 +1,24 @@
|
||||
object-literal-accessor-values.ts:18:28 - error SC1090: JSON.stringify of '{ get doubled(): number; count: number }' values (only number, string, boolean, records, arrays, unions of those, and 'unknown' stringify) are not supported yet
|
||||
|
||||
17 | // JSON.stringify of the typed value would omit the getter's property.
|
||||
18 | console.log(JSON.stringify(counter));
|
||||
| ^~~~~~~
|
||||
19 |
|
||||
|
||||
object-literal-accessor-values.ts:21:6 - error SC1101: converting typed values to 'unknown' is not supported yet
|
||||
|
||||
20 | // Converting the typed value to `unknown` or `any` would lose the getter.
|
||||
21 | hold(counter);
|
||||
| ^~~~~~~
|
||||
22 | const viaAny: any = counter;
|
||||
|
||||
hint: numbers, strings, booleans, JSON-safe records/arrays/unions (a deep copy), functions, program class instances, and supported native handles convert into 'unknown' slots; functions, exact-class round trips, and handles preserve identity, while this value's type has no dynamic representation yet
|
||||
|
||||
object-literal-accessor-values.ts:22:21 - error SC1101: converting typed values to 'unknown' is not supported yet
|
||||
|
||||
21 | hold(counter);
|
||||
22 | const viaAny: any = counter;
|
||||
| ^~~~~~~
|
||||
23 | console.log(viaAny);
|
||||
|
||||
hint: numbers, strings, booleans, JSON-safe records/arrays/unions (a deep copy), functions, program class instances, and supported native handles convert into 'unknown' slots; functions, exact-class round trips, and handles preserve identity, while this value's type has no dynamic representation yet
|
||||
Reference in New Issue
Block a user