mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-24 06:14:01 +08:00
Merge main
This commit is contained in:
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"order": [
|
||||
"<repo>/tests/corpus/5913-prototype-type-error-messages.ts"
|
||||
],
|
||||
"diags": []
|
||||
}
|
||||
@@ -1729,13 +1729,40 @@ static bool scr_dyn_typed_ref_prototype(const ScrDyn *value) {
|
||||
return view && (view->kind == SCR_DYN_OBJ || view->kind == SCR_DYN_ARR);
|
||||
}
|
||||
|
||||
/* True when `prototype` is null or an object or function, the values
|
||||
* Object.create and Object.setPrototypeOf accept. Otherwise throws Node's
|
||||
* TypeError, whose message ends with the value's string form. */
|
||||
static bool scr_dyn_prototype_valid(const ScrDyn *prototype) {
|
||||
if (scr_dyn_is_object(prototype) || scr_dyn_is_callable(prototype)) return true;
|
||||
if (scr_exc_pending()) return false;
|
||||
ScrStr *text = prototype->kind == SCR_DYN_SYMBOL
|
||||
? prototype->v.symbol.render(prototype->v.symbol.value) : scr_dyn_string_coerce_js(prototype);
|
||||
if (!text) return false;
|
||||
ScrJsonBuf b;
|
||||
scr_jb_init(&b);
|
||||
scr_jb_puts(&b, "Object prototype may only be an Object or null: ");
|
||||
scr_jb_put_str(&b, text);
|
||||
scr_str_release(text);
|
||||
scr_throw_error(SCR_ERR_TYPE, scr_jb_finish(&b));
|
||||
return false;
|
||||
}
|
||||
|
||||
/* A valid receiver or prototype whose kind this operation does not handle. */
|
||||
static void scr_dyn_prototype_unsupported(const char *operation) {
|
||||
ScrJsonBuf b;
|
||||
scr_jb_init(&b);
|
||||
scr_jb_puts(&b, operation);
|
||||
scr_jb_puts(&b, " with this value is not supported yet");
|
||||
scr_throw_error(SCR_ERR_ERROR, scr_jb_finish(&b));
|
||||
}
|
||||
|
||||
ScrDyn *scr_dyn_obj_create(ScrDyn *prototype) {
|
||||
if (!scr_dyn_prototype_valid(prototype)) return NULL;
|
||||
if (prototype != scr_builtin_object_prototype && scr_dyn_class_reflection_fence(prototype)) return NULL;
|
||||
bool typed = scr_dyn_typed_ref_prototype(prototype);
|
||||
if (scr_exc_pending()) return NULL;
|
||||
if (prototype->kind != SCR_DYN_OBJ && prototype->kind != SCR_DYN_ARR && prototype->kind != SCR_DYN_NULL && !typed) {
|
||||
static const char message[] = "Object prototype may only be an Object or null";
|
||||
scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
|
||||
scr_dyn_prototype_unsupported("Object.create");
|
||||
return NULL;
|
||||
}
|
||||
ScrDyn *object = prototype->kind == SCR_DYN_NULL ? scr_dyn_new_obj_null_proto() : scr_dyn_new_obj();
|
||||
@@ -1786,12 +1813,7 @@ ScrDyn *scr_dyn_set_prototype(ScrDyn *object, ScrDyn *prototype) {
|
||||
* only check. */
|
||||
if (object->kind == SCR_DYN_BOOL || object->kind == SCR_DYN_NUM || object->kind == SCR_DYN_STR ||
|
||||
object->kind == SCR_DYN_BIGINT || object->kind == SCR_DYN_SYMBOL) {
|
||||
bool valid = scr_dyn_is_object(prototype) || scr_dyn_is_callable(prototype);
|
||||
if (scr_exc_pending()) return NULL;
|
||||
if (valid) return scr_dyn_retain(object);
|
||||
static const char message[] = "Object prototype may only be an Object or null";
|
||||
scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
|
||||
return NULL;
|
||||
return scr_dyn_prototype_valid(prototype) ? scr_dyn_retain(object) : NULL;
|
||||
}
|
||||
if (scr_dyn_class_reflection_fence(object) || scr_dyn_class_reflection_fence(prototype)) return NULL;
|
||||
if (object->kind == SCR_DYN_TYPED_REF) {
|
||||
@@ -1821,12 +1843,12 @@ ScrDyn *scr_dyn_set_prototype(ScrDyn *object, ScrDyn *prototype) {
|
||||
scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
|
||||
return NULL;
|
||||
}
|
||||
if (!scr_dyn_prototype_valid(prototype)) return NULL;
|
||||
bool typed = scr_dyn_typed_ref_prototype(prototype);
|
||||
if (scr_exc_pending()) return NULL;
|
||||
if ((object->kind != SCR_DYN_OBJ && object->kind != SCR_DYN_ARR) ||
|
||||
(prototype->kind != SCR_DYN_OBJ && prototype->kind != SCR_DYN_ARR && prototype->kind != SCR_DYN_FUNC && prototype->kind != SCR_DYN_NULL && !typed)) {
|
||||
static const char message[] = "Object prototype may only be an Object or null";
|
||||
scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
|
||||
scr_dyn_prototype_unsupported("Object.setPrototypeOf");
|
||||
return NULL;
|
||||
}
|
||||
for (const ScrDyn *current = scr_dyn_chain_link(prototype); current;) {
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
// Object.setPrototypeOf and Object.create reject a prototype that is
|
||||
// neither an object nor null with Node's TypeError, whose message ends with
|
||||
// the value's string form: numbers as String(n) (-0 as 0), bigints without
|
||||
// the n suffix, symbols as Symbol(description), and the empty string as
|
||||
// nothing.
|
||||
|
||||
function message(run: () => unknown): string {
|
||||
try {
|
||||
run();
|
||||
return "no error";
|
||||
} catch (error) {
|
||||
return `${error instanceof TypeError} ${(error as Error).message}`;
|
||||
}
|
||||
}
|
||||
|
||||
const prototypes: [string, unknown][] = [
|
||||
["number", 7],
|
||||
["fraction", 1.5],
|
||||
["negative zero", -0],
|
||||
["nan", NaN],
|
||||
["string", "proto"],
|
||||
["empty string", ""],
|
||||
["boolean", true],
|
||||
["undefined", undefined],
|
||||
["bigint", 10n],
|
||||
["symbol", Symbol("tag")],
|
||||
];
|
||||
|
||||
for (const [label, prototype] of prototypes) {
|
||||
const invalid = prototype as object | null;
|
||||
const target: unknown = JSON.parse('{"own":1}');
|
||||
console.log(label, "object receiver |", message(() => Object.setPrototypeOf(target, invalid)));
|
||||
console.log(label, "primitive receiver |", message(() => Object.setPrototypeOf(5, invalid)));
|
||||
console.log(label, "create |", message(() => Object.create(invalid)));
|
||||
}
|
||||
|
||||
const valid: unknown = JSON.parse('{"own":1}');
|
||||
console.log("null prototype |", message(() => Object.setPrototypeOf(valid, null)));
|
||||
console.log("object prototype |", message(() => Object.create({ inherited: true })));
|
||||
@@ -1841,6 +1841,9 @@
|
||||
"5648-dns-lookup-forms.ts": 2992,
|
||||
"5649-dns-service-servers.ts": 2712,
|
||||
"5650-dns-lookup-errors-untyped.cjs": 2822,
|
||||
"5910-set-prototype-of-primitive-object-kinds.ts": 2719,
|
||||
"5911-dyn-class-to-primitive.ts": 2850,
|
||||
"5913-prototype-type-error-messages.ts": 2484,
|
||||
"5939-js-let-object-reassigned-wider.js": 1945,
|
||||
"5950-tuple-predicate-methods.ts": 5990,
|
||||
"5951-result-never-widening.ts": 4710,
|
||||
@@ -4473,6 +4476,9 @@
|
||||
"5648-dns-lookup-forms.ts": 3416,
|
||||
"5649-dns-service-servers.ts": 4916,
|
||||
"5650-dns-lookup-errors-untyped.cjs": 3889,
|
||||
"5910-set-prototype-of-primitive-object-kinds.ts": 5033,
|
||||
"5911-dyn-class-to-primitive.ts": 4732,
|
||||
"5913-prototype-type-error-messages.ts": 4068,
|
||||
"5939-js-let-object-reassigned-wider.js": 4436,
|
||||
"5950-tuple-predicate-methods.ts": 7790,
|
||||
"5951-result-never-widening.ts": 6120,
|
||||
|
||||
Reference in New Issue
Block a user