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);
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) {
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) {
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;
{
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 */
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;
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;
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;
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;
}