diff --git a/quickjs.c b/quickjs.c index 4a88e80..78376ef 100644 --- a/quickjs.c +++ b/quickjs.c @@ -1176,8 +1176,8 @@ static int JS_ToUint8ClampFree(JSContext *ctx, int32_t *pres, JSValue val); static JSValue js_new_string8_len(JSContext *ctx, const char *buf, int len); static JSValue js_compile_regexp(JSContext *ctx, JSValueConst pattern, JSValueConst flags); -static JSValue js_regexp_constructor_internal(JSContext *ctx, JSValueConst ctor, - JSValue pattern, JSValue bc); +static JSValue js_regexp_set_internal(JSContext *ctx, JSValue obj, + JSValue pattern, JSValue bc); static void gc_decref(JSRuntime *rt); static int JS_NewClass1(JSRuntime *rt, JSClassID class_id, const JSClassDef *class_def, JSAtom name); @@ -5238,7 +5238,7 @@ static JSValue JS_NewObjectFromShape(JSContext *ctx, JSShape *sh, JSClassID clas case JS_CLASS_REGEXP: p->u.regexp.pattern = NULL; p->u.regexp.bytecode = NULL; - goto set_exotic; + break; default: set_exotic: if (ctx->rt->class_array[class_id].exotic) { @@ -13426,6 +13426,11 @@ static void js_print_regexp(JSPrintValueState *s, JSObject *p1) int i, n, c, c2, bra, flags; static const char regexp_flags[] = { 'g', 'i', 'm', 's', 'u', 'y', 'd', 'v' }; + if (!re->pattern || !re->bytecode) { + /* the regexp fields are zeroed at init */ + js_puts(s, "[uninitialized_regexp]"); + return; + } p = re->pattern; js_putc(s, '/'); if (p->len == 0) { @@ -17638,8 +17643,13 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, CASE(OP_regexp): { - sp[-2] = js_regexp_constructor_internal(ctx, JS_UNDEFINED, - sp[-2], sp[-1]); + JSValue obj; + obj = JS_NewObjectClass(ctx, JS_CLASS_REGEXP); + if (JS_IsException(obj)) + goto exception; + sp[-2] = js_regexp_set_internal(ctx, obj, sp[-2], sp[-1]); + if (JS_IsException(sp[-2])) + goto exception; sp--; } BREAK; @@ -46105,8 +46115,10 @@ static void js_regexp_finalizer(JSRuntime *rt, JSValue val) { JSObject *p = JS_VALUE_GET_OBJ(val); JSRegExp *re = &p->u.regexp; - JS_FreeValueRT(rt, JS_MKPTR(JS_TAG_STRING, re->bytecode)); - JS_FreeValueRT(rt, JS_MKPTR(JS_TAG_STRING, re->pattern)); + if (re->bytecode != NULL) + JS_FreeValueRT(rt, JS_MKPTR(JS_TAG_STRING, re->bytecode)); + if (re->pattern != NULL) + JS_FreeValueRT(rt, JS_MKPTR(JS_TAG_STRING, re->pattern)); } /* create a string containing the RegExp bytecode */ @@ -46188,32 +46200,29 @@ static JSValue js_compile_regexp(JSContext *ctx, JSValueConst pattern, return ret; } -/* create a RegExp object from a string containing the RegExp bytecode - and the source pattern */ -static JSValue js_regexp_constructor_internal(JSContext *ctx, JSValueConst ctor, - JSValue pattern, JSValue bc) +/* set the RegExp fields */ +static JSValue js_regexp_set_internal(JSContext *ctx, + JSValue obj, + JSValue pattern, JSValue bc) { - JSValue obj; JSObject *p; JSRegExp *re; /* sanity check */ - if (JS_VALUE_GET_TAG(bc) != JS_TAG_STRING || - JS_VALUE_GET_TAG(pattern) != JS_TAG_STRING) { + if (unlikely(JS_VALUE_GET_TAG(bc) != JS_TAG_STRING || + JS_VALUE_GET_TAG(pattern) != JS_TAG_STRING)) { JS_ThrowTypeError(ctx, "string expected"); - fail: + JS_FreeValue(ctx, obj); JS_FreeValue(ctx, bc); JS_FreeValue(ctx, pattern); return JS_EXCEPTION; } - obj = js_create_from_ctor(ctx, ctor, JS_CLASS_REGEXP); - if (JS_IsException(obj)) - goto fail; p = JS_VALUE_GET_OBJ(obj); re = &p->u.regexp; re->pattern = JS_VALUE_GET_STRING(pattern); re->bytecode = JS_VALUE_GET_STRING(bc); + /* Note: cannot fail because the field is preallocated */ JS_DefinePropertyValue(ctx, obj, JS_ATOM_lastIndex, JS_NewInt32(ctx, 0), JS_PROP_WRITABLE); return obj; @@ -46250,7 +46259,7 @@ static int js_is_regexp(JSContext *ctx, JSValueConst obj) static JSValue js_regexp_constructor(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv) { - JSValue pattern, flags, bc, val; + JSValue pattern, flags, bc, val, obj = JS_UNDEFINED; JSValueConst pat, flags1; JSRegExp *re; int pat_is_regexp; @@ -46280,11 +46289,12 @@ static JSValue js_regexp_constructor(JSContext *ctx, JSValueConst new_target, pattern = JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, re->pattern)); if (JS_IsUndefined(flags1)) { bc = JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, re->bytecode)); + obj = js_create_from_ctor(ctx, new_target, JS_CLASS_REGEXP); + if (JS_IsException(obj)) + goto fail; goto no_compilation; } else { - flags = JS_ToString(ctx, flags1); - if (JS_IsException(flags)) - goto fail; + flags = JS_DupValue(ctx, flags1); } } else { flags = JS_UNDEFINED; @@ -46313,15 +46323,19 @@ static JSValue js_regexp_constructor(JSContext *ctx, JSValueConst new_target, goto fail; } } + obj = js_create_from_ctor(ctx, new_target, JS_CLASS_REGEXP); + if (JS_IsException(obj)) + goto fail; bc = js_compile_regexp(ctx, pattern, flags); if (JS_IsException(bc)) goto fail; JS_FreeValue(ctx, flags); no_compilation: - return js_regexp_constructor_internal(ctx, new_target, pattern, bc); + return js_regexp_set_internal(ctx, obj, pattern, bc); fail: JS_FreeValue(ctx, pattern); JS_FreeValue(ctx, flags); + JS_FreeValue(ctx, obj); return JS_EXCEPTION; } diff --git a/test262_errors.txt b/test262_errors.txt index 7cd4963..f97c940 100644 --- a/test262_errors.txt +++ b/test262_errors.txt @@ -14,8 +14,6 @@ test262/test/staging/sm/Function/function-name-for.js:13: Test262Error: Expected test262/test/staging/sm/Function/implicit-this-in-parameter-expression.js:12: Test262Error: Expected SameValue(«[object Object]», «undefined») to be true test262/test/staging/sm/Function/invalid-parameter-list.js:13: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all test262/test/staging/sm/Function/invalid-parameter-list.js:13: strict mode: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all -test262/test/staging/sm/RegExp/constructor-ordering-2.js:12: Test262Error: Expected SameValue(«false», «true») to be true -test262/test/staging/sm/RegExp/constructor-ordering-2.js:12: strict mode: Test262Error: Expected SameValue(«false», «true») to be true test262/test/staging/sm/RegExp/regress-613820-1.js:12: Test262Error: Actual [aaa, aa, a] and expected [aa, a, a] should have the same contents. test262/test/staging/sm/RegExp/regress-613820-1.js:12: strict mode: Test262Error: Actual [aaa, aa, a] and expected [aa, a, a] should have the same contents. test262/test/staging/sm/RegExp/regress-613820-2.js:12: Test262Error: Actual [foobar, f, o, o, b, a, r] and expected [foobar, undefined, undefined, undefined, b, a, r] should have the same contents.