diff options
Diffstat (limited to 'js/src/builtin/RegExp.cpp')
-rw-r--r-- | js/src/builtin/RegExp.cpp | 140 |
1 files changed, 84 insertions, 56 deletions
diff --git a/js/src/builtin/RegExp.cpp b/js/src/builtin/RegExp.cpp index 80a4bb5bd..b20f41c53 100644 --- a/js/src/builtin/RegExp.cpp +++ b/js/src/builtin/RegExp.cpp @@ -577,14 +577,29 @@ js::regexp_clone(JSContext* cx, unsigned argc, Value* vp) return true; } -/* ES6 draft rev32 21.2.5.4. */ +MOZ_ALWAYS_INLINE bool +IsRegExpInstanceOrPrototype(HandleValue v) +{ + if (!v.isObject()) + return false; + + return StandardProtoKeyOrNull(&v.toObject()) == JSProto_RegExp; +} + +// ES 2017 draft 21.2.5.4. MOZ_ALWAYS_INLINE bool regexp_global_impl(JSContext* cx, const CallArgs& args) { - MOZ_ASSERT(IsRegExpObject(args.thisv())); - Rooted<RegExpObject*> reObj(cx, &args.thisv().toObject().as<RegExpObject>()); + MOZ_ASSERT(IsRegExpInstanceOrPrototype(args.thisv())); - /* Steps 4-6. */ + // Step 3.a. + if (!IsRegExpObject(args.thisv())) { + args.rval().setUndefined(); + return true; + } + + // Steps 4-6. + Rooted<RegExpObject*> reObj(cx, &args.thisv().toObject().as<RegExpObject>()); args.rval().setBoolean(reObj->global()); return true; } @@ -592,19 +607,25 @@ regexp_global_impl(JSContext* cx, const CallArgs& args) bool js::regexp_global(JSContext* cx, unsigned argc, JS::Value* vp) { - /* Steps 1-3. */ + // Steps 1-3. CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod<IsRegExpObject, regexp_global_impl>(cx, args); + return CallNonGenericMethod<IsRegExpInstanceOrPrototype, regexp_global_impl>(cx, args); } -/* ES6 draft rev32 21.2.5.5. */ +// ES 2017 draft 21.2.5.5. MOZ_ALWAYS_INLINE bool regexp_ignoreCase_impl(JSContext* cx, const CallArgs& args) { - MOZ_ASSERT(IsRegExpObject(args.thisv())); - Rooted<RegExpObject*> reObj(cx, &args.thisv().toObject().as<RegExpObject>()); + MOZ_ASSERT(IsRegExpInstanceOrPrototype(args.thisv())); - /* Steps 4-6. */ + // Step 3.a + if (!IsRegExpObject(args.thisv())) { + args.rval().setUndefined(); + return true; + } + + // Steps 4-6. + Rooted<RegExpObject*> reObj(cx, &args.thisv().toObject().as<RegExpObject>()); args.rval().setBoolean(reObj->ignoreCase()); return true; } @@ -612,19 +633,25 @@ regexp_ignoreCase_impl(JSContext* cx, const CallArgs& args) bool js::regexp_ignoreCase(JSContext* cx, unsigned argc, JS::Value* vp) { - /* Steps 1-3. */ + // Steps 1-3. CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod<IsRegExpObject, regexp_ignoreCase_impl>(cx, args); + return CallNonGenericMethod<IsRegExpInstanceOrPrototype, regexp_ignoreCase_impl>(cx, args); } -/* ES6 draft rev32 21.2.5.7. */ +// ES 2017 draft 21.2.5.7. MOZ_ALWAYS_INLINE bool regexp_multiline_impl(JSContext* cx, const CallArgs& args) { - MOZ_ASSERT(IsRegExpObject(args.thisv())); - Rooted<RegExpObject*> reObj(cx, &args.thisv().toObject().as<RegExpObject>()); + MOZ_ASSERT(IsRegExpInstanceOrPrototype(args.thisv())); - /* Steps 4-6. */ + // Step 3.a. + if (!IsRegExpObject(args.thisv())) { + args.rval().setUndefined(); + return true; + } + + // Steps 4-6. + Rooted<RegExpObject*> reObj(cx, &args.thisv().toObject().as<RegExpObject>()); args.rval().setBoolean(reObj->multiline()); return true; } @@ -632,24 +659,30 @@ regexp_multiline_impl(JSContext* cx, const CallArgs& args) bool js::regexp_multiline(JSContext* cx, unsigned argc, JS::Value* vp) { - /* Steps 1-3. */ + // Steps 1-3. CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod<IsRegExpObject, regexp_multiline_impl>(cx, args); + return CallNonGenericMethod<IsRegExpInstanceOrPrototype, regexp_multiline_impl>(cx, args); } -/* ES6 draft rev32 21.2.5.10. */ +// ES 2017 draft rev32 21.2.5.10. MOZ_ALWAYS_INLINE bool regexp_source_impl(JSContext* cx, const CallArgs& args) { - MOZ_ASSERT(IsRegExpObject(args.thisv())); - Rooted<RegExpObject*> reObj(cx, &args.thisv().toObject().as<RegExpObject>()); + MOZ_ASSERT(IsRegExpInstanceOrPrototype(args.thisv())); + + // Step 3.a. + if (!IsRegExpObject(args.thisv())) { + args.rval().setString(cx->names().emptyRegExp); + return true; + } - /* Step 5. */ + // Step 5. + Rooted<RegExpObject*> reObj(cx, &args.thisv().toObject().as<RegExpObject>()); RootedAtom src(cx, reObj->getSource()); if (!src) return false; - /* Step 7. */ + // Step 7. RootedString str(cx, EscapeRegExpPattern(cx, src)); if (!str) return false; @@ -661,19 +694,25 @@ regexp_source_impl(JSContext* cx, const CallArgs& args) static bool regexp_source(JSContext* cx, unsigned argc, JS::Value* vp) { - /* Steps 1-4. */ + // Steps 1-4. CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod<IsRegExpObject, regexp_source_impl>(cx, args); + return CallNonGenericMethod<IsRegExpInstanceOrPrototype, regexp_source_impl>(cx, args); } -/* ES6 draft rev32 21.2.5.12. */ +// ES 2017 draft 21.2.5.12. MOZ_ALWAYS_INLINE bool regexp_sticky_impl(JSContext* cx, const CallArgs& args) { - MOZ_ASSERT(IsRegExpObject(args.thisv())); - Rooted<RegExpObject*> reObj(cx, &args.thisv().toObject().as<RegExpObject>()); + MOZ_ASSERT(IsRegExpInstanceOrPrototype(args.thisv())); - /* Steps 4-6. */ + // Step 3.a. + if (!IsRegExpObject(args.thisv())) { + args.rval().setUndefined(); + return true; + } + + // Steps 4-6. + Rooted<RegExpObject*> reObj(cx, &args.thisv().toObject().as<RegExpObject>()); args.rval().setBoolean(reObj->sticky()); return true; } @@ -681,27 +720,35 @@ regexp_sticky_impl(JSContext* cx, const CallArgs& args) bool js::regexp_sticky(JSContext* cx, unsigned argc, JS::Value* vp) { - /* Steps 1-3. */ + // Steps 1-3. CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod<IsRegExpObject, regexp_sticky_impl>(cx, args); + return CallNonGenericMethod<IsRegExpInstanceOrPrototype, regexp_sticky_impl>(cx, args); } -/* ES6 21.2.5.15. */ +// ES 2017 draft 21.2.5.15. MOZ_ALWAYS_INLINE bool regexp_unicode_impl(JSContext* cx, const CallArgs& args) { - MOZ_ASSERT(IsRegExpObject(args.thisv())); - /* Steps 4-6. */ - args.rval().setBoolean(args.thisv().toObject().as<RegExpObject>().unicode()); + MOZ_ASSERT(IsRegExpInstanceOrPrototype(args.thisv())); + + // Step 3.a. + if (!IsRegExpObject(args.thisv())) { + args.rval().setUndefined(); + return true; + } + + // Steps 4-6. + Rooted<RegExpObject*> reObj(cx, &args.thisv().toObject().as<RegExpObject>()); + args.rval().setBoolean(reObj->unicode()); return true; } bool js::regexp_unicode(JSContext* cx, unsigned argc, JS::Value* vp) { - /* Steps 1-3. */ + // Steps 1-3. CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod<IsRegExpObject, regexp_unicode_impl>(cx, args); + return CallNonGenericMethod<IsRegExpInstanceOrPrototype, regexp_unicode_impl>(cx, args); } const JSPropertySpec js::regexp_properties[] = { @@ -829,25 +876,6 @@ const JSPropertySpec js::regexp_static_props[] = { JS_PS_END }; -JSObject* -js::CreateRegExpPrototype(JSContext* cx, JSProtoKey key) -{ - MOZ_ASSERT(key == JSProto_RegExp); - - Rooted<RegExpObject*> proto(cx, cx->global()->createBlankPrototype<RegExpObject>(cx)); - if (!proto) - return nullptr; - proto->NativeObject::setPrivate(nullptr); - - if (!RegExpObject::assignInitialShape(cx, proto)) - return nullptr; - - RootedAtom source(cx, cx->names().empty); - proto->initAndZeroLastIndex(source, RegExpFlag(0), cx); - - return proto; -} - template <typename CharT> static bool IsTrailSurrogateWithLeadSurrogateImpl(JSContext* cx, HandleLinearString input, size_t index) |