diff --git a/quickjs.c b/quickjs.c index 8dbc83e82..8f2d99fbf 100644 --- a/quickjs.c +++ b/quickjs.c @@ -454,6 +454,7 @@ struct JSContext { JSValue error_prepare_stack; JSValue error_stack_trace_limit; JSValue iterator_ctor; + JSValue iterator_ctor_getset; JSValue iterator_proto; JSValue async_iterator_proto; JSValue array_proto_values; @@ -2303,6 +2304,7 @@ JSContext *JS_NewContextRaw(JSRuntime *rt) ctx->class_proto[i] = JS_NULL; ctx->array_ctor = JS_NULL; ctx->iterator_ctor = JS_NULL; + ctx->iterator_ctor_getset = JS_NULL; ctx->regexp_ctor = JS_NULL; ctx->promise_ctor = JS_NULL; ctx->error_ctor = JS_NULL; @@ -2433,6 +2435,7 @@ static void JS_MarkContext(JSRuntime *rt, JSContext *ctx, JS_MarkValue(rt, ctx->class_proto[i], mark_func); } JS_MarkValue(rt, ctx->iterator_ctor, mark_func); + JS_MarkValue(rt, ctx->iterator_ctor_getset, mark_func); JS_MarkValue(rt, ctx->async_iterator_proto, mark_func); JS_MarkValue(rt, ctx->promise_ctor, mark_func); JS_MarkValue(rt, ctx->array_ctor, mark_func); @@ -2503,6 +2506,7 @@ void JS_FreeContext(JSContext *ctx) } js_free_rt(rt, ctx->class_proto); JS_FreeValue(ctx, ctx->iterator_ctor); + JS_FreeValue(ctx, ctx->iterator_ctor_getset); JS_FreeValue(ctx, ctx->async_iterator_proto); JS_FreeValue(ctx, ctx->promise_ctor); JS_FreeValue(ctx, ctx->array_ctor); @@ -41672,6 +41676,26 @@ static const JSCFunctionListEntry js_iterator_wrap_proto_funcs[] = { JS_ITERATOR_NEXT_DEF("return", 0, js_iterator_wrap_next, GEN_MAGIC_RETURN ), }; +static JSValue js_iterator_constructor_getset(JSContext *ctx, + JSValueConst this_val, + int argc, JSValueConst *argv, + int magic, + JSValueConst *func_data) +{ + int ret; + + if (argc > 0) { // if setter + if (!JS_IsObject(argv[0])) + return JS_ThrowTypeErrorNotAnObject(ctx); + ret = JS_DefinePropertyValue(ctx, this_val, JS_ATOM_constructor, + js_dup(argv[0]), + JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + if (ret < 0) + return JS_EXCEPTION; + } + return js_dup(func_data[0]); +} + static JSValue js_iterator_constructor(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv) { @@ -53275,6 +53299,16 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx) countof(js_iterator_proto_funcs)); obj = JS_NewGlobalCConstructor(ctx, "Iterator", js_iterator_constructor, 0, ctx->class_proto[JS_CLASS_ITERATOR]); + // quirk: Iterator.prototype.constructor is an accessor property + // TODO(bnoordhuis) mildly inefficient because JS_NewGlobalCConstructor + // first creates a .constructor value property that we then replace with + // an accessor + ctx->iterator_ctor_getset = JS_NewCFunctionData(ctx, js_iterator_constructor_getset, + 0, 0, 1, vc(&obj)); + JS_DefineProperty(ctx, ctx->class_proto[JS_CLASS_ITERATOR], + JS_ATOM_constructor, JS_UNDEFINED, + ctx->iterator_ctor_getset, ctx->iterator_ctor_getset, + JS_PROP_HAS_GET|JS_PROP_HAS_SET|JS_PROP_WRITABLE|JS_PROP_CONFIGURABLE); ctx->iterator_ctor = js_dup(obj); JS_SetPropertyFunctionList(ctx, obj, js_iterator_funcs, diff --git a/test262_errors.txt b/test262_errors.txt index 98a30b229..4d7bbc09c 100644 --- a/test262_errors.txt +++ b/test262_errors.txt @@ -24,10 +24,6 @@ test262/test/built-ins/AsyncFromSyncIteratorPrototype/throw/throw-undefined-retu test262/test/built-ins/AsyncFromSyncIteratorPrototype/throw/throw-undefined-return-not-object.js:72: strict mode: TypeError: $DONE() not called test262/test/built-ins/AsyncFromSyncIteratorPrototype/throw/throw-undefined-return-object.js:66: TypeError: $DONE() not called test262/test/built-ins/AsyncFromSyncIteratorPrototype/throw/throw-undefined-return-object.js:66: strict mode: TypeError: $DONE() not called -test262/test/built-ins/Iterator/prototype/constructor/prop-desc.js:10: Test262Error: Expected SameValue(«"undefined"», «"function"») to be true -test262/test/built-ins/Iterator/prototype/constructor/prop-desc.js:10: strict mode: Test262Error: Expected SameValue(«"undefined"», «"function"») to be true -test262/test/built-ins/Iterator/prototype/constructor/weird-setter.js:23: TypeError: cannot read property 'call' of undefined -test262/test/built-ins/Iterator/prototype/constructor/weird-setter.js:23: strict mode: TypeError: cannot read property 'call' of undefined test262/test/built-ins/Object/defineProperties/typedarray-backed-by-resizable-buffer.js:20: Test262Error: Expected a TypeError to be thrown but no exception was thrown at all test262/test/built-ins/Object/defineProperties/typedarray-backed-by-resizable-buffer.js:20: strict mode: Test262Error: Expected a TypeError to be thrown but no exception was thrown at all test262/test/built-ins/Object/defineProperty/coerced-P-grow.js:45: TypeError: out-of-bound index in typed array