From 87e4f43be04313da7b4b5ede81c9c97b6bd5394c Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Sat, 14 Apr 2018 08:40:37 +0200 Subject: Bug 1320993 - Fix exporting default class expression --- js/src/builtin/ModuleObject.cpp | 70 ++++++++++++++-------------- js/src/jit-test/tests/modules/bug-1320993.js | 2 + 2 files changed, 37 insertions(+), 35 deletions(-) create mode 100644 js/src/jit-test/tests/modules/bug-1320993.js (limited to 'js/src') diff --git a/js/src/builtin/ModuleObject.cpp b/js/src/builtin/ModuleObject.cpp index 710c7a76c..e2f7f997e 100644 --- a/js/src/builtin/ModuleObject.cpp +++ b/js/src/builtin/ModuleObject.cpp @@ -1164,6 +1164,13 @@ ModuleBuilder::processExport(frontend::ParseNode* pn) bool isDefault = pn->getKind() == PNK_EXPORT_DEFAULT; ParseNode* kid = isDefault ? pn->pn_left : pn->pn_kid; + if (isDefault && pn->pn_right) { + // This is an export default containing an expression. + RootedAtom localName(cx_, cx_->names().starDefaultStar); + RootedAtom exportName(cx_, cx_->names().default_); + return appendExportEntry(exportName, localName); + } + switch (kid->getKind()) { case PNK_EXPORT_SPEC_LIST: MOZ_ASSERT(!isDefault); @@ -1177,53 +1184,46 @@ ModuleBuilder::processExport(frontend::ParseNode* pn) break; case PNK_CLASS: { - const ClassNode& cls = kid->as(); - MOZ_ASSERT(cls.names()); - RootedAtom localName(cx_, cls.names()->innerBinding()->pn_atom); - RootedAtom exportName(cx_, isDefault ? cx_->names().default_ : localName.get()); - if (!appendExportEntry(exportName, localName)) - return false; - break; + const ClassNode& cls = kid->as(); + MOZ_ASSERT(cls.names()); + RootedAtom localName(cx_, cls.names()->innerBinding()->pn_atom); + RootedAtom exportName(cx_, isDefault ? cx_->names().default_ : localName.get()); + if (!appendExportEntry(exportName, localName)) + return false; + break; } case PNK_VAR: case PNK_CONST: case PNK_LET: { - MOZ_ASSERT(kid->isArity(PN_LIST)); - for (ParseNode* var = kid->pn_head; var; var = var->pn_next) { - if (var->isKind(PNK_ASSIGN)) - var = var->pn_left; - MOZ_ASSERT(var->isKind(PNK_NAME)); - RootedAtom localName(cx_, var->pn_atom); - RootedAtom exportName(cx_, isDefault ? cx_->names().default_ : localName.get()); - if (!appendExportEntry(exportName, localName)) - return false; - } - break; + MOZ_ASSERT(kid->isArity(PN_LIST)); + for (ParseNode* var = kid->pn_head; var; var = var->pn_next) { + if (var->isKind(PNK_ASSIGN)) + var = var->pn_left; + MOZ_ASSERT(var->isKind(PNK_NAME)); + RootedAtom localName(cx_, var->pn_atom); + RootedAtom exportName(cx_, isDefault ? cx_->names().default_ : localName.get()); + if (!appendExportEntry(exportName, localName)) + return false; + } + break; } case PNK_FUNCTION: { - RootedFunction func(cx_, kid->pn_funbox->function()); - if (!func->isArrow()) { - RootedAtom localName(cx_, func->explicitName()); - RootedAtom exportName(cx_, isDefault ? cx_->names().default_ : localName.get()); - MOZ_ASSERT_IF(isDefault, localName); - if (!appendExportEntry(exportName, localName)) - return false; - break; - } - } - - MOZ_FALLTHROUGH; // Arrow functions are handled below. - - default: - MOZ_ASSERT(isDefault); - RootedAtom localName(cx_, cx_->names().starDefaultStar); - RootedAtom exportName(cx_, cx_->names().default_); + RootedFunction func(cx_, kid->pn_funbox->function()); + MOZ_ASSERT(!func->isArrow()); + RootedAtom localName(cx_, func->explicitName()); + RootedAtom exportName(cx_, isDefault ? cx_->names().default_ : localName.get()); + MOZ_ASSERT_IF(isDefault, localName); if (!appendExportEntry(exportName, localName)) return false; break; + } + + default: + MOZ_CRASH("Unexpected parse node"); } + return true; } diff --git a/js/src/jit-test/tests/modules/bug-1320993.js b/js/src/jit-test/tests/modules/bug-1320993.js new file mode 100644 index 000000000..bece5731a --- /dev/null +++ b/js/src/jit-test/tests/modules/bug-1320993.js @@ -0,0 +1,2 @@ +parseModule("export default (class {})"); +parseModule("export default (class A {})"); -- cgit v1.2.3 From b2ec36808a240cd8169190168c915cd0463f8c87 Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Sat, 14 Apr 2018 08:49:15 +0200 Subject: Bug 1326453 - Part 1: Remove @@iterator method from module namespace objects per ES2017 --- js/src/builtin/Module.js | 8 ------ js/src/builtin/ModuleObject.cpp | 30 +---------------------- js/src/builtin/ModuleObject.h | 7 ------ js/src/jit-test/tests/modules/import-namespace.js | 19 -------------- 4 files changed, 1 insertion(+), 63 deletions(-) (limited to 'js/src') diff --git a/js/src/builtin/Module.js b/js/src/builtin/Module.js index 7b70a7fe8..a678864d1 100644 --- a/js/src/builtin/Module.js +++ b/js/src/builtin/Module.js @@ -318,11 +318,3 @@ function ModuleEvaluation() return EvaluateModule(module); } _SetCanonicalName(ModuleEvaluation, "ModuleEvaluation"); - -function ModuleNamespaceEnumerate() -{ - if (!IsObject(this) || !IsModuleNamespace(this)) - return callFunction(CallModuleMethodIfWrapped, this, "ModuleNamespaceEnumerate"); - - return CreateListIterator(ModuleNamespaceExports(this)); -} diff --git a/js/src/builtin/ModuleObject.cpp b/js/src/builtin/ModuleObject.cpp index e2f7f997e..921319028 100644 --- a/js/src/builtin/ModuleObject.cpp +++ b/js/src/builtin/ModuleObject.cpp @@ -289,14 +289,6 @@ ModuleNamespaceObject::create(JSContext* cx, HandleModuleObject module) if (!object) return nullptr; - RootedId funName(cx, INTERNED_STRING_TO_JSID(cx, cx->names().Symbol_iterator_fun)); - RootedFunction enumerateFun(cx); - enumerateFun = JS::GetSelfHostedFunction(cx, "ModuleNamespaceEnumerate", funName, 0); - if (!enumerateFun) - return nullptr; - - SetProxyExtra(object, ProxyHandler::EnumerateFunctionSlot, ObjectValue(*enumerateFun)); - return &object->as(); } @@ -341,11 +333,6 @@ ModuleNamespaceObject::ProxyHandler::ProxyHandler() : BaseProxyHandler(&family, true) {} -JS::Value ModuleNamespaceObject::ProxyHandler::getEnumerateFunction(HandleObject proxy) const -{ - return GetProxyExtra(proxy, EnumerateFunctionSlot); -} - bool ModuleNamespaceObject::ProxyHandler::getPrototype(JSContext* cx, HandleObject proxy, MutableHandleObject protop) const @@ -402,15 +389,6 @@ ModuleNamespaceObject::ProxyHandler::getOwnPropertyDescriptor(JSContext* cx, Han Rooted ns(cx, &proxy->as()); if (JSID_IS_SYMBOL(id)) { Rooted symbol(cx, JSID_TO_SYMBOL(id)); - if (symbol == cx->wellKnownSymbols().iterator) { - RootedValue enumerateFun(cx, getEnumerateFunction(proxy)); - desc.object().set(proxy); - desc.setConfigurable(false); - desc.setEnumerable(false); - desc.setValue(enumerateFun); - return true; - } - if (symbol == cx->wellKnownSymbols().toStringTag) { RootedValue value(cx, StringValue(cx->names().Module)); desc.object().set(proxy); @@ -458,8 +436,7 @@ ModuleNamespaceObject::ProxyHandler::has(JSContext* cx, HandleObject proxy, Hand Rooted ns(cx, &proxy->as()); if (JSID_IS_SYMBOL(id)) { Rooted symbol(cx, JSID_TO_SYMBOL(id)); - return symbol == cx->wellKnownSymbols().iterator || - symbol == cx->wellKnownSymbols().toStringTag; + return symbol == cx->wellKnownSymbols().toStringTag; } *bp = ns->bindings().has(id); @@ -473,11 +450,6 @@ ModuleNamespaceObject::ProxyHandler::get(JSContext* cx, HandleObject proxy, Hand Rooted ns(cx, &proxy->as()); if (JSID_IS_SYMBOL(id)) { Rooted symbol(cx, JSID_TO_SYMBOL(id)); - if (symbol == cx->wellKnownSymbols().iterator) { - vp.set(getEnumerateFunction(proxy)); - return true; - } - if (symbol == cx->wellKnownSymbols().toStringTag) { vp.setString(cx->names().Module); return true; diff --git a/js/src/builtin/ModuleObject.h b/js/src/builtin/ModuleObject.h index d0ed8ed08..51a428271 100644 --- a/js/src/builtin/ModuleObject.h +++ b/js/src/builtin/ModuleObject.h @@ -142,15 +142,8 @@ class ModuleNamespaceObject : public ProxyObject private: struct ProxyHandler : public BaseProxyHandler { - enum - { - EnumerateFunctionSlot = 0 - }; - ProxyHandler(); - JS::Value getEnumerateFunction(HandleObject proxy) const; - bool getOwnPropertyDescriptor(JSContext* cx, HandleObject proxy, HandleId id, MutableHandle desc) const override; bool defineProperty(JSContext* cx, HandleObject proxy, HandleId id, diff --git a/js/src/jit-test/tests/modules/import-namespace.js b/js/src/jit-test/tests/modules/import-namespace.js index f44d4568a..94a48461d 100644 --- a/js/src/jit-test/tests/modules/import-namespace.js +++ b/js/src/jit-test/tests/modules/import-namespace.js @@ -64,25 +64,6 @@ assertEq(typeof desc.get, "undefined"); assertEq(typeof desc.set, "undefined"); assertEq(Object.prototype.toString.call(ns), "[object Module]"); -// Test @@iterator method. -let iteratorFun = ns[Symbol.iterator]; -assertEq(iteratorFun.name, "[Symbol.iterator]"); - -let iterator = ns[Symbol.iterator](); -assertEq(iterator[Symbol.iterator](), iterator); -assertIteratorNext(iterator, "a"); -assertIteratorNext(iterator, "b"); -assertIteratorDone(iterator); - -// The iterator's next method can only be called on the object it was originally -// associated with. -iterator = ns[Symbol.iterator](); -let iterator2 = ns[Symbol.iterator](); -assertThrowsInstanceOf(() => iterator.next.call({}), TypeError); -assertThrowsInstanceOf(() => iterator.next.call(iterator2), TypeError); -assertEq(iterator.next.call(iterator).value, "a"); -assertEq(iterator2.next.call(iterator2).value, "a"); - // Test cyclic namespace import and access in module evaluation. let c = moduleRepo['c'] = parseModule("export let c = 1; import * as ns from 'd'; let d = ns.d;"); -- cgit v1.2.3 From a7f7a2231938e49ca2521fd417be7a313045c006 Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Sat, 14 Apr 2018 08:50:17 +0200 Subject: Bug 1326453 - Part 2: Change @@toStringTag for module namespace objects to non-configurable --- js/src/builtin/ModuleObject.cpp | 2 +- js/src/jit-test/tests/modules/import-namespace.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'js/src') diff --git a/js/src/builtin/ModuleObject.cpp b/js/src/builtin/ModuleObject.cpp index 921319028..f7323e852 100644 --- a/js/src/builtin/ModuleObject.cpp +++ b/js/src/builtin/ModuleObject.cpp @@ -394,7 +394,7 @@ ModuleNamespaceObject::ProxyHandler::getOwnPropertyDescriptor(JSContext* cx, Han desc.object().set(proxy); desc.setWritable(false); desc.setEnumerable(false); - desc.setConfigurable(true); + desc.setConfigurable(false); desc.setValue(value); return true; } diff --git a/js/src/jit-test/tests/modules/import-namespace.js b/js/src/jit-test/tests/modules/import-namespace.js index 94a48461d..71a1ce7df 100644 --- a/js/src/jit-test/tests/modules/import-namespace.js +++ b/js/src/jit-test/tests/modules/import-namespace.js @@ -59,7 +59,7 @@ desc = Object.getOwnPropertyDescriptor(ns, Symbol.toStringTag); assertEq(desc.value, "Module"); assertEq(desc.writable, false); assertEq(desc.enumerable, false); -assertEq(desc.configurable, true); +assertEq(desc.configurable, false); assertEq(typeof desc.get, "undefined"); assertEq(typeof desc.set, "undefined"); assertEq(Object.prototype.toString.call(ns), "[object Module]"); -- cgit v1.2.3 From e2719e1dbf7b706cd5ec8b3ecd899d2fc063c20f Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Sat, 14 Apr 2018 08:51:05 +0200 Subject: Bug 1326453 - Part 3: Don't throw a TypeError when SetPrototypeOf for module namespace objects is called with null --- js/src/builtin/ModuleObject.cpp | 2 ++ js/src/jit-test/tests/modules/import-namespace.js | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'js/src') diff --git a/js/src/builtin/ModuleObject.cpp b/js/src/builtin/ModuleObject.cpp index f7323e852..28a3329a8 100644 --- a/js/src/builtin/ModuleObject.cpp +++ b/js/src/builtin/ModuleObject.cpp @@ -345,6 +345,8 @@ bool ModuleNamespaceObject::ProxyHandler::setPrototype(JSContext* cx, HandleObject proxy, HandleObject proto, ObjectOpResult& result) const { + if (!proto) + return result.succeed(); return result.failCantSetProto(); } diff --git a/js/src/jit-test/tests/modules/import-namespace.js b/js/src/jit-test/tests/modules/import-namespace.js index 71a1ce7df..27d0193aa 100644 --- a/js/src/jit-test/tests/modules/import-namespace.js +++ b/js/src/jit-test/tests/modules/import-namespace.js @@ -39,7 +39,9 @@ assertEq(getModuleEnvironmentValue(b, "x"), 3); // Test module namespace internal methods as defined in 9.4.6 assertEq(Object.getPrototypeOf(ns), null); -assertThrowsInstanceOf(() => Object.setPrototypeOf(ns, null), TypeError); +assertEq(Reflect.setPrototypeOf(ns, null), true); +assertEq(Reflect.setPrototypeOf(ns, Object.prototype), false); +assertThrowsInstanceOf(() => Object.setPrototypeOf(ns, {}), TypeError); assertThrowsInstanceOf(function() { ns.foo = 1; }, TypeError); assertEq(Object.isExtensible(ns), false); Object.preventExtensions(ns); -- cgit v1.2.3 From 6452e3c9785260f21c5013d31e855e7b3e0497f4 Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Sat, 14 Apr 2018 08:52:37 +0200 Subject: Bug 1326453 - Part 4: Return @@toStringTag in [[OwnPropertyKeys]] trap for module namespace objects --- js/src/builtin/ModuleObject.cpp | 4 +++- js/src/jit-test/tests/modules/import-namespace.js | 19 +++++++++++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) (limited to 'js/src') diff --git a/js/src/builtin/ModuleObject.cpp b/js/src/builtin/ModuleObject.cpp index 28a3329a8..6d42508e0 100644 --- a/js/src/builtin/ModuleObject.cpp +++ b/js/src/builtin/ModuleObject.cpp @@ -500,7 +500,7 @@ ModuleNamespaceObject::ProxyHandler::ownPropertyKeys(JSContext* cx, HandleObject Rooted ns(cx, &proxy->as()); RootedObject exports(cx, &ns->exports()); uint32_t count; - if (!GetLengthProperty(cx, exports, &count) || !props.reserve(props.length() + count)) + if (!GetLengthProperty(cx, exports, &count) || !props.reserve(props.length() + count + 1)) return false; Rooted names(cx, ValueVector(cx)); @@ -510,6 +510,8 @@ ModuleNamespaceObject::ProxyHandler::ownPropertyKeys(JSContext* cx, HandleObject for (uint32_t i = 0; i < count; i++) props.infallibleAppend(AtomToId(&names[i].toString()->asAtom())); + props.infallibleAppend(SYMBOL_TO_JSID(cx->wellKnownSymbols().toStringTag)); + return true; } diff --git a/js/src/jit-test/tests/modules/import-namespace.js b/js/src/jit-test/tests/modules/import-namespace.js index 27d0193aa..2094c27fe 100644 --- a/js/src/jit-test/tests/modules/import-namespace.js +++ b/js/src/jit-test/tests/modules/import-namespace.js @@ -19,9 +19,19 @@ function testHasNames(names, expected) { }); } +function testEqualArrays(actual, expected) { + assertEq(Array.isArray(actual), true); + assertEq(Array.isArray(expected), true); + assertEq(actual.length, expected.length); + for (let i = 0; i < expected.length; i++) { + assertEq(actual[i], expected[i]); + } +} + let a = moduleRepo['a'] = parseModule( - `export var a = 1; - export var b = 2;` + `// Reflection methods should return these exports alphabetically sorted. + export var b = 2; + export var a = 1;` ); let b = moduleRepo['b'] = parseModule( @@ -66,6 +76,11 @@ assertEq(typeof desc.get, "undefined"); assertEq(typeof desc.set, "undefined"); assertEq(Object.prototype.toString.call(ns), "[object Module]"); +// Test [[OwnPropertyKeys]] internal method. +testEqualArrays(Reflect.ownKeys(ns), ["a", "b", Symbol.toStringTag]); +testEqualArrays(Object.getOwnPropertyNames(ns), ["a", "b"]); +testEqualArrays(Object.getOwnPropertySymbols(ns), [Symbol.toStringTag]); + // Test cyclic namespace import and access in module evaluation. let c = moduleRepo['c'] = parseModule("export let c = 1; import * as ns from 'd'; let d = ns.d;"); -- cgit v1.2.3 From ba6602b2de951beb74ef0f43a1cbae33ff0548e2 Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Sat, 14 Apr 2018 08:55:29 +0200 Subject: Bug 1326453 - Part 5: Remove no longer used ListIterator implementation --- js/src/builtin/Iterator.js | 41 ------------------------------- js/src/builtin/SelfHostingDefines.h | 2 -- js/src/jit-test/tests/basic/bug1220766.js | 3 --- js/src/jit/InlinableNatives.h | 1 - js/src/jit/MCallOptimize.cpp | 2 -- js/src/jsiter.cpp | 12 --------- js/src/jsiter.h | 6 ----- js/src/vm/SelfHosting.cpp | 40 ------------------------------ 8 files changed, 107 deletions(-) delete mode 100644 js/src/jit-test/tests/basic/bug1220766.js (limited to 'js/src') diff --git a/js/src/builtin/Iterator.js b/js/src/builtin/Iterator.js index 735eec7a0..e25b76156 100644 --- a/js/src/builtin/Iterator.js +++ b/js/src/builtin/Iterator.js @@ -84,44 +84,3 @@ function LegacyIteratorShim() { function LegacyGeneratorIteratorShim() { return NewLegacyIterator(ToObject(this), LegacyGeneratorIterator); } - -// 7.4.8 CreateListIterator() -function CreateListIterator(array) { - let iterator = NewListIterator(); - UnsafeSetReservedSlot(iterator, ITERATOR_SLOT_TARGET, array); - UnsafeSetReservedSlot(iterator, ITERATOR_SLOT_NEXT_INDEX, 0); - - // 7.4.8.1 ListIterator next() - // The spec requires that we use a new next function per iterator object. - let next = function() { - if (!IsObject(this) || !IsListIterator(this)) - return callFunction(CallListIteratorMethodIfWrapped, this, "ListIteratorNext"); - - if (ActiveFunction() !== UnsafeGetReservedSlot(this, ITERATOR_SLOT_NEXT_METHOD)) - ThrowTypeError(JSMSG_INCOMPATIBLE_METHOD, "next", "method", ToString(this)); - - let array = UnsafeGetObjectFromReservedSlot(this, ITERATOR_SLOT_TARGET); - let index = UnsafeGetReservedSlot(this, ITERATOR_SLOT_NEXT_INDEX); - - if (index >= ToLength(array.length)) { - UnsafeSetReservedSlot(this, ITERATOR_SLOT_NEXT_INDEX, 1/0); - return { value: undefined, done: true }; - } - - UnsafeSetReservedSlot(this, ITERATOR_SLOT_NEXT_INDEX, index + 1); - return { value: array[index], done: false }; - }; - - UnsafeSetReservedSlot(iterator, ITERATOR_SLOT_NEXT_METHOD, next); - iterator.next = next; - - iterator[std_iterator] = ListIteratorIdentity; - return iterator; -} - -function ListIteratorIdentity() { - if (!IsObject(this) || !IsListIterator(this)) - return callFunction(CallListIteratorMethodIfWrapped, this, "ListIteratorIdentity"); - - return this; -} diff --git a/js/src/builtin/SelfHostingDefines.h b/js/src/builtin/SelfHostingDefines.h index b57c17269..d676270a1 100644 --- a/js/src/builtin/SelfHostingDefines.h +++ b/js/src/builtin/SelfHostingDefines.h @@ -71,8 +71,6 @@ // Used for list, i.e. Array and String, iterators. #define ITERATOR_SLOT_NEXT_INDEX 1 #define ITERATOR_SLOT_ITEM_KIND 2 -// Used for ListIterator. -#define ITERATOR_SLOT_NEXT_METHOD 2 #define ITEM_KIND_KEY 0 #define ITEM_KIND_VALUE 1 diff --git a/js/src/jit-test/tests/basic/bug1220766.js b/js/src/jit-test/tests/basic/bug1220766.js deleted file mode 100644 index fca11eafe..000000000 --- a/js/src/jit-test/tests/basic/bug1220766.js +++ /dev/null @@ -1,3 +0,0 @@ -iter = getSelfHostedValue("CreateListIterator")([]); -iter.next(); -iter.next(); diff --git a/js/src/jit/InlinableNatives.h b/js/src/jit/InlinableNatives.h index 89c2ff0a4..15352c04f 100644 --- a/js/src/jit/InlinableNatives.h +++ b/js/src/jit/InlinableNatives.h @@ -121,7 +121,6 @@ _(IntrinsicIsMapIterator) \ _(IntrinsicIsSetIterator) \ _(IntrinsicIsStringIterator) \ - _(IntrinsicIsListIterator) \ \ _(IntrinsicGetNextMapEntryForIterator) \ \ diff --git a/js/src/jit/MCallOptimize.cpp b/js/src/jit/MCallOptimize.cpp index 202aef497..293253253 100644 --- a/js/src/jit/MCallOptimize.cpp +++ b/js/src/jit/MCallOptimize.cpp @@ -288,8 +288,6 @@ IonBuilder::inlineNativeCall(CallInfo& callInfo, JSFunction* target) return inlineHasClass(callInfo, &SetIteratorObject::class_); case InlinableNative::IntrinsicIsStringIterator: return inlineHasClass(callInfo, &StringIteratorObject::class_); - case InlinableNative::IntrinsicIsListIterator: - return inlineHasClass(callInfo, &ListIteratorObject::class_); case InlinableNative::IntrinsicDefineDataProperty: return inlineDefineDataProperty(callInfo); case InlinableNative::IntrinsicObjectHasPrototype: diff --git a/js/src/jsiter.cpp b/js/src/jsiter.cpp index c1ae5dc15..59893fa98 100644 --- a/js/src/jsiter.cpp +++ b/js/src/jsiter.cpp @@ -1157,18 +1157,6 @@ static const JSFunctionSpec string_iterator_methods[] = { JS_FS_END }; -enum { - ListIteratorSlotIteratedObject, - ListIteratorSlotNextIndex, - ListIteratorSlotNextMethod, - ListIteratorSlotCount -}; - -const Class ListIteratorObject::class_ = { - "List Iterator", - JSCLASS_HAS_RESERVED_SLOTS(ListIteratorSlotCount) -}; - JSObject* js::ValueToIterator(JSContext* cx, unsigned flags, HandleValue vp) { diff --git a/js/src/jsiter.h b/js/src/jsiter.h index f11f09b55..a3035ddd0 100644 --- a/js/src/jsiter.h +++ b/js/src/jsiter.h @@ -151,12 +151,6 @@ class StringIteratorObject : public JSObject static const Class class_; }; -class ListIteratorObject : public JSObject -{ - public: - static const Class class_; -}; - bool GetIterator(JSContext* cx, HandleObject obj, unsigned flags, MutableHandleObject objp); diff --git a/js/src/vm/SelfHosting.cpp b/js/src/vm/SelfHosting.cpp index bf49f2268..c7e7cc863 100644 --- a/js/src/vm/SelfHosting.cpp +++ b/js/src/vm/SelfHosting.cpp @@ -840,37 +840,6 @@ intrinsic_NewStringIterator(JSContext* cx, unsigned argc, Value* vp) return true; } -static bool -intrinsic_NewListIterator(JSContext* cx, unsigned argc, Value* vp) -{ - CallArgs args = CallArgsFromVp(argc, vp); - MOZ_ASSERT(args.length() == 0); - - RootedObject proto(cx, GlobalObject::getOrCreateIteratorPrototype(cx, cx->global())); - if (!proto) - return false; - - RootedObject iterator(cx); - iterator = NewObjectWithGivenProto(cx, &ListIteratorObject::class_, proto); - if (!iterator) - return false; - - args.rval().setObject(*iterator); - return true; -} - -static bool -intrinsic_ActiveFunction(JSContext* cx, unsigned argc, Value* vp) -{ - CallArgs args = CallArgsFromVp(argc, vp); - MOZ_ASSERT(args.length() == 0); - - ScriptFrameIter iter(cx); - MOZ_ASSERT(iter.isFunctionFrame()); - args.rval().setObject(*iter.callee(cx)); - return true; -} - static bool intrinsic_SetCanonicalName(JSContext* cx, unsigned argc, Value* vp) { @@ -2294,11 +2263,6 @@ static const JSFunctionSpec intrinsic_functions[] = { JS_FN("CallArrayIteratorMethodIfWrapped", CallNonGenericSelfhostedMethod>, 2,0), - JS_FN("NewListIterator", intrinsic_NewListIterator, 0,0), - JS_FN("CallListIteratorMethodIfWrapped", - CallNonGenericSelfhostedMethod>, 2,0), - JS_FN("ActiveFunction", intrinsic_ActiveFunction, 0,0), - JS_FN("_SetCanonicalName", intrinsic_SetCanonicalName, 2,0), JS_INLINABLE_FN("IsArrayIterator", @@ -2313,9 +2277,6 @@ static const JSFunctionSpec intrinsic_functions[] = { JS_INLINABLE_FN("IsStringIterator", intrinsic_IsInstanceOfBuiltin, 1,0, IntrinsicIsStringIterator), - JS_INLINABLE_FN("IsListIterator", - intrinsic_IsInstanceOfBuiltin, 1,0, - IntrinsicIsListIterator), JS_FN("_CreateMapIterationResultPair", intrinsic_CreateMapIterationResultPair, 0, 0), JS_INLINABLE_FN("_GetNextMapEntryForIterator", intrinsic_GetNextMapEntryForIterator, 2,0, @@ -2531,7 +2492,6 @@ static const JSFunctionSpec intrinsic_functions[] = { intrinsic_InstantiateModuleFunctionDeclarations, 1, 0), JS_FN("SetModuleState", intrinsic_SetModuleState, 1, 0), JS_FN("EvaluateModule", intrinsic_EvaluateModule, 1, 0), - JS_FN("IsModuleNamespace", intrinsic_IsInstanceOfBuiltin, 1, 0), JS_FN("NewModuleNamespace", intrinsic_NewModuleNamespace, 2, 0), JS_FN("AddModuleNamespaceBinding", intrinsic_AddModuleNamespaceBinding, 4, 0), JS_FN("ModuleNamespaceExports", intrinsic_ModuleNamespaceExports, 1, 0), -- cgit v1.2.3 From 05505d2e83d0c11beb6bc8b5c5a0daf68934c342 Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Sat, 14 Apr 2018 08:56:17 +0200 Subject: Bug 1340268 - [[HasProperty]] on module namespace object should work even when binding is uninitialized --- js/src/builtin/ModuleObject.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'js/src') diff --git a/js/src/builtin/ModuleObject.cpp b/js/src/builtin/ModuleObject.cpp index 6d42508e0..f13a2b78a 100644 --- a/js/src/builtin/ModuleObject.cpp +++ b/js/src/builtin/ModuleObject.cpp @@ -330,7 +330,7 @@ ModuleNamespaceObject::addBinding(JSContext* cx, HandleAtom exportedName, const char ModuleNamespaceObject::ProxyHandler::family = 0; ModuleNamespaceObject::ProxyHandler::ProxyHandler() - : BaseProxyHandler(&family, true) + : BaseProxyHandler(&family, false) {} bool @@ -438,7 +438,8 @@ ModuleNamespaceObject::ProxyHandler::has(JSContext* cx, HandleObject proxy, Hand Rooted ns(cx, &proxy->as()); if (JSID_IS_SYMBOL(id)) { Rooted symbol(cx, JSID_TO_SYMBOL(id)); - return symbol == cx->wellKnownSymbols().toStringTag; + *bp = symbol == cx->wellKnownSymbols().toStringTag; + return true; } *bp = ns->bindings().has(id); @@ -457,7 +458,8 @@ ModuleNamespaceObject::ProxyHandler::get(JSContext* cx, HandleObject proxy, Hand return true; } - return false; + vp.setUndefined(); + return true; } ModuleEnvironmentObject* env; -- cgit v1.2.3 From 3bd16c90800e8ec6ef8d7f135d8435bbbc0b94e6 Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Sat, 14 Apr 2018 08:57:05 +0200 Subject: Bug 1341256 - Fix module namespace object get handler --- js/src/builtin/ModuleObject.cpp | 6 ++++-- js/src/jit-test/tests/modules/import-namespace.js | 3 +++ 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'js/src') diff --git a/js/src/builtin/ModuleObject.cpp b/js/src/builtin/ModuleObject.cpp index f13a2b78a..444d8962d 100644 --- a/js/src/builtin/ModuleObject.cpp +++ b/js/src/builtin/ModuleObject.cpp @@ -464,8 +464,10 @@ ModuleNamespaceObject::ProxyHandler::get(JSContext* cx, HandleObject proxy, Hand ModuleEnvironmentObject* env; Shape* shape; - if (!ns->bindings().lookup(id, &env, &shape)) - return false; + if (!ns->bindings().lookup(id, &env, &shape)) { + vp.setUndefined(); + return true; + } RootedValue value(cx, env->getSlot(shape->slot())); if (value.isMagic(JS_UNINITIALIZED_LEXICAL)) { diff --git a/js/src/jit-test/tests/modules/import-namespace.js b/js/src/jit-test/tests/modules/import-namespace.js index 2094c27fe..0287f7a60 100644 --- a/js/src/jit-test/tests/modules/import-namespace.js +++ b/js/src/jit-test/tests/modules/import-namespace.js @@ -45,6 +45,9 @@ b.evaluation(); testHasNames(getModuleEnvironmentNames(b), ["ns", "x"]); let ns = getModuleEnvironmentValue(b, "ns"); testHasNames(Object.keys(ns), ["a", "b"]); +assertEq(ns.a, 1); +assertEq(ns.b, 2); +assertEq(ns.c, undefined); assertEq(getModuleEnvironmentValue(b, "x"), 3); // Test module namespace internal methods as defined in 9.4.6 -- cgit v1.2.3 From c60cefb1b02be321f56f64dcccc6d6b7670e4293 Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Sat, 14 Apr 2018 08:59:22 +0200 Subject: Bug 1339986 - Handle export* when checking for duplicate export --- js/src/builtin/ModuleObject.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'js/src') diff --git a/js/src/builtin/ModuleObject.cpp b/js/src/builtin/ModuleObject.cpp index 444d8962d..7d2204259 100644 --- a/js/src/builtin/ModuleObject.cpp +++ b/js/src/builtin/ModuleObject.cpp @@ -147,7 +147,7 @@ DEFINE_GETTER_FUNCTIONS(ExportEntryObject, moduleRequest, ModuleRequestSlot) DEFINE_GETTER_FUNCTIONS(ExportEntryObject, importName, ImportNameSlot) DEFINE_GETTER_FUNCTIONS(ExportEntryObject, localName, LocalNameSlot) -DEFINE_ATOM_ACCESSOR_METHOD(ExportEntryObject, exportName) +DEFINE_ATOM_OR_NULL_ACCESSOR_METHOD(ExportEntryObject, exportName) DEFINE_ATOM_OR_NULL_ACCESSOR_METHOD(ExportEntryObject, moduleRequest) DEFINE_ATOM_OR_NULL_ACCESSOR_METHOD(ExportEntryObject, importName) DEFINE_ATOM_OR_NULL_ACCESSOR_METHOD(ExportEntryObject, localName) -- cgit v1.2.3 From 8af513a2072d7f808f03a44b32130ff6ffcd7daa Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Sat, 14 Apr 2018 09:00:53 +0200 Subject: Bug 1341411 - Support circular module dependencies through export* per ES2017 --- js/src/builtin/Module.js | 28 ++++++++-------------- js/src/builtin/ModuleObject.cpp | 2 +- js/src/jit-test/modules/empty.js | 1 + js/src/jit-test/modules/export-star-circular-1.js | 1 + js/src/jit-test/modules/export-star-circular-2.js | 3 +++ .../export-star-cannot-rescue-missing-export.js | 4 ++++ .../modules/export-star-circular-dependencies.js | 6 +++++ 7 files changed, 26 insertions(+), 19 deletions(-) create mode 100644 js/src/jit-test/modules/empty.js create mode 100644 js/src/jit-test/modules/export-star-circular-1.js create mode 100644 js/src/jit-test/modules/export-star-circular-2.js create mode 100644 js/src/jit-test/tests/modules/export-star-cannot-rescue-missing-export.js create mode 100644 js/src/jit-test/tests/modules/export-star-circular-dependencies.js (limited to 'js/src') diff --git a/js/src/builtin/Module.js b/js/src/builtin/Module.js index a678864d1..95f97495d 100644 --- a/js/src/builtin/Module.js +++ b/js/src/builtin/Module.js @@ -65,12 +65,12 @@ function ModuleGetExportedNames(exportStarSet = []) return exportedNames; } -// 15.2.1.16.3 ResolveExport(exportName, resolveSet, exportStarSet) -function ModuleResolveExport(exportName, resolveSet = [], exportStarSet = []) +// 15.2.1.16.3 ResolveExport(exportName, resolveSet) +function ModuleResolveExport(exportName, resolveSet = []) { if (!IsObject(this) || !IsModule(this)) { return callFunction(CallModuleMethodIfWrapped, this, exportName, resolveSet, - exportStarSet, "ModuleResolveExport"); + "ModuleResolveExport"); } // Step 1 @@ -101,37 +101,28 @@ function ModuleResolveExport(exportName, resolveSet = [], exportStarSet = []) if (exportName === e.exportName) { let importedModule = CallModuleResolveHook(module, e.moduleRequest, MODULE_STATE_INSTANTIATED); - let indirectResolution = callFunction(importedModule.resolveExport, importedModule, - e.importName, resolveSet, exportStarSet); - if (indirectResolution !== null) - return indirectResolution; + return callFunction(importedModule.resolveExport, importedModule, e.importName, + resolveSet); } } // Step 6 if (exportName === "default") { // A default export cannot be provided by an export *. - ThrowSyntaxError(JSMSG_BAD_DEFAULT_EXPORT); + return null; } // Step 7 - if (callFunction(ArrayIncludes, exportStarSet, module)) - return null; - - // Step 8 - _DefineDataProperty(exportStarSet, exportStarSet.length, module); - - // Step 9 let starResolution = null; - // Step 10 + // Step 8 let starExportEntries = module.starExportEntries; for (let i = 0; i < starExportEntries.length; i++) { let e = starExportEntries[i]; let importedModule = CallModuleResolveHook(module, e.moduleRequest, MODULE_STATE_INSTANTIATED); let resolution = callFunction(importedModule.resolveExport, importedModule, - exportName, resolveSet, exportStarSet); + exportName, resolveSet); if (resolution === "ambiguous") return resolution; @@ -148,6 +139,7 @@ function ModuleResolveExport(exportName, resolveSet = [], exportStarSet = []) } } + // Step 9 return starResolution; } @@ -279,7 +271,7 @@ function ModuleDeclarationInstantiation() } } - // Step 16.iv + // Step 17.a.iii InstantiateModuleFunctionDeclarations(module); } catch (e) { RecordInstantationFailure(module); diff --git a/js/src/builtin/ModuleObject.cpp b/js/src/builtin/ModuleObject.cpp index 7d2204259..333cb3e11 100644 --- a/js/src/builtin/ModuleObject.cpp +++ b/js/src/builtin/ModuleObject.cpp @@ -994,7 +994,7 @@ GlobalObject::initModuleProto(JSContext* cx, Handle global) static const JSFunctionSpec protoFunctions[] = { JS_SELF_HOSTED_FN("getExportedNames", "ModuleGetExportedNames", 1, 0), - JS_SELF_HOSTED_FN("resolveExport", "ModuleResolveExport", 3, 0), + JS_SELF_HOSTED_FN("resolveExport", "ModuleResolveExport", 2, 0), JS_SELF_HOSTED_FN("declarationInstantiation", "ModuleDeclarationInstantiation", 0, 0), JS_SELF_HOSTED_FN("evaluation", "ModuleEvaluation", 0, 0), JS_FS_END diff --git a/js/src/jit-test/modules/empty.js b/js/src/jit-test/modules/empty.js new file mode 100644 index 000000000..bd9ec079d --- /dev/null +++ b/js/src/jit-test/modules/empty.js @@ -0,0 +1 @@ +// Intentionally empty. diff --git a/js/src/jit-test/modules/export-star-circular-1.js b/js/src/jit-test/modules/export-star-circular-1.js new file mode 100644 index 000000000..9a0771b02 --- /dev/null +++ b/js/src/jit-test/modules/export-star-circular-1.js @@ -0,0 +1 @@ +export* from "export-star-circular-2.js"; diff --git a/js/src/jit-test/modules/export-star-circular-2.js b/js/src/jit-test/modules/export-star-circular-2.js new file mode 100644 index 000000000..b273d9cef --- /dev/null +++ b/js/src/jit-test/modules/export-star-circular-2.js @@ -0,0 +1,3 @@ +export {y as x} from "export-star-circular-1.js"; + +export var y = "pass"; diff --git a/js/src/jit-test/tests/modules/export-star-cannot-rescue-missing-export.js b/js/src/jit-test/tests/modules/export-star-cannot-rescue-missing-export.js new file mode 100644 index 000000000..f87829d89 --- /dev/null +++ b/js/src/jit-test/tests/modules/export-star-cannot-rescue-missing-export.js @@ -0,0 +1,4 @@ +// |jit-test| module; error:SyntaxError + +export { a } from "empty.js"; +export* from "module1.js"; diff --git a/js/src/jit-test/tests/modules/export-star-circular-dependencies.js b/js/src/jit-test/tests/modules/export-star-circular-dependencies.js new file mode 100644 index 000000000..9aa612f08 --- /dev/null +++ b/js/src/jit-test/tests/modules/export-star-circular-dependencies.js @@ -0,0 +1,6 @@ +// |jit-test| module + +import { x, y } from "export-star-circular-1.js"; + +assertEq(x, "pass"); +assertEq(y, "pass"); -- cgit v1.2.3 From ad9ee72dcd7981bc47b3844a224d69fadfdfd8ef Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Sat, 14 Apr 2018 09:02:03 +0200 Subject: Bug 1341298 - Relax expected module state when resolving modules and circular module dependencies are present --- js/src/builtin/Module.js | 10 ++++++---- .../jit-test/modules/export-circular-nonexisting-binding-1.js | 4 ++++ .../jit-test/modules/export-circular-nonexisting-binding-2.js | 1 + .../tests/modules/export-circular-nonexisting-binding.js | 3 +++ js/src/vm/EnvironmentObject.cpp | 2 +- 5 files changed, 15 insertions(+), 5 deletions(-) create mode 100644 js/src/jit-test/modules/export-circular-nonexisting-binding-1.js create mode 100644 js/src/jit-test/modules/export-circular-nonexisting-binding-2.js create mode 100644 js/src/jit-test/tests/modules/export-circular-nonexisting-binding.js (limited to 'js/src') diff --git a/js/src/builtin/Module.js b/js/src/builtin/Module.js index 95f97495d..5c3d5e147 100644 --- a/js/src/builtin/Module.js +++ b/js/src/builtin/Module.js @@ -100,7 +100,7 @@ function ModuleResolveExport(exportName, resolveSet = []) let e = indirectExportEntries[i]; if (exportName === e.exportName) { let importedModule = CallModuleResolveHook(module, e.moduleRequest, - MODULE_STATE_INSTANTIATED); + MODULE_STATE_PARSED); return callFunction(importedModule.resolveExport, importedModule, e.importName, resolveSet); } @@ -120,7 +120,7 @@ function ModuleResolveExport(exportName, resolveSet = []) for (let i = 0; i < starExportEntries.length; i++) { let e = starExportEntries[i]; let importedModule = CallModuleResolveHook(module, e.moduleRequest, - MODULE_STATE_INSTANTIATED); + MODULE_STATE_PARSED); let resolution = callFunction(importedModule.resolveExport, importedModule, exportName, resolveSet); if (resolution === "ambiguous") @@ -205,8 +205,8 @@ function GetModuleEnvironment(module) function RecordInstantationFailure(module) { - // Set the module's environment slot to 'null' to indicate a failed module - // instantiation. + // Set the module's state to 'failed' to indicate a failed module + // instantiation and reset the environment slot to 'undefined'. assert(IsModule(module), "Non-module passed to RecordInstantationFailure"); SetModuleState(module, MODULE_STATE_FAILED); UnsafeSetReservedSlot(module, MODULE_OBJECT_ENVIRONMENT_SLOT, undefined); @@ -267,6 +267,8 @@ function ModuleDeclarationInstantiation() ThrowSyntaxError(JSMSG_MISSING_IMPORT, imp.importName); if (resolution === "ambiguous") ThrowSyntaxError(JSMSG_AMBIGUOUS_IMPORT, imp.importName); + if (resolution.module.state < MODULE_STATE_INSTANTIATED) + ThrowInternalError(JSMSG_BAD_MODULE_STATE); CreateImportBinding(env, imp.localName, resolution.module, resolution.bindingName); } } diff --git a/js/src/jit-test/modules/export-circular-nonexisting-binding-1.js b/js/src/jit-test/modules/export-circular-nonexisting-binding-1.js new file mode 100644 index 000000000..2b91b6a28 --- /dev/null +++ b/js/src/jit-test/modules/export-circular-nonexisting-binding-1.js @@ -0,0 +1,4 @@ +import "export-circular-nonexisting-binding-2.js"; + +export* from "empty.js"; +export {x} from "empty.js"; diff --git a/js/src/jit-test/modules/export-circular-nonexisting-binding-2.js b/js/src/jit-test/modules/export-circular-nonexisting-binding-2.js new file mode 100644 index 000000000..ba7dcc1b4 --- /dev/null +++ b/js/src/jit-test/modules/export-circular-nonexisting-binding-2.js @@ -0,0 +1 @@ +export {x} from "export-circular-nonexisting-binding-1.js"; diff --git a/js/src/jit-test/tests/modules/export-circular-nonexisting-binding.js b/js/src/jit-test/tests/modules/export-circular-nonexisting-binding.js new file mode 100644 index 000000000..387c7c369 --- /dev/null +++ b/js/src/jit-test/tests/modules/export-circular-nonexisting-binding.js @@ -0,0 +1,3 @@ +// |jit-test| module; error:SyntaxError + +import "export-circular-nonexisting-binding-1.js"; diff --git a/js/src/vm/EnvironmentObject.cpp b/js/src/vm/EnvironmentObject.cpp index 34c39eabf..9b20c2b9c 100644 --- a/js/src/vm/EnvironmentObject.cpp +++ b/js/src/vm/EnvironmentObject.cpp @@ -491,7 +491,7 @@ ModuleEnvironmentObject::createImportBinding(JSContext* cx, HandleAtom importNam { RootedId importNameId(cx, AtomToId(importName)); RootedId localNameId(cx, AtomToId(localName)); - RootedModuleEnvironmentObject env(cx, module->environment()); + RootedModuleEnvironmentObject env(cx, &module->initialEnvironment()); if (!importBindings().putNew(cx, importNameId, env, localNameId)) { ReportOutOfMemory(cx); return false; -- cgit v1.2.3 From 924693bdb01ec7e8053317cd45e8d4215ddbc320 Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Wed, 2 Oct 2019 14:00:30 +0200 Subject: No issue - Update TZ data to 2019c --- js/src/builtin/IntlTimeZoneData.h | 2 +- js/src/tests/Intl/DateTimeFormat/timeZone_backward_links.js | 2 +- js/src/tests/Intl/DateTimeFormat/timeZone_backzone.js | 2 +- js/src/tests/Intl/DateTimeFormat/timeZone_backzone_links.js | 2 +- js/src/tests/Intl/DateTimeFormat/timeZone_notbackward_links.js | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) (limited to 'js/src') diff --git a/js/src/builtin/IntlTimeZoneData.h b/js/src/builtin/IntlTimeZoneData.h index 8f963ffbc..1612f0f6b 100644 --- a/js/src/builtin/IntlTimeZoneData.h +++ b/js/src/builtin/IntlTimeZoneData.h @@ -1,5 +1,5 @@ // Generated by make_intl_data.py. DO NOT EDIT. -// tzdata version = 2019a +// tzdata version = 2019c #ifndef builtin_IntlTimeZoneData_h #define builtin_IntlTimeZoneData_h diff --git a/js/src/tests/Intl/DateTimeFormat/timeZone_backward_links.js b/js/src/tests/Intl/DateTimeFormat/timeZone_backward_links.js index 8cda44d87..8bd0512c5 100644 --- a/js/src/tests/Intl/DateTimeFormat/timeZone_backward_links.js +++ b/js/src/tests/Intl/DateTimeFormat/timeZone_backward_links.js @@ -1,7 +1,7 @@ // |reftest| skip-if(!this.hasOwnProperty("Intl")) // Generated by make_intl_data.py. DO NOT EDIT. -// tzdata version = 2019a +// tzdata version = 2019c const tzMapper = [ x => x, diff --git a/js/src/tests/Intl/DateTimeFormat/timeZone_backzone.js b/js/src/tests/Intl/DateTimeFormat/timeZone_backzone.js index a3efe0310..c760fd85e 100644 --- a/js/src/tests/Intl/DateTimeFormat/timeZone_backzone.js +++ b/js/src/tests/Intl/DateTimeFormat/timeZone_backzone.js @@ -1,7 +1,7 @@ // |reftest| skip-if(!this.hasOwnProperty("Intl")) // Generated by make_intl_data.py. DO NOT EDIT. -// tzdata version = 2019a +// tzdata version = 2019c const tzMapper = [ x => x, diff --git a/js/src/tests/Intl/DateTimeFormat/timeZone_backzone_links.js b/js/src/tests/Intl/DateTimeFormat/timeZone_backzone_links.js index b61593f78..38db5e77d 100644 --- a/js/src/tests/Intl/DateTimeFormat/timeZone_backzone_links.js +++ b/js/src/tests/Intl/DateTimeFormat/timeZone_backzone_links.js @@ -1,7 +1,7 @@ // |reftest| skip-if(!this.hasOwnProperty("Intl")) // Generated by make_intl_data.py. DO NOT EDIT. -// tzdata version = 2019a +// tzdata version = 2019c const tzMapper = [ x => x, diff --git a/js/src/tests/Intl/DateTimeFormat/timeZone_notbackward_links.js b/js/src/tests/Intl/DateTimeFormat/timeZone_notbackward_links.js index 12b55c214..64a25c241 100644 --- a/js/src/tests/Intl/DateTimeFormat/timeZone_notbackward_links.js +++ b/js/src/tests/Intl/DateTimeFormat/timeZone_notbackward_links.js @@ -1,7 +1,7 @@ // |reftest| skip-if(!this.hasOwnProperty("Intl")) // Generated by make_intl_data.py. DO NOT EDIT. -// tzdata version = 2019a +// tzdata version = 2019c const tzMapper = [ x => x, -- cgit v1.2.3 From a68a09618787980ff58b248c484b4017e3d2e663 Mon Sep 17 00:00:00 2001 From: Dmitry Grigoryev Date: Fri, 4 Oct 2019 22:58:16 +0200 Subject: Replace calls to undefined functions isMarkable() and toMarkablePointer() --- js/src/jit/arm/MacroAssembler-arm.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'js/src') diff --git a/js/src/jit/arm/MacroAssembler-arm.cpp b/js/src/jit/arm/MacroAssembler-arm.cpp index a4161ab00..3421001f7 100644 --- a/js/src/jit/arm/MacroAssembler-arm.cpp +++ b/js/src/jit/arm/MacroAssembler-arm.cpp @@ -3462,8 +3462,8 @@ MacroAssemblerARMCompat::storePayload(const Value& val, const Address& dest) ScratchRegisterScope scratch(asMasm()); SecondScratchRegisterScope scratch2(asMasm()); - if (val.isMarkable()) - ma_mov(ImmGCPtr(val.toMarkablePointer()), scratch); + if (val.isGCThing()) + ma_mov(ImmGCPtr(val.toGCThing()), scratch); else ma_mov(Imm32(val.toNunboxPayload()), scratch); ma_str(scratch, ToPayload(dest), scratch2); -- cgit v1.2.3 From e31d79e8da99456247df84c2f99ba9083d46efe1 Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Wed, 16 Oct 2019 12:37:07 -0400 Subject: Fix build errors with newer glibc versions --- js/src/jsnativestack.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'js/src') diff --git a/js/src/jsnativestack.cpp b/js/src/jsnativestack.cpp index 98f8fc741..94a296bd0 100644 --- a/js/src/jsnativestack.cpp +++ b/js/src/jsnativestack.cpp @@ -26,11 +26,7 @@ # include # include # include -static pid_t -gettid() -{ - return syscall(__NR_gettid); -} +# define gettid() static_cast(syscall(SYS_gettid)) # endif #else -- cgit v1.2.3 From afc187cc3f907947453b428f857acf16b2b0774e Mon Sep 17 00:00:00 2001 From: athenian200 Date: Tue, 1 Oct 2019 06:07:31 -0500 Subject: MoonchildProductions#1251 - Part 1: Restore initial Solaris support, fixed up. Compared with what Pale Moon had for Solaris originally, this is mostly the same zero point I started patching from, but I've made the following changes here after reviewing all this initial code I never looked at closely before. 1. In package-manifest.in for both Basilisk and Pale Moon, I've made the SPARC code for libfreebl not interefere with the x86 code, use the proper build flags, and also updated it to allow a SPARC64 build which is more likely to be used than the 32-bit SPARC code we had there. 2. See Mozilla bug #832272 and the old rules.mk patch from around Firefox 30 in oracle/solaris-userland. I believe they screwed up NSINSTALL on Solaris when they were trying to streamline the NSS buildsystem, because they started having unexplained issues with it around that time after Firefox 22 that they never properly resolved until Mozilla began building NSS with gyp files. I'm actually not even sure how relevant the thing they broke actually is to Solaris at this point, bug 665509 is so old it predates Firefox itself and goes back to the Mozilla suite days. I believe $(INSTALL) -t was wrong, and they meant $(NSINSTALL) -t because that makes more sense and is closer to what was there originally. It's what they have for WINNT, and it's possible a fix more like that could serve for Solaris as well. Alternatively, we could get rid of all these half-broken Makefiles and start building NSS with gyp files like Mozilla did. 3. I've completely cut out support for the Sun compiler and taken into account the reality that everyone builds Firefox (and therefore its forks) with GCC now on Solaris. This alone helped clean up a lot of the uglier parts of the code. 4. I've updated all remaining SOLARIS build flags to the newer XP_SOLARIS, because the SOLARIS flag is no longer set when building Solaris. 5. I've confirmed the workaround in gtxFontconfigFonts.cpp is no longer necessary. The Solaris people got impatient about implementing a half-baked patch for a fontconfig feature that wasn't ready yet back in 2009, and somehow convinced Mozilla to patch their software to work around it when really they should have just fixed or removed their broken fontconfig patch. The feature they wanted has since been implemented properly, and no version of Solaris still uses the broken patch that required this fix. If anyone had ever properly audited this code, it would have been removed a long time ago. --- js/src/Makefile.in | 11 +++++++++++ js/src/builtin/TestingFunctions.cpp | 5 ++++- js/src/ctypes/CTypes.cpp | 4 ++++ js/src/jsnativestack.cpp | 13 +++++++++++++ js/src/moz.build | 8 ++++++++ js/src/vm/Time.cpp | 12 ++++++++++++ 6 files changed, 52 insertions(+), 1 deletion(-) (limited to 'js/src') diff --git a/js/src/Makefile.in b/js/src/Makefile.in index 20678c68c..bc99e62b5 100644 --- a/js/src/Makefile.in +++ b/js/src/Makefile.in @@ -138,6 +138,17 @@ distclean:: CFLAGS += $(MOZ_ZLIB_CFLAGS) +ifeq ($(OS_ARCH),SunOS) +ifeq ($(TARGET_CPU),sparc) + +ifdef GNU_CC +CFLAGS += -mcpu=v9 +CXXFLAGS += -mcpu=v9 +endif #GNU_CC + +endif +endif + $(LIBRARY_NAME).pc: js.pc cp $^ $@ diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctions.cpp index 992fe2c97..6beb82932 100644 --- a/js/src/builtin/TestingFunctions.cpp +++ b/js/src/builtin/TestingFunctions.cpp @@ -239,8 +239,11 @@ GetBuildConfiguration(JSContext* cx, unsigned argc, Value* vp) value = BooleanValue(true); if (!JS_SetProperty(cx, info, "intl-api", value)) return false; - +#if defined(XP_SOLARIS) + value = BooleanValue(false); +#else value = BooleanValue(true); +#endif if (!JS_SetProperty(cx, info, "mapped-array-buffer", value)) return false; diff --git a/js/src/ctypes/CTypes.cpp b/js/src/ctypes/CTypes.cpp index d6adfac2c..aed1114bd 100644 --- a/js/src/ctypes/CTypes.cpp +++ b/js/src/ctypes/CTypes.cpp @@ -20,6 +20,10 @@ #include #endif +#if defined(XP_SOLARIS) +#include +#endif + #ifdef HAVE_SSIZE_T #include #endif diff --git a/js/src/jsnativestack.cpp b/js/src/jsnativestack.cpp index 94a296bd0..389d7e657 100644 --- a/js/src/jsnativestack.cpp +++ b/js/src/jsnativestack.cpp @@ -67,6 +67,19 @@ js::GetNativeStackBaseImpl() # endif } +#elif defined(XP_SOLARIS) + +#include + +JS_STATIC_ASSERT(JS_STACK_GROWTH_DIRECTION < 0); + +void js::GetNativeStackBaseImpl() +{ + stack_t st; + stack_getbounds(&st); + return static_cast(st.ss_sp) + st.ss_size; +} + #elif defined(XP_LINUX) && !defined(ANDROID) && defined(__GLIBC__) void* js::GetNativeStackBaseImpl() diff --git a/js/src/moz.build b/js/src/moz.build index a0f074d1c..47ffe0159 100644 --- a/js/src/moz.build +++ b/js/src/moz.build @@ -721,6 +721,14 @@ if CONFIG['OS_ARCH'] == 'Linux': 'dl', ] +if CONFIG['OS_ARCH'] == 'SunOS': + OS_LIBS += [ + 'posix4', + 'dl', + 'nsl', + 'socket', + ] + OS_LIBS += CONFIG['REALTIME_LIBS'] CFLAGS += CONFIG['MOZ_ICU_CFLAGS'] diff --git a/js/src/vm/Time.cpp b/js/src/vm/Time.cpp index 87531c148..a9a5b7f0f 100644 --- a/js/src/vm/Time.cpp +++ b/js/src/vm/Time.cpp @@ -11,6 +11,10 @@ #include "mozilla/DebugOnly.h" #include "mozilla/MathAlgorithms.h" +#ifdef XP_SOLARIS +#define _REENTRANT 1 +#endif + #include #include @@ -30,6 +34,10 @@ #ifdef XP_UNIX +#ifdef _SVID_GETTOD /* Defined only on Solaris, see Solaris */ +extern int gettimeofday(struct timeval* tv); +#endif + #include #endif /* XP_UNIX */ @@ -42,7 +50,11 @@ PRMJ_Now() { struct timeval tv; +#ifdef _SVID_GETTOD /* Defined only on Solaris, see Solaris */ + gettimeofday(&tv); +#else gettimeofday(&tv, 0); +#endif /* _SVID_GETTOD */ return int64_t(tv.tv_sec) * PRMJ_USEC_PER_SEC + int64_t(tv.tv_usec); } -- cgit v1.2.3 From 3647f42c27761472e4ee204bade964e8ffad4679 Mon Sep 17 00:00:00 2001 From: athenian200 Date: Tue, 1 Oct 2019 21:36:29 -0500 Subject: MoonchildProductions#1251 - Part 7: All the posix_m* memory-related stuff, gathered together. https://bugzilla.mozilla.org/show_bug.cgi?id=1158445 https://bugzilla.mozilla.org/show_bug.cgi?id=963983 https://bugzilla.mozilla.org/show_bug.cgi?id=1542758 Solaris madvise and malign don't perfectly map to their POSIX counterparts, and some Linux versions (especially Android) don't define the POSIX counterparts at all, so options are limited. Ideally posix_madvise and posix_malign should be the safer and more portable options for all platforms. --- js/src/gc/Memory.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'js/src') diff --git a/js/src/gc/Memory.cpp b/js/src/gc/Memory.cpp index 268e1e489..5cf0cd2f7 100644 --- a/js/src/gc/Memory.cpp +++ b/js/src/gc/Memory.cpp @@ -678,7 +678,11 @@ MarkPagesUnused(void* p, size_t size) return false; MOZ_ASSERT(OffsetFromAligned(p, pageSize) == 0); - int result = madvise(p, size, MADV_DONTNEED); +#if defined(XP_SOLARIS) + int result = posix_madvise(p, size, POSIX_MADV_DONTNEED); +#else + int result = madvise(p, size, MADV_DONTNEED); +#endif return result != -1; } -- cgit v1.2.3 From c0d814c1d52b0e9ae884b83f214218b954133acb Mon Sep 17 00:00:00 2001 From: athenian200 Date: Tue, 1 Oct 2019 22:59:38 -0500 Subject: MoonchildProductions#1251 - Part 8: Align pointer for char_16t. https://bugzilla.mozilla.org/show_bug.cgi?id=1352449 Mozilla patch that's been in the code since Firefox 55. Seems like there have been no ill effects from implementing it, and it would only increase the portability of the UXP code. All the Solaris Firefox repos I've seen implement some variation on the jsexn patch, and this seems to be the cleanest version of it. I can add ifdefs if needed or there are performance concerns associated with this patch, but I get the impression this alignment backlog issue might affect a few platforms other than Solaris, though none were named. Otherwise I think they wouldn't have used "platforms that need it" in plural form or failed to ifdef it. --- js/src/jsexn.cpp | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'js/src') diff --git a/js/src/jsexn.cpp b/js/src/jsexn.cpp index 65cc81a1a..3fc9200c1 100644 --- a/js/src/jsexn.cpp +++ b/js/src/jsexn.cpp @@ -205,7 +205,12 @@ size_t ExtraMallocSize(JSErrorReport* report) { if (report->linebuf()) - return (report->linebufLength() + 1) * sizeof(char16_t); + /* + * Mozilla bug 1352449. Count with null + * terminator and alignment. See CopyExtraData for + * the details about alignment. + */ + return (report->linebufLength() + 1) * sizeof(char16_t) + 1; return 0; } @@ -220,10 +225,20 @@ bool CopyExtraData(JSContext* cx, uint8_t** cursor, JSErrorReport* copy, JSErrorReport* report) { if (report->linebuf()) { + /* + * Make sure cursor is properly aligned for char16_t for platforms + * which need it and it's at the end of the buffer on exit. + */ + size_t alignment_backlog = 0; + if (size_t(*cursor) % 2) + (*cursor)++; + else + alignment_backlog = 1; + size_t linebufSize = (report->linebufLength() + 1) * sizeof(char16_t); const char16_t* linebufCopy = (const char16_t*)(*cursor); js_memcpy(*cursor, report->linebuf(), linebufSize); - *cursor += linebufSize; + *cursor += linebufSize + alignment_backlog; copy->initBorrowedLinebuf(linebufCopy, report->linebufLength(), report->tokenOffset()); } -- cgit v1.2.3 From cf75ede0de7cc8febc12d666783631836c6b8e43 Mon Sep 17 00:00:00 2001 From: athenian200 Date: Tue, 1 Oct 2019 23:39:11 -0500 Subject: MoonchildProductions#1251 - Part 9: Look for hypot in the math library (libm). https://bugzilla.mozilla.org/show_bug.cgi?id=1351309 https://bugzilla.mozilla.org/show_bug.cgi?id=1309157 I assess this change to be low-risk for the following reasons: 1. It has been in Firefox since version 55 without issues. 2. It's nearly identical to the fix for bug 1309157 which is already in our tree, so that one would be causing problems if this one were going to. 3. Linux, Windows, and BSD are known to have a hypot function in their math libraries. 4. Even if it does break something, it should only break a test and not critical functionality. --- js/src/jit-test/tests/ctypes/function-definition.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'js/src') diff --git a/js/src/jit-test/tests/ctypes/function-definition.js b/js/src/jit-test/tests/ctypes/function-definition.js index 4df317a09..5882ba889 100644 --- a/js/src/jit-test/tests/ctypes/function-definition.js +++ b/js/src/jit-test/tests/ctypes/function-definition.js @@ -27,7 +27,7 @@ function test() { let lib; try { - lib = ctypes.open(ctypes.libraryName("c")); + lib = ctypes.open(ctypes.libraryName("m")); } catch (e) { } if (!lib) -- cgit v1.2.3 From 76c55f747ce5878d1d37d8bf3bd0a50c1b478bec Mon Sep 17 00:00:00 2001 From: athenian200 Date: Wed, 2 Oct 2019 14:08:55 -0500 Subject: MoonchildProductions#1251 - Part 12: Add Solaris/illumos support to WasmSignalHandlers. https://www.illumos.org/issues/5876 https://bugzilla.mozilla.org/show_bug.cgi?id=135050 --- js/src/wasm/WasmSignalHandlers.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'js/src') diff --git a/js/src/wasm/WasmSignalHandlers.cpp b/js/src/wasm/WasmSignalHandlers.cpp index c4733cc96..21093ca9a 100644 --- a/js/src/wasm/WasmSignalHandlers.cpp +++ b/js/src/wasm/WasmSignalHandlers.cpp @@ -130,11 +130,16 @@ class AutoSetHandlingSegFault # define EPC_sig(p) ((p)->sc_pc) # define RFP_sig(p) ((p)->sc_regs[30]) # endif -#elif defined(__linux__) +#elif defined(__linux__) || defined(__sun) # if defined(__linux__) # define XMM_sig(p,i) ((p)->uc_mcontext.fpregs->_xmm[i]) # define EIP_sig(p) ((p)->uc_mcontext.gregs[REG_EIP]) -# else +# else // defined(__sun) +/* See https://www.illumos.org/issues/5876. They keep arguing over whether + * should provide the register index defines in regset.h or + * require applications to request them specifically, and we need them here. */ +#include +#include # define XMM_sig(p,i) ((p)->uc_mcontext.fpregs.fp_reg_set.fpchip_state.xmm[i]) # define EIP_sig(p) ((p)->uc_mcontext.gregs[REG_PC]) # endif -- cgit v1.2.3 From beea314ffe6c9cefeb232e9b38fcecf66154854f Mon Sep 17 00:00:00 2001 From: athenian200 Date: Wed, 2 Oct 2019 19:51:00 -0500 Subject: MoonchildProductions#1251 - Part 17: All the libffi and libxul.so issues, resolved. https://bugzilla.mozilla.org/show_bug.cgi?id=1185424 http://www.mindfruit.co.uk/2012/06/relocations-relocations.html The libxul.so fix was implemented by Mozilla in Firefox 57 and personally recommended to me by an Oracle employee on the OpenIndiana mailing list. It can easily be made ifdef XP_SOLARIS, but it seems like the new way is considered a better solution overall by the original author of the code that had it use that null pointer hack to begin with. I can't link where I found the fix for libffi because I came up with it myself while looking at the way sysv.S does things. Something clicked in my brain while reading that mindfruit link above, though, and gave me enough of a sense of what was going on to be able to fix libffi. The libffi fix looks a bit hairy because of all the FDE_ENCODE statements, but if you examine the code closely, you should find that it does exactly what it did before on all platforms besides Solaris. I later discovered that people who originally ported Firefox to Solaris never figured this out during the Firefox 52 era and had to use GNU LD for linking libxul.so while using the Sun LD for the rest of the build to make it work. For whatever reason, it works for me now without the GNU LD trick. --- js/src/ctypes/libffi/src/x86/win32.S | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) (limited to 'js/src') diff --git a/js/src/ctypes/libffi/src/x86/win32.S b/js/src/ctypes/libffi/src/x86/win32.S index daf0e799c..4f702e8b1 100644 --- a/js/src/ctypes/libffi/src/x86/win32.S +++ b/js/src/ctypes/libffi/src/x86/win32.S @@ -1158,8 +1158,24 @@ L_ffi_closure_SYSV_inner$stub: .byte 0x7c /* .sleb128 -4; CIE Data Alignment Factor */ .byte 0x8 /* CIE RA Column */ #ifdef __PIC__ - .byte 0x1 /* .uleb128 0x1; Augmentation size */ - .byte 0x1b /* FDE Encoding (pcrel sdata4) */ +# if defined __sun__ && defined __svr4__ +/* 32-bit Solaris 2/x86 uses datarel encoding for PIC. GNU ld before 2.22 + doesn't correctly sort .eh_frame_hdr with mixed encodings, so match this. */ +# define FDE_ENCODING 0x30 /* datarel */ +# define FDE_ENCODE(X) X@GOTOFF +# else +# define FDE_ENCODING 0x1b /* pcrel sdata4 */ +# if defined HAVE_AS_X86_PCREL +# define FDE_ENCODE(X) X-. +# else +# define FDE_ENCODE(X) X@rel +# endif +# endif +#else +# define FDE_ENCODING 0 /* absolute */ +# define FDE_ENCODE(X) X +.byte 0x1 /* .uleb128 0x1; Augmentation size */ +.byte FDE_ENCODING #endif .byte 0xc /* DW_CFA_def_cfa CFA = r4 + 4 = 4(%esp) */ .byte 0x4 /* .uleb128 0x4 */ @@ -1176,7 +1192,7 @@ L_ffi_closure_SYSV_inner$stub: #if defined __PIC__ && defined HAVE_AS_X86_PCREL .long .LFB1-. /* FDE initial location */ #else - .long .LFB1 + .long FDE_ENCODE(.LFB1) #endif .long .LFE1-.LFB1 /* FDE address range */ #ifdef __PIC__ @@ -1207,7 +1223,7 @@ L_ffi_closure_SYSV_inner$stub: #if defined __PIC__ && defined HAVE_AS_X86_PCREL .long .LFB3-. /* FDE initial location */ #else - .long .LFB3 + .long FDE_ENCODE(.LFB3) #endif .long .LFE3-.LFB3 /* FDE address range */ #ifdef __PIC__ @@ -1240,7 +1256,7 @@ L_ffi_closure_SYSV_inner$stub: #if defined __PIC__ && defined HAVE_AS_X86_PCREL .long .LFB4-. /* FDE initial location */ #else - .long .LFB4 + .long FDE_ENCODE(.LFB4) #endif .long .LFE4-.LFB4 /* FDE address range */ #ifdef __PIC__ @@ -1278,7 +1294,7 @@ L_ffi_closure_SYSV_inner$stub: #if defined __PIC__ && defined HAVE_AS_X86_PCREL .long .LFB5-. /* FDE initial location */ #else - .long .LFB5 + .long FDE_ENCODE(.LFB5) #endif .long .LFE5-.LFB5 /* FDE address range */ #ifdef __PIC__ -- cgit v1.2.3 From 575f51a27d6b3627ae5675cc8e920c8dcae073bd Mon Sep 17 00:00:00 2001 From: athenian200 Date: Fri, 4 Oct 2019 04:37:51 -0500 Subject: Fix a bunch of dumb typos and omissions. --- js/src/jsnativestack.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'js/src') diff --git a/js/src/jsnativestack.cpp b/js/src/jsnativestack.cpp index 389d7e657..4e96e01e8 100644 --- a/js/src/jsnativestack.cpp +++ b/js/src/jsnativestack.cpp @@ -73,7 +73,8 @@ js::GetNativeStackBaseImpl() JS_STATIC_ASSERT(JS_STACK_GROWTH_DIRECTION < 0); -void js::GetNativeStackBaseImpl() +void* +js::GetNativeStackBaseImpl() { stack_t st; stack_getbounds(&st); -- cgit v1.2.3 From 2f4488521db663520c703a9a836d5549d679266c Mon Sep 17 00:00:00 2001 From: athenian200 Date: Thu, 10 Oct 2019 15:38:27 -0500 Subject: MoonchildProductions#1251 - Part 23: Allow AMD64 build to work. https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/Build_Instructions/Compiling_32-bit_Firefox_on_a_Linux_64-bit_OS Setting this up turned out to be easier than I thought it would be. All I had to do was apply these instructions in reverse and add the following to my .mozconfig file: CC="gcc -m64" CXX="g++ -m64" AS="gas --64" ac_add_options --target=x86_64-pc-solaris2.11 export PKG_CONFIG_PATH=/usr/lib/amd64/pkgconfig ac_add_options --libdir=/usr/lib/amd64 ac_add_options --x-libraries=/usr/lib/amd64 Most of these changes were fairly trivial, just requiring me to make a few of the changes I made earlier conditional on a 32-bit build. The biggest challenge was figuring out why the JavaScript engine triggered a segfault everytime it tried to allocate memory. But this patch fixes it: https://github.com/OpenIndiana/oi-userland/blob/oi/hipster/components/web/firefox/patches/patch-js_src_gc_Memory.cpp.patch Turns out that Solaris on AMD64 handles memory management in a fairly unusual way with a segmented memory model, but it's not that different from what we see on other 64-bit processors. In fact, I saw a SPARC crash for a similar reason, and noticed that it looked just like mine except the numbers in the first segment were reversed. Having played around with hex editors before, I had a feeling I might be dealing with a little-endian version of a big-endian problem, but I didn't expect that knowledge to actually yield an easy solution. https://bugzilla.mozilla.org/show_bug.cgi?id=577056 https://www.oracle.com/technetwork/server-storage/solaris10/solaris-memory-135224.html As far as I can tell, this was the last barrier to an AMD64 Solaris build of Pale Moon. --- js/src/gc/Memory.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'js/src') diff --git a/js/src/gc/Memory.cpp b/js/src/gc/Memory.cpp index 5cf0cd2f7..2bc1b9f50 100644 --- a/js/src/gc/Memory.cpp +++ b/js/src/gc/Memory.cpp @@ -415,8 +415,15 @@ InitMemorySubsystem() static inline void* MapMemoryAt(void* desired, size_t length, int prot = PROT_READ | PROT_WRITE, int flags = MAP_PRIVATE | MAP_ANON, int fd = -1, off_t offset = 0) + +// Solaris manages 64-bit address space in a different manner from every other +// AMD64 operating system, but fortunately the fix is the same one +// required for every operating system on 64-bit SPARC, Itanium, and ARM. +// Most people's intuition failed them here and they thought this couldn't +// possibly be correct on AMD64, but for Solaris/illumos it is. + { -#if defined(__ia64__) || (defined(__sparc64__) && defined(__NetBSD__)) || defined(__aarch64__) +#if defined(__ia64__) || (defined(__sparc64__) && defined(__NetBSD__)) || defined(__aarch64__) || (defined(__sun) && defined(__x86_64__)) MOZ_ASSERT((0xffff800000000000ULL & (uintptr_t(desired) + length - 1)) == 0); #endif void* region = mmap(desired, length, prot, flags, fd, offset); @@ -466,7 +473,7 @@ MapMemory(size_t length, int prot = PROT_READ | PROT_WRITE, return nullptr; } return region; -#elif defined(__aarch64__) +#elif defined(__aarch64__) || (defined(__sun) && defined(__x86_64__)) /* * There might be similar virtual address issue on arm64 which depends on * hardware and kernel configurations. But the work around is slightly -- cgit v1.2.3 From 21146d0d5e4b6c985a3dce26460a5f495f1deb6e Mon Sep 17 00:00:00 2001 From: athenian200 Date: Thu, 17 Oct 2019 17:26:58 -0500 Subject: MoonchildProductions#1251 - Part 25: Fix link paths. This fix is a bit ugly and may need to be changed later if we switch a new GCC version, but the fact is that we use an architecture-specific path for GCC libraries on Solaris, so knowing the right prefix for GCC would only help so much, because it would still need to decide between ${gccdir}/lib and ${gccdir}/lib/amd64. The MOZ_FIX_LINK_PATHS variable puts the search paths into the right order without the need for me to use elfedit on the binaries afterwards. --- js/src/old-configure.in | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'js/src') diff --git a/js/src/old-configure.in b/js/src/old-configure.in index 45108ee59..6566ce05e 100644 --- a/js/src/old-configure.in +++ b/js/src/old-configure.in @@ -923,6 +923,14 @@ case "$target" in fi ;; +i*86-*-solaris*) + MOZ_FIX_LINK_PATHS="-L${DIST}/bin -R'\$\$ORIGIN':/usr/gcc/7/lib" + ;; + +x86_64-*-solaris*) + MOZ_FIX_LINK_PATHS="-L${DIST}/bin -R'\$\$ORIGIN':/usr/gcc/7/lib/amd64" + ;; + esac dnl Only one oddball right now (QNX), but this gives us flexibility -- cgit v1.2.3 From 687a798e6dedacb8b42826debcd8e89baa69ce94 Mon Sep 17 00:00:00 2001 From: athenian200 Date: Sat, 19 Oct 2019 14:24:49 -0500 Subject: MoonchildProductions#1251 - Part 27: Fix ifdef style. This should do it for all the commits to files I changed, but while I'm in here I could probably go ahead and turn ALL the singular if defined statements into ifdef statements by using grep/find on the tree. On the other hand, perhaps we should do that as a separate issue so that this doesn't become a case of scope creep. --- js/src/builtin/TestingFunctions.cpp | 2 +- js/src/gc/Memory.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'js/src') diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctions.cpp index 6beb82932..4363c7aed 100644 --- a/js/src/builtin/TestingFunctions.cpp +++ b/js/src/builtin/TestingFunctions.cpp @@ -239,7 +239,7 @@ GetBuildConfiguration(JSContext* cx, unsigned argc, Value* vp) value = BooleanValue(true); if (!JS_SetProperty(cx, info, "intl-api", value)) return false; -#if defined(XP_SOLARIS) +#ifdef XP_SOLARIS value = BooleanValue(false); #else value = BooleanValue(true); diff --git a/js/src/gc/Memory.cpp b/js/src/gc/Memory.cpp index 2bc1b9f50..418984057 100644 --- a/js/src/gc/Memory.cpp +++ b/js/src/gc/Memory.cpp @@ -685,7 +685,7 @@ MarkPagesUnused(void* p, size_t size) return false; MOZ_ASSERT(OffsetFromAligned(p, pageSize) == 0); -#if defined(XP_SOLARIS) +#ifdef XP_SOLARIS int result = posix_madvise(p, size, POSIX_MADV_DONTNEED); #else int result = madvise(p, size, MADV_DONTNEED); -- cgit v1.2.3 From dee457e63aa52ac83c0545ae87dc273cbdd072f1 Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Tue, 22 Oct 2019 20:57:58 +0200 Subject: Avoid uint32_t overflow in js shell by checking size of file before trying to stuff something insanely large into a Uint8Array. See also: BMO 1571911 --- js/src/shell/OSObject.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'js/src') diff --git a/js/src/shell/OSObject.cpp b/js/src/shell/OSObject.cpp index 846ec7b15..4fb3d4e77 100644 --- a/js/src/shell/OSObject.cpp +++ b/js/src/shell/OSObject.cpp @@ -184,6 +184,11 @@ FileAsTypedArray(JSContext* cx, JS::HandleString pathnameStr) return nullptr; JS_ReportErrorUTF8(cx, "can't seek start of %s", pathname.ptr()); } else { + if (len > INT32_MAX) { + JS_ReportErrorUTF8(cx, "file %s is too large for a Uint8Array", + pathname.ptr()); + return nullptr; + } obj = JS_NewUint8Array(cx, len); if (!obj) return nullptr; -- cgit v1.2.3 From e8c5582bec49058508b2de9f2f292f3a25e5278e Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Thu, 24 Oct 2019 12:13:26 +0200 Subject: Fix type barrier in IonBuilder::jsop_getimport. --- js/src/jit/IonBuilder.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'js/src') diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp index 2d053de5a..0c69729a4 100644 --- a/js/src/jit/IonBuilder.cpp +++ b/js/src/jit/IonBuilder.cpp @@ -8895,10 +8895,8 @@ IonBuilder::jsop_getimport(PropertyName* name) if (!emitted) { // This can happen if we don't have type information. - TypeSet::ObjectKey* staticKey = TypeSet::ObjectKey::get(targetEnv); TemporaryTypeSet* types = bytecodeTypes(pc); - BarrierKind barrier = PropertyReadNeedsTypeBarrier(analysisContext, constraints(), staticKey, - name, types, /* updateObserved = */ true); + BarrierKind barrier = BarrierKind::TypeSet; if (!loadStaticSlot(targetEnv, barrier, types, shape->slot())) return false; -- cgit v1.2.3 From c59c9682d351e641f184e1f8095f399fee179f62 Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Sat, 26 Oct 2019 13:08:45 +0200 Subject: Issue #1257 - Part1: Remove watch class-hook and proxy trap. --- js/src/builtin/TypedObject.cpp | 1 - js/src/jsobj.cpp | 6 ------ js/src/jsobj.h | 2 -- js/src/jswrapper.h | 7 ------- js/src/proxy/BaseProxyHandler.cpp | 14 -------------- js/src/proxy/Proxy.cpp | 27 --------------------------- js/src/proxy/Proxy.h | 3 --- js/src/proxy/SecurityWrapper.cpp | 19 ------------------- js/src/vm/EnvironmentObject.cpp | 3 --- 9 files changed, 82 deletions(-) (limited to 'js/src') diff --git a/js/src/builtin/TypedObject.cpp b/js/src/builtin/TypedObject.cpp index ff3680774..50bf0b836 100644 --- a/js/src/builtin/TypedObject.cpp +++ b/js/src/builtin/TypedObject.cpp @@ -2215,7 +2215,6 @@ const ObjectOps TypedObject::objectOps_ = { TypedObject::obj_setProperty, TypedObject::obj_getOwnPropertyDescriptor, TypedObject::obj_deleteProperty, - nullptr, nullptr, /* watch/unwatch */ nullptr, /* getElements */ TypedObject::obj_enumerate, nullptr, /* thisValue */ diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index 6f9596924..ee66addc9 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -2836,9 +2836,6 @@ js::UnwatchGuts(JSContext* cx, JS::HandleObject origObj, JS::HandleId id) bool js::WatchProperty(JSContext* cx, HandleObject obj, HandleId id, HandleObject callable) { - if (WatchOp op = obj->getOpsWatch()) - return op(cx, obj, id, callable); - if (!obj->isNative() || obj->is()) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_CANT_WATCH, obj->getClass()->name); @@ -2851,9 +2848,6 @@ js::WatchProperty(JSContext* cx, HandleObject obj, HandleId id, HandleObject cal bool js::UnwatchProperty(JSContext* cx, HandleObject obj, HandleId id) { - if (UnwatchOp op = obj->getOpsUnwatch()) - return op(cx, obj, id); - return UnwatchGuts(cx, obj, id); } diff --git a/js/src/jsobj.h b/js/src/jsobj.h index db2c22b76..8a41d155e 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -141,8 +141,6 @@ class JSObject : public js::gc::Cell js::GetOwnPropertyOp getOpsGetOwnPropertyDescriptor() const { return getClass()->getOpsGetOwnPropertyDescriptor(); } js::DeletePropertyOp getOpsDeleteProperty() const { return getClass()->getOpsDeleteProperty(); } - js::WatchOp getOpsWatch() const { return getClass()->getOpsWatch(); } - js::UnwatchOp getOpsUnwatch() const { return getClass()->getOpsUnwatch(); } js::GetElementsOp getOpsGetElements() const { return getClass()->getOpsGetElements(); } JSNewEnumerateOp getOpsEnumerate() const { return getClass()->getOpsEnumerate(); } JSFunToStringOp getOpsFunToString() const { return getClass()->getOpsFunToString(); } diff --git a/js/src/jswrapper.h b/js/src/jswrapper.h index 5f3704e32..32336c68b 100644 --- a/js/src/jswrapper.h +++ b/js/src/jswrapper.h @@ -315,13 +315,6 @@ class JS_FRIEND_API(SecurityWrapper) : public Base virtual bool regexp_toShared(JSContext* cx, HandleObject proxy, RegExpGuard* g) const override; virtual bool boxedValue_unbox(JSContext* cx, HandleObject proxy, MutableHandleValue vp) const override; - // Allow isCallable and isConstructor. They used to be class-level, and so could not be guarded - // against. - - virtual bool watch(JSContext* cx, JS::HandleObject proxy, JS::HandleId id, - JS::HandleObject callable) const override; - virtual bool unwatch(JSContext* cx, JS::HandleObject proxy, JS::HandleId id) const override; - /* * Allow our subclasses to select the superclass behavior they want without * needing to specify an exact superclass. diff --git a/js/src/proxy/BaseProxyHandler.cpp b/js/src/proxy/BaseProxyHandler.cpp index 8d5f30a19..423aa8671 100644 --- a/js/src/proxy/BaseProxyHandler.cpp +++ b/js/src/proxy/BaseProxyHandler.cpp @@ -418,20 +418,6 @@ BaseProxyHandler::setImmutablePrototype(JSContext* cx, HandleObject proxy, bool* return true; } -bool -BaseProxyHandler::watch(JSContext* cx, HandleObject proxy, HandleId id, HandleObject callable) const -{ - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_CANT_WATCH, - proxy->getClass()->name); - return false; -} - -bool -BaseProxyHandler::unwatch(JSContext* cx, HandleObject proxy, HandleId id) const -{ - return true; -} - bool BaseProxyHandler::getElements(JSContext* cx, HandleObject proxy, uint32_t begin, uint32_t end, ElementAdder* adder) const diff --git a/js/src/proxy/Proxy.cpp b/js/src/proxy/Proxy.cpp index 2c1cffb77..6b3a3d1e9 100644 --- a/js/src/proxy/Proxy.cpp +++ b/js/src/proxy/Proxy.cpp @@ -504,20 +504,6 @@ Proxy::boxedValue_unbox(JSContext* cx, HandleObject proxy, MutableHandleValue vp JSObject * const TaggedProto::LazyProto = reinterpret_cast(0x1); -/* static */ bool -Proxy::watch(JSContext* cx, JS::HandleObject proxy, JS::HandleId id, JS::HandleObject callable) -{ - JS_CHECK_RECURSION(cx, return false); - return proxy->as().handler()->watch(cx, proxy, id, callable); -} - -/* static */ bool -Proxy::unwatch(JSContext* cx, JS::HandleObject proxy, JS::HandleId id) -{ - JS_CHECK_RECURSION(cx, return false); - return proxy->as().handler()->unwatch(cx, proxy, id); -} - /* static */ bool Proxy::getElements(JSContext* cx, HandleObject proxy, uint32_t begin, uint32_t end, ElementAdder* adder) @@ -698,18 +684,6 @@ js::proxy_Construct(JSContext* cx, unsigned argc, Value* vp) return Proxy::construct(cx, proxy, args); } -bool -js::proxy_Watch(JSContext* cx, HandleObject obj, HandleId id, HandleObject callable) -{ - return Proxy::watch(cx, obj, id, callable); -} - -bool -js::proxy_Unwatch(JSContext* cx, HandleObject obj, HandleId id) -{ - return Proxy::unwatch(cx, obj, id); -} - bool js::proxy_GetElements(JSContext* cx, HandleObject proxy, uint32_t begin, uint32_t end, ElementAdder* adder) @@ -750,7 +724,6 @@ const ObjectOps js::ProxyObjectOps = { js::proxy_SetProperty, js::proxy_GetOwnPropertyDescriptor, js::proxy_DeleteProperty, - js::proxy_Watch, js::proxy_Unwatch, js::proxy_GetElements, nullptr, /* enumerate */ js::proxy_FunToString diff --git a/js/src/proxy/Proxy.h b/js/src/proxy/Proxy.h index 89909a085..4a8ecf8ab 100644 --- a/js/src/proxy/Proxy.h +++ b/js/src/proxy/Proxy.h @@ -65,9 +65,6 @@ class Proxy static bool regexp_toShared(JSContext* cx, HandleObject proxy, RegExpGuard* g); static bool boxedValue_unbox(JSContext* cx, HandleObject proxy, MutableHandleValue vp); - static bool watch(JSContext* cx, HandleObject proxy, HandleId id, HandleObject callable); - static bool unwatch(JSContext* cx, HandleObject proxy, HandleId id); - static bool getElements(JSContext* cx, HandleObject obj, uint32_t begin, uint32_t end, ElementAdder* adder); diff --git a/js/src/proxy/SecurityWrapper.cpp b/js/src/proxy/SecurityWrapper.cpp index 710faf9b0..71d22fca6 100644 --- a/js/src/proxy/SecurityWrapper.cpp +++ b/js/src/proxy/SecurityWrapper.cpp @@ -130,24 +130,5 @@ SecurityWrapper::defineProperty(JSContext* cx, HandleObject wrapper, Handl return Base::defineProperty(cx, wrapper, id, desc, result); } -template -bool -SecurityWrapper::watch(JSContext* cx, HandleObject proxy, - HandleId id, HandleObject callable) const -{ - ReportUnwrapDenied(cx); - return false; -} - -template -bool -SecurityWrapper::unwatch(JSContext* cx, HandleObject proxy, - HandleId id) const -{ - ReportUnwrapDenied(cx); - return false; -} - - template class js::SecurityWrapper; template class js::SecurityWrapper; diff --git a/js/src/vm/EnvironmentObject.cpp b/js/src/vm/EnvironmentObject.cpp index a5aac2ab4..3680c5b7b 100644 --- a/js/src/vm/EnvironmentObject.cpp +++ b/js/src/vm/EnvironmentObject.cpp @@ -408,7 +408,6 @@ const ObjectOps ModuleEnvironmentObject::objectOps_ = { ModuleEnvironmentObject::setProperty, ModuleEnvironmentObject::getOwnPropertyDescriptor, ModuleEnvironmentObject::deleteProperty, - nullptr, nullptr, /* watch/unwatch */ nullptr, /* getElements */ ModuleEnvironmentObject::enumerate, nullptr @@ -790,7 +789,6 @@ static const ObjectOps WithEnvironmentObjectOps = { with_SetProperty, with_GetOwnPropertyDescriptor, with_DeleteProperty, - nullptr, nullptr, /* watch/unwatch */ nullptr, /* getElements */ nullptr, /* enumerate (native enumeration of target doesn't work) */ nullptr, @@ -1159,7 +1157,6 @@ static const ObjectOps RuntimeLexicalErrorObjectObjectOps = { lexicalError_SetProperty, lexicalError_GetOwnPropertyDescriptor, lexicalError_DeleteProperty, - nullptr, nullptr, /* watch/unwatch */ nullptr, /* getElements */ nullptr, /* enumerate (native enumeration of target doesn't work) */ nullptr, /* this */ -- cgit v1.2.3 From 44a077980abb92dcea9ed374fd9719eaaf2f1458 Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Sun, 27 Oct 2019 02:51:11 +0200 Subject: Issue #1257 - Part 2: Remove watch/unwatch and JS watchpoint class. --- js/src/builtin/Object.cpp | 95 ----------------- js/src/gc/Marking.cpp | 7 +- js/src/gc/RootMarking.cpp | 1 - js/src/jit/BaselineIC.cpp | 6 -- js/src/jit/IonCaches.cpp | 5 +- js/src/js.msg | 2 - js/src/jsapi.cpp | 1 - js/src/jscntxt.cpp | 1 - js/src/jscompartment.cpp | 12 --- js/src/jscompartment.h | 3 - js/src/jsfriendapi.cpp | 2 - js/src/jsfriendapi.h | 24 ----- js/src/jsgc.cpp | 14 --- js/src/jsobj.cpp | 66 +----------- js/src/jsobj.h | 20 ---- js/src/jsobjinlines.h | 6 -- js/src/jsversion.h | 1 - js/src/jswatchpoint.cpp | 246 ------------------------------------------- js/src/jswatchpoint.h | 90 ---------------- js/src/moz.build | 1 - js/src/vm/NativeObject-inl.h | 8 +- js/src/vm/NativeObject.cpp | 14 +-- js/src/vm/Runtime.cpp | 1 - js/src/vm/Shape.h | 2 +- js/src/vm/TypeInference.cpp | 114 ++++++++++---------- 25 files changed, 65 insertions(+), 677 deletions(-) delete mode 100644 js/src/jswatchpoint.cpp delete mode 100644 js/src/jswatchpoint.h (limited to 'js/src') diff --git a/js/src/builtin/Object.cpp b/js/src/builtin/Object.cpp index 56c77f304..bfcc8d20e 100644 --- a/js/src/builtin/Object.cpp +++ b/js/src/builtin/Object.cpp @@ -568,97 +568,6 @@ obj_setPrototypeOf(JSContext* cx, unsigned argc, Value* vp) return true; } -#if JS_HAS_OBJ_WATCHPOINT - -bool -js::WatchHandler(JSContext* cx, JSObject* obj_, jsid id_, const JS::Value& old, - JS::Value* nvp, void* closure) -{ - RootedObject obj(cx, obj_); - RootedId id(cx, id_); - - /* Avoid recursion on (obj, id) already being watched on cx. */ - AutoResolving resolving(cx, obj, id, AutoResolving::WATCH); - if (resolving.alreadyStarted()) - return true; - - FixedInvokeArgs<3> args(cx); - - args[0].set(IdToValue(id)); - args[1].set(old); - args[2].set(*nvp); - - RootedValue callable(cx, ObjectValue(*static_cast(closure))); - RootedValue thisv(cx, ObjectValue(*obj)); - RootedValue rv(cx); - if (!Call(cx, callable, thisv, args, &rv)) - return false; - - *nvp = rv; - return true; -} - -static bool -obj_watch(JSContext* cx, unsigned argc, Value* vp) -{ - CallArgs args = CallArgsFromVp(argc, vp); - - RootedObject obj(cx, ToObject(cx, args.thisv())); - if (!obj) - return false; - - if (!GlobalObject::warnOnceAboutWatch(cx, obj)) - return false; - - if (args.length() <= 1) { - ReportMissingArg(cx, args.calleev(), 1); - return false; - } - - RootedObject callable(cx, ValueToCallable(cx, args[1], args.length() - 2)); - if (!callable) - return false; - - RootedId propid(cx); - if (!ValueToId(cx, args[0], &propid)) - return false; - - if (!WatchProperty(cx, obj, propid, callable)) - return false; - - args.rval().setUndefined(); - return true; -} - -static bool -obj_unwatch(JSContext* cx, unsigned argc, Value* vp) -{ - CallArgs args = CallArgsFromVp(argc, vp); - - RootedObject obj(cx, ToObject(cx, args.thisv())); - if (!obj) - return false; - - if (!GlobalObject::warnOnceAboutWatch(cx, obj)) - return false; - - RootedId id(cx); - if (args.length() != 0) { - if (!ValueToId(cx, args[0], &id)) - return false; - } else { - id = JSID_VOID; - } - - if (!UnwatchProperty(cx, obj, id)) - return false; - - args.rval().setUndefined(); - return true; -} - -#endif /* JS_HAS_OBJ_WATCHPOINT */ - /* ECMA 15.2.4.5. */ bool js::obj_hasOwnProperty(JSContext* cx, unsigned argc, Value* vp) @@ -1290,10 +1199,6 @@ static const JSFunctionSpec object_methods[] = { JS_FN(js_toString_str, obj_toString, 0,0), JS_SELF_HOSTED_FN(js_toLocaleString_str, "Object_toLocaleString", 0, 0), JS_SELF_HOSTED_FN(js_valueOf_str, "Object_valueOf", 0,0), -#if JS_HAS_OBJ_WATCHPOINT - JS_FN(js_watch_str, obj_watch, 2,0), - JS_FN(js_unwatch_str, obj_unwatch, 1,0), -#endif JS_FN(js_hasOwnProperty_str, obj_hasOwnProperty, 1,0), JS_FN(js_isPrototypeOf_str, obj_isPrototypeOf, 1,0), JS_FN(js_propertyIsEnumerable_str, obj_propertyIsEnumerable, 1,0), diff --git a/js/src/gc/Marking.cpp b/js/src/gc/Marking.cpp index da3ef7d0d..262fc8cbc 100644 --- a/js/src/gc/Marking.cpp +++ b/js/src/gc/Marking.cpp @@ -2846,10 +2846,9 @@ struct UnmarkGrayTracer : public JS::CallbackTracer * * There is an additional complication for certain kinds of edges that are not * contained explicitly in the source object itself, such as from a weakmap key - * to its value, and from an object being watched by a watchpoint to the - * watchpoint's closure. These "implicit edges" are represented in some other - * container object, such as the weakmap or the watchpoint itself. In these - * cases, calling unmark gray on an object won't find all of its children. + * to its value. These "implicit edges" are represented in some other + * container object, such as the weakmap itself. In these cases, calling unmark + * gray on an object won't find all of its children. * * Handling these implicit edges has two parts: * - A special pass enumerating all of the containers that know about the diff --git a/js/src/gc/RootMarking.cpp b/js/src/gc/RootMarking.cpp index f5969bc1f..7d665e8eb 100644 --- a/js/src/gc/RootMarking.cpp +++ b/js/src/gc/RootMarking.cpp @@ -14,7 +14,6 @@ #include "jsgc.h" #include "jsprf.h" #include "jstypes.h" -#include "jswatchpoint.h" #include "builtin/MapObject.h" #include "frontend/BytecodeCompiler.h" diff --git a/js/src/jit/BaselineIC.cpp b/js/src/jit/BaselineIC.cpp index a001357f8..9530f65fa 100644 --- a/js/src/jit/BaselineIC.cpp +++ b/js/src/jit/BaselineIC.cpp @@ -4053,9 +4053,6 @@ TryAttachSetValuePropStub(JSContext* cx, HandleScript script, jsbytecode* pc, IC { MOZ_ASSERT(!*attached); - if (obj->watched()) - return true; - RootedShape shape(cx); RootedObject holder(cx); if (!EffectlesslyLookupProperty(cx, obj, id, &holder, &shape)) @@ -4151,9 +4148,6 @@ TryAttachSetAccessorPropStub(JSContext* cx, HandleScript script, jsbytecode* pc, MOZ_ASSERT(!*attached); MOZ_ASSERT(!*isTemporarilyUnoptimizable); - if (obj->watched()) - return true; - RootedShape shape(cx); RootedObject holder(cx); if (!EffectlesslyLookupProperty(cx, obj, id, &holder, &shape)) diff --git a/js/src/jit/IonCaches.cpp b/js/src/jit/IonCaches.cpp index 48e0792bb..fb4291188 100644 --- a/js/src/jit/IonCaches.cpp +++ b/js/src/jit/IonCaches.cpp @@ -3232,7 +3232,7 @@ SetPropertyIC::tryAttachStub(JSContext* cx, HandleScript outerScript, IonScript* MOZ_ASSERT(!*emitted); MOZ_ASSERT(!*tryNativeAddSlot); - if (!canAttachStub() || obj->watched()) + if (!canAttachStub()) return true; // Fail cache emission if the object is frozen @@ -3897,9 +3897,6 @@ IsDenseElementSetInlineable(JSObject* obj, const Value& idval, const ConstantOrR if (!obj->is()) return false; - if (obj->watched()) - return false; - if (!idval.isInt32()) return false; diff --git a/js/src/js.msg b/js/src/js.msg index f57b36a90..1612c831d 100644 --- a/js/src/js.msg +++ b/js/src/js.msg @@ -47,7 +47,6 @@ MSG_DEF(JSMSG_MORE_ARGS_NEEDED, 3, JSEXN_TYPEERR, "{0} requires more than MSG_DEF(JSMSG_INCOMPATIBLE_PROTO, 3, JSEXN_TYPEERR, "{0}.prototype.{1} called on incompatible {2}") MSG_DEF(JSMSG_NO_CONSTRUCTOR, 1, JSEXN_TYPEERR, "{0} has no constructor") MSG_DEF(JSMSG_BAD_SORT_ARG, 0, JSEXN_TYPEERR, "invalid Array.prototype.sort argument") -MSG_DEF(JSMSG_CANT_WATCH, 1, JSEXN_TYPEERR, "can't watch non-native objects of class {0}") MSG_DEF(JSMSG_READ_ONLY, 1, JSEXN_TYPEERR, "{0} is read-only") MSG_DEF(JSMSG_CANT_DELETE, 1, JSEXN_TYPEERR, "property {0} is non-configurable and can't be deleted") MSG_DEF(JSMSG_CANT_TRUNCATE_ARRAY, 0, JSEXN_TYPEERR, "can't delete non-configurable array element") @@ -72,7 +71,6 @@ MSG_DEF(JSMSG_UNDEFINED_PROP, 1, JSEXN_REFERENCEERR, "reference to unde MSG_DEF(JSMSG_INVALID_MAP_ITERABLE, 1, JSEXN_TYPEERR, "iterable for {0} should have array-like objects") MSG_DEF(JSMSG_NESTING_GENERATOR, 0, JSEXN_TYPEERR, "already executing generator") MSG_DEF(JSMSG_INCOMPATIBLE_METHOD, 3, JSEXN_TYPEERR, "{0} {1} called on incompatible {2}") -MSG_DEF(JSMSG_OBJECT_WATCH_DEPRECATED, 0, JSEXN_WARN, "Object.prototype.watch and unwatch are very slow, non-standard, and deprecated; use a getter/setter instead") MSG_DEF(JSMSG_ARRAYBUFFER_SLICE_DEPRECATED, 0, JSEXN_WARN, "ArrayBuffer.slice is deprecated; use ArrayBuffer.prototype.slice instead") MSG_DEF(JSMSG_BAD_SURROGATE_CHAR, 1, JSEXN_TYPEERR, "bad surrogate character {0}") MSG_DEF(JSMSG_UTF8_CHAR_TOO_LARGE, 1, JSEXN_TYPEERR, "UTF-8 character {0} too large") diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index cad0840e0..f9a0c6a6b 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -39,7 +39,6 @@ #include "jsstr.h" #include "jstypes.h" #include "jsutil.h" -#include "jswatchpoint.h" #include "jsweakmap.h" #include "jswrapper.h" diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index e505a4b34..23b9d27ae 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -37,7 +37,6 @@ #include "jsscript.h" #include "jsstr.h" #include "jstypes.h" -#include "jswatchpoint.h" #include "gc/Marking.h" #include "jit/Ion.h" diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp index d0caeb558..8ba186b08 100644 --- a/js/src/jscompartment.cpp +++ b/js/src/jscompartment.cpp @@ -13,7 +13,6 @@ #include "jsfriendapi.h" #include "jsgc.h" #include "jsiter.h" -#include "jswatchpoint.h" #include "jswrapper.h" #include "gc/Marking.h" @@ -76,7 +75,6 @@ JSCompartment::JSCompartment(Zone* zone, const JS::CompartmentOptions& options = gcIncomingGrayPointers(nullptr), debugModeBits(0), randomKeyGenerator_(runtime_->forkRandomKeyGenerator()), - watchpointMap(nullptr), scriptCountsMap(nullptr), debugScriptMap(nullptr), debugEnvs(nullptr), @@ -103,7 +101,6 @@ JSCompartment::~JSCompartment() rt->lcovOutput.writeLCovResult(lcovOutput); js_delete(jitCompartment_); - js_delete(watchpointMap); js_delete(scriptCountsMap); js_delete(debugScriptMap); js_delete(debugEnvs); @@ -662,12 +659,6 @@ JSCompartment::traceRoots(JSTracer* trc, js::gc::GCRuntime::TraceOrMarkRuntime t if (traceOrMark == js::gc::GCRuntime::MarkRuntime && !zone()->isCollecting()) return; - // During a GC, these are treated as weak pointers. - if (traceOrMark == js::gc::GCRuntime::TraceRuntime) { - if (watchpointMap) - watchpointMap->markAll(trc); - } - /* Mark debug scopes, if present */ if (debugEnvs) debugEnvs->mark(trc); @@ -712,9 +703,6 @@ JSCompartment::traceRoots(JSTracer* trc, js::gc::GCRuntime::TraceOrMarkRuntime t void JSCompartment::finishRoots() { - if (watchpointMap) - watchpointMap->clear(); - if (debugEnvs) debugEnvs->finish(); diff --git a/js/src/jscompartment.h b/js/src/jscompartment.h index 83c15da3b..05ff40b43 100644 --- a/js/src/jscompartment.h +++ b/js/src/jscompartment.h @@ -282,7 +282,6 @@ class MOZ_RAII AutoSetNewObjectMetadata : private JS::CustomAutoRooter namespace js { class DebugEnvironments; class ObjectWeakMap; -class WatchpointMap; class WeakMapBase; } // namespace js @@ -811,8 +810,6 @@ struct JSCompartment void sweepBreakpoints(js::FreeOp* fop); public: - js::WatchpointMap* watchpointMap; - js::ScriptCountsMap* scriptCountsMap; js::DebugScriptMap* debugScriptMap; diff --git a/js/src/jsfriendapi.cpp b/js/src/jsfriendapi.cpp index f7622cb44..bdb3c0a4d 100644 --- a/js/src/jsfriendapi.cpp +++ b/js/src/jsfriendapi.cpp @@ -15,7 +15,6 @@ #include "jsgc.h" #include "jsobj.h" #include "jsprf.h" -#include "jswatchpoint.h" #include "jsweakmap.h" #include "jswrapper.h" @@ -579,7 +578,6 @@ void js::TraceWeakMaps(WeakMapTracer* trc) { WeakMapBase::traceAllMappings(trc); - WatchpointMap::traceAll(trc); } extern JS_FRIEND_API(bool) diff --git a/js/src/jsfriendapi.h b/js/src/jsfriendapi.h index 351667fb3..491215456 100644 --- a/js/src/jsfriendapi.h +++ b/js/src/jsfriendapi.h @@ -2110,30 +2110,6 @@ JS_FRIEND_API(void*) JS_GetDataViewData(JSObject* obj, const JS::AutoCheckCannotGC&); namespace js { - -/** - * Add a watchpoint -- in the Object.prototype.watch sense -- to |obj| for the - * property |id|, using the callable object |callable| as the function to be - * called for notifications. - * - * This is an internal function exposed -- temporarily -- only so that DOM - * proxies can be watchable. Don't use it! We'll soon kill off the - * Object.prototype.{,un}watch functions, at which point this will go too. - */ -extern JS_FRIEND_API(bool) -WatchGuts(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleObject callable); - -/** - * Remove a watchpoint -- in the Object.prototype.watch sense -- from |obj| for - * the property |id|. - * - * This is an internal function exposed -- temporarily -- only so that DOM - * proxies can be watchable. Don't use it! We'll soon kill off the - * Object.prototype.{,un}watch functions, at which point this will go too. - */ -extern JS_FRIEND_API(bool) -UnwatchGuts(JSContext* cx, JS::HandleObject obj, JS::HandleId id); - namespace jit { enum class InlinableNative : uint16_t; diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index b2ee8d67b..5a9d732b6 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -207,7 +207,6 @@ #include "jsscript.h" #include "jstypes.h" #include "jsutil.h" -#include "jswatchpoint.h" #include "jsweakmap.h" #ifdef XP_WIN # include "jswin.h" @@ -2392,11 +2391,6 @@ GCRuntime::updatePointersToRelocatedCells(Zone* zone, AutoLockForExclusiveAccess Debugger::markIncomingCrossCompartmentEdges(&trc); WeakMapBase::markAll(zone, &trc); - for (CompartmentsInZoneIter c(zone); !c.done(); c.next()) { - c->trace(&trc); - if (c->watchpointMap) - c->watchpointMap->markAll(&trc); - } // Mark all gray roots, making sure we call the trace callback to get the // current set. @@ -2405,7 +2399,6 @@ GCRuntime::updatePointersToRelocatedCells(Zone* zone, AutoLockForExclusiveAccess } // Sweep everything to fix up weak pointers - WatchpointMap::sweepAll(rt); Debugger::sweepAll(rt->defaultFreeOp()); jit::JitRuntime::SweepJitcodeGlobalTable(rt); rt->gc.sweepZoneAfterCompacting(zone); @@ -3850,10 +3843,6 @@ GCRuntime::markWeakReferences(gcstats::Phase phase) for (ZoneIterT zone(rt); !zone.done(); zone.next()) markedAny |= WeakMapBase::markZoneIteratively(zone, &marker); } - for (CompartmentsIterT c(rt); !c.done(); c.next()) { - if (c->watchpointMap) - markedAny |= c->watchpointMap->markIteratively(&marker); - } markedAny |= Debugger::markAllIteratively(&marker); markedAny |= jit::JitRuntime::MarkJitcodeGlobalTableIteratively(&marker); @@ -4625,9 +4614,6 @@ GCRuntime::beginSweepingZoneGroup(AutoLockForExclusiveAccess& lock) // Bug 1071218: the following two methods have not yet been // refactored to work on a single zone-group at once. - // Collect watch points associated with unreachable objects. - WatchpointMap::sweepAll(rt); - // Detach unreachable debuggers and global objects from each other. Debugger::sweepAll(&fop); diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index ee66addc9..ef1291079 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -33,7 +33,6 @@ #include "jsstr.h" #include "jstypes.h" #include "jsutil.h" -#include "jswatchpoint.h" #include "jswin.h" #include "jswrapper.h" @@ -1011,13 +1010,7 @@ js::CreateThisForFunction(JSContext* cx, HandleObject callee, HandleObject newTa JSObject::nonNativeSetProperty(JSContext* cx, HandleObject obj, HandleId id, HandleValue v, HandleValue receiver, ObjectOpResult& result) { - RootedValue value(cx, v); - if (MOZ_UNLIKELY(obj->watched())) { - WatchpointMap* wpmap = cx->compartment()->watchpointMap; - if (wpmap && !wpmap->triggerWatchpoint(cx, obj, id, &value)) - return false; - } - return obj->getOpsSetProperty()(cx, obj, id, value, receiver, result); + return obj->getOpsSetProperty()(cx, obj, id, v, receiver, result); } /* static */ bool @@ -2795,62 +2788,6 @@ js::GetPropertyDescriptor(JSContext* cx, HandleObject obj, HandleId id, return true; } -bool -js::WatchGuts(JSContext* cx, JS::HandleObject origObj, JS::HandleId id, JS::HandleObject callable) -{ - RootedObject obj(cx, ToWindowIfWindowProxy(origObj)); - if (obj->isNative()) { - // Use sparse indexes for watched objects, as dense elements can be - // written to without checking the watchpoint map. - if (!NativeObject::sparsifyDenseElements(cx, obj.as())) - return false; - - MarkTypePropertyNonData(cx, obj, id); - } - - WatchpointMap* wpmap = cx->compartment()->watchpointMap; - if (!wpmap) { - wpmap = cx->runtime()->new_(); - if (!wpmap || !wpmap->init()) { - ReportOutOfMemory(cx); - js_delete(wpmap); - return false; - } - cx->compartment()->watchpointMap = wpmap; - } - - return wpmap->watch(cx, obj, id, js::WatchHandler, callable); -} - -bool -js::UnwatchGuts(JSContext* cx, JS::HandleObject origObj, JS::HandleId id) -{ - // Looking in the map for an unsupported object will never hit, so we don't - // need to check for nativeness or watchable-ness here. - RootedObject obj(cx, ToWindowIfWindowProxy(origObj)); - if (WatchpointMap* wpmap = cx->compartment()->watchpointMap) - wpmap->unwatch(obj, id, nullptr, nullptr); - return true; -} - -bool -js::WatchProperty(JSContext* cx, HandleObject obj, HandleId id, HandleObject callable) -{ - if (!obj->isNative() || obj->is()) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_CANT_WATCH, - obj->getClass()->name); - return false; - } - - return WatchGuts(cx, obj, id, callable); -} - -bool -js::UnwatchProperty(JSContext* cx, HandleObject obj, HandleId id) -{ - return UnwatchGuts(cx, obj, id); -} - const char* js::GetObjectClassName(JSContext* cx, HandleObject obj) { @@ -3410,7 +3347,6 @@ JSObject::dump(FILE* fp) const if (obj->isBoundFunction()) fprintf(fp, " bound_function"); if (obj->isQualifiedVarObj()) fprintf(fp, " varobj"); if (obj->isUnqualifiedVarObj()) fprintf(fp, " unqualified_varobj"); - if (obj->watched()) fprintf(fp, " watched"); if (obj->isIteratedSingleton()) fprintf(fp, " iterated_singleton"); if (obj->isNewGroupUnknown()) fprintf(fp, " new_type_unknown"); if (obj->hasUncacheableProto()) fprintf(fp, " has_uncacheable_proto"); diff --git a/js/src/jsobj.h b/js/src/jsobj.h index 8a41d155e..01845d7e6 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -219,11 +219,6 @@ class JSObject : public js::gc::Cell inline bool isBoundFunction() const; inline bool hasSpecialEquality() const; - inline bool watched() const; - static bool setWatched(js::ExclusiveContext* cx, JS::HandleObject obj) { - return setFlags(cx, obj, js::BaseShape::WATCHED, GENERATE_SHAPE); - } - // A "qualified" varobj is the object on which "qualified" variable // declarations (i.e., those defined with "var") are kept. // @@ -1030,21 +1025,6 @@ extern bool DefineFunctions(JSContext* cx, HandleObject obj, const JSFunctionSpec* fs, DefineAsIntrinsic intrinsic); -/* - * Set a watchpoint: a synchronous callback when the given property of the - * given object is set. - * - * Watchpoints are nonstandard and do not fit in well with the way ES6 - * specifies [[Set]]. They are also insufficient for implementing - * Object.observe. - */ -extern bool -WatchProperty(JSContext* cx, HandleObject obj, HandleId id, HandleObject callable); - -/* Clear a watchpoint. */ -extern bool -UnwatchProperty(JSContext* cx, HandleObject obj, HandleId id); - /* ES6 draft rev 36 (2015 March 17) 7.1.1 ToPrimitive(vp[, preferredType]) */ extern bool ToPrimitiveSlow(JSContext* cx, JSType hint, MutableHandleValue vp); diff --git a/js/src/jsobjinlines.h b/js/src/jsobjinlines.h index c132ee6b2..98e740142 100644 --- a/js/src/jsobjinlines.h +++ b/js/src/jsobjinlines.h @@ -463,12 +463,6 @@ JSObject::isBoundFunction() const return is() && as().isBoundFunction(); } -inline bool -JSObject::watched() const -{ - return hasAllFlags(js::BaseShape::WATCHED); -} - inline bool JSObject::isDelegate() const { diff --git a/js/src/jsversion.h b/js/src/jsversion.h index 8bdfe47b6..cf4c6e73a 100644 --- a/js/src/jsversion.h +++ b/js/src/jsversion.h @@ -12,7 +12,6 @@ */ #define JS_HAS_STR_HTML_HELPERS 1 /* (no longer used) */ #define JS_HAS_OBJ_PROTO_PROP 1 /* has o.__proto__ etc. */ -#define JS_HAS_OBJ_WATCHPOINT 1 /* has o.watch and o.unwatch */ #define JS_HAS_TOSOURCE 1 /* has Object/Array toSource method */ #define JS_HAS_CATCH_GUARD 1 /* has exception handling catch guard */ #define JS_HAS_UNEVAL 1 /* has uneval() top-level function */ diff --git a/js/src/jswatchpoint.cpp b/js/src/jswatchpoint.cpp deleted file mode 100644 index 34479a990..000000000 --- a/js/src/jswatchpoint.cpp +++ /dev/null @@ -1,246 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: set ts=8 sts=4 et sw=4 tw=99: - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "jswatchpoint.h" - -#include "jsatom.h" -#include "jscompartment.h" -#include "jsfriendapi.h" - -#include "gc/Marking.h" -#include "vm/Shape.h" - -#include "jsgcinlines.h" - -using namespace js; -using namespace js::gc; - -inline HashNumber -WatchKeyHasher::hash(const Lookup& key) -{ - return MovableCellHasher::hash(key.object) ^ HashId(key.id); -} - -namespace { - -class AutoEntryHolder { - typedef WatchpointMap::Map Map; - Generation gen; - Map& map; - Map::Ptr p; - RootedObject obj; - RootedId id; - - public: - AutoEntryHolder(JSContext* cx, Map& map, Map::Ptr p) - : gen(map.generation()), map(map), p(p), obj(cx, p->key().object), id(cx, p->key().id) - { - MOZ_ASSERT(!p->value().held); - p->value().held = true; - } - - ~AutoEntryHolder() { - if (gen != map.generation()) - p = map.lookup(WatchKey(obj, id)); - if (p) - p->value().held = false; - } -}; - -} /* anonymous namespace */ - -bool -WatchpointMap::init() -{ - return map.init(); -} - -bool -WatchpointMap::watch(JSContext* cx, HandleObject obj, HandleId id, - JSWatchPointHandler handler, HandleObject closure) -{ - MOZ_ASSERT(JSID_IS_STRING(id) || JSID_IS_INT(id) || JSID_IS_SYMBOL(id)); - - if (!JSObject::setWatched(cx, obj)) - return false; - - Watchpoint w(handler, closure, false); - if (!map.put(WatchKey(obj, id), w)) { - ReportOutOfMemory(cx); - return false; - } - /* - * For generational GC, we don't need to post-barrier writes to the - * hashtable here because we mark all watchpoints as part of root marking in - * markAll(). - */ - return true; -} - -void -WatchpointMap::unwatch(JSObject* obj, jsid id, - JSWatchPointHandler* handlerp, JSObject** closurep) -{ - if (Map::Ptr p = map.lookup(WatchKey(obj, id))) { - if (handlerp) - *handlerp = p->value().handler; - if (closurep) { - // Read barrier to prevent an incorrectly gray closure from escaping the - // watchpoint. See the comment before UnmarkGrayChildren in gc/Marking.cpp - JS::ExposeObjectToActiveJS(p->value().closure); - *closurep = p->value().closure; - } - map.remove(p); - } -} - -void -WatchpointMap::unwatchObject(JSObject* obj) -{ - for (Map::Enum e(map); !e.empty(); e.popFront()) { - Map::Entry& entry = e.front(); - if (entry.key().object == obj) - e.removeFront(); - } -} - -void -WatchpointMap::clear() -{ - map.clear(); -} - -bool -WatchpointMap::triggerWatchpoint(JSContext* cx, HandleObject obj, HandleId id, MutableHandleValue vp) -{ - Map::Ptr p = map.lookup(WatchKey(obj, id)); - if (!p || p->value().held) - return true; - - AutoEntryHolder holder(cx, map, p); - - /* Copy the entry, since GC would invalidate p. */ - JSWatchPointHandler handler = p->value().handler; - RootedObject closure(cx, p->value().closure); - - /* Determine the property's old value. */ - Value old; - old.setUndefined(); - if (obj->isNative()) { - NativeObject* nobj = &obj->as(); - if (Shape* shape = nobj->lookup(cx, id)) { - if (shape->hasSlot()) - old = nobj->getSlot(shape->slot()); - } - } - - // Read barrier to prevent an incorrectly gray closure from escaping the - // watchpoint. See the comment before UnmarkGrayChildren in gc/Marking.cpp - JS::ExposeObjectToActiveJS(closure); - - /* Call the handler. */ - return handler(cx, obj, id, old, vp.address(), closure); -} - -bool -WatchpointMap::markIteratively(JSTracer* trc) -{ - bool marked = false; - for (Map::Enum e(map); !e.empty(); e.popFront()) { - Map::Entry& entry = e.front(); - JSObject* priorKeyObj = entry.key().object; - jsid priorKeyId(entry.key().id.get()); - bool objectIsLive = - IsMarked(trc->runtime(), const_cast(&entry.key().object)); - if (objectIsLive || entry.value().held) { - if (!objectIsLive) { - TraceEdge(trc, const_cast(&entry.key().object), - "held Watchpoint object"); - marked = true; - } - - MOZ_ASSERT(JSID_IS_STRING(priorKeyId) || - JSID_IS_INT(priorKeyId) || - JSID_IS_SYMBOL(priorKeyId)); - TraceEdge(trc, const_cast(&entry.key().id), "WatchKey::id"); - - if (entry.value().closure && !IsMarked(trc->runtime(), &entry.value().closure)) { - TraceEdge(trc, &entry.value().closure, "Watchpoint::closure"); - marked = true; - } - - /* We will sweep this entry in sweepAll if !objectIsLive. */ - if (priorKeyObj != entry.key().object || priorKeyId != entry.key().id) - e.rekeyFront(WatchKey(entry.key().object, entry.key().id)); - } - } - return marked; -} - -void -WatchpointMap::markAll(JSTracer* trc) -{ - for (Map::Enum e(map); !e.empty(); e.popFront()) { - Map::Entry& entry = e.front(); - JSObject* object = entry.key().object; - jsid id = entry.key().id; - JSObject* priorObject = object; - jsid priorId = id; - MOZ_ASSERT(JSID_IS_STRING(priorId) || JSID_IS_INT(priorId) || JSID_IS_SYMBOL(priorId)); - - TraceManuallyBarrieredEdge(trc, &object, "held Watchpoint object"); - TraceManuallyBarrieredEdge(trc, &id, "WatchKey::id"); - TraceEdge(trc, &entry.value().closure, "Watchpoint::closure"); - - if (priorObject != object || priorId != id) - e.rekeyFront(WatchKey(object, id)); - } -} - -void -WatchpointMap::sweepAll(JSRuntime* rt) -{ - for (GCCompartmentsIter c(rt); !c.done(); c.next()) { - if (WatchpointMap* wpmap = c->watchpointMap) - wpmap->sweep(); - } -} - -void -WatchpointMap::sweep() -{ - for (Map::Enum e(map); !e.empty(); e.popFront()) { - Map::Entry& entry = e.front(); - JSObject* obj(entry.key().object); - if (IsAboutToBeFinalizedUnbarriered(&obj)) { - MOZ_ASSERT(!entry.value().held); - e.removeFront(); - } else if (obj != entry.key().object) { - e.rekeyFront(WatchKey(obj, entry.key().id)); - } - } -} - -void -WatchpointMap::traceAll(WeakMapTracer* trc) -{ - JSRuntime* rt = trc->context; - for (CompartmentsIter comp(rt, SkipAtoms); !comp.done(); comp.next()) { - if (WatchpointMap* wpmap = comp->watchpointMap) - wpmap->trace(trc); - } -} - -void -WatchpointMap::trace(WeakMapTracer* trc) -{ - for (Map::Range r = map.all(); !r.empty(); r.popFront()) { - Map::Entry& entry = r.front(); - trc->trace(nullptr, - JS::GCCellPtr(entry.key().object.get()), - JS::GCCellPtr(entry.value().closure.get())); - } -} diff --git a/js/src/jswatchpoint.h b/js/src/jswatchpoint.h deleted file mode 100644 index bba6c38ce..000000000 --- a/js/src/jswatchpoint.h +++ /dev/null @@ -1,90 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: set ts=8 sts=4 et sw=4 tw=99: - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef jswatchpoint_h -#define jswatchpoint_h - -#include "jsalloc.h" - -#include "gc/Barrier.h" -#include "js/HashTable.h" - -namespace js { - -struct WeakMapTracer; - -struct WatchKey { - WatchKey() {} - WatchKey(JSObject* obj, jsid id) : object(obj), id(id) {} - WatchKey(const WatchKey& key) : object(key.object.get()), id(key.id.get()) {} - - // These are traced unconditionally during minor GC, so do not require - // post-barriers. - PreBarrieredObject object; - PreBarrieredId id; - - bool operator!=(const WatchKey& other) const { - return object != other.object || id != other.id; - } -}; - -typedef bool -(* JSWatchPointHandler)(JSContext* cx, JSObject* obj, jsid id, const JS::Value& old, - JS::Value* newp, void* closure); - -struct Watchpoint { - JSWatchPointHandler handler; - PreBarrieredObject closure; /* This is always marked in minor GCs and so doesn't require a postbarrier. */ - bool held; /* true if currently running handler */ - Watchpoint(JSWatchPointHandler handler, JSObject* closure, bool held) - : handler(handler), closure(closure), held(held) {} -}; - -struct WatchKeyHasher -{ - typedef WatchKey Lookup; - static inline js::HashNumber hash(const Lookup& key); - - static bool match(const WatchKey& k, const Lookup& l) { - return MovableCellHasher::match(k.object, l.object) && - DefaultHasher::match(k.id, l.id); - } - - static void rekey(WatchKey& k, const WatchKey& newKey) { - k.object.unsafeSet(newKey.object); - k.id.unsafeSet(newKey.id); - } -}; - -class WatchpointMap { - public: - typedef HashMap Map; - - bool init(); - bool watch(JSContext* cx, HandleObject obj, HandleId id, - JSWatchPointHandler handler, HandleObject closure); - void unwatch(JSObject* obj, jsid id, - JSWatchPointHandler* handlerp, JSObject** closurep); - void unwatchObject(JSObject* obj); - void clear(); - - bool triggerWatchpoint(JSContext* cx, HandleObject obj, HandleId id, MutableHandleValue vp); - - bool markIteratively(JSTracer* trc); - void markAll(JSTracer* trc); - static void sweepAll(JSRuntime* rt); - void sweep(); - - static void traceAll(WeakMapTracer* trc); - void trace(WeakMapTracer* trc); - - private: - Map map; -}; - -} // namespace js - -#endif /* jswatchpoint_h */ diff --git a/js/src/moz.build b/js/src/moz.build index a0f074d1c..5ce0dfd98 100644 --- a/js/src/moz.build +++ b/js/src/moz.build @@ -291,7 +291,6 @@ UNIFIED_SOURCES += [ 'jspropertytree.cpp', 'jsscript.cpp', 'jsstr.cpp', - 'jswatchpoint.cpp', 'jsweakmap.cpp', 'perf/jsperf.cpp', 'proxy/BaseProxyHandler.cpp', diff --git a/js/src/vm/NativeObject-inl.h b/js/src/vm/NativeObject-inl.h index e55e3db04..030d92c12 100644 --- a/js/src/vm/NativeObject-inl.h +++ b/js/src/vm/NativeObject-inl.h @@ -158,11 +158,11 @@ NativeObject::extendDenseElements(ExclusiveContext* cx, MOZ_ASSERT(!denseElementsAreFrozen()); /* - * Don't grow elements for non-extensible objects or watched objects. Dense - * elements can be added/written with no extensible or watchpoint checks as - * long as there is capacity for them. + * Don't grow elements for non-extensible objects. Dense elements can be + * added/written with no extensible checks as long as there is capacity + * for them. */ - if (!nonProxyIsExtensible() || watched()) { + if (!nonProxyIsExtensible()) { MOZ_ASSERT(getDenseCapacity() == 0); return DenseElementResult::Incomplete; } diff --git a/js/src/vm/NativeObject.cpp b/js/src/vm/NativeObject.cpp index da0f59fe2..d801fad06 100644 --- a/js/src/vm/NativeObject.cpp +++ b/js/src/vm/NativeObject.cpp @@ -9,8 +9,6 @@ #include "mozilla/ArrayUtils.h" #include "mozilla/Casting.h" -#include "jswatchpoint.h" - #include "gc/Marking.h" #include "js/Value.h" #include "vm/Debugger.h" @@ -602,7 +600,7 @@ NativeObject::maybeDensifySparseElements(js::ExclusiveContext* cx, HandleNativeO return DenseElementResult::Incomplete; /* Watch for conditions under which an object's elements cannot be dense. */ - if (!obj->nonProxyIsExtensible() || obj->watched()) + if (!obj->nonProxyIsExtensible()) return DenseElementResult::Incomplete; /* @@ -2410,17 +2408,9 @@ SetExistingProperty(JSContext* cx, HandleNativeObject obj, HandleId id, HandleVa } bool -js::NativeSetProperty(JSContext* cx, HandleNativeObject obj, HandleId id, HandleValue value, +js::NativeSetProperty(JSContext* cx, HandleNativeObject obj, HandleId id, HandleValue v, HandleValue receiver, QualifiedBool qualified, ObjectOpResult& result) { - // Fire watchpoints, if any. - RootedValue v(cx, value); - if (MOZ_UNLIKELY(obj->watched())) { - WatchpointMap* wpmap = cx->compartment()->watchpointMap; - if (wpmap && !wpmap->triggerWatchpoint(cx, obj, id, &v)) - return false; - } - // Step numbers below reference ES6 rev 27 9.1.9, the [[Set]] internal // method for ordinary objects. We substitute our own names for these names // used in the spec: O -> pobj, P -> id, ownDesc -> shape. diff --git a/js/src/vm/Runtime.cpp b/js/src/vm/Runtime.cpp index 5fc8e0e17..284a4f3d7 100644 --- a/js/src/vm/Runtime.cpp +++ b/js/src/vm/Runtime.cpp @@ -34,7 +34,6 @@ #include "jsnativestack.h" #include "jsobj.h" #include "jsscript.h" -#include "jswatchpoint.h" #include "jswin.h" #include "jswrapper.h" diff --git a/js/src/vm/Shape.h b/js/src/vm/Shape.h index fd6d843e0..85bc044a5 100644 --- a/js/src/vm/Shape.h +++ b/js/src/vm/Shape.h @@ -387,7 +387,7 @@ class BaseShape : public gc::TenuredCell INDEXED = 0x20, /* (0x40 is unused) */ HAD_ELEMENTS_ACCESS = 0x80, - WATCHED = 0x100, + /* (0x100 is unused) */ ITERATED_SINGLETON = 0x200, NEW_GROUP_UNKNOWN = 0x400, UNCACHEABLE_PROTO = 0x800, diff --git a/js/src/vm/TypeInference.cpp b/js/src/vm/TypeInference.cpp index 88327b47e..2b1fa0e3b 100644 --- a/js/src/vm/TypeInference.cpp +++ b/js/src/vm/TypeInference.cpp @@ -2670,14 +2670,6 @@ ObjectGroup::updateNewPropertyTypes(ExclusiveContext* cx, JSObject* objArg, jsid if (shape) UpdatePropertyType(cx, types, obj, shape, false); } - - if (obj->watched()) { - /* - * Mark the property as non-data, to inhibit optimizations on it - * and avoid bypassing the watchpoint handler. - */ - types->setNonDataProperty(cx); - } } void @@ -3622,42 +3614,42 @@ struct DestroyTypeNewScript } // namespace -bool DPAConstraintInfo::finishConstraints(JSContext* cx, ObjectGroup* group) { - for (const ProtoConstraint& constraint : protoConstraints_) { - ObjectGroup* protoGroup = constraint.proto->group(); - - // Note: we rely on the group's type information being unchanged since - // AddClearDefiniteGetterSetterForPrototypeChain. - - bool unknownProperties = protoGroup->unknownProperties(); - MOZ_RELEASE_ASSERT(!unknownProperties); - - HeapTypeSet* protoTypes = - protoGroup->getProperty(cx, constraint.proto, constraint.id); - MOZ_RELEASE_ASSERT(protoTypes); - - MOZ_ASSERT(!protoTypes->nonDataProperty()); - MOZ_ASSERT(!protoTypes->nonWritableProperty()); - - if (!protoTypes->addConstraint( - cx, - cx->typeLifoAlloc().new_( - group))) { - ReportOutOfMemory(cx); - return false; - } - } - - for (const InliningConstraint& constraint : inliningConstraints_) { - if (!AddClearDefiniteFunctionUsesInScript(cx, group, constraint.caller, - constraint.callee)) { - ReportOutOfMemory(cx); - return false; - } - } - - return true; -} +bool DPAConstraintInfo::finishConstraints(JSContext* cx, ObjectGroup* group) { + for (const ProtoConstraint& constraint : protoConstraints_) { + ObjectGroup* protoGroup = constraint.proto->group(); + + // Note: we rely on the group's type information being unchanged since + // AddClearDefiniteGetterSetterForPrototypeChain. + + bool unknownProperties = protoGroup->unknownProperties(); + MOZ_RELEASE_ASSERT(!unknownProperties); + + HeapTypeSet* protoTypes = + protoGroup->getProperty(cx, constraint.proto, constraint.id); + MOZ_RELEASE_ASSERT(protoTypes); + + MOZ_ASSERT(!protoTypes->nonDataProperty()); + MOZ_ASSERT(!protoTypes->nonWritableProperty()); + + if (!protoTypes->addConstraint( + cx, + cx->typeLifoAlloc().new_( + group))) { + ReportOutOfMemory(cx); + return false; + } + } + + for (const InliningConstraint& constraint : inliningConstraints_) { + if (!AddClearDefiniteFunctionUsesInScript(cx, group, constraint.caller, + constraint.callee)) { + ReportOutOfMemory(cx); + return false; + } + } + + return true; +} bool TypeNewScript::maybeAnalyze(JSContext* cx, ObjectGroup* group, bool* regenerate, bool force) @@ -3826,13 +3818,13 @@ TypeNewScript::maybeAnalyze(JSContext* cx, ObjectGroup* group, bool* regenerate, // The definite properties analysis found exactly the properties that // are held in common by the preliminary objects. No further analysis // is needed. - - if (!constraintInfo.finishConstraints(cx, group)) { - return false; - } - if (!group->newScript()) { - return true; - } + + if (!constraintInfo.finishConstraints(cx, group)) { + return false; + } + if (!group->newScript()) { + return true; + } group->addDefiniteProperties(cx, templateObject()->lastProperty()); @@ -3854,16 +3846,16 @@ TypeNewScript::maybeAnalyze(JSContext* cx, ObjectGroup* group, bool* regenerate, initialFlags); if (!initialGroup) return false; - - // Add the constraints. Use the initialGroup as group referenced by the - // constraints because that's the group that will have the TypeNewScript - // associated with it. See the detachNewScript and setNewScript calls below. - if (!constraintInfo.finishConstraints(cx, initialGroup)) { - return false; - } - if (!group->newScript()) { - return true; - } + + // Add the constraints. Use the initialGroup as group referenced by the + // constraints because that's the group that will have the TypeNewScript + // associated with it. See the detachNewScript and setNewScript calls below. + if (!constraintInfo.finishConstraints(cx, initialGroup)) { + return false; + } + if (!group->newScript()) { + return true; + } initialGroup->addDefiniteProperties(cx, templateObject()->lastProperty()); group->addDefiniteProperties(cx, prefixShape); -- cgit v1.2.3 From 24027f0df9d23304709a80c22c6bfdbd27a95046 Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Sun, 27 Oct 2019 02:14:16 +0100 Subject: Issue #1257 - Part 3: Remove/update tests. This removes a ton of tests that are no longer relevant with (un)watch removed (e.g. testing stability/bugs in the watchpoint system itself which has never been the most stable), and updates others that would previously rely on watch/unwatch, so that they don't unexpectedly fail. --- js/src/jit-test/tests/auto-regress/bug466654.js | 8 -- js/src/jit-test/tests/auto-regress/bug516897.js | 6 -- js/src/jit-test/tests/auto-regress/bug537854.js | 4 - js/src/jit-test/tests/auto-regress/bug560796.js | 9 -- js/src/jit-test/tests/auto-regress/bug638735.js | 1 - js/src/jit-test/tests/auto-regress/bug639413.js | 9 -- js/src/jit-test/tests/auto-regress/bug698899.js | 9 -- js/src/jit-test/tests/auto-regress/bug746397.js | 10 --- js/src/jit-test/tests/auto-regress/bug769192.js | 6 -- js/src/jit-test/tests/baseline/bug843444.js | 8 -- js/src/jit-test/tests/basic/bug510437.js | 13 --- js/src/jit-test/tests/basic/bug605015.js | 9 -- js/src/jit-test/tests/basic/bug631305.js | 9 -- js/src/jit-test/tests/basic/bug662562.js | 6 -- js/src/jit-test/tests/basic/bug690292.js | 12 --- js/src/jit-test/tests/basic/bug696748.js | 3 - js/src/jit-test/tests/basic/bug831846.js | 3 - .../basic/testAssigningWatchedDeletedProperty.js | 7 -- js/src/jit-test/tests/basic/testBug566556.js | 9 -- js/src/jit-test/tests/basic/testBug578044.js | 13 --- js/src/jit-test/tests/basic/testBug584650.js | 9 -- js/src/jit-test/tests/basic/testBug780288-1.js | 20 ----- js/src/jit-test/tests/basic/testBug780288-2.js | 20 ----- .../basic/testEvalCalledFromWatchOverSetter.js | 3 - js/src/jit-test/tests/basic/testNonStubGetter.js | 7 -- .../basic/testSettingWatchPointOnReadOnlyProp.js | 7 -- js/src/jit-test/tests/basic/testTrueShiftTrue.js | 16 ---- js/src/jit-test/tests/basic/testWatchRecursion.js | 63 ------------- js/src/jit-test/tests/gc/bug-900405.js | 3 - js/src/jit-test/tests/gc/bug-913261.js | 5 -- js/src/jit-test/tests/gc/bug-986864.js | 8 -- js/src/jit-test/tests/ion/bug1063182.js | 8 -- js/src/jit-test/tests/ion/bug772901.js | 2 +- js/src/jit-test/tests/ion/bug774257-1.js | 8 -- js/src/jit-test/tests/ion/bug774257-2.js | 10 --- js/src/jit-test/tests/ion/bug779631.js | 9 -- js/src/jit-test/tests/ion/bug783590.js | 1 - js/src/jit-test/tests/jaeger/bug550665.js | 8 -- js/src/jit-test/tests/jaeger/bug557063.js | 7 -- js/src/jit-test/tests/jaeger/bug588338.js | 1 - js/src/jit-test/tests/jaeger/bug625438.js | 10 --- js/src/jit-test/tests/jaeger/bug630366.js | 7 -- .../jit-test/tests/jaeger/recompile/bug641225.js | 1 - js/src/jit-test/tests/pic/fuzz1.js | 4 - js/src/jit-test/tests/pic/fuzz3.js | 3 - js/src/jit-test/tests/pic/watch1.js | 7 -- js/src/jit-test/tests/pic/watch1a.js | 17 ---- js/src/jit-test/tests/pic/watch2.js | 8 -- js/src/jit-test/tests/pic/watch2a.js | 18 ---- js/src/jit-test/tests/pic/watch3.js | 7 -- js/src/jit-test/tests/pic/watch3a.js | 19 ---- js/src/jit-test/tests/pic/watch3b.js | 20 ----- js/src/jit-test/tests/pic/watch4.js | 9 -- js/src/jit-test/tests/pic/watch5.js | 27 ------ js/src/jit-test/tests/profiler/bug1140643.js | 14 --- js/src/tests/ecma_5/Array/frozen-dense-array.js | 19 ---- .../tests/ecma_5/extensions/watch-array-length.js | 41 --------- .../ecma_5/extensions/watch-inherited-property.js | 38 -------- .../ecma_5/extensions/watch-replaced-setter.js | 46 ---------- .../extensions/watch-setter-become-setter.js | 44 --------- .../extensions/watch-value-prop-becoming-setter.js | 43 --------- .../watchpoint-deletes-JSPropertyOp-setter.js | 56 ------------ js/src/tests/js1_5/Object/regress-362872-01.js | 41 --------- js/src/tests/js1_5/Object/regress-362872-02.js | 24 ----- js/src/tests/js1_5/Regress/regress-127243.js | 75 ---------------- js/src/tests/js1_5/Regress/regress-213482.js | 29 ------ js/src/tests/js1_5/Regress/regress-240577.js | 37 -------- js/src/tests/js1_5/Regress/regress-355341.js | 29 ------ js/src/tests/js1_5/Regress/regress-355344.js | 49 ---------- js/src/tests/js1_5/Regress/regress-361467.js | 32 ------- js/src/tests/js1_5/Regress/regress-361617.js | 35 -------- js/src/tests/js1_5/Regress/regress-385393-06.js | 28 ------ js/src/tests/js1_5/Regress/regress-506567.js | 45 ---------- js/src/tests/js1_5/extensions/regress-303277.js | 19 ---- js/src/tests/js1_5/extensions/regress-355339.js | 32 ------- js/src/tests/js1_5/extensions/regress-361346.js | 22 ----- js/src/tests/js1_5/extensions/regress-361360.js | 32 ------- js/src/tests/js1_5/extensions/regress-361552.js | 27 ------ js/src/tests/js1_5/extensions/regress-361558.js | 19 ---- js/src/tests/js1_5/extensions/regress-361571.js | 38 -------- js/src/tests/js1_5/extensions/regress-361856.js | 35 -------- js/src/tests/js1_5/extensions/regress-361964.js | 54 ----------- js/src/tests/js1_5/extensions/regress-385134.js | 38 -------- js/src/tests/js1_5/extensions/regress-385393-09.js | 18 ---- js/src/tests/js1_5/extensions/regress-390597.js | 42 --------- js/src/tests/js1_5/extensions/regress-420612.js | 21 ----- js/src/tests/js1_5/extensions/regress-435345-01.js | 100 --------------------- js/src/tests/js1_5/extensions/regress-454040.js | 25 ------ js/src/tests/js1_5/extensions/regress-454142.js | 30 ------- js/src/tests/js1_5/extensions/regress-455413.js | 24 ----- js/src/tests/js1_5/extensions/regress-465145.js | 24 ----- js/src/tests/js1_5/extensions/regress-472787.js | 31 ------- js/src/tests/js1_5/extensions/regress-488995.js | 46 ---------- js/src/tests/js1_6/Regress/regress-476655.js | 40 --------- js/src/tests/js1_6/extensions/regress-457521.js | 24 ----- js/src/tests/js1_6/extensions/regress-479567.js | 33 ------- js/src/tests/js1_7/extensions/regress-453955.js | 31 ------- js/src/tests/js1_7/extensions/regress-473282.js | 20 ----- js/src/tests/js1_7/regress/regress-385133-01.js | 37 -------- js/src/tests/js1_8/extensions/regress-394709.js | 51 ----------- js/src/tests/js1_8/extensions/regress-481989.js | 19 ---- .../tests/js1_8_1/extensions/regress-452498-193.js | 34 ------- .../tests/js1_8_1/extensions/regress-452498-196.js | 9 -- js/src/tests/js1_8_1/extensions/regress-520572.js | 41 --------- js/src/tests/js1_8_1/regress/regress-452498-160.js | 5 -- .../tests/js1_8_5/extensions/regress-604781-1.js | 24 ----- .../tests/js1_8_5/extensions/regress-604781-2.js | 13 --- .../tests/js1_8_5/extensions/regress-627984-1.js | 16 ---- .../tests/js1_8_5/extensions/regress-627984-2.js | 15 ---- .../tests/js1_8_5/extensions/regress-627984-3.js | 14 --- .../tests/js1_8_5/extensions/regress-627984-4.js | 15 ---- .../tests/js1_8_5/extensions/regress-627984-5.js | 13 --- .../tests/js1_8_5/extensions/regress-627984-6.js | 15 ---- .../tests/js1_8_5/extensions/regress-627984-7.js | 9 -- js/src/tests/js1_8_5/extensions/regress-631723.js | 10 --- js/src/tests/js1_8_5/extensions/regress-636697.js | 11 --- js/src/tests/js1_8_5/extensions/regress-637985.js | 8 -- js/src/tests/js1_8_5/extensions/regress-691746.js | 11 --- .../js1_8_5/extensions/watch-undefined-setter.js | 19 ---- js/src/tests/js1_8_5/regress/regress-533876.js | 23 ----- js/src/tests/js1_8_5/regress/regress-548276.js | 10 --- js/src/tests/js1_8_5/regress/regress-584648.js | 16 ---- js/src/tests/js1_8_5/regress/regress-635195.js | 8 -- js/src/tests/js1_8_5/regress/regress-636394.js | 10 --- 124 files changed, 1 insertion(+), 2531 deletions(-) delete mode 100644 js/src/jit-test/tests/auto-regress/bug466654.js delete mode 100644 js/src/jit-test/tests/auto-regress/bug516897.js delete mode 100644 js/src/jit-test/tests/auto-regress/bug537854.js delete mode 100644 js/src/jit-test/tests/auto-regress/bug560796.js delete mode 100644 js/src/jit-test/tests/auto-regress/bug639413.js delete mode 100644 js/src/jit-test/tests/auto-regress/bug698899.js delete mode 100644 js/src/jit-test/tests/auto-regress/bug746397.js delete mode 100644 js/src/jit-test/tests/auto-regress/bug769192.js delete mode 100644 js/src/jit-test/tests/baseline/bug843444.js delete mode 100644 js/src/jit-test/tests/basic/bug510437.js delete mode 100644 js/src/jit-test/tests/basic/bug605015.js delete mode 100644 js/src/jit-test/tests/basic/bug631305.js delete mode 100644 js/src/jit-test/tests/basic/bug662562.js delete mode 100644 js/src/jit-test/tests/basic/bug690292.js delete mode 100644 js/src/jit-test/tests/basic/bug831846.js delete mode 100644 js/src/jit-test/tests/basic/testAssigningWatchedDeletedProperty.js delete mode 100644 js/src/jit-test/tests/basic/testBug566556.js delete mode 100644 js/src/jit-test/tests/basic/testBug578044.js delete mode 100644 js/src/jit-test/tests/basic/testBug584650.js delete mode 100644 js/src/jit-test/tests/basic/testBug780288-1.js delete mode 100644 js/src/jit-test/tests/basic/testBug780288-2.js delete mode 100644 js/src/jit-test/tests/basic/testEvalCalledFromWatchOverSetter.js delete mode 100644 js/src/jit-test/tests/basic/testNonStubGetter.js delete mode 100644 js/src/jit-test/tests/basic/testSettingWatchPointOnReadOnlyProp.js delete mode 100644 js/src/jit-test/tests/basic/testTrueShiftTrue.js delete mode 100644 js/src/jit-test/tests/basic/testWatchRecursion.js delete mode 100644 js/src/jit-test/tests/gc/bug-900405.js delete mode 100644 js/src/jit-test/tests/gc/bug-913261.js delete mode 100644 js/src/jit-test/tests/gc/bug-986864.js delete mode 100644 js/src/jit-test/tests/ion/bug1063182.js delete mode 100644 js/src/jit-test/tests/ion/bug774257-1.js delete mode 100644 js/src/jit-test/tests/ion/bug774257-2.js delete mode 100644 js/src/jit-test/tests/ion/bug779631.js delete mode 100644 js/src/jit-test/tests/jaeger/bug550665.js delete mode 100644 js/src/jit-test/tests/jaeger/bug557063.js delete mode 100644 js/src/jit-test/tests/jaeger/bug625438.js delete mode 100644 js/src/jit-test/tests/jaeger/bug630366.js delete mode 100644 js/src/jit-test/tests/pic/fuzz1.js delete mode 100644 js/src/jit-test/tests/pic/fuzz3.js delete mode 100644 js/src/jit-test/tests/pic/watch1.js delete mode 100644 js/src/jit-test/tests/pic/watch1a.js delete mode 100644 js/src/jit-test/tests/pic/watch2.js delete mode 100644 js/src/jit-test/tests/pic/watch2a.js delete mode 100644 js/src/jit-test/tests/pic/watch3.js delete mode 100644 js/src/jit-test/tests/pic/watch3a.js delete mode 100644 js/src/jit-test/tests/pic/watch3b.js delete mode 100644 js/src/jit-test/tests/pic/watch4.js delete mode 100644 js/src/jit-test/tests/pic/watch5.js delete mode 100644 js/src/jit-test/tests/profiler/bug1140643.js delete mode 100644 js/src/tests/ecma_5/extensions/watch-array-length.js delete mode 100644 js/src/tests/ecma_5/extensions/watch-inherited-property.js delete mode 100644 js/src/tests/ecma_5/extensions/watch-replaced-setter.js delete mode 100644 js/src/tests/ecma_5/extensions/watch-setter-become-setter.js delete mode 100644 js/src/tests/ecma_5/extensions/watch-value-prop-becoming-setter.js delete mode 100644 js/src/tests/ecma_5/extensions/watchpoint-deletes-JSPropertyOp-setter.js delete mode 100644 js/src/tests/js1_5/Object/regress-362872-01.js delete mode 100644 js/src/tests/js1_5/Object/regress-362872-02.js delete mode 100644 js/src/tests/js1_5/Regress/regress-127243.js delete mode 100644 js/src/tests/js1_5/Regress/regress-213482.js delete mode 100644 js/src/tests/js1_5/Regress/regress-240577.js delete mode 100644 js/src/tests/js1_5/Regress/regress-355341.js delete mode 100644 js/src/tests/js1_5/Regress/regress-355344.js delete mode 100644 js/src/tests/js1_5/Regress/regress-361467.js delete mode 100644 js/src/tests/js1_5/Regress/regress-361617.js delete mode 100644 js/src/tests/js1_5/Regress/regress-385393-06.js delete mode 100644 js/src/tests/js1_5/Regress/regress-506567.js delete mode 100644 js/src/tests/js1_5/extensions/regress-303277.js delete mode 100644 js/src/tests/js1_5/extensions/regress-355339.js delete mode 100644 js/src/tests/js1_5/extensions/regress-361346.js delete mode 100644 js/src/tests/js1_5/extensions/regress-361360.js delete mode 100644 js/src/tests/js1_5/extensions/regress-361552.js delete mode 100644 js/src/tests/js1_5/extensions/regress-361558.js delete mode 100644 js/src/tests/js1_5/extensions/regress-361571.js delete mode 100644 js/src/tests/js1_5/extensions/regress-361856.js delete mode 100644 js/src/tests/js1_5/extensions/regress-361964.js delete mode 100644 js/src/tests/js1_5/extensions/regress-385134.js delete mode 100644 js/src/tests/js1_5/extensions/regress-385393-09.js delete mode 100644 js/src/tests/js1_5/extensions/regress-390597.js delete mode 100644 js/src/tests/js1_5/extensions/regress-420612.js delete mode 100644 js/src/tests/js1_5/extensions/regress-435345-01.js delete mode 100644 js/src/tests/js1_5/extensions/regress-454040.js delete mode 100644 js/src/tests/js1_5/extensions/regress-454142.js delete mode 100644 js/src/tests/js1_5/extensions/regress-455413.js delete mode 100644 js/src/tests/js1_5/extensions/regress-465145.js delete mode 100755 js/src/tests/js1_5/extensions/regress-472787.js delete mode 100644 js/src/tests/js1_5/extensions/regress-488995.js delete mode 100644 js/src/tests/js1_6/Regress/regress-476655.js delete mode 100644 js/src/tests/js1_6/extensions/regress-457521.js delete mode 100644 js/src/tests/js1_6/extensions/regress-479567.js delete mode 100644 js/src/tests/js1_7/extensions/regress-453955.js delete mode 100644 js/src/tests/js1_7/extensions/regress-473282.js delete mode 100644 js/src/tests/js1_7/regress/regress-385133-01.js delete mode 100644 js/src/tests/js1_8/extensions/regress-394709.js delete mode 100644 js/src/tests/js1_8/extensions/regress-481989.js delete mode 100644 js/src/tests/js1_8_1/extensions/regress-452498-193.js delete mode 100644 js/src/tests/js1_8_1/extensions/regress-520572.js delete mode 100644 js/src/tests/js1_8_5/extensions/regress-604781-1.js delete mode 100644 js/src/tests/js1_8_5/extensions/regress-604781-2.js delete mode 100644 js/src/tests/js1_8_5/extensions/regress-627984-1.js delete mode 100644 js/src/tests/js1_8_5/extensions/regress-627984-2.js delete mode 100644 js/src/tests/js1_8_5/extensions/regress-627984-3.js delete mode 100644 js/src/tests/js1_8_5/extensions/regress-627984-4.js delete mode 100644 js/src/tests/js1_8_5/extensions/regress-627984-5.js delete mode 100644 js/src/tests/js1_8_5/extensions/regress-627984-6.js delete mode 100644 js/src/tests/js1_8_5/extensions/regress-627984-7.js delete mode 100644 js/src/tests/js1_8_5/extensions/regress-631723.js delete mode 100644 js/src/tests/js1_8_5/extensions/regress-636697.js delete mode 100644 js/src/tests/js1_8_5/extensions/regress-637985.js delete mode 100644 js/src/tests/js1_8_5/extensions/regress-691746.js delete mode 100644 js/src/tests/js1_8_5/extensions/watch-undefined-setter.js delete mode 100644 js/src/tests/js1_8_5/regress/regress-533876.js delete mode 100644 js/src/tests/js1_8_5/regress/regress-548276.js delete mode 100644 js/src/tests/js1_8_5/regress/regress-584648.js delete mode 100644 js/src/tests/js1_8_5/regress/regress-635195.js delete mode 100644 js/src/tests/js1_8_5/regress/regress-636394.js (limited to 'js/src') diff --git a/js/src/jit-test/tests/auto-regress/bug466654.js b/js/src/jit-test/tests/auto-regress/bug466654.js deleted file mode 100644 index 6c82c425b..000000000 --- a/js/src/jit-test/tests/auto-regress/bug466654.js +++ /dev/null @@ -1,8 +0,0 @@ -// |jit-test| error:TypeError - -// Binary: cache/js-dbg-32-29add08d84ae-linux -// Flags: -j -// -this.watch('y', /x/g ); -for each (y in ['q', 'q', 'q']) continue; -gc(); diff --git a/js/src/jit-test/tests/auto-regress/bug516897.js b/js/src/jit-test/tests/auto-regress/bug516897.js deleted file mode 100644 index e3caf4e6e..000000000 --- a/js/src/jit-test/tests/auto-regress/bug516897.js +++ /dev/null @@ -1,6 +0,0 @@ -// Binary: cache/js-dbg-64-38754465ffde-linux -// Flags: -// -this.__defineSetter__("x", gc); -this.watch("x",function(){return}); -x = 3; diff --git a/js/src/jit-test/tests/auto-regress/bug537854.js b/js/src/jit-test/tests/auto-regress/bug537854.js deleted file mode 100644 index 80fb3c14a..000000000 --- a/js/src/jit-test/tests/auto-regress/bug537854.js +++ /dev/null @@ -1,4 +0,0 @@ -// Binary: cache/js-dbg-64-9d51f2a931f7-linux -// Flags: -// -({x:function(){}}).watch('x',function(){}); diff --git a/js/src/jit-test/tests/auto-regress/bug560796.js b/js/src/jit-test/tests/auto-regress/bug560796.js deleted file mode 100644 index 4ab93567e..000000000 --- a/js/src/jit-test/tests/auto-regress/bug560796.js +++ /dev/null @@ -1,9 +0,0 @@ -// Binary: cache/js-dbg-64-a6d7a5677b4c-linux -// Flags: -// -this.__defineSetter__("x", function(){}) -this.watch("x", "".localeCompare) -window = x -Object.defineProperty(this, "x", ({ - set: window -})) diff --git a/js/src/jit-test/tests/auto-regress/bug638735.js b/js/src/jit-test/tests/auto-regress/bug638735.js index 63071aa7c..c941f5369 100644 --- a/js/src/jit-test/tests/auto-regress/bug638735.js +++ b/js/src/jit-test/tests/auto-regress/bug638735.js @@ -4,7 +4,6 @@ var o9 = Function.prototype; var o13 = Array; function f5(o) { -o.watch('p3', function() {}); ox1 = new Proxy(o, {}); } f5(o9); diff --git a/js/src/jit-test/tests/auto-regress/bug639413.js b/js/src/jit-test/tests/auto-regress/bug639413.js deleted file mode 100644 index d8dd58eaf..000000000 --- a/js/src/jit-test/tests/auto-regress/bug639413.js +++ /dev/null @@ -1,9 +0,0 @@ -// |jit-test| error:TypeError - -// Binary: cache/js-dbg-32-1c8e91b2e3a4-linux -// Flags: -// -a = evalcx("lazy"); -a.watch("x", function() {}); -({}).watch("x", function() {}); -a.__defineGetter__("y", {}); diff --git a/js/src/jit-test/tests/auto-regress/bug698899.js b/js/src/jit-test/tests/auto-regress/bug698899.js deleted file mode 100644 index 644f45ec2..000000000 --- a/js/src/jit-test/tests/auto-regress/bug698899.js +++ /dev/null @@ -1,9 +0,0 @@ -// Binary: cache/js-dbg-32-f951e9151626-linux -// Flags: -m -n -// -o = evalcx("lazy").__proto__ -gc() -try { - o.watch() -} catch (e) {} -o.constructor() diff --git a/js/src/jit-test/tests/auto-regress/bug746397.js b/js/src/jit-test/tests/auto-regress/bug746397.js deleted file mode 100644 index d915ca7bb..000000000 --- a/js/src/jit-test/tests/auto-regress/bug746397.js +++ /dev/null @@ -1,10 +0,0 @@ -// |jit-test| error:ReferenceError - -// Binary: cache/js-dbg-64-67bf9a4a1f77-linux -// Flags: --ion-eager -// - -(function () { - var a = ['x', 'y']; - obj.watch(a[+("0")], counter); -})(); diff --git a/js/src/jit-test/tests/auto-regress/bug769192.js b/js/src/jit-test/tests/auto-regress/bug769192.js deleted file mode 100644 index 531e37912..000000000 --- a/js/src/jit-test/tests/auto-regress/bug769192.js +++ /dev/null @@ -1,6 +0,0 @@ -// |jit-test| error:TypeError - -// Binary: cache/js-dbg-64-bf8f2961d0cc-linux -// Flags: -// -Object.watch.call(new Uint8ClampedArray, "length", function() {}); diff --git a/js/src/jit-test/tests/baseline/bug843444.js b/js/src/jit-test/tests/baseline/bug843444.js deleted file mode 100644 index 3a77402ac..000000000 --- a/js/src/jit-test/tests/baseline/bug843444.js +++ /dev/null @@ -1,8 +0,0 @@ -gczeal(8, 1) -function recurse(x) { - recurse; - if (x < 20) - recurse(x + 1); -}; -this.watch(5, (function () {})) -recurse(0) diff --git a/js/src/jit-test/tests/basic/bug510437.js b/js/src/jit-test/tests/basic/bug510437.js deleted file mode 100644 index 2418b9b11..000000000 --- a/js/src/jit-test/tests/basic/bug510437.js +++ /dev/null @@ -1,13 +0,0 @@ -// Don't crash or assert. - -var d; -this.watch("d", eval); -(function () { - (eval("\ - (function () {\ - for (let x = 0; x < 2; ++x) {\ - d = x\ - }\ - })\ -"))() -})() diff --git a/js/src/jit-test/tests/basic/bug605015.js b/js/src/jit-test/tests/basic/bug605015.js deleted file mode 100644 index a35f7b6c7..000000000 --- a/js/src/jit-test/tests/basic/bug605015.js +++ /dev/null @@ -1,9 +0,0 @@ -// |jit-test| error: TypeError -// don't assert - -print(this.watch("x", -function() { - Object.defineProperty(this, "x", ({ - get: (Int8Array) - })) -}))(x = /x/) diff --git a/js/src/jit-test/tests/basic/bug631305.js b/js/src/jit-test/tests/basic/bug631305.js deleted file mode 100644 index b0cbbbb24..000000000 --- a/js/src/jit-test/tests/basic/bug631305.js +++ /dev/null @@ -1,9 +0,0 @@ -var n = 0; -var a = []; -for (var i = 0; i < 20; i++) - a[i] = {}; -a[18].watch("p", function () { n++; }); -delete a[18].p; -for (var i = 0; i < 20; i++) - a[i].p = 0; -assertEq(n, 1); diff --git a/js/src/jit-test/tests/basic/bug662562.js b/js/src/jit-test/tests/basic/bug662562.js deleted file mode 100644 index 45b48589a..000000000 --- a/js/src/jit-test/tests/basic/bug662562.js +++ /dev/null @@ -1,6 +0,0 @@ -// |jit-test| error: TypeError -function f(o) { - o.watch("x", this); -} -var c = evalcx(""); -f(c); diff --git a/js/src/jit-test/tests/basic/bug690292.js b/js/src/jit-test/tests/basic/bug690292.js deleted file mode 100644 index 43ab56dd7..000000000 --- a/js/src/jit-test/tests/basic/bug690292.js +++ /dev/null @@ -1,12 +0,0 @@ - -done = false; -try { - function x() {} - print(this.watch("d", Object.create)) - var d = {} -} catch (e) {} -try { - eval("d = ''") - done = true; -} catch (e) {} -assertEq(done, false); diff --git a/js/src/jit-test/tests/basic/bug696748.js b/js/src/jit-test/tests/basic/bug696748.js index fe171f976..33fb4d52f 100644 --- a/js/src/jit-test/tests/basic/bug696748.js +++ b/js/src/jit-test/tests/basic/bug696748.js @@ -1,6 +1,3 @@ -try { -this.watch("b", "".substring); -} catch(exc1) {} eval("\ var URI = '';\ test();\ diff --git a/js/src/jit-test/tests/basic/bug831846.js b/js/src/jit-test/tests/basic/bug831846.js deleted file mode 100644 index 30bb3aa86..000000000 --- a/js/src/jit-test/tests/basic/bug831846.js +++ /dev/null @@ -1,3 +0,0 @@ -// |jit-test| error:TypeError - -evalcx('').watch("", /()/); diff --git a/js/src/jit-test/tests/basic/testAssigningWatchedDeletedProperty.js b/js/src/jit-test/tests/basic/testAssigningWatchedDeletedProperty.js deleted file mode 100644 index c22eabed0..000000000 --- a/js/src/jit-test/tests/basic/testAssigningWatchedDeletedProperty.js +++ /dev/null @@ -1,7 +0,0 @@ -var o = {}; -o.watch("p", function() { }); - -for (var i = 0; i < 10; i++) { - o.p = 123; - delete o.p; -} diff --git a/js/src/jit-test/tests/basic/testBug566556.js b/js/src/jit-test/tests/basic/testBug566556.js deleted file mode 100644 index 244be57d2..000000000 --- a/js/src/jit-test/tests/basic/testBug566556.js +++ /dev/null @@ -1,9 +0,0 @@ -var msg = ""; -try { - this.__defineSetter__('x', Object.create); - this.watch('x', function() {}); - x = 3; -} catch (e) { - msg = e.toString(); -} -assertEq(msg, "TypeError: undefined is not an object or null"); diff --git a/js/src/jit-test/tests/basic/testBug578044.js b/js/src/jit-test/tests/basic/testBug578044.js deleted file mode 100644 index c5b811dc9..000000000 --- a/js/src/jit-test/tests/basic/testBug578044.js +++ /dev/null @@ -1,13 +0,0 @@ -this.watch("x", Object.create) -try { - (function() { - this.__defineGetter__("x", - function() { - return this - }) - })() -} catch(e) {} -Object.defineProperty(x, "x", ({ - set: Uint16Array -})) - diff --git a/js/src/jit-test/tests/basic/testBug584650.js b/js/src/jit-test/tests/basic/testBug584650.js deleted file mode 100644 index b6c9d8ab7..000000000 --- a/js/src/jit-test/tests/basic/testBug584650.js +++ /dev/null @@ -1,9 +0,0 @@ -if (typeof gczeal != "function") - gczeal = function() {} - -// don't crash -x = (evalcx('lazy')) -x.watch("", function () {}) -gczeal(1) -for (w in x) {} - diff --git a/js/src/jit-test/tests/basic/testBug780288-1.js b/js/src/jit-test/tests/basic/testBug780288-1.js deleted file mode 100644 index 90746a04a..000000000 --- a/js/src/jit-test/tests/basic/testBug780288-1.js +++ /dev/null @@ -1,20 +0,0 @@ -s = newGlobal() -try { - evalcx("\ - Object.defineProperty(this,\"i\",{enumerable:true,get:function(){t}});\ - for each(y in this)true\ - ", s) -} catch (e) {} -try { - evalcx("\ - for(z=0,(7).watch(\"\",eval);;g){\ - if(z=1){({t:function(){}})\ - }\ - ", s) -} catch (e) {} -try { - evalcx("\ - Object.defineProperty(this,\"g2\",{get:function(){return this}});\ - g2.y()\ - ", s) -} catch (e) {} diff --git a/js/src/jit-test/tests/basic/testBug780288-2.js b/js/src/jit-test/tests/basic/testBug780288-2.js deleted file mode 100644 index 8c4c1737c..000000000 --- a/js/src/jit-test/tests/basic/testBug780288-2.js +++ /dev/null @@ -1,20 +0,0 @@ -s = newGlobal() -try { - evalcx("\ - Object.defineProperty(this,\"i\",{enumerable:true,get:function(){t}});\ - for each(y in this)true\ - ", s) -} catch (e) {} -try { - evalcx("\ - for(z=0,(7).watch(\"\",eval);;g){\ - if(z=1){({t:function(){}})\ - }\ - ", s) -} catch (e) {} -try { - evalcx("\ - Object.defineProperty(this,\"g2\",{get:function(){return this}});\ - g2.y(\"\")\ - ", s) -} catch (e) {} diff --git a/js/src/jit-test/tests/basic/testEvalCalledFromWatchOverSetter.js b/js/src/jit-test/tests/basic/testEvalCalledFromWatchOverSetter.js deleted file mode 100644 index bcd60fd80..000000000 --- a/js/src/jit-test/tests/basic/testEvalCalledFromWatchOverSetter.js +++ /dev/null @@ -1,3 +0,0 @@ -this.__defineSetter__("x", function(){}); -this.watch("x", eval); -x = 0; diff --git a/js/src/jit-test/tests/basic/testNonStubGetter.js b/js/src/jit-test/tests/basic/testNonStubGetter.js deleted file mode 100644 index 58a698eb4..000000000 --- a/js/src/jit-test/tests/basic/testNonStubGetter.js +++ /dev/null @@ -1,7 +0,0 @@ -function testNonStubGetter() { - { let [] = []; (this.watch("x", function(p, o, n) { return /a/g.exec(p, o, n); })); }; - (function () { (eval("(function(){for each (x in [1, 2, 2]);});"))(); })(); - this.unwatch("x"); - return "ok"; -} -assertEq(testNonStubGetter(), "ok"); diff --git a/js/src/jit-test/tests/basic/testSettingWatchPointOnReadOnlyProp.js b/js/src/jit-test/tests/basic/testSettingWatchPointOnReadOnlyProp.js deleted file mode 100644 index 78c281f05..000000000 --- a/js/src/jit-test/tests/basic/testSettingWatchPointOnReadOnlyProp.js +++ /dev/null @@ -1,7 +0,0 @@ -for (var i = 0; i < 5; ++i) { - var o = {} - Object.defineProperty(o, 'x', { value:"cow", writable:false }); - var r = o.watch('x', function() {}); - assertEq(r, undefined); - o.x = 4; -} diff --git a/js/src/jit-test/tests/basic/testTrueShiftTrue.js b/js/src/jit-test/tests/basic/testTrueShiftTrue.js deleted file mode 100644 index 44c1290d8..000000000 --- a/js/src/jit-test/tests/basic/testTrueShiftTrue.js +++ /dev/null @@ -1,16 +0,0 @@ -// Test no assert or crash from outer recorders (bug 465145) -function testBug465145() { - this.__defineSetter__("x", function(){}); - this.watch("x", function(){}); - y = this; - for (var z = 0; z < 2; ++z) { x = y }; - this.__defineSetter__("x", function(){}); - for (var z = 0; z < 2; ++z) { x = y }; -} - -function testTrueShiftTrue() { - var a = new Array(5); - for (var i=0;i<5;++i) a[i] = "" + (true << true); - return a.join(","); -} -assertEq(testTrueShiftTrue(), "2,2,2,2,2"); diff --git a/js/src/jit-test/tests/basic/testWatchRecursion.js b/js/src/jit-test/tests/basic/testWatchRecursion.js deleted file mode 100644 index e5d5877df..000000000 --- a/js/src/jit-test/tests/basic/testWatchRecursion.js +++ /dev/null @@ -1,63 +0,0 @@ -// Test that the watch handler is not called recursively for the same object -// and property. -(function() { - var obj1 = {}, obj2 = {}; - var handler_entry_count = 0; - var handler_exit_count = 0; - - obj1.watch('x', handler); - obj1.watch('y', handler); - obj2.watch('x', handler); - obj1.x = 1; - assertEq(handler_entry_count, 3); - assertEq(handler_exit_count, 3); - - function handler(id) { - handler_entry_count++; - assertEq(handler_exit_count, 0); - switch (true) { - case this === obj1 && id === "x": - assertEq(handler_entry_count, 1); - obj2.x = 3; - assertEq(handler_exit_count, 2); - break; - case this === obj2 && id === "x": - assertEq(handler_entry_count, 2); - obj1.y = 4; - assertEq(handler_exit_count, 1); - break; - default: - assertEq(this, obj1); - assertEq(id, "y"); - assertEq(handler_entry_count, 3); - - // We expect no more watch handler invocations - obj1.x = 5; - obj1.y = 6; - obj2.x = 7; - assertEq(handler_exit_count, 0); - break; - } - ++handler_exit_count; - assertEq(handler_entry_count, 3); - } -})(); - - -// Test that run-away recursion in watch handlers is properly handled. -(function() { - var obj = {}; - var i = 0; - try { - handler(); - throw new Error("Unreachable"); - } catch(e) { - assertEq(e instanceof InternalError, true); - } - - function handler() { - var prop = "a" + ++i; - obj.watch(prop, handler); - obj[prop] = 2; - } -})(); diff --git a/js/src/jit-test/tests/gc/bug-900405.js b/js/src/jit-test/tests/gc/bug-900405.js deleted file mode 100644 index eeec6f25f..000000000 --- a/js/src/jit-test/tests/gc/bug-900405.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() { - [{ "9": [] }.watch([], function(){})] -})() diff --git a/js/src/jit-test/tests/gc/bug-913261.js b/js/src/jit-test/tests/gc/bug-913261.js deleted file mode 100644 index 43066053f..000000000 --- a/js/src/jit-test/tests/gc/bug-913261.js +++ /dev/null @@ -1,5 +0,0 @@ -// |jit-test| error: InternalError: too much recursion -(function f() { - "".watch(2, function() {}); - f(); -})() diff --git a/js/src/jit-test/tests/gc/bug-986864.js b/js/src/jit-test/tests/gc/bug-986864.js deleted file mode 100644 index abb8de6b2..000000000 --- a/js/src/jit-test/tests/gc/bug-986864.js +++ /dev/null @@ -1,8 +0,0 @@ -// |jit-test| slow -function x() {} -for (var j = 0; j < 9999; ++j) { - (function() { - x += x.watch("endsWith", ArrayBuffer); - return 0 >> Function(x) - })() -} diff --git a/js/src/jit-test/tests/ion/bug1063182.js b/js/src/jit-test/tests/ion/bug1063182.js deleted file mode 100644 index 9cda48099..000000000 --- a/js/src/jit-test/tests/ion/bug1063182.js +++ /dev/null @@ -1,8 +0,0 @@ -// |jit-test| error: ReferenceError - -eval("(function() { " + "\ -var o = {};\ -o.watch('p', function() { });\ -for (var i = 0; i < 10; \u5ede ++)\ - o.p = 123;\ -" + " })();"); diff --git a/js/src/jit-test/tests/ion/bug772901.js b/js/src/jit-test/tests/ion/bug772901.js index eb71f6afb..164afd151 100644 --- a/js/src/jit-test/tests/ion/bug772901.js +++ b/js/src/jit-test/tests/ion/bug772901.js @@ -4,4 +4,4 @@ function f(x) { delete ((x)++); arguments[0] !== undefined; } -f(1, x = [f.ArrayBuffer,unwatch.Int32Array], this, this, this) ; +f(1, x = [f.ArrayBuffer, undefined], this, this, this) ; diff --git a/js/src/jit-test/tests/ion/bug774257-1.js b/js/src/jit-test/tests/ion/bug774257-1.js deleted file mode 100644 index 9c998a028..000000000 --- a/js/src/jit-test/tests/ion/bug774257-1.js +++ /dev/null @@ -1,8 +0,0 @@ -Object.defineProperty(Object.prototype, 'x', { - set: function() { evalcx('lazy'); } -}); -var obj = {}; -obj.watch("x", function (id, oldval, newval) {}); -for (var str in 'A') { - obj.x = 1; -} diff --git a/js/src/jit-test/tests/ion/bug774257-2.js b/js/src/jit-test/tests/ion/bug774257-2.js deleted file mode 100644 index b31043b08..000000000 --- a/js/src/jit-test/tests/ion/bug774257-2.js +++ /dev/null @@ -1,10 +0,0 @@ -Object.defineProperty(Object.prototype, 'x', { - set: function() { evalcx('lazy'); } -}); -var obj = {}; -var prot = {}; -obj.__proto__ = prot; -obj.watch("x", function (id, oldval, newval) {}); -for (var str in 'A') { - obj.x = 1; -} diff --git a/js/src/jit-test/tests/ion/bug779631.js b/js/src/jit-test/tests/ion/bug779631.js deleted file mode 100644 index 087aa01ac..000000000 --- a/js/src/jit-test/tests/ion/bug779631.js +++ /dev/null @@ -1,9 +0,0 @@ -var flag = 0; -var a = {}; -Object.defineProperty(a, "value", {set: function(x) {}}); -a.watch("value", function(){flag++;}); - -for(var i = 0; i < 100; i++) { - a.value = i; - assertEq(flag, i+1); -} diff --git a/js/src/jit-test/tests/ion/bug783590.js b/js/src/jit-test/tests/ion/bug783590.js index d48cb609e..9d277e02c 100644 --- a/js/src/jit-test/tests/ion/bug783590.js +++ b/js/src/jit-test/tests/ion/bug783590.js @@ -7,7 +7,6 @@ Object.defineProperty(arr, 0, { glob.__proto__; }) }); -this.watch("s", function() {}); try { arr.pop(); } catch (e) {} diff --git a/js/src/jit-test/tests/jaeger/bug550665.js b/js/src/jit-test/tests/jaeger/bug550665.js deleted file mode 100644 index 816888b5e..000000000 --- a/js/src/jit-test/tests/jaeger/bug550665.js +++ /dev/null @@ -1,8 +0,0 @@ -(function () { - var a; - eval("for(w in ((function(x,y){b:0})())) ;"); -})(); - -this.__defineSetter__("l", function() { gc() }); -this.watch("l", function(x) { yield {} }); -l = true; diff --git a/js/src/jit-test/tests/jaeger/bug557063.js b/js/src/jit-test/tests/jaeger/bug557063.js deleted file mode 100644 index ea77fd2c8..000000000 --- a/js/src/jit-test/tests/jaeger/bug557063.js +++ /dev/null @@ -1,7 +0,0 @@ -(function() { - for (a = 0; a < 2; a++) - ''.watch("", function() {}) -})() - -/* Don't crash or assert. */ - diff --git a/js/src/jit-test/tests/jaeger/bug588338.js b/js/src/jit-test/tests/jaeger/bug588338.js index 457be238a..c400d7687 100644 --- a/js/src/jit-test/tests/jaeger/bug588338.js +++ b/js/src/jit-test/tests/jaeger/bug588338.js @@ -9,7 +9,6 @@ function f() { } } })(/x/))) -for (z = 0; z < 100; x.unwatch(), z++) for (e in [0]) { gczeal(2) } ( [1,2,3])("") diff --git a/js/src/jit-test/tests/jaeger/bug625438.js b/js/src/jit-test/tests/jaeger/bug625438.js deleted file mode 100644 index 32586d8ab..000000000 --- a/js/src/jit-test/tests/jaeger/bug625438.js +++ /dev/null @@ -1,10 +0,0 @@ -// vim: set ts=8 sts=4 et sw=4 tw=99: - -var count = 0; -this.watch("x", function() { - count++; -}); -for(var i=0; i<10; i++) { - x = 2; -} -assertEq(count, 10); diff --git a/js/src/jit-test/tests/jaeger/bug630366.js b/js/src/jit-test/tests/jaeger/bug630366.js deleted file mode 100644 index acac8d3ef..000000000 --- a/js/src/jit-test/tests/jaeger/bug630366.js +++ /dev/null @@ -1,7 +0,0 @@ -var o = {}; -for(var i=0; i<5; i++) { - o.p = 2; - o.watch("p", function() { }); - o.p = 2; - delete o.p; -} diff --git a/js/src/jit-test/tests/jaeger/recompile/bug641225.js b/js/src/jit-test/tests/jaeger/recompile/bug641225.js index a6e3a86c7..7b7978197 100644 --- a/js/src/jit-test/tests/jaeger/recompile/bug641225.js +++ b/js/src/jit-test/tests/jaeger/recompile/bug641225.js @@ -118,7 +118,6 @@ for(var o2 in f5) { f2(o5); f2(o5); f0(o3); - o9.watch('p3', function() {}); o8[o8] = o8; f0(o5); f1(o6); diff --git a/js/src/jit-test/tests/pic/fuzz1.js b/js/src/jit-test/tests/pic/fuzz1.js deleted file mode 100644 index 2481a1314..000000000 --- a/js/src/jit-test/tests/pic/fuzz1.js +++ /dev/null @@ -1,4 +0,0 @@ -(function() { - for (a = 0; a < 2; a++) - ''.watch("", function() {}) -})() diff --git a/js/src/jit-test/tests/pic/fuzz3.js b/js/src/jit-test/tests/pic/fuzz3.js deleted file mode 100644 index 17613b6f5..000000000 --- a/js/src/jit-test/tests/pic/fuzz3.js +++ /dev/null @@ -1,3 +0,0 @@ -for each(let w in [[], 0, [], 0]) { - w.unwatch() -} diff --git a/js/src/jit-test/tests/pic/watch1.js b/js/src/jit-test/tests/pic/watch1.js deleted file mode 100644 index 09d6347bf..000000000 --- a/js/src/jit-test/tests/pic/watch1.js +++ /dev/null @@ -1,7 +0,0 @@ -// assignments to watched objects must not be cached -var obj = {x: 0}; -var hits = 0; -obj.watch("x", function (id, oldval, newval) { hits++; return newval; }); -for (var i = 0; i < 10; i++) - obj.x = i; -assertEq(hits, 10); diff --git a/js/src/jit-test/tests/pic/watch1a.js b/js/src/jit-test/tests/pic/watch1a.js deleted file mode 100644 index 4b404f507..000000000 --- a/js/src/jit-test/tests/pic/watch1a.js +++ /dev/null @@ -1,17 +0,0 @@ -// assignments to watched objects must not be traced -var hits = 0; -function counter(id, oldval, newval) { - hits++; - return newval; -} - -(function () { - var obj = {x: 0, y: 0}; - var a = ['x', 'y']; - obj.watch('z', counter); - for (var i = 0; i < 14; i++) { - obj.watch(a[+(i > 8)], counter); - obj.y = i; - } -})(); -assertEq(hits, 5); diff --git a/js/src/jit-test/tests/pic/watch2.js b/js/src/jit-test/tests/pic/watch2.js deleted file mode 100644 index fb3e29617..000000000 --- a/js/src/jit-test/tests/pic/watch2.js +++ /dev/null @@ -1,8 +0,0 @@ -// assignments to watched properties via ++ must not be cached -var obj = {x: 0}; -var hits = 0; -obj.watch("x", function (id, oldval, newval) { hits++; return newval; }); -for (var i = 0; i < 10; i++) - obj.x++; -assertEq(hits, 10); - diff --git a/js/src/jit-test/tests/pic/watch2a.js b/js/src/jit-test/tests/pic/watch2a.js deleted file mode 100644 index ce3294ba3..000000000 --- a/js/src/jit-test/tests/pic/watch2a.js +++ /dev/null @@ -1,18 +0,0 @@ -// assignments to watched properties via ++ must not be traced -var hits = 0; -function counter(id, oldval, newval) { - hits++; - return newval; -} - -(function () { - var obj = {x: 0, y: 0}; - var a = ['x', 'y']; - obj.watch('z', counter); - for (var i = 0; i < 14; i++) { - obj.watch(a[+(i > 8)], counter); - obj.y++; - } -})(); -assertEq(hits, 5); - diff --git a/js/src/jit-test/tests/pic/watch3.js b/js/src/jit-test/tests/pic/watch3.js deleted file mode 100644 index 4c5c93d8b..000000000 --- a/js/src/jit-test/tests/pic/watch3.js +++ /dev/null @@ -1,7 +0,0 @@ -// assignment to watched global properties must not be cached -x = 0; -var hits = 0; -this.watch("x", function (id, oldval, newval) { hits++; return newval; }); -for (var i = 0; i < 10; i++) - x = i; -assertEq(hits, 10); diff --git a/js/src/jit-test/tests/pic/watch3a.js b/js/src/jit-test/tests/pic/watch3a.js deleted file mode 100644 index 700daf6af..000000000 --- a/js/src/jit-test/tests/pic/watch3a.js +++ /dev/null @@ -1,19 +0,0 @@ -// assignment to watched global properties must not be traced -var hits = 0; -function counter(id, oldval, newval) { - hits++; - return newval; -} - -var x = 0; -var y = 0; -(function () { - var a = ['x', 'y']; - this.watch('z', counter); - for (var i = 0; i < 14; i++) { - this.watch(a[+(i > 8)], counter); - y = 1; - } -})(); -assertEq(hits, 5); - diff --git a/js/src/jit-test/tests/pic/watch3b.js b/js/src/jit-test/tests/pic/watch3b.js deleted file mode 100644 index 9b0dc8cc9..000000000 --- a/js/src/jit-test/tests/pic/watch3b.js +++ /dev/null @@ -1,20 +0,0 @@ -// assignment to watched global properties must not be traced -var hits = 0; -function counter(id, oldval, newval) { - hits++; - return newval; -} - -var x = 0; -var y = 0; -function f() { - var a = [{}, this]; - for (var i = 0; i < 14; i++) { - print(shapeOf(this)); - Object.prototype.watch.call(a[+(i > 8)], "y", counter); - y++; - } -} -f(); -assertEq(hits, 5); - diff --git a/js/src/jit-test/tests/pic/watch4.js b/js/src/jit-test/tests/pic/watch4.js deleted file mode 100644 index 4b640c4df..000000000 --- a/js/src/jit-test/tests/pic/watch4.js +++ /dev/null @@ -1,9 +0,0 @@ -// adding assignment + watchpoint vs. caching -var hits = 0; -var obj = {}; -obj.watch("x", function (id, oldval, newval) { hits++; return newval; }); -for (var i = 0; i < 10; i++) { - obj.x = 1; - delete obj.x; -} -assertEq(hits, 10); diff --git a/js/src/jit-test/tests/pic/watch5.js b/js/src/jit-test/tests/pic/watch5.js deleted file mode 100644 index 6b22951a4..000000000 --- a/js/src/jit-test/tests/pic/watch5.js +++ /dev/null @@ -1,27 +0,0 @@ -// test against future pic support for symbols - -// assignments to watched objects must not be cached -var obj = {}; -var x = Symbol.for("x"); -obj[x] = 0; -var hits = 0; -obj.watch(x, function (id, oldval, newval) { hits++; return newval; }); -for (var i = 0; i < 10; i++) - obj[x] = i; -assertEq(hits, 10); - -// assignments to watched properties via ++ must not be cached -hits = 0; -for (var i = 0; i < 10; i++) - obj[x]++; -assertEq(hits, 10); - -// adding assignment + watchpoint vs. caching -hits = 0; -obj = {}; -obj.watch(x, function (id, oldval, newval) { hits++; return newval; }); -for (var i = 0; i < 10; i++) { - obj[x] = 1; - delete obj[x]; -} -assertEq(hits, 10); diff --git a/js/src/jit-test/tests/profiler/bug1140643.js b/js/src/jit-test/tests/profiler/bug1140643.js deleted file mode 100644 index 1b171aea2..000000000 --- a/js/src/jit-test/tests/profiler/bug1140643.js +++ /dev/null @@ -1,14 +0,0 @@ -// |jit-test| allow-oom -enableSPSProfiling(); -loadFile('\ -for (var i = 0; i < 2; i++) {\ - obj = { m: function () {} };\ - obj.watch("m", function () { float32 = 0 + obj.foo; });\ - obj.m = 0;\ -}\ -'); -gcparam("maxBytes", gcparam("gcBytes") + (1)*1024); -newGlobal("same-compartment"); -function loadFile(lfVarx) { - evaluate(lfVarx, { noScriptRval : true, isRunOnce : true }); -} diff --git a/js/src/tests/ecma_5/Array/frozen-dense-array.js b/js/src/tests/ecma_5/Array/frozen-dense-array.js index 9db63036f..cdb86daa3 100644 --- a/js/src/tests/ecma_5/Array/frozen-dense-array.js +++ b/js/src/tests/ecma_5/Array/frozen-dense-array.js @@ -38,24 +38,5 @@ assertEq(delete a[0], false); assertArrayIsExpected(); -var watchpointCalled = false; -// NOTE: Be careful with the position of this test, since this sparsifies the -// elements and you might not test what you think you're testing otherwise. -a.watch(2, function(prop, oldValue, newValue) { - watchpointCalled = true; - assertEq(prop, 2); - assertEq(oldValue, 1); - assertEq(newValue, "foo"); -}); - -assertArrayIsExpected(); - -a.length = 5; -a[2] = "foo"; -assertEq(watchpointCalled, true); -assertEq(delete a[0], false); - -assertArrayIsExpected(); - if (typeof reportCompare === "function") reportCompare(true, true); diff --git a/js/src/tests/ecma_5/extensions/watch-array-length.js b/js/src/tests/ecma_5/extensions/watch-array-length.js deleted file mode 100644 index e9b356efa..000000000 --- a/js/src/tests/ecma_5/extensions/watch-array-length.js +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/licenses/publicdomain/ - */ - -var hitCount; -function watcher(p,o,n) { hitCount++; return n; } - -var a = [1]; -a.watch('length', watcher); -hitCount = 0; -a.length = 0; -reportCompare(1, hitCount, "lenient; configurable: watchpoint hit"); - -var b = Object.defineProperty([1],'0',{configurable:false}); -b.watch('length', watcher); -hitCount = 0; -var result; -try { - b.length = 0; - result = "no error"; -} catch (x) { - result = x.toString(); -} -reportCompare(1, hitCount, "lenient; non-configurable: watchpoint hit"); -reportCompare(1, b.length, "lenient; non-configurable: length unchanged"); -reportCompare("no error", result, "lenient; non-configurable: no error thrown"); - -var c = Object.defineProperty([1],'0',{configurable:false}); -c.watch('length', watcher); -hitCount = 0; -var threwTypeError; -try { - (function(){'use strict'; c.length = 0;})(); - threwTypeError = false; -} catch (x) { - threwTypeError = x instanceof TypeError; -} -reportCompare(1, hitCount, "strict; non-configurable: watchpoint hit"); -reportCompare(1, c.length, "strict; non-configurable: length unchanged"); -reportCompare(true, threwTypeError, "strict; non-configurable: TypeError thrown"); diff --git a/js/src/tests/ecma_5/extensions/watch-inherited-property.js b/js/src/tests/ecma_5/extensions/watch-inherited-property.js deleted file mode 100644 index 1a0ad566b..000000000 --- a/js/src/tests/ecma_5/extensions/watch-inherited-property.js +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/licenses/publicdomain/ - */ - -/* Create a prototype object with a setter property. */ -var protoSetterCount; -var proto = ({ set x(v) { protoSetterCount++; } }); - -/* Put a watchpoint on that setter. */ -var protoWatchCount; -proto.watch('x', function() { protoWatchCount++; }); - -/* Make an object with the above as its prototype. */ -function C() { } -C.prototype = proto; -var o = new C(); - -/* - * Set a watchpoint on the property in the inheriting object. We have - * defined this to mean "duplicate the property, setter and all, in the - * inheriting object." I don't think debugging observation mechanisms - * should mutate the program being run, but that's what we've got. - */ -var oWatchCount; -o.watch('x', function() { oWatchCount++; }); - -/* - * Assign to the property. This should trip the watchpoint on the inheriting object and - * the setter. - */ -protoSetterCount = protoWatchCount = oWatchCount = 0; -o.x = 1; -assertEq(protoWatchCount, 0); -assertEq(oWatchCount, 1); -assertEq(protoSetterCount, 1); - -reportCompare(true, true); diff --git a/js/src/tests/ecma_5/extensions/watch-replaced-setter.js b/js/src/tests/ecma_5/extensions/watch-replaced-setter.js deleted file mode 100644 index 05cf60aff..000000000 --- a/js/src/tests/ecma_5/extensions/watch-replaced-setter.js +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/licenses/publicdomain/ - */ - -/* A stock watcher function. */ -var watcherCount; -function watcher(id, oldval, newval) { watcherCount++; return newval; } - -/* Create an object with a JavaScript setter. */ -var setterCount; -var o = { w:2, set x(v) { setterCount++; } }; - -/* - * Put the object in dictionary mode, so that JSObject::putProperty will - * mutate its shapes instead of creating new ones. - */ -delete o.w; - -/* - * Place a watchpoint on the property. The watchpoint structure holds the - * original JavaScript setter, and a pointer to the shape. - */ -o.watch('x', watcher); - -/* - * Replace the accessor property with a value property. The shape's setter - * should become a non-JS setter, js_watch_set, and the watchpoint - * structure's saved setter should be updated (in this case, cleared). - */ -Object.defineProperty(o, 'x', { value:3, - writable:true, - enumerable:true, - configurable:true }); - -/* - * Assign to the property. This should trigger js_watch_set, which should - * call the handler, and then see that there is no JS-level setter to pass - * control on to, and return. - */ -watcherCount = setterCount = 0; -o.x = 3; -assertEq(watcherCount, 1); -assertEq(setterCount, 0); - -reportCompare(true, true); diff --git a/js/src/tests/ecma_5/extensions/watch-setter-become-setter.js b/js/src/tests/ecma_5/extensions/watch-setter-become-setter.js deleted file mode 100644 index f5eff98b8..000000000 --- a/js/src/tests/ecma_5/extensions/watch-setter-become-setter.js +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/licenses/publicdomain/ - */ - -/* Create an object with a JavaScript setter. */ -var firstSetterCount; -var o = { w:2, set x(v) { firstSetterCount++; } }; - -/* - * Put the object in dictionary mode, so that JSObject::putProperty will - * mutate its shapes instead of creating new ones. - */ -delete o.w; - -/* A stock watcher function. */ -var watcherCount; -function watcher(id, oldval, newval) { watcherCount++; return newval; } - -/* - * Place a watchpoint on the property. The property's shape now has the - * watchpoint setter, with the original setter saved in the watchpoint - * structure. - */ -o.watch('x', watcher); - -/* - * Replace the setter with a new setter. The shape should get updated to - * refer to the new setter, and then the watchpoint setter should be - * re-established. - */ -var secondSetterCount; -Object.defineProperty(o, 'x', { set: function () { secondSetterCount++ } }); - -/* - * Assign to the property. This should trigger the watchpoint and the new setter. - */ -watcherCount = firstSetterCount = secondSetterCount = 0; -o.x = 3; -assertEq(watcherCount, 1); -assertEq(firstSetterCount, 0); -assertEq(secondSetterCount, 1); - -reportCompare(true, true); diff --git a/js/src/tests/ecma_5/extensions/watch-value-prop-becoming-setter.js b/js/src/tests/ecma_5/extensions/watch-value-prop-becoming-setter.js deleted file mode 100644 index 03cdd788e..000000000 --- a/js/src/tests/ecma_5/extensions/watch-value-prop-becoming-setter.js +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/licenses/publicdomain/ - */ - -/* A stock watcher function. */ -var watcherCount; -function watcher(id, old, newval) { - watcherCount++; - return newval; -} - -/* Create an object with a value property. */ -var o = { w:2, x:3 }; - -/* - * Place a watchpoint on the value property. The watchpoint structure holds - * the original JavaScript setter, and a pointer to the shape. - */ -o.watch('x', watcher); - -/* - * Put the object in dictionary mode, so that JSObject::putProperty will - * mutate its shapes instead of creating new ones. - */ -delete o.w; - -/* - * Replace the value property with a setter. - */ -var setterCount; -o.__defineSetter__('x', function() { setterCount++; }); - -/* - * Trigger the watchpoint. The watchpoint handler should run, and then the - * setter should run. - */ -watcherCount = setterCount = 0; -o.x = 4; -assertEq(watcherCount, 1); -assertEq(setterCount, 1); - -reportCompare(true, true); diff --git a/js/src/tests/ecma_5/extensions/watchpoint-deletes-JSPropertyOp-setter.js b/js/src/tests/ecma_5/extensions/watchpoint-deletes-JSPropertyOp-setter.js deleted file mode 100644 index 85410bbd4..000000000 --- a/js/src/tests/ecma_5/extensions/watchpoint-deletes-JSPropertyOp-setter.js +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/licenses/publicdomain/ - */ - -function make_watcher(name) { - return function (id, oldv, newv) { - print("watched " + name + "[0]"); - }; -} - -var o, p; -function f(flag) { - if (flag) { - o = arguments; - } else { - p = arguments; - o.watch(0, make_watcher('o')); - p.watch(0, make_watcher('p')); - - /* - * Previously, the watchpoint implementation actually substituted its magic setter - * functions for the setters of shared shapes, and then 1) carefully ignored calls - * to its magic setter from unrelated objects, and 2) avoided restoring the - * original setter until all watchpoints on that shape had been removed. - * - * However, when the watchpoint code began using JSObject::changeProperty and - * js_ChangeNativePropertyAttrs to change shapes' setters, the shape tree code - * became conscious of the presence of watchpoints, and shared shapes between - * objects only when their watchpoint nature coincided. Clearing the magic setter - * from one object's shape would not affect other objects, because the - * watchpointed and non-watchpointed shapes were distinct if they were shared. - * - * Thus, the first unwatch call must go ahead and fix p's shape, even though a - * watchpoint exists on the same shape in o. o's watchpoint's presence shouldn't - * cause 'unwatch' to leave p's magic setter in place. - */ - - /* DropWatchPointAndUnlock would see o's watchpoint, and not change p's property. */ - p.unwatch(0); - - /* DropWatchPointAndUnlock would fix o's property, but not p's; p's setter would be gone. */ - o.unwatch(0); - - /* This would fail to invoke the arguments object's setter. */ - p[0] = 4; - - /* And the formal parameter would not get updated. */ - assertEq(flag, 4); - } -} - -f(true); -f(false); - -reportCompare(true, true); diff --git a/js/src/tests/js1_5/Object/regress-362872-01.js b/js/src/tests/js1_5/Object/regress-362872-01.js deleted file mode 100644 index 0808ee82b..000000000 --- a/js/src/tests/js1_5/Object/regress-362872-01.js +++ /dev/null @@ -1,41 +0,0 @@ -/* -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 362872; -var summary = 'script should not drop watchpoint that is in use'; -var actual = 'No Crash'; -var expect = 'No Crash'; - - -//----------------------------------------------------------------------------- -test(); -//----------------------------------------------------------------------------- - -function test() -{ - enterFunc ('test'); - printBugNumber(BUGNUMBER); - printStatus (summary); - - function exploit() { - var rooter = {}, object = {}, filler1 = "", filler2 = "\u5555"; - for(var i = 0; i < 32/2-2; i++) { filler1 += "\u5050"; } - object.watch("foo", function(){ - object.unwatch("foo"); - object.unwatch("foo"); - for(var i = 0; i < 8 * 1024; i++) { - rooter[i] = filler1 + filler2; - } - }); - object.foo = "bar"; - } - exploit(); - - - reportCompare(expect, actual, summary); - - exitFunc ('test'); -} diff --git a/js/src/tests/js1_5/Object/regress-362872-02.js b/js/src/tests/js1_5/Object/regress-362872-02.js deleted file mode 100644 index edee43a4a..000000000 --- a/js/src/tests/js1_5/Object/regress-362872-02.js +++ /dev/null @@ -1,24 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* - * Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/licenses/publicdomain/ - * Contributor: Blake Kaplan - */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 362872; -var summary = 'script should not drop watchpoint that is in use'; -var actual = 'No Crash'; -var expect = 'No Crash'; - -printBugNumber(BUGNUMBER); -printStatus (summary); - -this.watch('x', function f() { - print("before"); - x = 3; - print("after"); - }); -x = 3; - -reportCompare(expect, actual, summary); diff --git a/js/src/tests/js1_5/Regress/regress-127243.js b/js/src/tests/js1_5/Regress/regress-127243.js deleted file mode 100644 index 11779f803..000000000 --- a/js/src/tests/js1_5/Regress/regress-127243.js +++ /dev/null @@ -1,75 +0,0 @@ -// |reftest| skip-if(xulRuntime.OS=="WINNT"&&isDebugBuild) slow -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 127243; -var summary = 'Do not crash on watch'; -var actual = 'No Crash'; -var expect = 'No Crash'; - -printBugNumber(BUGNUMBER); -printStatus (summary); - -if (typeof window != 'undefined' && typeof document != 'undefined') -{ - // delay test driver end - gDelayTestDriverEnd = true; - window.addEventListener('load', handleLoad, false); -} -else -{ - printStatus('This test must be run in the browser'); - reportCompare(expect, actual, summary); - -} - -var div; - -function handleLoad() -{ - div = document.createElement('div'); - document.body.appendChild(div); - div.setAttribute('id', 'id1'); - div.style.width = '50px'; - div.style.height = '100px'; - div.style.overflow = 'auto'; - - for (var i = 0; i < 5; i++) - { - var p = document.createElement('p'); - var t = document.createTextNode('blah'); - p.appendChild(t); - div.appendChild(p); - } - - div.watch('scrollTop', wee); - - setTimeout('setScrollTop()', 1000); -} - -function wee(id, oldval, newval) -{ - var t = document.createTextNode('setting ' + id + - ' value ' + div.scrollTop + - ' oldval ' + oldval + - ' newval ' + newval); - var p = document.createElement('p'); - p.appendChild(t); - document.body.appendChild(p); - - return newval; -} - -function setScrollTop() -{ - div.scrollTop = 42; - - reportCompare(expect, actual, summary); - - gDelayTestDriverEnd = false; - jsTestDriverEnd(); - -} diff --git a/js/src/tests/js1_5/Regress/regress-213482.js b/js/src/tests/js1_5/Regress/regress-213482.js deleted file mode 100644 index 26ed7e894..000000000 --- a/js/src/tests/js1_5/Regress/regress-213482.js +++ /dev/null @@ -1,29 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 213482; -var summary = 'Do not crash watching property when watcher sets property'; -var actual = 'No Crash'; -var expect = 'No Crash'; - -printBugNumber(BUGNUMBER); -printStatus (summary); - -var testobj = {value: 'foo'}; - -function watched (a, b, c) { - testobj.value = (new Date()).getTime(); -} - -function setTest() { - testobj.value = 'b'; -} - -testobj.watch("value", watched); - -setTest(); - -reportCompare(expect, actual, summary); diff --git a/js/src/tests/js1_5/Regress/regress-240577.js b/js/src/tests/js1_5/Regress/regress-240577.js deleted file mode 100644 index ba8330aa0..000000000 --- a/js/src/tests/js1_5/Regress/regress-240577.js +++ /dev/null @@ -1,37 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* - * Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/licenses/publicdomain/ - * Contributor: Bob Clary - */ - -//----------------------------------------------------------------------------- -// originally reported by Jens Thiele in -var BUGNUMBER = 240577; -var summary = 'object.watch execution context'; -var actual = ''; -var expect = ''; - -printBugNumber(BUGNUMBER); -printStatus (summary); - -var createWatcher = function ( watchlabel ) -{ - var watcher = function (property, oldvalue, newvalue) - { - actual += watchlabel; return newvalue; - }; - return watcher; -}; - -var watcher1 = createWatcher('watcher1'); - -var object = {property: 'value'}; - -object.watch('property', watcher1); - -object.property = 'newvalue'; - -expect = 'watcher1'; - -reportCompare(expect, actual, summary); diff --git a/js/src/tests/js1_5/Regress/regress-355341.js b/js/src/tests/js1_5/Regress/regress-355341.js deleted file mode 100644 index ab2a4b884..000000000 --- a/js/src/tests/js1_5/Regress/regress-355341.js +++ /dev/null @@ -1,29 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 355341; -var summary = 'Do not crash with watch and setter'; -var actual = ''; -var expect = ''; - - -//----------------------------------------------------------------------------- -test(); -//----------------------------------------------------------------------------- - -function test() -{ - enterFunc ('test'); - printBugNumber(BUGNUMBER); - printStatus (summary); - - Object.defineProperty(this, "x", { set: Function, enumerable: true, configurable: true }); - this.watch('x', function () { }); x = 3; - - reportCompare(expect, actual, summary); - - exitFunc ('test'); -} diff --git a/js/src/tests/js1_5/Regress/regress-355344.js b/js/src/tests/js1_5/Regress/regress-355344.js deleted file mode 100644 index 00bd39147..000000000 --- a/js/src/tests/js1_5/Regress/regress-355344.js +++ /dev/null @@ -1,49 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 355344; -var summary = 'Exceptions thrown by watch point'; -var actual = ''; -var expect = ''; - - -//----------------------------------------------------------------------------- -test(); -//----------------------------------------------------------------------------- - -function test() -{ - enterFunc ('test'); - printBugNumber(BUGNUMBER); - printStatus (summary); - - var o = {}; - - expect = 'setter: yikes'; - - o.watch('x', function(){throw 'yikes'}); - try - { - o.x = 3; - } - catch(ex) - { - actual = "setter: " + ex; - } - - try - { - eval("") ; - } - catch(e) - { - actual = "eval: " + e; - } - - reportCompare(expect, actual, summary); - - exitFunc ('test'); -} diff --git a/js/src/tests/js1_5/Regress/regress-361467.js b/js/src/tests/js1_5/Regress/regress-361467.js deleted file mode 100644 index 371c0a8b5..000000000 --- a/js/src/tests/js1_5/Regress/regress-361467.js +++ /dev/null @@ -1,32 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 361467; -var summary = 'Do not crash with certain watchers'; -var actual = ''; -var expect = ''; - - -//----------------------------------------------------------------------------- -test(); -//----------------------------------------------------------------------------- - -function test() -{ - enterFunc ('test'); - printBugNumber(BUGNUMBER); - printStatus (summary); - - expect = actual = 'No Crash'; - - var x; - this.watch('x', print); - x = 5; - - reportCompare(expect, actual, summary); - - exitFunc ('test'); -} diff --git a/js/src/tests/js1_5/Regress/regress-361617.js b/js/src/tests/js1_5/Regress/regress-361617.js deleted file mode 100644 index 5d20fd78f..000000000 --- a/js/src/tests/js1_5/Regress/regress-361617.js +++ /dev/null @@ -1,35 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 361617; -var summary = 'Do not crash with getter, watch and gc'; -var actual = 'No Crash'; -var expect = 'No Crash'; - - -//----------------------------------------------------------------------------- -test(); -//----------------------------------------------------------------------------- - -function test() -{ - enterFunc ('test'); - printBugNumber(BUGNUMBER); - printStatus (summary); - - (function() { - Object.defineProperty(this, "x", { get: function(){}, enumerable: true, configurable: true }); - })(); - this.watch('x', print); - Object.defineProperty(this, "x", { get: function(){}, enumerable: true, configurable: true }); - gc(); - this.unwatch('x'); - x; - - reportCompare(expect, actual, summary); - - exitFunc ('test'); -} diff --git a/js/src/tests/js1_5/Regress/regress-385393-06.js b/js/src/tests/js1_5/Regress/regress-385393-06.js deleted file mode 100644 index 327103f39..000000000 --- a/js/src/tests/js1_5/Regress/regress-385393-06.js +++ /dev/null @@ -1,28 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - - -//----------------------------------------------------------------------------- -var BUGNUMBER = 385393; -var summary = 'Regression test for bug 385393'; -var actual = 'No Crash'; -var expect = 'No Crash'; - -//----------------------------------------------------------------------------- -test(); -//----------------------------------------------------------------------------- - -function test() -{ - enterFunc ('test'); - printBugNumber(BUGNUMBER); - printStatus (summary); - - reportCompare(expect, actual, summary); - - true.watch("x", function(){}); - - exitFunc ('test'); -} diff --git a/js/src/tests/js1_5/Regress/regress-506567.js b/js/src/tests/js1_5/Regress/regress-506567.js deleted file mode 100644 index e78dfe1db..000000000 --- a/js/src/tests/js1_5/Regress/regress-506567.js +++ /dev/null @@ -1,45 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 506567; -var summary = 'Do not crash with watched variables'; -var actual = ''; -var expect = ''; - - -//----------------------------------------------------------------------------- -test(); -//----------------------------------------------------------------------------- - -function test() -{ - enterFunc ('test'); - printBugNumber(BUGNUMBER); - printStatus (summary); - - if (typeof clearInterval == 'undefined') - { - clearInterval = (function () {}); - } - - var obj = new Object(); - obj.test = null; - obj.watch("test", (function(prop, oldval, newval) - { - if(false) - { - var test = newval % oldval; - var func = (function(){clearInterval(myInterval);}); - } - })); - - obj.test = 'null'; - print(obj.test); - - reportCompare(expect, actual, summary); - - exitFunc ('test'); -} diff --git a/js/src/tests/js1_5/extensions/regress-303277.js b/js/src/tests/js1_5/extensions/regress-303277.js deleted file mode 100644 index 319d9a2ed..000000000 --- a/js/src/tests/js1_5/extensions/regress-303277.js +++ /dev/null @@ -1,19 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 303277; -var summary = 'Do not crash with crash with a watchpoint for __proto__ property '; -var actual = 'No Crash'; -var expect = 'No Crash'; - -printBugNumber(BUGNUMBER); -printStatus (summary); - -var o = {}; -o.watch("__proto__", function(){return null;}); -o.__proto__ = null; - -reportCompare(expect, actual, summary); diff --git a/js/src/tests/js1_5/extensions/regress-355339.js b/js/src/tests/js1_5/extensions/regress-355339.js deleted file mode 100644 index 9b15bd742..000000000 --- a/js/src/tests/js1_5/extensions/regress-355339.js +++ /dev/null @@ -1,32 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 355339; -var summary = 'Do not assert: sprop->setter != js_watch_set'; -var actual = ''; -var expect = ''; - - -//----------------------------------------------------------------------------- -test(); -//----------------------------------------------------------------------------- - -function test() -{ - enterFunc ('test'); - printBugNumber(BUGNUMBER); - printStatus (summary); - - expect = actual = 'No Crash'; - o = {}; - o.watch("j", function(a,b,c) { print("*",a,b,c) }); - o.unwatch("j"); - o.watch("j", function(a,b,c) { print("*",a,b,c) }); - - reportCompare(expect, actual, summary); - - exitFunc ('test'); -} diff --git a/js/src/tests/js1_5/extensions/regress-361346.js b/js/src/tests/js1_5/extensions/regress-361346.js deleted file mode 100644 index 297c3b1f2..000000000 --- a/js/src/tests/js1_5/extensions/regress-361346.js +++ /dev/null @@ -1,22 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 361346; -var summary = 'Crash with setter, watch, GC'; -var actual = ''; -var expect = ''; - -printBugNumber(BUGNUMBER); -printStatus (summary); - -expect = actual = 'No Crash'; - -Object.defineProperty(this, "x", { set: new Function, enumerable: true, configurable: true }); -this.watch('x', function(){}); -gc(); -x = {}; - -reportCompare(expect, actual, summary); diff --git a/js/src/tests/js1_5/extensions/regress-361360.js b/js/src/tests/js1_5/extensions/regress-361360.js deleted file mode 100644 index 98e6575d9..000000000 --- a/js/src/tests/js1_5/extensions/regress-361360.js +++ /dev/null @@ -1,32 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 361360; -var summary = 'Do not assert: !caller || caller->pc involving setter and watch'; -var actual = ''; -var expect = ''; - - -//----------------------------------------------------------------------------- -test(); -//----------------------------------------------------------------------------- - -function test() -{ - enterFunc ('test'); - printBugNumber(BUGNUMBER); - printStatus (summary); - - expect = actual = 'No Crash'; - - this.__defineSetter__('x', eval); - this.watch('x', function(){}); - x = 3; - - reportCompare(expect, actual, summary); - - exitFunc ('test'); -} diff --git a/js/src/tests/js1_5/extensions/regress-361552.js b/js/src/tests/js1_5/extensions/regress-361552.js deleted file mode 100644 index eed54e6dd..000000000 --- a/js/src/tests/js1_5/extensions/regress-361552.js +++ /dev/null @@ -1,27 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 361552; -var summary = 'Crash with setter, watch, Script'; -var actual = ''; -var expect = ''; - -printBugNumber(BUGNUMBER); -printStatus (summary); - -expect = actual = 'No Crash'; - -if (typeof Script == 'undefined') -{ - print('Test skipped. Script not defined.'); -} -else -{ - this.__defineSetter__('x', gc); - this.watch('x', new Script('')); - x = 3; -} -reportCompare(expect, actual, summary); diff --git a/js/src/tests/js1_5/extensions/regress-361558.js b/js/src/tests/js1_5/extensions/regress-361558.js deleted file mode 100644 index a9a3ae725..000000000 --- a/js/src/tests/js1_5/extensions/regress-361558.js +++ /dev/null @@ -1,19 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 361558; -var summary = 'Do not assert: sprop->setter != js_watch_set'; -var actual = ''; -var expect = ''; - -printBugNumber(BUGNUMBER); -printStatus (summary); - -expect = actual = 'No Crash'; - -({}.__proto__.watch('x', print)); ({}.watch('x', print)); - -reportCompare(expect, actual, summary); diff --git a/js/src/tests/js1_5/extensions/regress-361571.js b/js/src/tests/js1_5/extensions/regress-361571.js deleted file mode 100644 index bf89d794b..000000000 --- a/js/src/tests/js1_5/extensions/regress-361571.js +++ /dev/null @@ -1,38 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 361571; -var summary = 'Do not assert: fp->scopeChain == parent'; -var actual = 'No Crash'; -var expect = 'No Crash'; - -//----------------------------------------------------------------------------- -test(); -//----------------------------------------------------------------------------- - -function test() -{ - enterFunc ('test'); - printBugNumber(BUGNUMBER); - printStatus (summary); - - try - { - o = {}; - o.__defineSetter__('y', eval); - o.watch('y', function () { return "";}); - o.y = 1; - } - catch(ex) - { - printStatus('Note eval can no longer be called directly'); - expect = 'EvalError: function eval must be called directly, and not by way of a function of another name'; - actual = ex + ''; - } - reportCompare(expect, actual, summary); - - exitFunc ('test'); -} diff --git a/js/src/tests/js1_5/extensions/regress-361856.js b/js/src/tests/js1_5/extensions/regress-361856.js deleted file mode 100644 index e7e2f675b..000000000 --- a/js/src/tests/js1_5/extensions/regress-361856.js +++ /dev/null @@ -1,35 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 361856; -var summary = 'Do not assert: overwriting @ js_AddScopeProperty'; -var actual = ''; -var expect = ''; - - -//----------------------------------------------------------------------------- -test(); -//----------------------------------------------------------------------------- - -function test() -{ - enterFunc ('test'); - printBugNumber(BUGNUMBER); - printStatus (summary); - - function testit() { - var obj = {}; - obj.watch("foo", function(){}); - delete obj.foo; - obj = null; - gc(); - } - testit(); - - reportCompare(expect, actual, summary); - - exitFunc ('test'); -} diff --git a/js/src/tests/js1_5/extensions/regress-361964.js b/js/src/tests/js1_5/extensions/regress-361964.js deleted file mode 100644 index fcb8bba01..000000000 --- a/js/src/tests/js1_5/extensions/regress-361964.js +++ /dev/null @@ -1,54 +0,0 @@ -// |reftest| skip -- slow, alert not dismissed, now busted by harness -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 361964; -var summary = 'Crash [@ MarkGCThingChildren] involving watch and setter'; -var actual = 'No Crash'; -var expect = 'No Crash'; - - -//----------------------------------------------------------------------------- -test(); -//----------------------------------------------------------------------------- - -function test() -{ - enterFunc ('test'); - printBugNumber(BUGNUMBER); - printStatus (summary); - - var doc; - if (typeof document == 'undefined') - { - doc = {}; - } - else - { - doc = document; - } - - if (typeof alert == 'undefined') - { - alert = print; - } - -// Crash: - doc.watch("title", function(a,b,c,d) { - return { toString : function() { alert(1); } }; - }); - doc.title = "xxx"; - -// No crash: - doc.watch("title", function() { - return { toString : function() { alert(1); } }; - }); - doc.title = "xxx"; - - reportCompare(expect, actual, summary); - - exitFunc ('test'); -} diff --git a/js/src/tests/js1_5/extensions/regress-385134.js b/js/src/tests/js1_5/extensions/regress-385134.js deleted file mode 100644 index 041f4d6e7..000000000 --- a/js/src/tests/js1_5/extensions/regress-385134.js +++ /dev/null @@ -1,38 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 385134; -var summary = 'Do not crash with setter, watch, uneval'; -var actual = 'No Crash'; -var expect = 'No Crash'; - - -//----------------------------------------------------------------------------- -test(); -//----------------------------------------------------------------------------- - -function test() -{ - enterFunc ('test'); - printBugNumber(BUGNUMBER); - printStatus (summary); - - if (typeof this.__defineSetter__ != 'undefined' && - typeof this.watch != 'undefined' && - typeof uneval != 'undefined') - { - try { - this.__defineSetter__(0, function(){}); - } catch (exc) { - // In the browser, this fails. Ignore the error. - } - this.watch(0, function(){}); - uneval(this); - } - reportCompare(expect, actual, summary); - - exitFunc ('test'); -} diff --git a/js/src/tests/js1_5/extensions/regress-385393-09.js b/js/src/tests/js1_5/extensions/regress-385393-09.js deleted file mode 100644 index 42834824a..000000000 --- a/js/src/tests/js1_5/extensions/regress-385393-09.js +++ /dev/null @@ -1,18 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - - -//----------------------------------------------------------------------------- -var BUGNUMBER = 385393; -var summary = 'Regression test for bug 385393'; -var actual = 'No Crash'; -var expect = 'No Crash'; - -printBugNumber(BUGNUMBER); -printStatus (summary); - -eval("this.__defineSetter__('x', gc); this.watch('x', [].slice); x = 1;"); - -reportCompare(expect, actual, summary); diff --git a/js/src/tests/js1_5/extensions/regress-390597.js b/js/src/tests/js1_5/extensions/regress-390597.js deleted file mode 100644 index 9f8596adc..000000000 --- a/js/src/tests/js1_5/extensions/regress-390597.js +++ /dev/null @@ -1,42 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 390597; -var summary = 'watch point + eval-as-setter allows access to dead JSStackFrame'; -var actual = 'No Crash'; -var expect = 'No Crash'; - - -//----------------------------------------------------------------------------- -test(); -//----------------------------------------------------------------------------- - -function test() -{ - enterFunc ('test'); - printBugNumber(BUGNUMBER); - printStatus (summary); - - function exploit() { - try - { - var obj = this, args = null; - obj.__defineSetter__("evil", eval); - obj.watch("evil", function() { return "args = arguments;"; }); - obj.evil = null; - eval("print(args[0]);"); - } - catch(ex) - { - print('Caught ' + ex); - } - } - exploit(); - - reportCompare(expect, actual, summary); - - exitFunc ('test'); -} diff --git a/js/src/tests/js1_5/extensions/regress-420612.js b/js/src/tests/js1_5/extensions/regress-420612.js deleted file mode 100644 index a4491095e..000000000 --- a/js/src/tests/js1_5/extensions/regress-420612.js +++ /dev/null @@ -1,21 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 420612; -var summary = 'Do not assert: obj == pobj'; -var actual = 'No Crash'; -var expect = 'No Crash'; - -printBugNumber(BUGNUMBER); -printStatus (summary); - -var obj = Object.create([]); -obj.unwatch("x"); - -if (typeof reportCompare === "function") - reportCompare(true, true); - -print("Tests complete"); diff --git a/js/src/tests/js1_5/extensions/regress-435345-01.js b/js/src/tests/js1_5/extensions/regress-435345-01.js deleted file mode 100644 index 28beab473..000000000 --- a/js/src/tests/js1_5/extensions/regress-435345-01.js +++ /dev/null @@ -1,100 +0,0 @@ -// |reftest| fails -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 435345; -var summary = 'Watch the length property of arrays'; -var actual = ''; -var expect = ''; - -// see http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Object:watch - -//----------------------------------------------------------------------------- -test(); -//----------------------------------------------------------------------------- - -function test() -{ - enterFunc ('test'); - printBugNumber(BUGNUMBER); - printStatus (summary); - - var arr; - - try - { - expect = 'watcher: propname=length, oldval=0, newval=1; '; - actual = ''; - arr = []; - arr.watch('length', watcher); - arr[0] = '0'; - } - catch(ex) - { - actual = ex + ''; - } - reportCompare(expect, actual, summary + ': 1'); - - try - { - expect = 'watcher: propname=length, oldval=1, newval=2; ' + - 'watcher: propname=length, oldval=2, newval=2; '; - actual = ''; - arr.push(5); - } - catch(ex) - { - actual = ex + ''; - } - reportCompare(expect, actual, summary + ': 2'); - - try - { - expect = 'watcher: propname=length, oldval=2, newval=1; '; - actual = ''; - arr.pop(); - } - catch(ex) - { - actual = ex + ''; - } - reportCompare(expect, actual, summary + ': 3'); - - try - { - expect = 'watcher: propname=length, oldval=1, newval=2; '; - actual = ''; - arr.length++; - } - catch(ex) - { - actual = ex + ''; - } - reportCompare(expect, actual, summary + ': 4'); - - try - { - expect = 'watcher: propname=length, oldval=2, newval=5; '; - actual = ''; - arr.length = 5; - } - catch(ex) - { - actual = ex + ''; - } - reportCompare(expect, actual, summary + ': 5'); - - exitFunc ('test'); -} - -function watcher(propname, oldval, newval) -{ - actual += 'watcher: propname=' + propname + ', oldval=' + oldval + - ', newval=' + newval + '; '; - - return newval; -} - diff --git a/js/src/tests/js1_5/extensions/regress-454040.js b/js/src/tests/js1_5/extensions/regress-454040.js deleted file mode 100644 index 63b5e1488..000000000 --- a/js/src/tests/js1_5/extensions/regress-454040.js +++ /dev/null @@ -1,25 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 454040; -var summary = 'Do not crash @ js_ComputeFilename'; -var actual = ''; -var expect = ''; - -printBugNumber(BUGNUMBER); -printStatus (summary); - -try -{ - this.__defineGetter__("x", Function); - this.__defineSetter__("x", Function); - this.watch("x", x.__proto__); - x = 1; -} -catch(ex) -{ -} -reportCompare(expect, actual, summary); diff --git a/js/src/tests/js1_5/extensions/regress-454142.js b/js/src/tests/js1_5/extensions/regress-454142.js deleted file mode 100644 index 05f331278..000000000 --- a/js/src/tests/js1_5/extensions/regress-454142.js +++ /dev/null @@ -1,30 +0,0 @@ -// |reftest| skip-if(Android) -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 454142; -var summary = 'Do not crash with gczeal, setter, watch'; -var actual = ''; -var expect = ''; - -printBugNumber(BUGNUMBER); -printStatus (summary); - -this.watch("x", function(){}); -delete x; -if (typeof gczeal == 'function') -{ - gczeal(2); -} - -this.__defineSetter__("x", function(){}); - -if (typeof gczeal == 'function') -{ - gczeal(0); -} - -reportCompare(expect, actual, summary); diff --git a/js/src/tests/js1_5/extensions/regress-455413.js b/js/src/tests/js1_5/extensions/regress-455413.js deleted file mode 100644 index d00ab135b..000000000 --- a/js/src/tests/js1_5/extensions/regress-455413.js +++ /dev/null @@ -1,24 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 455413; -var summary = 'Do not assert with JIT: (m != JSVAL_INT) || isInt32(*vp)'; -var actual = 'No Crash'; -var expect = 'No Crash'; - - -//----------------------------------------------------------------------------- -test(); -//----------------------------------------------------------------------------- - -printBugNumber(BUGNUMBER); -printStatus (summary); - - -this.watch('x', Math.pow); (function() { for(var j=0;j<4;++j){x=1;} })(); - - -reportCompare(expect, actual, summary); diff --git a/js/src/tests/js1_5/extensions/regress-465145.js b/js/src/tests/js1_5/extensions/regress-465145.js deleted file mode 100644 index 84f81703b..000000000 --- a/js/src/tests/js1_5/extensions/regress-465145.js +++ /dev/null @@ -1,24 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 465145; -var summary = 'Do not crash with watched defined setter'; -var actual = ''; -var expect = ''; - -printBugNumber(BUGNUMBER); -printStatus (summary); - - -this.__defineSetter__("x", function(){}); -this.watch("x", function(){}); -y = this; -for (var z = 0; z < 2; ++z) { x = y }; -this.__defineSetter__("x", function(){}); -for (var z = 0; z < 2; ++z) { x = y }; - - -reportCompare(expect, actual, summary); diff --git a/js/src/tests/js1_5/extensions/regress-472787.js b/js/src/tests/js1_5/extensions/regress-472787.js deleted file mode 100755 index d3196f05f..000000000 --- a/js/src/tests/js1_5/extensions/regress-472787.js +++ /dev/null @@ -1,31 +0,0 @@ -// |reftest| skip-if(Android) -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 472787; -var summary = 'Do not hang with gczeal, watch and concat'; -var actual = ''; -var expect = ''; - -printBugNumber(BUGNUMBER); -printStatus (summary); - -this.__defineSetter__("x", Math.sin); -this.watch("x", '' .concat); - -if (typeof gczeal == 'function') -{ - gczeal(2); -} - -x = 1; - -if (typeof gczeal == 'function') -{ - gczeal(0); -} - -reportCompare(expect, actual, summary); diff --git a/js/src/tests/js1_5/extensions/regress-488995.js b/js/src/tests/js1_5/extensions/regress-488995.js deleted file mode 100644 index f7abbe439..000000000 --- a/js/src/tests/js1_5/extensions/regress-488995.js +++ /dev/null @@ -1,46 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 488995; -var summary = 'Do not crash with watch, __defineSetter__ on svg'; -var actual = ''; -var expect = ''; - - -//----------------------------------------------------------------------------- -test(); -//----------------------------------------------------------------------------- - -function test() -{ - enterFunc ('test'); - printBugNumber(BUGNUMBER); - printStatus (summary); - - if (typeof document == 'undefined') - { - print('Test skipped: requires browser.'); - } - else - { - try - { - var o=document.createElementNS("http://www.w3.org/2000/svg", "svg"); - var p=o.y; - p.watch('animVal', function(id, oldvar, newval) {} ); - p.type='xxx'; - p.__defineSetter__('animVal', function() {}); - p.animVal=0; - } - catch(ex) - { - } - } - - reportCompare(expect, actual, summary); - - exitFunc ('test'); -} diff --git a/js/src/tests/js1_6/Regress/regress-476655.js b/js/src/tests/js1_6/Regress/regress-476655.js deleted file mode 100644 index 9077ba3a0..000000000 --- a/js/src/tests/js1_6/Regress/regress-476655.js +++ /dev/null @@ -1,40 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 476655; -var summary = 'TM: Do not assert: count <= (size_t) (fp->regs->sp - StackBase(fp) - depth)'; -var actual = ''; -var expect = ''; - - -//----------------------------------------------------------------------------- -test(); -//----------------------------------------------------------------------------- - -function test() -{ - enterFunc ('test'); - printBugNumber(BUGNUMBER); - printStatus (summary); - - - try - { - eval( - "(function (){ for (var y in this) {} })();" + - "[''.watch(\"\", function(){}) for each (x in ['', '', eval, '', '']) if " + - "(x)].map(Function)" - ); - } - catch(ex) - { - } - - - reportCompare(expect, actual, summary); - - exitFunc ('test'); -} diff --git a/js/src/tests/js1_6/extensions/regress-457521.js b/js/src/tests/js1_6/extensions/regress-457521.js deleted file mode 100644 index 6f4fbda50..000000000 --- a/js/src/tests/js1_6/extensions/regress-457521.js +++ /dev/null @@ -1,24 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 457521; -var summary = 'Do not crash @ js_DecompileValueGenerator'; -var actual = ''; -var expect = ''; - -printBugNumber(BUGNUMBER); -printStatus (summary); - -try -{ - this.__defineSetter__("x", [,,,].map); - this.watch("x", (new Function("var y, eval"))); - x = true; -} -catch(ex) -{ -} -reportCompare(expect, actual, summary); diff --git a/js/src/tests/js1_6/extensions/regress-479567.js b/js/src/tests/js1_6/extensions/regress-479567.js deleted file mode 100644 index 6f3525130..000000000 --- a/js/src/tests/js1_6/extensions/regress-479567.js +++ /dev/null @@ -1,33 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 479567; -var summary = 'Do not assert: thing'; -var actual = ''; -var expect = ''; - -printBugNumber(BUGNUMBER); -printStatus (summary); - - -function f() -{ - (eval("(function(){for each (y in [false, false, false]);});"))(); -} - -try -{ - this.__defineGetter__("x", gc); - uneval(this.watch("y", this.toSource)) - f(); - throw x; -} -catch(ex) -{ -} - - -reportCompare(expect, actual, summary); diff --git a/js/src/tests/js1_7/extensions/regress-453955.js b/js/src/tests/js1_7/extensions/regress-453955.js deleted file mode 100644 index 454f712f3..000000000 --- a/js/src/tests/js1_7/extensions/regress-453955.js +++ /dev/null @@ -1,31 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 453955; -var summary = 'Do not assert: sprop->setter != js_watch_set || pobj != obj'; -var actual = ''; -var expect = ''; - - -//----------------------------------------------------------------------------- -test(); -//----------------------------------------------------------------------------- - -function test() -{ - enterFunc ('test'); - printBugNumber(BUGNUMBER); - printStatus (summary); - - for (var z = 0; z < 2; ++z) - { - [].filter.watch("9", function(y) { yield y; }); - } - - reportCompare(expect, actual, summary); - - exitFunc ('test'); -} diff --git a/js/src/tests/js1_7/extensions/regress-473282.js b/js/src/tests/js1_7/extensions/regress-473282.js deleted file mode 100644 index c50ac9234..000000000 --- a/js/src/tests/js1_7/extensions/regress-473282.js +++ /dev/null @@ -1,20 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 473282; -var summary = 'Do not assert: thing'; -var actual = ''; -var expect = ''; - -printBugNumber(BUGNUMBER); -printStatus (summary); - -this.watch("b", "".substring); -this.__defineGetter__("a", gc); -for each (b in [this, null, null]); -a; - -reportCompare(expect, actual, summary); diff --git a/js/src/tests/js1_7/regress/regress-385133-01.js b/js/src/tests/js1_7/regress/regress-385133-01.js deleted file mode 100644 index 03b09f535..000000000 --- a/js/src/tests/js1_7/regress/regress-385133-01.js +++ /dev/null @@ -1,37 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 385133; -var summary = 'Do not crash due to recursion with watch, setter, delete, generator'; -var actual = 'No Crash'; -var expect = 'No Crash'; - - -//----------------------------------------------------------------------------- -test(); -//----------------------------------------------------------------------------- - -function test() -{ - enterFunc ('test'); - printBugNumber(BUGNUMBER); - printStatus (summary); - - try - { - Object.defineProperty(this, "x", { set: {}.watch, enumerable: true, configurable: true }); - this.watch('x', 'foo'.split); - delete x; - function g(){ x = 1; yield; } - for (i in g()) { } - } - catch(ex) - { - } - reportCompare(expect, actual, summary); - - exitFunc ('test'); -} diff --git a/js/src/tests/js1_8/extensions/regress-394709.js b/js/src/tests/js1_8/extensions/regress-394709.js deleted file mode 100644 index d04d8832f..000000000 --- a/js/src/tests/js1_8/extensions/regress-394709.js +++ /dev/null @@ -1,51 +0,0 @@ -// |reftest| skip-if(!xulRuntime.shell) -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 394709; -var summary = 'Do not leak with object.watch and closure'; -var actual = 'No Leak'; -var expect = 'No Leak'; - -//----------------------------------------------------------------------------- -test(); -//----------------------------------------------------------------------------- - -function test() -{ - enterFunc ('test'); - printBugNumber(BUGNUMBER); - printStatus (summary); - - assertEq(finalizeCount(), 0, "invalid initial state"); - - runtest(); - gc(); - assertEq(finalizeCount(), 1, "leaked"); - - runtest(); - gc(); - assertEq(finalizeCount(), 2, "leaked"); - - runtest(); - gc(); - assertEq(finalizeCount(), 3, "leaked"); - - - function runtest () { - var obj = { b: makeFinalizeObserver() }; - obj.watch('b', watcher); - - function watcher(id, old, value) { - ++obj.n; - return value; - } - } - - reportCompare(expect, actual, summary); - - exitFunc ('test'); -} diff --git a/js/src/tests/js1_8/extensions/regress-481989.js b/js/src/tests/js1_8/extensions/regress-481989.js deleted file mode 100644 index 36efb7567..000000000 --- a/js/src/tests/js1_8/extensions/regress-481989.js +++ /dev/null @@ -1,19 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 481989; -var summary = 'TM: Do not assert: SPROP_HAS_STUB_SETTER(sprop)'; -var actual = ''; -var expect = ''; - -printBugNumber(BUGNUMBER); -printStatus (summary); - - -y = this.watch("x", function(){}); for each (let y in ['', '']) x = y; - - -reportCompare(expect, actual, summary); diff --git a/js/src/tests/js1_8_1/extensions/regress-452498-193.js b/js/src/tests/js1_8_1/extensions/regress-452498-193.js deleted file mode 100644 index 1397bf4bb..000000000 --- a/js/src/tests/js1_8_1/extensions/regress-452498-193.js +++ /dev/null @@ -1,34 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 452498; -var summary = 'TM: upvar2 regression tests'; -var actual = ''; -var expect = ''; - -//------- Comment #193 From Gary Kwong - -//----------------------------------------------------------------------------- -test(); -//----------------------------------------------------------------------------- - -function test() -{ - enterFunc ('test'); - printBugNumber(BUGNUMBER); - printStatus (summary); - -// Assertion failure: afunbox->parent, at ../jsparse.cpp:1912 - - this.x = undefined; - this.watch("x", Function); - NaN = uneval({ get \u3056 (){ return undefined } }); - x+=NaN; - - reportCompare(expect, actual, summary); - - exitFunc ('test'); -} diff --git a/js/src/tests/js1_8_1/extensions/regress-452498-196.js b/js/src/tests/js1_8_1/extensions/regress-452498-196.js index 69d5a3586..5b9191199 100644 --- a/js/src/tests/js1_8_1/extensions/regress-452498-196.js +++ b/js/src/tests/js1_8_1/extensions/regress-452498-196.js @@ -21,15 +21,6 @@ function test() printBugNumber(BUGNUMBER); printStatus (summary); -// Assertion failure: localKind == JSLOCAL_VAR || localKind == JSLOCAL_CONST, at ../jsfun.cpp:916 - - this.x = undefined; - this.watch("x", Function); - NaN = uneval({ get \u3056 (){ return undefined } }); - x+=NaN; - - reportCompare(expect, actual, summary + ': 1'); - // Assertion failure: lexdep->isLet(), at ../jsparse.cpp:1900 (function (){ diff --git a/js/src/tests/js1_8_1/extensions/regress-520572.js b/js/src/tests/js1_8_1/extensions/regress-520572.js deleted file mode 100644 index 97f00029a..000000000 --- a/js/src/tests/js1_8_1/extensions/regress-520572.js +++ /dev/null @@ -1,41 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 4 -*- */ -/* - * Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/licenses/publicdomain/ - * Contributor: Blake Kaplan - */ - -//----------------------------------------------------------------------------- -var BUGNUMBER = 520572; -var summary = 'watch should innerize the object being watched'; -var actual = 0; -var expect = 2; - - -//----------------------------------------------------------------------------- -test(); -//----------------------------------------------------------------------------- - -function test() -{ - enterFunc ('test'); - printBugNumber(BUGNUMBER); - printStatus (summary); - - if ("evalcx" in this) { - // shell - let s = evalcx("lazy"); - s.n = 0; - evalcx('this.watch("x", function(){ n++; }); this.x = 4; x = 6', s); - actual = s.n; - reportCompare(expect, actual, summary); - } else { - // browser - this.watch('x', function(){ actual++; }); - this.x = 4; - x = 6; - reportCompare(expect, actual, summary); - } - - exitFunc ('test'); -} diff --git a/js/src/tests/js1_8_1/regress/regress-452498-160.js b/js/src/tests/js1_8_1/regress/regress-452498-160.js index 6498a0b5a..305b41795 100644 --- a/js/src/tests/js1_8_1/regress/regress-452498-160.js +++ b/js/src/tests/js1_8_1/regress/regress-452498-160.js @@ -21,11 +21,6 @@ function test() printBugNumber(BUGNUMBER); printStatus (summary); -// crash [@ js_Interpret] - (eval("(function(){ this.watch(\"x\", function () { new function ()y } ); const y = undefined });"))(); - x = NaN; - reportCompare(expect, actual, summary + ': 2'); - // Assertion failure: JOF_OPTYPE(op) == JOF_ATOM, at ../jsemit.cpp:5916 ({ set z(v){}, set y(v)--x, set w(v)--w }); reportCompare(expect, actual, summary + ': 3'); diff --git a/js/src/tests/js1_8_5/extensions/regress-604781-1.js b/js/src/tests/js1_8_5/extensions/regress-604781-1.js deleted file mode 100644 index a7c43f95d..000000000 --- a/js/src/tests/js1_8_5/extensions/regress-604781-1.js +++ /dev/null @@ -1,24 +0,0 @@ -// Any copyright is dedicated to the Public Domain. -// http://creativecommons.org/licenses/publicdomain/ - -var watcherCount, setterCount; -function watcher(id, oldval, newval) { watcherCount++; return newval; } -function setter(newval) { setterCount++; } - -var p = { set x(v) { setter(v); } }; -p.watch('x', watcher); - -watcherCount = setterCount = 0; -p.x = 2; -assertEq(setterCount, 1); -assertEq(watcherCount, 1); - -var o = Object.defineProperty({}, 'x', { set:setter, enumerable:true, configurable:true }); -o.watch('x', watcher); - -watcherCount = setterCount = 0; -o.x = 2; -assertEq(setterCount, 1); -assertEq(watcherCount, 1); - -reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/js1_8_5/extensions/regress-604781-2.js b/js/src/tests/js1_8_5/extensions/regress-604781-2.js deleted file mode 100644 index 7aba4a274..000000000 --- a/js/src/tests/js1_8_5/extensions/regress-604781-2.js +++ /dev/null @@ -1,13 +0,0 @@ -// Any copyright is dedicated to the Public Domain. -// http://creativecommons.org/licenses/publicdomain/ - -var log; -function watcher(id, old, newval) { log += 'watcher'; return newval; } -var o = { set x(v) { log += 'setter'; } }; -o.watch('x', watcher); -Object.defineProperty(o, 'x', {value: 3, writable: true}); -log = ''; -o.x = 3; -assertEq(log, 'watcher'); - -reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/js1_8_5/extensions/regress-627984-1.js b/js/src/tests/js1_8_5/extensions/regress-627984-1.js deleted file mode 100644 index a3726630a..000000000 --- a/js/src/tests/js1_8_5/extensions/regress-627984-1.js +++ /dev/null @@ -1,16 +0,0 @@ -// Any copyright is dedicated to the Public Domain. -// http://creativecommons.org/licenses/publicdomain/ - -// See bug 627984, comment 17, item 1. -var obj; -var methods = []; -for (var i = 0; i < 2; i++) { - obj = {m: function () { return this.x; }}; - obj.watch("m", function (id, oldval, newval) { methods[i] = oldval; }); - obj.m = 0; -} -assertEq(typeof methods[0], "function"); -assertEq(typeof methods[1], "function"); -assertEq(methods[0] !== methods[1], true); - -reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/js1_8_5/extensions/regress-627984-2.js b/js/src/tests/js1_8_5/extensions/regress-627984-2.js deleted file mode 100644 index c4f1b508c..000000000 --- a/js/src/tests/js1_8_5/extensions/regress-627984-2.js +++ /dev/null @@ -1,15 +0,0 @@ -// Any copyright is dedicated to the Public Domain. -// http://creativecommons.org/licenses/publicdomain/ - -// See bug 627984, comment 17, item 2. -var obj = {}; -var x; -obj.watch("m", function (id, oldval, newval) { - x = this.m; - return newval; - }); -delete obj.m; -obj.m = function () { return this.method; }; -obj.m = 2; - -reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/js1_8_5/extensions/regress-627984-3.js b/js/src/tests/js1_8_5/extensions/regress-627984-3.js deleted file mode 100644 index cbe4e10fa..000000000 --- a/js/src/tests/js1_8_5/extensions/regress-627984-3.js +++ /dev/null @@ -1,14 +0,0 @@ -// Any copyright is dedicated to the Public Domain. -// http://creativecommons.org/licenses/publicdomain/ - -// Don't write string value to method slot. -// See bug 627984, comment 17, item 2. -var obj = {}; -obj.watch("m", function (id, oldval, newval) { - return 'ok'; - }); -delete obj.m; -obj.m = function () { return this.x; }; -assertEq(obj.m, 'ok'); - -reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/js1_8_5/extensions/regress-627984-4.js b/js/src/tests/js1_8_5/extensions/regress-627984-4.js deleted file mode 100644 index bbc017ffb..000000000 --- a/js/src/tests/js1_8_5/extensions/regress-627984-4.js +++ /dev/null @@ -1,15 +0,0 @@ -// Any copyright is dedicated to the Public Domain. -// http://creativecommons.org/licenses/publicdomain/ - -// See bug 627984, comment 17, item 3. -var obj = {}; -obj.watch("m", function (id, oldval, newval) { - delete obj.m; - obj.m = function () {}; - return newval; - }); -delete obj.m; -obj.m = 1; -assertEq(obj.m, 1); - -reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/js1_8_5/extensions/regress-627984-5.js b/js/src/tests/js1_8_5/extensions/regress-627984-5.js deleted file mode 100644 index 704d8421c..000000000 --- a/js/src/tests/js1_8_5/extensions/regress-627984-5.js +++ /dev/null @@ -1,13 +0,0 @@ -// Any copyright is dedicated to the Public Domain. -// http://creativecommons.org/licenses/publicdomain/ - -// Bug 627984 comment 11. -var o = ({}); -o.p = function() {}; -o.watch('p', function() { }); -o.q = function() {} -delete o.p; -o.p = function() {}; -assertEq(o.p, void 0); - -reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/js1_8_5/extensions/regress-627984-6.js b/js/src/tests/js1_8_5/extensions/regress-627984-6.js deleted file mode 100644 index cb1a0fca9..000000000 --- a/js/src/tests/js1_8_5/extensions/regress-627984-6.js +++ /dev/null @@ -1,15 +0,0 @@ -// Any copyright is dedicated to the Public Domain. -// http://creativecommons.org/licenses/publicdomain/ - -// Bug 627984 description. -var o = Array; -o.p = function() {}; -o.watch('p', function() { }); -for(var x in o) { - o[x]; -} -delete o.p; -o.p = function() {}; -assertEq(o.p, void 0); - -reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/js1_8_5/extensions/regress-627984-7.js b/js/src/tests/js1_8_5/extensions/regress-627984-7.js deleted file mode 100644 index b13a0e912..000000000 --- a/js/src/tests/js1_8_5/extensions/regress-627984-7.js +++ /dev/null @@ -1,9 +0,0 @@ -// Any copyright is dedicated to the Public Domain. -// http://creativecommons.org/licenses/publicdomain/ - -// See bug 627984 comment 20. -var obj = {m: function () {}}; -obj.watch("m", function () { throw 'FAIL'; }); -var f = obj.m; // don't call the watchpoint - -reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/js1_8_5/extensions/regress-631723.js b/js/src/tests/js1_8_5/extensions/regress-631723.js deleted file mode 100644 index f7c755603..000000000 --- a/js/src/tests/js1_8_5/extensions/regress-631723.js +++ /dev/null @@ -1,10 +0,0 @@ -// Any copyright is dedicated to the Public Domain. -// http://creativecommons.org/licenses/publicdomain/ - -var o = {a:1, b:2}; -o.watch("p", function() { return 13; }); -delete o.p; -o.p = 0; -assertEq(o.p, 13); - -reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/js1_8_5/extensions/regress-636697.js b/js/src/tests/js1_8_5/extensions/regress-636697.js deleted file mode 100644 index 6b3b1de37..000000000 --- a/js/src/tests/js1_8_5/extensions/regress-636697.js +++ /dev/null @@ -1,11 +0,0 @@ -// Any copyright is dedicated to the Public Domain. -// http://creativecommons.org/licenses/publicdomain/ - -var a = {set p(x) {}}; -a.watch('p', function () {}); -var b = Object.create(a); -b.watch('p', function () {}); -delete b.p; -b.p = 0; - -reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/js1_8_5/extensions/regress-637985.js b/js/src/tests/js1_8_5/extensions/regress-637985.js deleted file mode 100644 index 305bfc820..000000000 --- a/js/src/tests/js1_8_5/extensions/regress-637985.js +++ /dev/null @@ -1,8 +0,0 @@ -// Any copyright is dedicated to the Public Domain. -// http://creativecommons.org/licenses/publicdomain/ - -var obj = {}; -obj.watch(-1, function(){}); -obj.unwatch("-1"); // don't assert - -reportCompare(0, 0, 'ok'); \ No newline at end of file diff --git a/js/src/tests/js1_8_5/extensions/regress-691746.js b/js/src/tests/js1_8_5/extensions/regress-691746.js deleted file mode 100644 index 26f732d07..000000000 --- a/js/src/tests/js1_8_5/extensions/regress-691746.js +++ /dev/null @@ -1,11 +0,0 @@ -// Any copyright is dedicated to the Public Domain. -// http://creativecommons.org/licenses/publicdomain/ - -var obj = {}; -try { - obj.watch(QName(), function () {}); -} catch (exc) { -} -gc(); - -reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/js1_8_5/extensions/watch-undefined-setter.js b/js/src/tests/js1_8_5/extensions/watch-undefined-setter.js deleted file mode 100644 index 92608de0e..000000000 --- a/js/src/tests/js1_8_5/extensions/watch-undefined-setter.js +++ /dev/null @@ -1,19 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* - * Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/licenses/publicdomain/ - * Contributor: - * Gary Kwong - */ - -var gTestfile = 'watch-undefined-setter.js'; -//----------------------------------------------------------------------------- -var BUGNUMBER = 560277; -var summary = - 'Crash [@ JSObject::getParent] or [@ js_WrapWatchedSetter] or ' + - '[@ js_GetClassPrototype]'; - -this.watch("x", function() { }); -Object.defineProperty(this, "x", { set: undefined, configurable: true }); - -reportCompare(true, true); diff --git a/js/src/tests/js1_8_5/regress/regress-533876.js b/js/src/tests/js1_8_5/regress/regress-533876.js deleted file mode 100644 index e44bc8a4f..000000000 --- a/js/src/tests/js1_8_5/regress/regress-533876.js +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/licenses/publicdomain/ - * Contributors: Gary Kwong and Jason Orendorff - */ - -var savedEval = eval; -var x = [0]; -eval(); - -x.__proto__ = this; // x has non-dictionary scope -try { - DIE; -} catch(e) { -} - -delete eval; // force dictionary scope for global -gc(); -eval = savedEval; -var f = eval("(function () { return /x/; })"); -x.watch('x', f); // clone property from global to x, including SPROP_IN_DICTIONARY flag - -reportCompare("ok", "ok", "bug 533876"); diff --git a/js/src/tests/js1_8_5/regress/regress-548276.js b/js/src/tests/js1_8_5/regress/regress-548276.js deleted file mode 100644 index 5e306eba1..000000000 --- a/js/src/tests/js1_8_5/regress/regress-548276.js +++ /dev/null @@ -1,10 +0,0 @@ -// |reftest| skip -/* - * Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/licenses/publicdomain/ - * Contributors: Gary Kwong and Jason Orendorff - */ -var obj = {}; -obj.__defineSetter__("x", function() {}); -obj.watch("x", function() {}); -obj.__defineSetter__("x", /a/); diff --git a/js/src/tests/js1_8_5/regress/regress-584648.js b/js/src/tests/js1_8_5/regress/regress-584648.js deleted file mode 100644 index a1635ea51..000000000 --- a/js/src/tests/js1_8_5/regress/regress-584648.js +++ /dev/null @@ -1,16 +0,0 @@ -// |reftest| skip -// Any copyright is dedicated to the Public Domain. -// http://creativecommons.org/licenses/publicdomain/ -// Contributors: Gary Kwong -// Jason Orendorff - -// on a non-global object -var x = {}; -x.watch("p", function () { evalcx(''); }); -x.p = 0; - -// on the global -watch("e", (function () { evalcx(''); })); -e = function () {}; - -reportCompare(0, 0, "ok"); diff --git a/js/src/tests/js1_8_5/regress/regress-635195.js b/js/src/tests/js1_8_5/regress/regress-635195.js deleted file mode 100644 index 89980b05a..000000000 --- a/js/src/tests/js1_8_5/regress/regress-635195.js +++ /dev/null @@ -1,8 +0,0 @@ -// Any copyright is dedicated to the Public Domain. -// http://creativecommons.org/licenses/publicdomain/ - -var obj = {set x(v) {}}; -obj.watch("x", function() { delete obj.x; }); -obj.x = "hi"; // don't assert - -reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/js1_8_5/regress/regress-636394.js b/js/src/tests/js1_8_5/regress/regress-636394.js deleted file mode 100644 index d1a249786..000000000 --- a/js/src/tests/js1_8_5/regress/regress-636394.js +++ /dev/null @@ -1,10 +0,0 @@ -// Any copyright is dedicated to the Public Domain. -// http://creativecommons.org/licenses/publicdomain/ - -var a = {p0: function () {}}; -var b = /f/; -b.__proto__ = a; -b.watch("p0", function () {}); -b.p0; - -reportCompare(0, 0, "ok"); -- cgit v1.2.3 From fa473930f424bf17a9e545b601c84dd2e61364e3 Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Mon, 11 Nov 2019 23:37:35 +0100 Subject: Issue #1279 - Implement regular expression lookbehind Based on Tom Schuster's work, with extra minters for unicode. --- js/src/irregexp/NativeRegExpMacroAssembler.cpp | 8 +- js/src/irregexp/NativeRegExpMacroAssembler.h | 7 +- js/src/irregexp/RegExpAST.cpp | 8 +- js/src/irregexp/RegExpAST.h | 33 ++++-- js/src/irregexp/RegExpBytecode.h | 23 ++-- js/src/irregexp/RegExpEngine.cpp | 151 ++++++++++++++++--------- js/src/irregexp/RegExpEngine.h | 31 +++-- js/src/irregexp/RegExpInterpreter.cpp | 74 +++++++++++- js/src/irregexp/RegExpMacroAssembler.cpp | 17 ++- js/src/irregexp/RegExpMacroAssembler.h | 15 +-- js/src/irregexp/RegExpParser.cpp | 130 ++++++++++++++------- js/src/irregexp/RegExpParser.h | 19 +++- 12 files changed, 359 insertions(+), 157 deletions(-) (limited to 'js/src') diff --git a/js/src/irregexp/NativeRegExpMacroAssembler.cpp b/js/src/irregexp/NativeRegExpMacroAssembler.cpp index 0fb507297..e17eecb9b 100644 --- a/js/src/irregexp/NativeRegExpMacroAssembler.cpp +++ b/js/src/irregexp/NativeRegExpMacroAssembler.cpp @@ -582,7 +582,7 @@ NativeRegExpMacroAssembler::CheckAtStart(Label* on_at_start) } void -NativeRegExpMacroAssembler::CheckNotAtStart(Label* on_not_at_start) +NativeRegExpMacroAssembler::CheckNotAtStart(int cp_offset, Label* on_not_at_start) { JitSpew(SPEW_PREFIX "CheckNotAtStart"); @@ -673,7 +673,7 @@ NativeRegExpMacroAssembler::CheckGreedyLoop(Label* on_tos_equals_current_positio } void -NativeRegExpMacroAssembler::CheckNotBackReference(int start_reg, Label* on_no_match) +NativeRegExpMacroAssembler::CheckNotBackReference(int start_reg, bool read_backward, Label* on_no_match) { JitSpew(SPEW_PREFIX "CheckNotBackReference(%d)", start_reg); @@ -744,8 +744,8 @@ NativeRegExpMacroAssembler::CheckNotBackReference(int start_reg, Label* on_no_ma } void -NativeRegExpMacroAssembler::CheckNotBackReferenceIgnoreCase(int start_reg, Label* on_no_match, - bool unicode) +NativeRegExpMacroAssembler::CheckNotBackReferenceIgnoreCase(int start_reg, bool read_backward, + Label* on_no_match, bool unicode) { JitSpew(SPEW_PREFIX "CheckNotBackReferenceIgnoreCase(%d, %d)", start_reg, unicode); diff --git a/js/src/irregexp/NativeRegExpMacroAssembler.h b/js/src/irregexp/NativeRegExpMacroAssembler.h index 7a72e252f..fc582dccf 100644 --- a/js/src/irregexp/NativeRegExpMacroAssembler.h +++ b/js/src/irregexp/NativeRegExpMacroAssembler.h @@ -105,9 +105,10 @@ class MOZ_STACK_CLASS NativeRegExpMacroAssembler final : public RegExpMacroAssem void CheckCharacterGT(char16_t limit, jit::Label* on_greater); void CheckCharacterLT(char16_t limit, jit::Label* on_less); void CheckGreedyLoop(jit::Label* on_tos_equals_current_position); - void CheckNotAtStart(jit::Label* on_not_at_start); - void CheckNotBackReference(int start_reg, jit::Label* on_no_match); - void CheckNotBackReferenceIgnoreCase(int start_reg, jit::Label* on_no_match, bool unicode); + void CheckNotAtStart(int cp_offset, jit::Label* on_not_at_start); + void CheckNotBackReference(int start_reg, bool read_backward, jit::Label* on_no_match); + void CheckNotBackReferenceIgnoreCase(int start_reg, bool read_backward, + jit::Label* on_no_match, bool unicode); void CheckNotCharacter(unsigned c, jit::Label* on_not_equal); void CheckNotCharacterAfterAnd(unsigned c, unsigned and_with, jit::Label* on_not_equal); void CheckNotCharacterAfterMinusAnd(char16_t c, char16_t minus, char16_t and_with, diff --git a/js/src/irregexp/RegExpAST.cpp b/js/src/irregexp/RegExpAST.cpp index 8dfd99057..43867c312 100644 --- a/js/src/irregexp/RegExpAST.cpp +++ b/js/src/irregexp/RegExpAST.cpp @@ -250,16 +250,16 @@ RegExpCapture::CaptureRegisters() } // ---------------------------------------------------------------------------- -// RegExpLookahead +// RegExpLookaround Interval -RegExpLookahead::CaptureRegisters() +RegExpLookaround::CaptureRegisters() { return body()->CaptureRegisters(); } bool -RegExpLookahead::IsAnchoredAtStart() +RegExpLookaround::IsAnchoredAtStart() { - return is_positive() && body()->IsAnchoredAtStart(); + return is_positive() && type() == LOOKAHEAD && body()->IsAnchoredAtStart(); } diff --git a/js/src/irregexp/RegExpAST.h b/js/src/irregexp/RegExpAST.h index 7bda6fc7e..6f59842bc 100644 --- a/js/src/irregexp/RegExpAST.h +++ b/js/src/irregexp/RegExpAST.h @@ -360,6 +360,7 @@ class RegExpCapture : public RegExpTree virtual int min_match() { return body_->min_match(); } virtual int max_match() { return body_->max_match(); } RegExpTree* body() { return body_; } + void set_body(RegExpTree* body) { body_ = body; } int index() { return index_; } static int StartRegister(int index) { return index * 2; } static int EndRegister(int index) { return index * 2 + 1; } @@ -369,25 +370,29 @@ class RegExpCapture : public RegExpTree int index_; }; -class RegExpLookahead : public RegExpTree +class RegExpLookaround : public RegExpTree { public: - RegExpLookahead(RegExpTree* body, - bool is_positive, - int capture_count, - int capture_from) + enum Type { LOOKAHEAD, LOOKBEHIND }; + + RegExpLookaround(RegExpTree* body, + bool is_positive, + int capture_count, + int capture_from, + Type type) : body_(body), is_positive_(is_positive), capture_count_(capture_count), - capture_from_(capture_from) + capture_from_(capture_from), + type_(type) {} virtual void* Accept(RegExpVisitor* visitor, void* data); virtual RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success); - virtual RegExpLookahead* AsLookahead(); + virtual RegExpLookaround* AsLookaround(); virtual Interval CaptureRegisters(); - virtual bool IsLookahead(); + virtual bool IsLookaround(); virtual bool IsAnchoredAtStart(); virtual int min_match() { return 0; } virtual int max_match() { return 0; } @@ -395,12 +400,14 @@ class RegExpLookahead : public RegExpTree bool is_positive() { return is_positive_; } int capture_count() { return capture_count_; } int capture_from() { return capture_from_; } + Type type() { return type_; } private: RegExpTree* body_; bool is_positive_; int capture_count_; int capture_from_; + Type type_; }; typedef InfallibleVector RegExpCaptureVector; @@ -417,8 +424,14 @@ class RegExpBackReference : public RegExpTree RegExpNode* on_success); virtual RegExpBackReference* AsBackReference(); virtual bool IsBackReference(); - virtual int min_match() { return 0; } - virtual int max_match() { return capture_->max_match(); } + virtual int min_match() override { return 0; } + // The capture may not be completely parsed yet, if the reference occurs + // before the capture. In the ordinary case, nothing has been captured yet, + // so the back reference must have the length 0. If the back reference is + // inside a lookbehind, effectively making it a forward reference, we return + virtual int max_match() override { + return capture_->body() ? capture_->max_match() : 0; + } int index() { return capture_->index(); } RegExpCapture* capture() { return capture_; } private: diff --git a/js/src/irregexp/RegExpBytecode.h b/js/src/irregexp/RegExpBytecode.h index f31b78c59..ea3f80b4f 100644 --- a/js/src/irregexp/RegExpBytecode.h +++ b/js/src/irregexp/RegExpBytecode.h @@ -82,16 +82,19 @@ V(CHECK_LT, 35, 8) /* bc8 pad8 uc16 addr32 */ \ V(CHECK_GT, 36, 8) /* bc8 pad8 uc16 addr32 */ \ V(CHECK_NOT_BACK_REF, 37, 8) /* bc8 reg_idx24 addr32 */ \ V(CHECK_NOT_BACK_REF_NO_CASE, 38, 8) /* bc8 reg_idx24 addr32 */ \ -V(CHECK_NOT_REGS_EQUAL, 39, 12) /* bc8 regidx24 reg_idx32 addr32 */ \ -V(CHECK_REGISTER_LT, 40, 12) /* bc8 reg_idx24 value32 addr32 */ \ -V(CHECK_REGISTER_GE, 41, 12) /* bc8 reg_idx24 value32 addr32 */ \ -V(CHECK_REGISTER_EQ_POS, 42, 8) /* bc8 reg_idx24 addr32 */ \ -V(CHECK_AT_START, 43, 8) /* bc8 pad24 addr32 */ \ -V(CHECK_NOT_AT_START, 44, 8) /* bc8 pad24 addr32 */ \ -V(CHECK_GREEDY, 45, 8) /* bc8 pad24 addr32 */ \ -V(ADVANCE_CP_AND_GOTO, 46, 8) /* bc8 offset24 addr32 */ \ -V(SET_CURRENT_POSITION_FROM_END, 47, 4) /* bc8 idx24 */ \ -V(CHECK_NOT_BACK_REF_NO_CASE_UNICODE, 48, 8) /* bc8 reg_idx24 addr32 */ +V(CHECK_NOT_BACK_REF_BACKWARD, 39, 8) /* bc8 reg_idx24 addr32 */ \ +V(CHECK_NOT_BACK_REF_NO_CASE_BACKWARD, 40, 8) /* bc8 reg_idx24 addr32 */ \ +V(CHECK_NOT_REGS_EQUAL, 41, 12) /* bc8 regidx24 reg_idx32 addr32 */ \ +V(CHECK_REGISTER_LT, 42, 12) /* bc8 reg_idx24 value32 addr32 */ \ +V(CHECK_REGISTER_GE, 43, 12) /* bc8 reg_idx24 value32 addr32 */ \ +V(CHECK_REGISTER_EQ_POS, 44, 8) /* bc8 reg_idx24 addr32 */ \ +V(CHECK_AT_START, 45, 8) /* bc8 pad24 addr32 */ \ +V(CHECK_NOT_AT_START, 46, 8) /* bc8 pad24 addr32 */ \ +V(CHECK_GREEDY, 47, 8) /* bc8 pad24 addr32 */ \ +V(ADVANCE_CP_AND_GOTO, 48, 8) /* bc8 offset24 addr32 */ \ +V(SET_CURRENT_POSITION_FROM_END, 49, 4) /* bc8 idx24 */ \ +V(CHECK_NOT_BACK_REF_NO_CASE_UNICODE, 50, 8) /* bc8 reg_idx24 addr32 */ \ +V(CHECK_NOT_BACK_REF_NO_CASE_BACKWARD_UNICODE, 51, 8) /* bc8 reg_idx24 addr32 */ #define DECLARE_BYTECODES(name, code, length) \ static const int BC_##name = code; diff --git a/js/src/irregexp/RegExpEngine.cpp b/js/src/irregexp/RegExpEngine.cpp index 4d691a5dc..62f94c3e7 100644 --- a/js/src/irregexp/RegExpEngine.cpp +++ b/js/src/irregexp/RegExpEngine.cpp @@ -721,6 +721,8 @@ ActionNode::EmptyMatchCheck(int start_register, int TextNode::EatsAtLeast(int still_to_find, int budget, bool not_at_start) { + if (read_backward()) + return 0; int answer = Length(); if (answer >= still_to_find) return answer; @@ -736,8 +738,7 @@ TextNode::EatsAtLeast(int still_to_find, int budget, bool not_at_start) int TextNode::GreedyLoopTextLength() { - TextElement elm = elements()[elements().length() - 1]; - return elm.cp_offset() + elm.length(); + return Length(); } RegExpNode* @@ -887,6 +888,8 @@ AssertionNode::FillInBMInfo(int offset, int budget, BoyerMooreLookahead* bm, boo int BackReferenceNode::EatsAtLeast(int still_to_find, int budget, bool not_at_start) { + if (read_backward()) + return 0; if (budget <= 0) return 0; return on_success()->EatsAtLeast(still_to_find, budget - 1, not_at_start); @@ -1578,6 +1581,9 @@ class irregexp::RegExpCompiler current_expansion_factor_ = value; } + bool read_backward() { return read_backward_; } + void set_read_backward(bool value) { read_backward_ = value; } + JSContext* cx() const { return cx_; } LifoAlloc* alloc() const { return alloc_; } @@ -1595,6 +1601,7 @@ class irregexp::RegExpCompiler bool unicode_; bool reg_exp_too_big_; int current_expansion_factor_; + bool read_backward_; FrequencyCollator frequency_collator_; JSContext* cx_; LifoAlloc* alloc_; @@ -1624,6 +1631,7 @@ RegExpCompiler::RegExpCompiler(JSContext* cx, LifoAlloc* alloc, int capture_coun unicode_(unicode), reg_exp_too_big_(false), current_expansion_factor_(1), + read_backward_(false), frequency_collator_(), cx_(cx), alloc_(alloc) @@ -1747,7 +1755,7 @@ irregexp::CompilePattern(JSContext* cx, RegExpShared* shared, RegExpCompileData* // at the start of input. ChoiceNode* first_step_node = alloc.newInfallible(&alloc, 2); RegExpNode* char_class = - alloc.newInfallible(alloc.newInfallible('*'), loop_node); + alloc.newInfallible(alloc.newInfallible('*'), false, loop_node); first_step_node->AddAlternative(GuardedAlternative(captured_body)); first_step_node->AddAlternative(GuardedAlternative(char_class)); node = first_step_node; @@ -1850,19 +1858,19 @@ RegExpAtom::ToNode(RegExpCompiler* compiler, RegExpNode* on_success) TextElementVector* elms = compiler->alloc()->newInfallible(*compiler->alloc()); elms->append(TextElement::Atom(this)); - return compiler->alloc()->newInfallible(elms, on_success); + return compiler->alloc()->newInfallible(elms, compiler->read_backward(), on_success); } RegExpNode* RegExpText::ToNode(RegExpCompiler* compiler, RegExpNode* on_success) { - return compiler->alloc()->newInfallible(&elements_, on_success); + return compiler->alloc()->newInfallible(&elements_, compiler->read_backward(), on_success); } RegExpNode* RegExpCharacterClass::ToNode(RegExpCompiler* compiler, RegExpNode* on_success) { - return compiler->alloc()->newInfallible(this, on_success); + return compiler->alloc()->newInfallible(this, compiler->read_backward(), on_success); } RegExpNode* @@ -2003,7 +2011,8 @@ RegExpQuantifier::ToNode(int min, alternation->AddAlternative(GuardedAlternative(body->ToNode(compiler, answer))); } answer = alternation; - if (not_at_start) alternation->set_not_at_start(); + if (not_at_start && !compiler->read_backward()) + alternation->set_not_at_start(); } return answer; } @@ -2015,8 +2024,9 @@ RegExpQuantifier::ToNode(int min, int reg_ctr = needs_counter ? compiler->AllocateRegister() : RegExpCompiler::kNoRegister; - LoopChoiceNode* center = alloc->newInfallible(alloc, body->min_match() == 0); - if (not_at_start) + LoopChoiceNode* center = alloc->newInfallible(alloc, body->min_match() == 0, + compiler->read_backward()); + if (not_at_start && !compiler->read_backward()) center->set_not_at_start(); RegExpNode* loop_return = needs_counter ? static_cast(ActionNode::IncrementRegister(reg_ctr, center)) @@ -2092,7 +2102,7 @@ RegExpAssertion::ToNode(RegExpCompiler* compiler, CharacterRange::AddClassEscape(alloc, 'n', newline_ranges); RegExpCharacterClass* newline_atom = alloc->newInfallible('n'); TextNode* newline_matcher = - alloc->newInfallible(newline_atom, + alloc->newInfallible(newline_atom, false, ActionNode::PositiveSubmatchSuccess(stack_pointer_register, position_register, 0, // No captures inside. @@ -2124,6 +2134,7 @@ RegExpBackReference::ToNode(RegExpCompiler* compiler, RegExpNode* on_success) { return compiler->alloc()->newInfallible(RegExpCapture::StartRegister(index()), RegExpCapture::EndRegister(index()), + compiler->read_backward(), on_success); } @@ -2134,7 +2145,7 @@ RegExpEmpty::ToNode(RegExpCompiler* compiler, RegExpNode* on_success) } RegExpNode* -RegExpLookahead::ToNode(RegExpCompiler* compiler, RegExpNode* on_success) +RegExpLookaround::ToNode(RegExpCompiler* compiler, RegExpNode* on_success) { int stack_pointer_register = compiler->AllocateRegister(); int position_register = compiler->AllocateRegister(); @@ -2145,6 +2156,10 @@ RegExpLookahead::ToNode(RegExpCompiler* compiler, RegExpNode* on_success) int register_start = register_of_first_capture + capture_from_ * registers_per_capture; + RegExpNode* result; + bool was_reading_backward = compiler->read_backward(); + compiler->set_read_backward(type() == LOOKBEHIND); + if (is_positive()) { RegExpNode* bodyNode = body()->ToNode(compiler, @@ -2153,37 +2168,39 @@ RegExpLookahead::ToNode(RegExpCompiler* compiler, RegExpNode* on_success) register_count, register_start, on_success)); - return ActionNode::BeginSubmatch(stack_pointer_register, + result = ActionNode::BeginSubmatch(stack_pointer_register, + position_register, + bodyNode); + } else { + // We use a ChoiceNode for a negative lookahead because it has most of + // the characteristics we need. It has the body of the lookahead as its + // first alternative and the expression after the lookahead of the second + // alternative. If the first alternative succeeds then the + // NegativeSubmatchSuccess will unwind the stack including everything the + // choice node set up and backtrack. If the first alternative fails then + // the second alternative is tried, which is exactly the desired result + // for a negative lookahead. The NegativeLookaheadChoiceNode is a special + // ChoiceNode that knows to ignore the first exit when calculating quick + // checks. + LifoAlloc* alloc = compiler->alloc(); + + RegExpNode* success = + alloc->newInfallible(alloc, + stack_pointer_register, + position_register, + register_count, + register_start); + GuardedAlternative body_alt(body()->ToNode(compiler, success)); + + ChoiceNode* choice_node = + alloc->newInfallible(alloc, body_alt, GuardedAlternative(on_success)); + + result = ActionNode::BeginSubmatch(stack_pointer_register, position_register, - bodyNode); - } - - // We use a ChoiceNode for a negative lookahead because it has most of - // the characteristics we need. It has the body of the lookahead as its - // first alternative and the expression after the lookahead of the second - // alternative. If the first alternative succeeds then the - // NegativeSubmatchSuccess will unwind the stack including everything the - // choice node set up and backtrack. If the first alternative fails then - // the second alternative is tried, which is exactly the desired result - // for a negative lookahead. The NegativeLookaheadChoiceNode is a special - // ChoiceNode that knows to ignore the first exit when calculating quick - // checks. - LifoAlloc* alloc = compiler->alloc(); - - RegExpNode* success = - alloc->newInfallible(alloc, - stack_pointer_register, - position_register, - register_count, - register_start); - GuardedAlternative body_alt(body()->ToNode(compiler, success)); - - ChoiceNode* choice_node = - alloc->newInfallible(alloc, body_alt, GuardedAlternative(on_success)); - - return ActionNode::BeginSubmatch(stack_pointer_register, - position_register, - choice_node); + choice_node); + } + compiler->set_read_backward(was_reading_backward); + return result; } RegExpNode* @@ -2198,8 +2215,14 @@ RegExpCapture::ToNode(RegExpTree* body, RegExpCompiler* compiler, RegExpNode* on_success) { + MOZ_ASSERT(body); int start_reg = RegExpCapture::StartRegister(index); int end_reg = RegExpCapture::EndRegister(index); + if (compiler->read_backward()) { + // std::swap(start_reg, end_reg); + start_reg = RegExpCapture::EndRegister(index); + end_reg = RegExpCapture::StartRegister(index); + } RegExpNode* store_end = ActionNode::StorePosition(end_reg, true, on_success); RegExpNode* body_node = body->ToNode(compiler, store_end); return ActionNode::StorePosition(start_reg, true, body_node); @@ -2210,8 +2233,15 @@ RegExpAlternative::ToNode(RegExpCompiler* compiler, RegExpNode* on_success) { const RegExpTreeVector& children = nodes(); RegExpNode* current = on_success; - for (int i = children.length() - 1; i >= 0; i--) - current = children[i]->ToNode(compiler, current); + if (compiler->read_backward()) { + for (int i = 0; i < children.length(); i++) { + current = children[i]->ToNode(compiler, current); + } + } else { + for (int i = children.length() - 1; i >= 0; i--) { + current = children[i]->ToNode(compiler, current); + } + } return current; } @@ -2764,7 +2794,6 @@ Trace::InvalidateCurrentCharacter() void Trace::AdvanceCurrentPositionInTrace(int by, RegExpCompiler* compiler) { - MOZ_ASSERT(by > 0); // We don't have an instruction for shifting the current character register // down or for using a shifted value for anything so lets just forget that // we preloaded any characters into it. @@ -3109,9 +3138,9 @@ AssertionNode::Emit(RegExpCompiler* compiler, Trace* trace) return; } if (trace->at_start() == Trace::UNKNOWN) { - assembler->CheckNotAtStart(trace->backtrack()); + assembler->CheckNotAtStart(trace->cp_offset(), trace->backtrack()); Trace at_start_trace = *trace; - at_start_trace.set_at_start(true); + at_start_trace.set_at_start(Trace::TRUE_VALUE); on_success()->Emit(compiler, &at_start_trace); return; } @@ -3814,9 +3843,10 @@ TextNode::TextEmitPass(RegExpCompiler* compiler, jit::Label* backtrack = trace->backtrack(); QuickCheckDetails* quick_check = trace->quick_check_performed(); int element_count = elements().length(); + int backward_offset = read_backward() ? -Length() : 0; for (int i = preloaded ? 0 : element_count - 1; i >= 0; i--) { TextElement elm = elements()[i]; - int cp_offset = trace->cp_offset() + elm.cp_offset(); + int cp_offset = trace->cp_offset() + elm.cp_offset() + backward_offset; if (elm.text_type() == TextElement::ATOM) { const CharacterVector& quarks = elm.atom()->data(); for (int j = preloaded ? 0 : quarks.length() - 1; j >= 0; j--) { @@ -3844,11 +3874,12 @@ TextNode::TextEmitPass(RegExpCompiler* compiler, break; } if (emit_function != nullptr) { + bool bounds_check = *checked_up_to < cp_offset + j || read_backward(); bool bound_checked = emit_function(compiler, quarks[j], backtrack, cp_offset + j, - *checked_up_to < cp_offset + j, + bounds_check, preloaded); if (bound_checked) UpdateBoundsCheck(cp_offset + j, checked_up_to); } @@ -3859,13 +3890,14 @@ TextNode::TextEmitPass(RegExpCompiler* compiler, if (first_element_checked && i == 0) continue; if (DeterminedAlready(quick_check, elm.cp_offset())) continue; RegExpCharacterClass* cc = elm.char_class(); + bool bounds_check = *checked_up_to < cp_offset || read_backward(); EmitCharClass(alloc(), assembler, cc, ascii, backtrack, cp_offset, - *checked_up_to < cp_offset, + bounds_check, preloaded); UpdateBoundsCheck(cp_offset, checked_up_to); } @@ -3945,8 +3977,11 @@ TextNode::Emit(RegExpCompiler* compiler, Trace* trace) } Trace successor_trace(*trace); - successor_trace.set_at_start(false); - successor_trace.AdvanceCurrentPositionInTrace(Length(), compiler); + // If we advance backward, we may end up at the start. + successor_trace.AdvanceCurrentPositionInTrace( + read_backward() ? -Length() : Length(), compiler); + successor_trace.set_at_start(read_backward() ? Trace::UNKNOWN + : Trace::FALSE_VALUE); RecursionCheck rc(compiler); on_success()->Emit(compiler, &successor_trace); } @@ -4118,6 +4153,8 @@ ChoiceNode::CalculatePreloadCharacters(RegExpCompiler* compiler, int eats_at_lea RegExpNode* TextNode::GetSuccessorOfOmnivorousTextNode(RegExpCompiler* compiler) { + if (read_backward()) return NULL; + if (elements().length() != 1) return nullptr; @@ -4165,7 +4202,7 @@ ChoiceNode::GreedyLoopTextLengthForAlternative(GuardedAlternative* alternative) SeqRegExpNode* seq_node = static_cast(node); node = seq_node->on_success(); } - return length; + return read_backward() ? -length : length; } // Creates a list of AlternativeGenerations. If the list has a reasonable @@ -4240,7 +4277,7 @@ ChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) jit::Label greedy_loop_label; Trace counter_backtrack_trace; counter_backtrack_trace.set_backtrack(&greedy_loop_label); - if (not_at_start()) counter_backtrack_trace.set_at_start(false); + if (not_at_start()) counter_backtrack_trace.set_at_start(Trace::FALSE_VALUE); if (choice_count > 1 && text_length != kNodeIsTooComplexForGreedyLoops) { // Here we have special handling for greedy loops containing only text nodes @@ -4256,7 +4293,7 @@ ChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) current_trace = &counter_backtrack_trace; jit::Label greedy_match_failed; Trace greedy_match_trace; - if (not_at_start()) greedy_match_trace.set_at_start(false); + if (not_at_start()) greedy_match_trace.set_at_start(Trace::FALSE_VALUE); greedy_match_trace.set_backtrack(&greedy_match_failed); jit::Label loop_label; macro_assembler->Bind(&loop_label); @@ -4605,11 +4642,14 @@ BackReferenceNode::Emit(RegExpCompiler* compiler, Trace* trace) MOZ_ASSERT(start_reg_ + 1 == end_reg_); if (compiler->ignore_case()) { assembler->CheckNotBackReferenceIgnoreCase(start_reg_, + read_backward(), trace->backtrack(), compiler->unicode()); } else { - assembler->CheckNotBackReference(start_reg_, trace->backtrack()); + assembler->CheckNotBackReference(start_reg_, read_backward(), trace->backtrack()); } + // We are going to advance backward, so we may end up at the start. + if (read_backward()) trace->set_at_start(Trace::UNKNOWN); on_success()->Emit(compiler, trace); } @@ -4977,7 +5017,6 @@ QuickCheckDetails::Clear() void QuickCheckDetails::Advance(int by, bool ascii) { - MOZ_ASSERT(by >= 0); if (by >= characters_) { Clear(); return; diff --git a/js/src/irregexp/RegExpEngine.h b/js/src/irregexp/RegExpEngine.h index 1a8fd4b22..c4409dcca 100644 --- a/js/src/irregexp/RegExpEngine.h +++ b/js/src/irregexp/RegExpEngine.h @@ -119,7 +119,7 @@ InterpretCode(JSContext* cx, const uint8_t* byteCode, const CharT* chars, size_t VISIT(Atom) \ VISIT(Quantifier) \ VISIT(Capture) \ - VISIT(Lookahead) \ + VISIT(Lookaround) \ VISIT(BackReference) \ VISIT(Empty) \ VISIT(Text) @@ -763,15 +763,19 @@ class TextNode : public SeqRegExpNode { public: TextNode(TextElementVector* elements, + bool read_backward, RegExpNode* on_success) : SeqRegExpNode(on_success), - elements_(elements) + elements_(elements), + read_backward_(read_backward) {} TextNode(RegExpCharacterClass* that, + bool read_backward, RegExpNode* on_success) : SeqRegExpNode(on_success), - elements_(alloc()->newInfallible(*alloc())) + elements_(alloc()->newInfallible(*alloc())), + read_backward_(read_backward) { elements_->append(TextElement::CharClass(that)); } @@ -784,6 +788,7 @@ class TextNode : public SeqRegExpNode int characters_filled_in, bool not_at_start); TextElementVector& elements() { return *elements_; } + bool read_backward() { return read_backward_; } void MakeCaseIndependent(bool is_ascii, bool unicode); virtual int GreedyLoopTextLength(); virtual RegExpNode* GetSuccessorOfOmnivorousTextNode( @@ -814,6 +819,7 @@ class TextNode : public SeqRegExpNode int* checked_up_to); int Length(); TextElementVector* elements_; + bool read_backward_; }; class AssertionNode : public SeqRegExpNode @@ -882,15 +888,18 @@ class BackReferenceNode : public SeqRegExpNode public: BackReferenceNode(int start_reg, int end_reg, + bool read_backward, RegExpNode* on_success) : SeqRegExpNode(on_success), start_reg_(start_reg), - end_reg_(end_reg) + end_reg_(end_reg), + read_backward_(read_backward) {} virtual void Accept(NodeVisitor* visitor); int start_register() { return start_reg_; } int end_register() { return end_reg_; } + bool read_backward() { return read_backward_; } virtual void Emit(RegExpCompiler* compiler, Trace* trace); virtual int EatsAtLeast(int still_to_find, int recursion_depth, @@ -909,6 +918,7 @@ class BackReferenceNode : public SeqRegExpNode private: int start_reg_; int end_reg_; + bool read_backward_; }; class EndNode : public RegExpNode @@ -1053,6 +1063,7 @@ class ChoiceNode : public RegExpNode void set_being_calculated(bool b) { being_calculated_ = b; } virtual bool try_to_emit_quick_check_for_alternative(int i) { return true; } virtual RegExpNode* FilterASCII(int depth, bool ignore_case, bool unicode); + virtual bool read_backward() { return false; } protected: int GreedyLoopTextLengthForAlternative(GuardedAlternative* alternative); @@ -1111,11 +1122,13 @@ class NegativeLookaheadChoiceNode : public ChoiceNode class LoopChoiceNode : public ChoiceNode { public: - explicit LoopChoiceNode(LifoAlloc* alloc, bool body_can_be_zero_length) + explicit LoopChoiceNode(LifoAlloc* alloc, bool body_can_be_zero_length, + bool read_backward) : ChoiceNode(alloc, 2), loop_node_(nullptr), continue_node_(nullptr), - body_can_be_zero_length_(body_can_be_zero_length) + body_can_be_zero_length_(body_can_be_zero_length), + read_backward_(read_backward) {} void AddLoopAlternative(GuardedAlternative alt); @@ -1133,6 +1146,7 @@ class LoopChoiceNode : public ChoiceNode RegExpNode* loop_node() { return loop_node_; } RegExpNode* continue_node() { return continue_node_; } bool body_can_be_zero_length() { return body_can_be_zero_length_; } + virtual bool read_backward() { return read_backward_; } virtual void Accept(NodeVisitor* visitor); virtual RegExpNode* FilterASCII(int depth, bool ignore_case, bool unicode); @@ -1147,6 +1161,7 @@ class LoopChoiceNode : public ChoiceNode RegExpNode* loop_node_; RegExpNode* continue_node_; bool body_can_be_zero_length_; + bool read_backward_; }; // Improve the speed that we scan for an initial point where a non-anchored @@ -1422,8 +1437,8 @@ class Trace } TriBool at_start() { return at_start_; } - void set_at_start(bool at_start) { - at_start_ = at_start ? TRUE_VALUE : FALSE_VALUE; + void set_at_start(TriBool at_start) { + at_start_ = at_start; } jit::Label* backtrack() { return backtrack_; } jit::Label* loop_label() { return loop_label_; } diff --git a/js/src/irregexp/RegExpInterpreter.cpp b/js/src/irregexp/RegExpInterpreter.cpp index 7fd2d983a..d09b4671e 100644 --- a/js/src/irregexp/RegExpInterpreter.cpp +++ b/js/src/irregexp/RegExpInterpreter.cpp @@ -222,8 +222,8 @@ irregexp::InterpretCode(JSContext* cx, const uint8_t* byteCode, const CharT* cha } break; BYTECODE(LOAD_CURRENT_CHAR) { - size_t pos = current + (insn >> BYTECODE_SHIFT); - if (pos >= length) { + int pos = current + (insn >> BYTECODE_SHIFT); + if (pos >= (int)length || pos < 0) { pc = byteCode + Load32Aligned(pc + 4); } else { current_char = chars[pos]; @@ -238,8 +238,8 @@ irregexp::InterpretCode(JSContext* cx, const uint8_t* byteCode, const CharT* cha break; } BYTECODE(LOAD_2_CURRENT_CHARS) { - size_t pos = current + (insn >> BYTECODE_SHIFT); - if (pos + 2 > length) { + int pos = current + (insn >> BYTECODE_SHIFT); + if (pos + 2 > (int)length || pos < 0) { pc = byteCode + Load32Aligned(pc + 4); } else { CharT next = chars[pos + 1]; @@ -425,6 +425,30 @@ irregexp::InterpretCode(JSContext* cx, const uint8_t* byteCode, const CharT* cha pc += BC_CHECK_NOT_BACK_REF_LENGTH; break; } + BYTECODE(CHECK_NOT_BACK_REF_BACKWARD) { + int from = registers[insn >> BYTECODE_SHIFT]; + int len = registers[(insn >> BYTECODE_SHIFT) + 1] - from; + if (from < 0 || len <= 0) { + pc += BC_CHECK_NOT_BACK_REF_BACKWARD_LENGTH; + break; + } + if (int(current) - len < 0) { + pc = byteCode + Load32Aligned(pc + 4); + break; + } else { + int i; + for (i = 0; i < len; i++) { + if (chars[from + i] != chars[int(current) - len + i]) { + pc = byteCode + Load32Aligned(pc + 4); + break; + } + } + if (i < len) break; + current -= len; + } + pc += BC_CHECK_NOT_BACK_REF_BACKWARD_LENGTH; + break; + } BYTECODE(CHECK_NOT_BACK_REF_NO_CASE) { int from = registers[insn >> BYTECODE_SHIFT]; int len = registers[(insn >> BYTECODE_SHIFT) + 1] - from; @@ -465,6 +489,46 @@ irregexp::InterpretCode(JSContext* cx, const uint8_t* byteCode, const CharT* cha } break; } + BYTECODE(CHECK_NOT_BACK_REF_NO_CASE_BACKWARD) { + int from = registers[insn >> BYTECODE_SHIFT]; + int len = registers[(insn >> BYTECODE_SHIFT) + 1] - from; + if (from < 0 || len <= 0) { + pc += BC_CHECK_NOT_BACK_REF_NO_CASE_BACKWARD_LENGTH; + break; + } + if (int(current) - len < 0) { + pc = byteCode + Load32Aligned(pc + 4); + break; + } + if (CaseInsensitiveCompareStrings(chars + from, chars + int(current) - len, len * sizeof(CharT))) { + current -= len; + pc += BC_CHECK_NOT_BACK_REF_NO_CASE_BACKWARD_LENGTH; + } else { + pc = byteCode + Load32Aligned(pc + 4); + } + break; + + } + BYTECODE(CHECK_NOT_BACK_REF_NO_CASE_BACKWARD_UNICODE) { + int from = registers[insn >> BYTECODE_SHIFT]; + int len = registers[(insn >> BYTECODE_SHIFT) + 1] - from; + if (from < 0 || len <= 0) { + pc += BC_CHECK_NOT_BACK_REF_NO_CASE_BACKWARD_LENGTH; + break; + } + if (int(current) - len < 0) { + pc = byteCode + Load32Aligned(pc + 4); + break; + } + if (CaseInsensitiveCompareUCStrings(chars + from, chars + int(current) - len, len * sizeof(CharT))) { + current -= len; + pc += BC_CHECK_NOT_BACK_REF_NO_CASE_BACKWARD_LENGTH; + } else { + pc = byteCode + Load32Aligned(pc + 4); + } + break; + + } BYTECODE(CHECK_AT_START) if (current == 0) pc = byteCode + Load32Aligned(pc + 4); @@ -472,7 +536,7 @@ irregexp::InterpretCode(JSContext* cx, const uint8_t* byteCode, const CharT* cha pc += BC_CHECK_AT_START_LENGTH; break; BYTECODE(CHECK_NOT_AT_START) - if (current == 0) + if (current + (insn >> BYTECODE_SHIFT) == 0) pc += BC_CHECK_NOT_AT_START_LENGTH; else pc = byteCode + Load32Aligned(pc + 4); diff --git a/js/src/irregexp/RegExpMacroAssembler.cpp b/js/src/irregexp/RegExpMacroAssembler.cpp index d66d0d204..6b1ceba8a 100644 --- a/js/src/irregexp/RegExpMacroAssembler.cpp +++ b/js/src/irregexp/RegExpMacroAssembler.cpp @@ -226,32 +226,37 @@ InterpretedRegExpMacroAssembler::CheckGreedyLoop(jit::Label* on_tos_equals_curre } void -InterpretedRegExpMacroAssembler::CheckNotAtStart(jit::Label* on_not_at_start) +InterpretedRegExpMacroAssembler::CheckNotAtStart(int cp_offset, jit::Label* on_not_at_start) { - Emit(BC_CHECK_NOT_AT_START, 0); + Emit(BC_CHECK_NOT_AT_START, cp_offset); EmitOrLink(on_not_at_start); } void -InterpretedRegExpMacroAssembler::CheckNotBackReference(int start_reg, jit::Label* on_no_match) +InterpretedRegExpMacroAssembler::CheckNotBackReference(int start_reg, bool read_backward, + jit::Label* on_no_match) { MOZ_ASSERT(start_reg >= 0); MOZ_ASSERT(start_reg <= kMaxRegister); - Emit(BC_CHECK_NOT_BACK_REF, start_reg); + Emit(read_backward ? BC_CHECK_NOT_BACK_REF_BACKWARD : BC_CHECK_NOT_BACK_REF, + start_reg); EmitOrLink(on_no_match); } void InterpretedRegExpMacroAssembler::CheckNotBackReferenceIgnoreCase(int start_reg, + bool read_backward, jit::Label* on_no_match, bool unicode) { MOZ_ASSERT(start_reg >= 0); MOZ_ASSERT(start_reg <= kMaxRegister); if (unicode) - Emit(BC_CHECK_NOT_BACK_REF_NO_CASE_UNICODE, start_reg); + Emit(read_backward ? BC_CHECK_NOT_BACK_REF_NO_CASE_BACKWARD_UNICODE : BC_CHECK_NOT_BACK_REF_NO_CASE_UNICODE, + start_reg); else - Emit(BC_CHECK_NOT_BACK_REF_NO_CASE, start_reg); + Emit(read_backward ? BC_CHECK_NOT_BACK_REF_NO_CASE_BACKWARD : BC_CHECK_NOT_BACK_REF_NO_CASE, + start_reg); EmitOrLink(on_no_match); } diff --git a/js/src/irregexp/RegExpMacroAssembler.h b/js/src/irregexp/RegExpMacroAssembler.h index dca2edf90..c5def92f2 100644 --- a/js/src/irregexp/RegExpMacroAssembler.h +++ b/js/src/irregexp/RegExpMacroAssembler.h @@ -110,10 +110,10 @@ class MOZ_STACK_CLASS RegExpMacroAssembler virtual void CheckCharacterGT(char16_t limit, jit::Label* on_greater) = 0; virtual void CheckCharacterLT(char16_t limit, jit::Label* on_less) = 0; virtual void CheckGreedyLoop(jit::Label* on_tos_equals_current_position) = 0; - virtual void CheckNotAtStart(jit::Label* on_not_at_start) = 0; - virtual void CheckNotBackReference(int start_reg, jit::Label* on_no_match) = 0; - virtual void CheckNotBackReferenceIgnoreCase(int start_reg, jit::Label* on_no_match, - bool unicode) = 0; + virtual void CheckNotAtStart(int cp_offset, jit::Label* on_not_at_start) = 0; + virtual void CheckNotBackReference(int start_reg, bool read_backward, jit::Label* on_no_match) = 0; + virtual void CheckNotBackReferenceIgnoreCase(int start_reg, bool read_backward, + jit::Label* on_no_match, bool unicode) = 0; // Check the current character for a match with a literal character. If we // fail to match then goto the on_failure label. End of input always @@ -245,9 +245,10 @@ class MOZ_STACK_CLASS InterpretedRegExpMacroAssembler final : public RegExpMacro void CheckCharacterGT(char16_t limit, jit::Label* on_greater); void CheckCharacterLT(char16_t limit, jit::Label* on_less); void CheckGreedyLoop(jit::Label* on_tos_equals_current_position); - void CheckNotAtStart(jit::Label* on_not_at_start); - void CheckNotBackReference(int start_reg, jit::Label* on_no_match); - void CheckNotBackReferenceIgnoreCase(int start_reg, jit::Label* on_no_match, bool unicode); + void CheckNotAtStart(int cp_offset, jit::Label* on_not_at_start); + void CheckNotBackReference(int start_reg, bool read_backward, jit::Label* on_no_match); + void CheckNotBackReferenceIgnoreCase(int start_reg, bool read_backward, + jit::Label* on_no_match, bool unicode); void CheckNotCharacter(unsigned c, jit::Label* on_not_equal); void CheckNotCharacterAfterAnd(unsigned c, unsigned and_with, jit::Label* on_not_equal); void CheckNotCharacterAfterMinusAnd(char16_t c, char16_t minus, char16_t and_with, diff --git a/js/src/irregexp/RegExpParser.cpp b/js/src/irregexp/RegExpParser.cpp index 8bd88047a..9ef9fe3e2 100644 --- a/js/src/irregexp/RegExpParser.cpp +++ b/js/src/irregexp/RegExpParser.cpp @@ -227,6 +227,7 @@ RegExpParser::RegExpParser(frontend::TokenStream& ts, LifoAlloc* alloc, alloc(alloc), captures_(nullptr), next_pos_(chars), + captures_started_(0), end_(end), current_(kEndMarker), capture_count_(0), @@ -418,7 +419,8 @@ RangeAtom(LifoAlloc* alloc, char16_t from, char16_t to) static inline RegExpTree* NegativeLookahead(LifoAlloc* alloc, char16_t from, char16_t to) { - return alloc->newInfallible(RangeAtom(alloc, from, to), false, 0, 0); + return alloc->newInfallible(RangeAtom(alloc, from, to), false, + 0, 0, RegExpLookaround::LOOKAHEAD); } static bool @@ -1213,6 +1215,38 @@ RegExpParser::ParseBackReferenceIndex(int* index_out) return true; } +template +RegExpCapture* +RegExpParser::GetCapture(int index) { + // The index for the capture groups are one-based. Its index in the list is + // zero-based. + int known_captures = + is_scanned_for_captures_ ? capture_count_ : captures_started_; + MOZ_ASSERT(index <= known_captures); + if (captures_ == NULL) { + captures_ = alloc->newInfallible(*alloc); + } + while ((int)captures_->length() < known_captures) { + RegExpCapture* capture = alloc->newInfallible(nullptr, captures_->length() + 1); + captures_->append(capture); + } + return (*captures_)[index - 1]; +} + + +template +bool +RegExpParser::RegExpParserState::IsInsideCaptureGroup(int index) { + for (RegExpParserState* s = this; s != NULL; s = s->previous_state()) { + if (s->group_type() != CAPTURE) continue; + // Return true if we found the matching capture index. + if (index == s->capture_index()) return true; + // Abort if index is larger than what has been parsed up till this state. + if (index > s->capture_index()) return false; + } + return false; +} + // QuantifierPrefix :: // { DecimalDigits } // { DecimalDigits , } @@ -1423,24 +1457,24 @@ RegExpTree* RegExpParser::ParseDisjunction() { // Used to store current state while parsing subexpressions. - RegExpParserState initial_state(alloc, nullptr, INITIAL, 0); - RegExpParserState* stored_state = &initial_state; + RegExpParserState initial_state(alloc, nullptr, INITIAL, RegExpLookaround::LOOKAHEAD, 0); + RegExpParserState* state = &initial_state; // Cache the builder in a local variable for quick access. RegExpBuilder* builder = initial_state.builder(); while (true) { switch (current()) { case kEndMarker: - if (stored_state->IsSubexpression()) { + if (state->IsSubexpression()) { // Inside a parenthesized group when hitting end of input. return ReportError(JSMSG_MISSING_PAREN); } - MOZ_ASSERT(INITIAL == stored_state->group_type()); + MOZ_ASSERT(INITIAL == state->group_type()); // Parsing completed successfully. return builder->ToRegExp(); case ')': { - if (!stored_state->IsSubexpression()) + if (!state->IsSubexpression()) return ReportError(JSMSG_UNMATCHED_RIGHT_PAREN); - MOZ_ASSERT(INITIAL != stored_state->group_type()); + MOZ_ASSERT(INITIAL != state->group_type()); Advance(); // End disjunction parsing and convert builder content to new single @@ -1449,29 +1483,30 @@ RegExpParser::ParseDisjunction() int end_capture_index = captures_started(); - int capture_index = stored_state->capture_index(); - SubexpressionType group_type = stored_state->group_type(); - - // Restore previous state. - stored_state = stored_state->previous_state(); - builder = stored_state->builder(); + int capture_index = state->capture_index(); + SubexpressionType group_type = state->group_type(); // Build result of subexpression. if (group_type == CAPTURE) { - RegExpCapture* capture = alloc->newInfallible(body, capture_index); - (*captures_)[capture_index - 1] = capture; + RegExpCapture* capture = GetCapture(capture_index); + capture->set_body(body); body = capture; } else if (group_type != GROUPING) { - MOZ_ASSERT(group_type == POSITIVE_LOOKAHEAD || - group_type == NEGATIVE_LOOKAHEAD); - bool is_positive = (group_type == POSITIVE_LOOKAHEAD); - body = alloc->newInfallible(body, + MOZ_ASSERT(group_type == POSITIVE_LOOKAROUND || + group_type == NEGATIVE_LOOKAROUND); + bool is_positive = (group_type == POSITIVE_LOOKAROUND); + body = alloc->newInfallible(body, is_positive, end_capture_index - capture_index, - capture_index); + capture_index, + state->lookaround_type()); } + + // Restore previous state. + state = state->previous_state(); + builder = state->builder(); builder->AddAtom(body); - if (unicode_ && (group_type == POSITIVE_LOOKAHEAD || group_type == NEGATIVE_LOOKAHEAD)) + if (unicode_ && (group_type == POSITIVE_LOOKAROUND || group_type == NEGATIVE_LOOKAROUND)) continue; // For compatability with JSC and ES3, we allow quantifiers after // lookaheads, and break in all cases. @@ -1519,6 +1554,7 @@ RegExpParser::ParseDisjunction() } case '(': { SubexpressionType subexpr_type = CAPTURE; + RegExpLookaround::Type lookaround_type = state->lookaround_type(); Advance(); if (current() == '?') { switch (Next()) { @@ -1526,26 +1562,39 @@ RegExpParser::ParseDisjunction() subexpr_type = GROUPING; break; case '=': - subexpr_type = POSITIVE_LOOKAHEAD; + lookaround_type = RegExpLookaround::LOOKAHEAD; + subexpr_type = POSITIVE_LOOKAROUND; break; case '!': - subexpr_type = NEGATIVE_LOOKAHEAD; + lookaround_type = RegExpLookaround::LOOKAHEAD; + subexpr_type = NEGATIVE_LOOKAROUND; break; + case '<': + Advance(); + lookaround_type = RegExpLookaround::LOOKBEHIND; + if (Next() == '=') { + subexpr_type = POSITIVE_LOOKAROUND; + break; + } else if (Next() == '!') { + subexpr_type = NEGATIVE_LOOKAROUND; + break; + } + // We didn't get a positive or negative after '<'. + // That's an error. + return ReportError(JSMSG_INVALID_GROUP); default: return ReportError(JSMSG_INVALID_GROUP); } Advance(2); } else { - if (captures_ == nullptr) - captures_ = alloc->newInfallible(*alloc); if (captures_started() >= kMaxCaptures) return ReportError(JSMSG_TOO_MANY_PARENS); - captures_->append((RegExpCapture*) nullptr); + captures_started_++; } // Store current state and begin new disjunction parsing. - stored_state = alloc->newInfallible(alloc, stored_state, subexpr_type, - captures_started()); - builder = stored_state->builder(); + state = alloc->newInfallible(alloc, state, subexpr_type, + lookaround_type, captures_started_); + builder = state->builder(); continue; } case '[': { @@ -1600,19 +1649,18 @@ RegExpParser::ParseDisjunction() case '7': case '8': case '9': { int index = 0; if (ParseBackReferenceIndex(&index)) { - RegExpCapture* capture = nullptr; - if (captures_ != nullptr && index <= (int) captures_->length()) { - capture = (*captures_)[index - 1]; - } - if (capture == nullptr) { - builder->AddEmpty(); - break; + if (state->IsInsideCaptureGroup(index)) { + // The backreference is inside the capture group it refers to. + // Nothing can possibly have been captured yet. + builder->AddEmpty(); + } else { + RegExpCapture* capture = GetCapture(index); + RegExpTree* atom = alloc->newInfallible(capture); + if (unicode_) + builder->AddAtom(UnicodeBackReferenceAtom(alloc, atom)); + else + builder->AddAtom(atom); } - RegExpTree* atom = alloc->newInfallible(capture); - if (unicode_) - builder->AddAtom(UnicodeBackReferenceAtom(alloc, atom)); - else - builder->AddAtom(atom); break; } if (unicode_) diff --git a/js/src/irregexp/RegExpParser.h b/js/src/irregexp/RegExpParser.h index 0a7e61858..2f02625b5 100644 --- a/js/src/irregexp/RegExpParser.h +++ b/js/src/irregexp/RegExpParser.h @@ -229,7 +229,7 @@ class RegExpParser bool simple() { return simple_; } bool contains_anchor() { return contains_anchor_; } void set_contains_anchor() { contains_anchor_ = true; } - int captures_started() { return captures_ == nullptr ? 0 : captures_->length(); } + int captures_started() { return captures_started_; } const CharT* position() { return next_pos_ - 1; } static const int kMaxCaptures = 1 << 16; @@ -239,8 +239,8 @@ class RegExpParser enum SubexpressionType { INITIAL, CAPTURE, // All positive values represent captures. - POSITIVE_LOOKAHEAD, - NEGATIVE_LOOKAHEAD, + POSITIVE_LOOKAROUND, + NEGATIVE_LOOKAROUND, GROUPING }; @@ -249,10 +249,12 @@ class RegExpParser RegExpParserState(LifoAlloc* alloc, RegExpParserState* previous_state, SubexpressionType group_type, + RegExpLookaround::Type lookaround_type, int disjunction_capture_index) : previous_state_(previous_state), builder_(alloc->newInfallible(alloc)), group_type_(group_type), + lookaround_type_(lookaround_type), disjunction_capture_index_(disjunction_capture_index) {} // Parser state of containing expression, if any. @@ -262,11 +264,16 @@ class RegExpParser RegExpBuilder* builder() { return builder_; } // Type of regexp being parsed (parenthesized group or entire regexp). SubexpressionType group_type() { return group_type_; } + // Lookahead or Lookbehind. + RegExpLookaround::Type lookaround_type() { return lookaround_type_; } // Index in captures array of first capture in this sub-expression, if any. // Also the capture index of this sub-expression itself, if group_type // is CAPTURE. int capture_index() { return disjunction_capture_index_; } + // Check whether the parser is inside a capture group with the given index. + bool IsInsideCaptureGroup(int index); + private: // Linked list implementation of stack of states. RegExpParserState* previous_state_; @@ -274,10 +281,15 @@ class RegExpParser RegExpBuilder* builder_; // Stored disjunction type (capture, look-ahead or grouping), if any. SubexpressionType group_type_; + // Stored read direction. + RegExpLookaround::Type lookaround_type_; // Stored disjunction's capture index (if any). int disjunction_capture_index_; }; + // Return the 1-indexed RegExpCapture object, allocate if necessary. + RegExpCapture* GetCapture(int index); + widechar current() { return current_; } bool has_more() { return has_more_; } bool has_next() { return next_pos_ < end_; } @@ -294,6 +306,7 @@ class RegExpParser const CharT* next_pos_; const CharT* end_; widechar current_; + int captures_started_; // The capture count is only valid after we have scanned for captures. int capture_count_; bool has_more_; -- cgit v1.2.3 From 899be7cedbef6678280d56a4725f2697f808bbb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bargull?= Date: Tue, 12 Nov 2019 17:02:16 +0100 Subject: Issue #1283 - Implement Promise.prototype.finally() This resolves #1283. --- js/src/builtin/Promise.cpp | 8 ++++++ js/src/builtin/Promise.h | 8 ++++++ js/src/builtin/Promise.js | 69 ++++++++++++++++++++++++++++++++++++++++++++++ js/src/vm/SelfHosting.cpp | 19 +++++++++++++ 4 files changed, 104 insertions(+) (limited to 'js/src') diff --git a/js/src/builtin/Promise.cpp b/js/src/builtin/Promise.cpp index ec7845e89..1d068f8c6 100644 --- a/js/src/builtin/Promise.cpp +++ b/js/src/builtin/Promise.cpp @@ -2006,6 +2006,13 @@ CommonStaticResolveRejectImpl(JSContext* cx, HandleValue thisVal, HandleValue ar return promise; } +MOZ_MUST_USE JSObject* +js::PromiseResolve(JSContext* cx, HandleObject constructor, HandleValue value) +{ + RootedValue C(cx, ObjectValue(*constructor)); + return CommonStaticResolveRejectImpl(cx, C, value, ResolveMode); +} + /** * ES2016, 25.4.4.4, Promise.reject. */ @@ -2739,6 +2746,7 @@ CreatePromisePrototype(JSContext* cx, JSProtoKey key) static const JSFunctionSpec promise_methods[] = { JS_SELF_HOSTED_FN("catch", "Promise_catch", 1, 0), JS_FN("then", Promise_then, 2, 0), + JS_SELF_HOSTED_FN("finally", "Promise_finally", 1, 0), JS_FS_END }; diff --git a/js/src/builtin/Promise.h b/js/src/builtin/Promise.h index c76dc358c..6a6453e46 100644 --- a/js/src/builtin/Promise.h +++ b/js/src/builtin/Promise.h @@ -128,6 +128,14 @@ OriginalPromiseThen(JSContext* cx, Handle promise, HandleValue onFulfilled, HandleValue onRejected, MutableHandleObject dependent, bool createDependent); +/** + * PromiseResolve ( C, x ) + * + * The abstract operation PromiseResolve, given a constructor and a value, + * returns a new promise resolved with that value. + */ +MOZ_MUST_USE JSObject* +PromiseResolve(JSContext* cx, HandleObject constructor, HandleValue value); MOZ_MUST_USE PromiseObject* CreatePromiseObjectForAsync(JSContext* cx, HandleValue generatorVal); diff --git a/js/src/builtin/Promise.js b/js/src/builtin/Promise.js index 704cbab0b..91a1e1f56 100644 --- a/js/src/builtin/Promise.js +++ b/js/src/builtin/Promise.js @@ -14,3 +14,72 @@ function Promise_catch(onRejected) { // Steps 1-2. return callContentFunction(this.then, this, undefined, onRejected); } + +// Promise.prototype.finally(onFinally) +// See https://tc39.es/proposal-promise-finally/ +function Promise_finally(onFinally) { + // Step 1. + var promise = this; + + // Step 2. + if (!IsObject(promise)) + ThrowTypeError(JSMSG_INCOMPATIBLE_PROTO, "Promise", "finally", "value"); + + // Step 3. + var C = SpeciesConstructor(promise, GetBuiltinConstructor("Promise")); + + // Step 4. + assert(IsConstructor(C), "SpeciesConstructor returns a constructor function"); + + // Steps 5-6. + var thenFinally, catchFinally; + if (!IsCallable(onFinally)) { + thenFinally = onFinally; + catchFinally = onFinally; + } else { + // ThenFinally Function. + // The parentheses prevent the inferring of a function name. + (thenFinally) = function(value) { + // Steps 1-2 (implicit). + + // Step 3. + var result = onFinally(); + + // Steps 4-5 (implicit). + + // Step 6. + var promise = PromiseResolve(C, result); + + // Step 7. + // FIXME: spec issue - "be equivalent to a function that" is not a defined spec term. + // https://github.com/tc39/ecma262/issues/933 + + // Step 8. + return callContentFunction(promise.then, promise, function() { return value; }); + }; + + // CatchFinally Function. + // The parentheses prevent the inferring of a function name. + (catchFinally) = function(reason) { + // Steps 1-2 (implicit). + + // Step 3. + var result = onFinally(); + + // Steps 4-5 (implicit). + + // Step 6. + var promise = PromiseResolve(C, result); + + // Step 7. + // FIXME: spec issue - "be equivalent to a function that" is not a defined spec term. + // https://github.com/tc39/ecma262/issues/933 + + // Step 8. + return callContentFunction(promise.then, promise, function() { throw reason; }); + }; + } + + // Step 7. + return callContentFunction(promise.then, promise, thenFinally, catchFinally); +} diff --git a/js/src/vm/SelfHosting.cpp b/js/src/vm/SelfHosting.cpp index 82d2cde64..833410465 100644 --- a/js/src/vm/SelfHosting.cpp +++ b/js/src/vm/SelfHosting.cpp @@ -2102,6 +2102,21 @@ intrinsic_ModuleNamespaceExports(JSContext* cx, unsigned argc, Value* vp) return true; } +static bool +intrinsic_PromiseResolve(JSContext* cx, unsigned argc, Value* vp) +{ + CallArgs args = CallArgsFromVp(argc, vp); + MOZ_ASSERT(args.length() == 2); + + RootedObject constructor(cx, &args[0].toObject()); + JSObject* promise = js::PromiseResolve(cx, constructor, args[1]); + if (!promise) + return false; + + args.rval().setObject(*promise); + return true; +} + // The self-hosting global isn't initialized with the normal set of builtins. // Instead, individual C++-implemented functions that're required by // self-hosted code are defined as global functions. Accessing these @@ -2498,6 +2513,10 @@ static const JSFunctionSpec intrinsic_functions[] = { JS_FN("AddModuleNamespaceBinding", intrinsic_AddModuleNamespaceBinding, 4, 0), JS_FN("ModuleNamespaceExports", intrinsic_ModuleNamespaceExports, 1, 0), + JS_FN("IsPromiseObject", intrinsic_IsInstanceOfBuiltin, 1, 0), + JS_FN("CallPromiseMethodIfWrapped", CallNonGenericSelfhostedMethod>, 2, 0), + JS_FN("PromiseResolve", intrinsic_PromiseResolve, 2, 0), + JS_FS_END }; -- cgit v1.2.3 From e79607a7a694dc2d48d65697b48138fa585145c9 Mon Sep 17 00:00:00 2001 From: Gaming4JC Date: Thu, 14 Nov 2019 22:40:15 -0500 Subject: Issue #1279 - Update js/src/builtin/TestingFunctions.cpp for regex lookbehind changes This fixes debug builds --- js/src/builtin/TestingFunctions.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'js/src') diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctions.cpp index 4363c7aed..072a72b75 100644 --- a/js/src/builtin/TestingFunctions.cpp +++ b/js/src/builtin/TestingFunctions.cpp @@ -3900,10 +3900,10 @@ ConvertRegExpTreeToObject(JSContext* cx, irregexp::RegExpTree* tree) return nullptr; return obj; } - if (tree->IsLookahead()) { - if (!StringProp(cx, obj, "type", "Lookahead")) + if (tree->IsLookaround()) { + if (!StringProp(cx, obj, "type", "Lookaround")) return nullptr; - irregexp::RegExpLookahead* t = tree->AsLookahead(); + irregexp::RegExpLookaround* t = tree->AsLookaround(); if (!BooleanProp(cx, obj, "is_positive", t->is_positive())) return nullptr; if (!TreeProp(cx, obj, "body", t->body())) -- cgit v1.2.3 From f31b04a303607cd82757e7c4f60bb536658c8a30 Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Mon, 18 Nov 2019 12:20:44 +0100 Subject: Issue #1284 - Implement /s (dotAll) for regular expressions. Resolves #1284. --- js/src/builtin/RegExp.cpp | 24 +++++++++++++++++ js/src/builtin/RegExp.h | 2 ++ js/src/builtin/RegExp.js | 5 ++++ js/src/builtin/SelfHostingDefines.h | 1 + js/src/frontend/TokenStream.cpp | 2 ++ js/src/irregexp/RegExpParser.cpp | 52 ++++++++++++++++++++++++++++++++++--- js/src/irregexp/RegExpParser.h | 1 + js/src/vm/RegExpObject.h | 7 +++-- 8 files changed, 88 insertions(+), 6 deletions(-) (limited to 'js/src') diff --git a/js/src/builtin/RegExp.cpp b/js/src/builtin/RegExp.cpp index 7cf20d23c..93a7f2b79 100644 --- a/js/src/builtin/RegExp.cpp +++ b/js/src/builtin/RegExp.cpp @@ -664,6 +664,29 @@ js::regexp_multiline(JSContext* cx, unsigned argc, JS::Value* vp) return CallNonGenericMethod(cx, args); } +// ES 2018 dotAll +MOZ_ALWAYS_INLINE bool +regexp_dotall_impl(JSContext* cx, const CallArgs& args) +{ + MOZ_ASSERT(IsRegExpInstanceOrPrototype(args.thisv())); + + if (!IsRegExpObject(args.thisv())) { + args.rval().setUndefined(); + return true; + } + + Rooted reObj(cx, &args.thisv().toObject().as()); + args.rval().setBoolean(reObj->dotall()); + return true; +} + +bool +js::regexp_dotall(JSContext* cx, unsigned argc, JS::Value* vp) +{ + CallArgs args = CallArgsFromVp(argc, vp); + return CallNonGenericMethod(cx, args); +} + // ES 2017 draft rev32 21.2.5.10. MOZ_ALWAYS_INLINE bool regexp_source_impl(JSContext* cx, const CallArgs& args) @@ -759,6 +782,7 @@ const JSPropertySpec js::regexp_properties[] = { JS_PSG("source", regexp_source, 0), JS_PSG("sticky", regexp_sticky, 0), JS_PSG("unicode", regexp_unicode, 0), + JS_PSG("dotall", regexp_dotall, 0), JS_PS_END }; diff --git a/js/src/builtin/RegExp.h b/js/src/builtin/RegExp.h index 4e0ff6948..f808f5146 100644 --- a/js/src/builtin/RegExp.h +++ b/js/src/builtin/RegExp.h @@ -153,6 +153,8 @@ extern MOZ_MUST_USE bool regexp_sticky(JSContext* cx, unsigned argc, JS::Value* vp); extern MOZ_MUST_USE bool regexp_unicode(JSContext* cx, unsigned argc, JS::Value* vp); +extern MOZ_MUST_USE bool +regexp_dotall(JSContext* cx, unsigned argc, JS::Value* vp); } /* namespace js */ diff --git a/js/src/builtin/RegExp.js b/js/src/builtin/RegExp.js index 0b849292c..1a2276594 100644 --- a/js/src/builtin/RegExp.js +++ b/js/src/builtin/RegExp.js @@ -3,6 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ // ES6 draft rev34 (2015/02/20) 21.2.5.3 get RegExp.prototype.flags +// Updated for ES2018 /s (dotAll) function RegExpFlagsGetter() { // Steps 1-2. var R = this; @@ -31,6 +32,10 @@ function RegExpFlagsGetter() { // Steps 16-18. if (R.sticky) result += "y"; + + // ES2018 + if (R.dotall) + result += "s"; // Step 19. return result; diff --git a/js/src/builtin/SelfHostingDefines.h b/js/src/builtin/SelfHostingDefines.h index d676270a1..6512810ca 100644 --- a/js/src/builtin/SelfHostingDefines.h +++ b/js/src/builtin/SelfHostingDefines.h @@ -90,6 +90,7 @@ #define REGEXP_MULTILINE_FLAG 0x04 #define REGEXP_STICKY_FLAG 0x08 #define REGEXP_UNICODE_FLAG 0x10 +#define REGEXP_DOTALL_FLAG 0x20 #define MODULE_OBJECT_ENVIRONMENT_SLOT 2 diff --git a/js/src/frontend/TokenStream.cpp b/js/src/frontend/TokenStream.cpp index b8623d545..e07f8df8a 100644 --- a/js/src/frontend/TokenStream.cpp +++ b/js/src/frontend/TokenStream.cpp @@ -1843,6 +1843,8 @@ TokenStream::getTokenInternal(TokenKind* ttp, Modifier modifier) reflags = RegExpFlag(reflags | StickyFlag); else if (c == 'u' && !(reflags & UnicodeFlag)) reflags = RegExpFlag(reflags | UnicodeFlag); + else if (c == 's' && !(reflags & DotAllFlag)) + reflags = RegExpFlag(reflags | DotAllFlag); else break; getChar(); diff --git a/js/src/irregexp/RegExpParser.cpp b/js/src/irregexp/RegExpParser.cpp index 9ef9fe3e2..28abdb0b4 100644 --- a/js/src/irregexp/RegExpParser.cpp +++ b/js/src/irregexp/RegExpParser.cpp @@ -1384,7 +1384,7 @@ UnicodeEverythingAtom(LifoAlloc* alloc) { RegExpBuilder* builder = alloc->newInfallible(alloc); - // everything except \x0a, \x0d, \u2028 and \u2029 + // Everything except \x0a, \x0d, \u2028 and \u2029 CharacterRangeVector* ranges = alloc->newInfallible(*alloc); ranges->append(CharacterRange::Range(0x0, 0x09)); @@ -1414,6 +1414,38 @@ UnicodeEverythingAtom(LifoAlloc* alloc) return builder->ToRegExp(); } +static inline RegExpTree* +UnicodeDotAllAtom(LifoAlloc* alloc) +{ + RegExpBuilder* builder = alloc->newInfallible(alloc); + + // Full range excluding surrogates because /s was specified + + CharacterRangeVector* ranges = alloc->newInfallible(*alloc); + ranges->append(CharacterRange::Range(0x0, unicode::LeadSurrogateMin - 1)); + ranges->append(CharacterRange::Range(unicode::TrailSurrogateMax + 1, unicode::UTF16Max)); + builder->AddAtom(alloc->newInfallible(ranges, false)); + + builder->NewAlternative(); + + builder->AddAtom(RangeAtom(alloc, unicode::LeadSurrogateMin, unicode::LeadSurrogateMax)); + builder->AddAtom(NegativeLookahead(alloc, unicode::TrailSurrogateMin, + unicode::TrailSurrogateMax)); + + builder->NewAlternative(); + + builder->AddAssertion(alloc->newInfallible( + RegExpAssertion::NOT_AFTER_LEAD_SURROGATE)); + builder->AddAtom(RangeAtom(alloc, unicode::TrailSurrogateMin, unicode::TrailSurrogateMax)); + + builder->NewAlternative(); + + builder->AddAtom(RangeAtom(alloc, unicode::LeadSurrogateMin, unicode::LeadSurrogateMax)); + builder->AddAtom(RangeAtom(alloc, unicode::TrailSurrogateMin, unicode::TrailSurrogateMax)); + + return builder->ToRegExp(); +} + RegExpTree* UnicodeCharacterClassEscapeAtom(LifoAlloc* alloc, char16_t char_class, bool ignore_case) { @@ -1541,13 +1573,25 @@ RegExpParser::ParseDisjunction() } case '.': { Advance(); - // everything except \x0a, \x0d, \u2028 and \u2029 + if (unicode_) { - builder->AddAtom(UnicodeEverythingAtom(alloc)); + if (dotall_) { + // Everything + builder->AddAtom(UnicodeDotAllAtom(alloc)); + } else { + // Everything except \x0a, \x0d, \u2028 and \u2029 + builder->AddAtom(UnicodeEverythingAtom(alloc)); + } break; } CharacterRangeVector* ranges = alloc->newInfallible(*alloc); - CharacterRange::AddClassEscape(alloc, '.', ranges); + if (dotall_) { + // Everything + CharacterRange::AddClassEscape(alloc, '*', ranges); + } else { + // Everything except \x0a, \x0d, \u2028 and \u2029 + CharacterRange::AddClassEscape(alloc, '.', ranges); + } RegExpTree* atom = alloc->newInfallible(ranges, false); builder->AddAtom(atom); break; diff --git a/js/src/irregexp/RegExpParser.h b/js/src/irregexp/RegExpParser.h index 2f02625b5..36c24cd7c 100644 --- a/js/src/irregexp/RegExpParser.h +++ b/js/src/irregexp/RegExpParser.h @@ -313,6 +313,7 @@ class RegExpParser bool multiline_; bool unicode_; bool ignore_case_; + bool dotall_; bool simple_; bool contains_anchor_; bool is_scanned_for_captures_; diff --git a/js/src/vm/RegExpObject.h b/js/src/vm/RegExpObject.h index f1ea101ed..4548521df 100644 --- a/js/src/vm/RegExpObject.h +++ b/js/src/vm/RegExpObject.h @@ -53,16 +53,18 @@ enum RegExpFlag MultilineFlag = 0x04, StickyFlag = 0x08, UnicodeFlag = 0x10, + DotAllFlag = 0x20, NoFlags = 0x00, - AllFlags = 0x1f + AllFlags = 0x3f }; static_assert(IgnoreCaseFlag == REGEXP_IGNORECASE_FLAG && GlobalFlag == REGEXP_GLOBAL_FLAG && MultilineFlag == REGEXP_MULTILINE_FLAG && StickyFlag == REGEXP_STICKY_FLAG && - UnicodeFlag == REGEXP_UNICODE_FLAG, + UnicodeFlag == REGEXP_UNICODE_FLAG && + DotAllFlag == REGEXP_DOTALL_FLAG, "Flag values should be in sync with self-hosted JS"); enum RegExpRunStatus @@ -480,6 +482,7 @@ class RegExpObject : public NativeObject bool multiline() const { return getFlags() & MultilineFlag; } bool sticky() const { return getFlags() & StickyFlag; } bool unicode() const { return getFlags() & UnicodeFlag; } + bool dotall() const { return getFlags() & DotAllFlag; } static bool isOriginalFlagGetter(JSNative native, RegExpFlag* mask); -- cgit v1.2.3 From bd529c60c67af685de029e2408da3d2bc6980291 Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Mon, 18 Nov 2019 13:34:18 +0100 Subject: Revert "Issue #1284 - Implement /s (dotAll) for regular expressions." This reverts commit f31b04a303607cd82757e7c4f60bb536658c8a30. --- js/src/builtin/RegExp.cpp | 24 ----------------- js/src/builtin/RegExp.h | 2 -- js/src/builtin/RegExp.js | 5 ---- js/src/builtin/SelfHostingDefines.h | 1 - js/src/frontend/TokenStream.cpp | 2 -- js/src/irregexp/RegExpParser.cpp | 52 +++---------------------------------- js/src/irregexp/RegExpParser.h | 1 - js/src/vm/RegExpObject.h | 7 ++--- 8 files changed, 6 insertions(+), 88 deletions(-) (limited to 'js/src') diff --git a/js/src/builtin/RegExp.cpp b/js/src/builtin/RegExp.cpp index 93a7f2b79..7cf20d23c 100644 --- a/js/src/builtin/RegExp.cpp +++ b/js/src/builtin/RegExp.cpp @@ -664,29 +664,6 @@ js::regexp_multiline(JSContext* cx, unsigned argc, JS::Value* vp) return CallNonGenericMethod(cx, args); } -// ES 2018 dotAll -MOZ_ALWAYS_INLINE bool -regexp_dotall_impl(JSContext* cx, const CallArgs& args) -{ - MOZ_ASSERT(IsRegExpInstanceOrPrototype(args.thisv())); - - if (!IsRegExpObject(args.thisv())) { - args.rval().setUndefined(); - return true; - } - - Rooted reObj(cx, &args.thisv().toObject().as()); - args.rval().setBoolean(reObj->dotall()); - return true; -} - -bool -js::regexp_dotall(JSContext* cx, unsigned argc, JS::Value* vp) -{ - CallArgs args = CallArgsFromVp(argc, vp); - return CallNonGenericMethod(cx, args); -} - // ES 2017 draft rev32 21.2.5.10. MOZ_ALWAYS_INLINE bool regexp_source_impl(JSContext* cx, const CallArgs& args) @@ -782,7 +759,6 @@ const JSPropertySpec js::regexp_properties[] = { JS_PSG("source", regexp_source, 0), JS_PSG("sticky", regexp_sticky, 0), JS_PSG("unicode", regexp_unicode, 0), - JS_PSG("dotall", regexp_dotall, 0), JS_PS_END }; diff --git a/js/src/builtin/RegExp.h b/js/src/builtin/RegExp.h index f808f5146..4e0ff6948 100644 --- a/js/src/builtin/RegExp.h +++ b/js/src/builtin/RegExp.h @@ -153,8 +153,6 @@ extern MOZ_MUST_USE bool regexp_sticky(JSContext* cx, unsigned argc, JS::Value* vp); extern MOZ_MUST_USE bool regexp_unicode(JSContext* cx, unsigned argc, JS::Value* vp); -extern MOZ_MUST_USE bool -regexp_dotall(JSContext* cx, unsigned argc, JS::Value* vp); } /* namespace js */ diff --git a/js/src/builtin/RegExp.js b/js/src/builtin/RegExp.js index 1a2276594..0b849292c 100644 --- a/js/src/builtin/RegExp.js +++ b/js/src/builtin/RegExp.js @@ -3,7 +3,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ // ES6 draft rev34 (2015/02/20) 21.2.5.3 get RegExp.prototype.flags -// Updated for ES2018 /s (dotAll) function RegExpFlagsGetter() { // Steps 1-2. var R = this; @@ -32,10 +31,6 @@ function RegExpFlagsGetter() { // Steps 16-18. if (R.sticky) result += "y"; - - // ES2018 - if (R.dotall) - result += "s"; // Step 19. return result; diff --git a/js/src/builtin/SelfHostingDefines.h b/js/src/builtin/SelfHostingDefines.h index 6512810ca..d676270a1 100644 --- a/js/src/builtin/SelfHostingDefines.h +++ b/js/src/builtin/SelfHostingDefines.h @@ -90,7 +90,6 @@ #define REGEXP_MULTILINE_FLAG 0x04 #define REGEXP_STICKY_FLAG 0x08 #define REGEXP_UNICODE_FLAG 0x10 -#define REGEXP_DOTALL_FLAG 0x20 #define MODULE_OBJECT_ENVIRONMENT_SLOT 2 diff --git a/js/src/frontend/TokenStream.cpp b/js/src/frontend/TokenStream.cpp index e07f8df8a..b8623d545 100644 --- a/js/src/frontend/TokenStream.cpp +++ b/js/src/frontend/TokenStream.cpp @@ -1843,8 +1843,6 @@ TokenStream::getTokenInternal(TokenKind* ttp, Modifier modifier) reflags = RegExpFlag(reflags | StickyFlag); else if (c == 'u' && !(reflags & UnicodeFlag)) reflags = RegExpFlag(reflags | UnicodeFlag); - else if (c == 's' && !(reflags & DotAllFlag)) - reflags = RegExpFlag(reflags | DotAllFlag); else break; getChar(); diff --git a/js/src/irregexp/RegExpParser.cpp b/js/src/irregexp/RegExpParser.cpp index 28abdb0b4..9ef9fe3e2 100644 --- a/js/src/irregexp/RegExpParser.cpp +++ b/js/src/irregexp/RegExpParser.cpp @@ -1384,7 +1384,7 @@ UnicodeEverythingAtom(LifoAlloc* alloc) { RegExpBuilder* builder = alloc->newInfallible(alloc); - // Everything except \x0a, \x0d, \u2028 and \u2029 + // everything except \x0a, \x0d, \u2028 and \u2029 CharacterRangeVector* ranges = alloc->newInfallible(*alloc); ranges->append(CharacterRange::Range(0x0, 0x09)); @@ -1414,38 +1414,6 @@ UnicodeEverythingAtom(LifoAlloc* alloc) return builder->ToRegExp(); } -static inline RegExpTree* -UnicodeDotAllAtom(LifoAlloc* alloc) -{ - RegExpBuilder* builder = alloc->newInfallible(alloc); - - // Full range excluding surrogates because /s was specified - - CharacterRangeVector* ranges = alloc->newInfallible(*alloc); - ranges->append(CharacterRange::Range(0x0, unicode::LeadSurrogateMin - 1)); - ranges->append(CharacterRange::Range(unicode::TrailSurrogateMax + 1, unicode::UTF16Max)); - builder->AddAtom(alloc->newInfallible(ranges, false)); - - builder->NewAlternative(); - - builder->AddAtom(RangeAtom(alloc, unicode::LeadSurrogateMin, unicode::LeadSurrogateMax)); - builder->AddAtom(NegativeLookahead(alloc, unicode::TrailSurrogateMin, - unicode::TrailSurrogateMax)); - - builder->NewAlternative(); - - builder->AddAssertion(alloc->newInfallible( - RegExpAssertion::NOT_AFTER_LEAD_SURROGATE)); - builder->AddAtom(RangeAtom(alloc, unicode::TrailSurrogateMin, unicode::TrailSurrogateMax)); - - builder->NewAlternative(); - - builder->AddAtom(RangeAtom(alloc, unicode::LeadSurrogateMin, unicode::LeadSurrogateMax)); - builder->AddAtom(RangeAtom(alloc, unicode::TrailSurrogateMin, unicode::TrailSurrogateMax)); - - return builder->ToRegExp(); -} - RegExpTree* UnicodeCharacterClassEscapeAtom(LifoAlloc* alloc, char16_t char_class, bool ignore_case) { @@ -1573,25 +1541,13 @@ RegExpParser::ParseDisjunction() } case '.': { Advance(); - + // everything except \x0a, \x0d, \u2028 and \u2029 if (unicode_) { - if (dotall_) { - // Everything - builder->AddAtom(UnicodeDotAllAtom(alloc)); - } else { - // Everything except \x0a, \x0d, \u2028 and \u2029 - builder->AddAtom(UnicodeEverythingAtom(alloc)); - } + builder->AddAtom(UnicodeEverythingAtom(alloc)); break; } CharacterRangeVector* ranges = alloc->newInfallible(*alloc); - if (dotall_) { - // Everything - CharacterRange::AddClassEscape(alloc, '*', ranges); - } else { - // Everything except \x0a, \x0d, \u2028 and \u2029 - CharacterRange::AddClassEscape(alloc, '.', ranges); - } + CharacterRange::AddClassEscape(alloc, '.', ranges); RegExpTree* atom = alloc->newInfallible(ranges, false); builder->AddAtom(atom); break; diff --git a/js/src/irregexp/RegExpParser.h b/js/src/irregexp/RegExpParser.h index 36c24cd7c..2f02625b5 100644 --- a/js/src/irregexp/RegExpParser.h +++ b/js/src/irregexp/RegExpParser.h @@ -313,7 +313,6 @@ class RegExpParser bool multiline_; bool unicode_; bool ignore_case_; - bool dotall_; bool simple_; bool contains_anchor_; bool is_scanned_for_captures_; diff --git a/js/src/vm/RegExpObject.h b/js/src/vm/RegExpObject.h index 4548521df..f1ea101ed 100644 --- a/js/src/vm/RegExpObject.h +++ b/js/src/vm/RegExpObject.h @@ -53,18 +53,16 @@ enum RegExpFlag MultilineFlag = 0x04, StickyFlag = 0x08, UnicodeFlag = 0x10, - DotAllFlag = 0x20, NoFlags = 0x00, - AllFlags = 0x3f + AllFlags = 0x1f }; static_assert(IgnoreCaseFlag == REGEXP_IGNORECASE_FLAG && GlobalFlag == REGEXP_GLOBAL_FLAG && MultilineFlag == REGEXP_MULTILINE_FLAG && StickyFlag == REGEXP_STICKY_FLAG && - UnicodeFlag == REGEXP_UNICODE_FLAG && - DotAllFlag == REGEXP_DOTALL_FLAG, + UnicodeFlag == REGEXP_UNICODE_FLAG, "Flag values should be in sync with self-hosted JS"); enum RegExpRunStatus @@ -482,7 +480,6 @@ class RegExpObject : public NativeObject bool multiline() const { return getFlags() & MultilineFlag; } bool sticky() const { return getFlags() & StickyFlag; } bool unicode() const { return getFlags() & UnicodeFlag; } - bool dotall() const { return getFlags() & DotAllFlag; } static bool isOriginalFlagGetter(JSNative native, RegExpFlag* mask); -- cgit v1.2.3 From 122e1ee6cd24b5de80a1702313db732c8961202a Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Mon, 18 Nov 2019 16:50:40 +0100 Subject: Issue #1284 - Implement /s (dotAll) for regular expressions, v2. Resolves #1284. --- js/src/builtin/RegExp.cpp | 33 +++++++++++++++- js/src/builtin/RegExp.h | 2 + js/src/builtin/RegExp.js | 5 +++ js/src/builtin/SelfHostingDefines.h | 1 + js/src/frontend/TokenStream.cpp | 2 + js/src/irregexp/RegExpParser.cpp | 75 +++++++++++++++++++++++++++++-------- js/src/irregexp/RegExpParser.h | 7 ++-- js/src/jsapi.h | 1 + js/src/vm/CommonPropertyNames.h | 1 + js/src/vm/RegExpObject.cpp | 5 ++- js/src/vm/RegExpObject.h | 8 +++- 11 files changed, 117 insertions(+), 23 deletions(-) (limited to 'js/src') diff --git a/js/src/builtin/RegExp.cpp b/js/src/builtin/RegExp.cpp index 7cf20d23c..b7853d533 100644 --- a/js/src/builtin/RegExp.cpp +++ b/js/src/builtin/RegExp.cpp @@ -178,7 +178,7 @@ CheckPatternSyntax(JSContext* cx, HandleAtom pattern, RegExpFlag flags) CompileOptions options(cx); frontend::TokenStream dummyTokenStream(cx, options, nullptr, 0, nullptr); return irregexp::ParsePatternSyntax(dummyTokenStream, cx->tempLifoAlloc(), pattern, - flags & UnicodeFlag); + flags & UnicodeFlag, flags & DotAllFlag); } enum RegExpSharedUse { @@ -664,6 +664,29 @@ js::regexp_multiline(JSContext* cx, unsigned argc, JS::Value* vp) return CallNonGenericMethod(cx, args); } +// ES 2018 dotAll +MOZ_ALWAYS_INLINE bool +regexp_dotall_impl(JSContext* cx, const CallArgs& args) +{ + MOZ_ASSERT(IsRegExpInstanceOrPrototype(args.thisv())); + + if (!IsRegExpObject(args.thisv())) { + args.rval().setUndefined(); + return true; + } + + Rooted reObj(cx, &args.thisv().toObject().as()); + args.rval().setBoolean(reObj->dotall()); + return true; +} + +bool +js::regexp_dotall(JSContext* cx, unsigned argc, JS::Value* vp) +{ + CallArgs args = CallArgsFromVp(argc, vp); + return CallNonGenericMethod(cx, args); +} + // ES 2017 draft rev32 21.2.5.10. MOZ_ALWAYS_INLINE bool regexp_source_impl(JSContext* cx, const CallArgs& args) @@ -759,6 +782,7 @@ const JSPropertySpec js::regexp_properties[] = { JS_PSG("source", regexp_source, 0), JS_PSG("sticky", regexp_sticky, 0), JS_PSG("unicode", regexp_unicode, 0), + JS_PSG("dotall", regexp_dotall, 0), JS_PS_END }; @@ -1642,6 +1666,13 @@ js::RegExpPrototypeOptimizableRaw(JSContext* cx, JSObject* proto) if (unicodeGetter != regexp_unicode) return false; + JSNative dotAllGetter; + if (!GetOwnNativeGetterPure(cx, proto, NameToId(cx->names().dotall), &dotAllGetter)) + return false; + + if (dotAllGetter != regexp_dotall) + return false; + // Check if @@match, @@search, and exec are own data properties, // those values should be tested in selfhosted JS. bool has = false; diff --git a/js/src/builtin/RegExp.h b/js/src/builtin/RegExp.h index 4e0ff6948..f808f5146 100644 --- a/js/src/builtin/RegExp.h +++ b/js/src/builtin/RegExp.h @@ -153,6 +153,8 @@ extern MOZ_MUST_USE bool regexp_sticky(JSContext* cx, unsigned argc, JS::Value* vp); extern MOZ_MUST_USE bool regexp_unicode(JSContext* cx, unsigned argc, JS::Value* vp); +extern MOZ_MUST_USE bool +regexp_dotall(JSContext* cx, unsigned argc, JS::Value* vp); } /* namespace js */ diff --git a/js/src/builtin/RegExp.js b/js/src/builtin/RegExp.js index 0b849292c..1a2276594 100644 --- a/js/src/builtin/RegExp.js +++ b/js/src/builtin/RegExp.js @@ -3,6 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ // ES6 draft rev34 (2015/02/20) 21.2.5.3 get RegExp.prototype.flags +// Updated for ES2018 /s (dotAll) function RegExpFlagsGetter() { // Steps 1-2. var R = this; @@ -31,6 +32,10 @@ function RegExpFlagsGetter() { // Steps 16-18. if (R.sticky) result += "y"; + + // ES2018 + if (R.dotall) + result += "s"; // Step 19. return result; diff --git a/js/src/builtin/SelfHostingDefines.h b/js/src/builtin/SelfHostingDefines.h index d676270a1..6512810ca 100644 --- a/js/src/builtin/SelfHostingDefines.h +++ b/js/src/builtin/SelfHostingDefines.h @@ -90,6 +90,7 @@ #define REGEXP_MULTILINE_FLAG 0x04 #define REGEXP_STICKY_FLAG 0x08 #define REGEXP_UNICODE_FLAG 0x10 +#define REGEXP_DOTALL_FLAG 0x20 #define MODULE_OBJECT_ENVIRONMENT_SLOT 2 diff --git a/js/src/frontend/TokenStream.cpp b/js/src/frontend/TokenStream.cpp index b8623d545..e07f8df8a 100644 --- a/js/src/frontend/TokenStream.cpp +++ b/js/src/frontend/TokenStream.cpp @@ -1843,6 +1843,8 @@ TokenStream::getTokenInternal(TokenKind* ttp, Modifier modifier) reflags = RegExpFlag(reflags | StickyFlag); else if (c == 'u' && !(reflags & UnicodeFlag)) reflags = RegExpFlag(reflags | UnicodeFlag); + else if (c == 's' && !(reflags & DotAllFlag)) + reflags = RegExpFlag(reflags | DotAllFlag); else break; getChar(); diff --git a/js/src/irregexp/RegExpParser.cpp b/js/src/irregexp/RegExpParser.cpp index 9ef9fe3e2..1ad044e8e 100644 --- a/js/src/irregexp/RegExpParser.cpp +++ b/js/src/irregexp/RegExpParser.cpp @@ -222,7 +222,7 @@ RegExpBuilder::AddQuantifierToAtom(int min, int max, template RegExpParser::RegExpParser(frontend::TokenStream& ts, LifoAlloc* alloc, const CharT* chars, const CharT* end, bool multiline_mode, - bool unicode, bool ignore_case) + bool unicode, bool ignore_case, bool dotall) : ts(ts), alloc(alloc), captures_(nullptr), @@ -235,6 +235,7 @@ RegExpParser::RegExpParser(frontend::TokenStream& ts, LifoAlloc* alloc, multiline_(multiline_mode), unicode_(unicode), ignore_case_(ignore_case), + dotall_(dotall), simple_(false), contains_anchor_(false), is_scanned_for_captures_(false) @@ -1384,7 +1385,7 @@ UnicodeEverythingAtom(LifoAlloc* alloc) { RegExpBuilder* builder = alloc->newInfallible(alloc); - // everything except \x0a, \x0d, \u2028 and \u2029 + // Everything except \x0a, \x0d, \u2028 and \u2029 CharacterRangeVector* ranges = alloc->newInfallible(*alloc); ranges->append(CharacterRange::Range(0x0, 0x09)); @@ -1414,6 +1415,38 @@ UnicodeEverythingAtom(LifoAlloc* alloc) return builder->ToRegExp(); } +static inline RegExpTree* +UnicodeDotAllAtom(LifoAlloc* alloc) +{ + RegExpBuilder* builder = alloc->newInfallible(alloc); + + // Full range excluding surrogates because /s was specified + + CharacterRangeVector* ranges = alloc->newInfallible(*alloc); + ranges->append(CharacterRange::Range(0x0, unicode::LeadSurrogateMin - 1)); + ranges->append(CharacterRange::Range(unicode::TrailSurrogateMax + 1, unicode::UTF16Max)); + builder->AddAtom(alloc->newInfallible(ranges, false)); + + builder->NewAlternative(); + + builder->AddAtom(RangeAtom(alloc, unicode::LeadSurrogateMin, unicode::LeadSurrogateMax)); + builder->AddAtom(NegativeLookahead(alloc, unicode::TrailSurrogateMin, + unicode::TrailSurrogateMax)); + + builder->NewAlternative(); + + builder->AddAssertion(alloc->newInfallible( + RegExpAssertion::NOT_AFTER_LEAD_SURROGATE)); + builder->AddAtom(RangeAtom(alloc, unicode::TrailSurrogateMin, unicode::TrailSurrogateMax)); + + builder->NewAlternative(); + + builder->AddAtom(RangeAtom(alloc, unicode::LeadSurrogateMin, unicode::LeadSurrogateMax)); + builder->AddAtom(RangeAtom(alloc, unicode::TrailSurrogateMin, unicode::TrailSurrogateMax)); + + return builder->ToRegExp(); +} + RegExpTree* UnicodeCharacterClassEscapeAtom(LifoAlloc* alloc, char16_t char_class, bool ignore_case) { @@ -1541,13 +1574,25 @@ RegExpParser::ParseDisjunction() } case '.': { Advance(); - // everything except \x0a, \x0d, \u2028 and \u2029 + if (unicode_) { - builder->AddAtom(UnicodeEverythingAtom(alloc)); + if (dotall_) { + // Everything + builder->AddAtom(UnicodeDotAllAtom(alloc)); + } else { + // Everything except \x0a, \x0d, \u2028 and \u2029 + builder->AddAtom(UnicodeEverythingAtom(alloc)); + } break; } CharacterRangeVector* ranges = alloc->newInfallible(*alloc); - CharacterRange::AddClassEscape(alloc, '.', ranges); + if (dotall_) { + // Everything + CharacterRange::AddClassEscape(alloc, '*', ranges); + } else { + // Everything except \x0a, \x0d, \u2028 and \u2029 + CharacterRange::AddClassEscape(alloc, '.', ranges); + } RegExpTree* atom = alloc->newInfallible(ranges, false); builder->AddAtom(atom); break; @@ -1880,7 +1925,7 @@ template static bool ParsePattern(frontend::TokenStream& ts, LifoAlloc& alloc, const CharT* chars, size_t length, bool multiline, bool match_only, bool unicode, bool ignore_case, - bool global, bool sticky, RegExpCompileData* data) + bool global, bool sticky, bool dotall, RegExpCompileData* data) { if (match_only) { // Try to strip a leading '.*' from the RegExp, but only if it is not @@ -1907,7 +1952,7 @@ ParsePattern(frontend::TokenStream& ts, LifoAlloc& alloc, const CharT* chars, si } } - RegExpParser parser(ts, &alloc, chars, chars + length, multiline, unicode, ignore_case); + RegExpParser parser(ts, &alloc, chars, chars + length, multiline, unicode, ignore_case, dotall); data->tree = parser.ParsePattern(); if (!data->tree) return false; @@ -1921,33 +1966,33 @@ ParsePattern(frontend::TokenStream& ts, LifoAlloc& alloc, const CharT* chars, si bool irregexp::ParsePattern(frontend::TokenStream& ts, LifoAlloc& alloc, JSAtom* str, bool multiline, bool match_only, bool unicode, bool ignore_case, - bool global, bool sticky, RegExpCompileData* data) + bool global, bool sticky, bool dotall, RegExpCompileData* data) { JS::AutoCheckCannotGC nogc; return str->hasLatin1Chars() ? ::ParsePattern(ts, alloc, str->latin1Chars(nogc), str->length(), - multiline, match_only, unicode, ignore_case, global, sticky, data) + multiline, match_only, unicode, ignore_case, global, sticky, dotall, data) : ::ParsePattern(ts, alloc, str->twoByteChars(nogc), str->length(), - multiline, match_only, unicode, ignore_case, global, sticky, data); + multiline, match_only, unicode, ignore_case, global, sticky, dotall, data); } template static bool ParsePatternSyntax(frontend::TokenStream& ts, LifoAlloc& alloc, const CharT* chars, size_t length, - bool unicode) + bool unicode, bool dotall) { LifoAllocScope scope(&alloc); - RegExpParser parser(ts, &alloc, chars, chars + length, false, unicode, false); + RegExpParser parser(ts, &alloc, chars, chars + length, false, unicode, dotall, false); return parser.ParsePattern() != nullptr; } bool irregexp::ParsePatternSyntax(frontend::TokenStream& ts, LifoAlloc& alloc, JSAtom* str, - bool unicode) + bool unicode, bool dotall) { JS::AutoCheckCannotGC nogc; return str->hasLatin1Chars() - ? ::ParsePatternSyntax(ts, alloc, str->latin1Chars(nogc), str->length(), unicode) - : ::ParsePatternSyntax(ts, alloc, str->twoByteChars(nogc), str->length(), unicode); + ? ::ParsePatternSyntax(ts, alloc, str->latin1Chars(nogc), str->length(), unicode, dotall) + : ::ParsePatternSyntax(ts, alloc, str->twoByteChars(nogc), str->length(), unicode, dotall); } diff --git a/js/src/irregexp/RegExpParser.h b/js/src/irregexp/RegExpParser.h index 2f02625b5..ee57f0436 100644 --- a/js/src/irregexp/RegExpParser.h +++ b/js/src/irregexp/RegExpParser.h @@ -44,11 +44,11 @@ namespace irregexp { bool ParsePattern(frontend::TokenStream& ts, LifoAlloc& alloc, JSAtom* str, bool multiline, bool match_only, bool unicode, bool ignore_case, - bool global, bool sticky, RegExpCompileData* data); + bool global, bool sticky, bool dotall, RegExpCompileData* data); bool ParsePatternSyntax(frontend::TokenStream& ts, LifoAlloc& alloc, JSAtom* str, - bool unicode); + bool unicode, bool dotall); // A BufferedVector is an automatically growing list, just like (and backed // by) a Vector, that is optimized for the case of adding and removing @@ -178,7 +178,7 @@ class RegExpParser public: RegExpParser(frontend::TokenStream& ts, LifoAlloc* alloc, const CharT* chars, const CharT* end, bool multiline_mode, bool unicode, - bool ignore_case); + bool ignore_case, bool dotall); RegExpTree* ParsePattern(); RegExpTree* ParseDisjunction(); @@ -313,6 +313,7 @@ class RegExpParser bool multiline_; bool unicode_; bool ignore_case_; + bool dotall_; bool simple_; bool contains_anchor_; bool is_scanned_for_captures_; diff --git a/js/src/jsapi.h b/js/src/jsapi.h index dc00c650d..1a69b1513 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -5704,6 +5704,7 @@ JS_ObjectIsDate(JSContext* cx, JS::HandleObject obj, bool* isDate); #define JSREG_MULTILINE 0x04u /* treat ^ and $ as begin and end of line */ #define JSREG_STICKY 0x08u /* only match starting at lastIndex */ #define JSREG_UNICODE 0x10u /* unicode */ +#define JSREG_DOTALL 0x20u /* match . to everything including newlines */ extern JS_PUBLIC_API(JSObject*) JS_NewRegExpObject(JSContext* cx, const char* bytes, size_t length, unsigned flags); diff --git a/js/src/vm/CommonPropertyNames.h b/js/src/vm/CommonPropertyNames.h index fd1c9f5e6..4ae49d577 100644 --- a/js/src/vm/CommonPropertyNames.h +++ b/js/src/vm/CommonPropertyNames.h @@ -97,6 +97,7 @@ macro(displayURL, displayURL, "displayURL") \ macro(do, do_, "do") \ macro(done, done, "done") \ + macro(dotall, dotall, "dotall") \ macro(dotGenerator, dotGenerator, ".generator") \ macro(dotThis, dotThis, ".this") \ macro(each, each, "each") \ diff --git a/js/src/vm/RegExpObject.cpp b/js/src/vm/RegExpObject.cpp index ef97ed816..cd0b54c9d 100644 --- a/js/src/vm/RegExpObject.cpp +++ b/js/src/vm/RegExpObject.cpp @@ -49,6 +49,7 @@ JS_STATIC_ASSERT(GlobalFlag == JSREG_GLOB); JS_STATIC_ASSERT(MultilineFlag == JSREG_MULTILINE); JS_STATIC_ASSERT(StickyFlag == JSREG_STICKY); JS_STATIC_ASSERT(UnicodeFlag == JSREG_UNICODE); +JS_STATIC_ASSERT(DotAllFlag == JSREG_DOTALL); RegExpObject* js::RegExpAlloc(ExclusiveContext* cx, HandleObject proto /* = nullptr */) @@ -267,7 +268,7 @@ RegExpObject::create(ExclusiveContext* cx, HandleAtom source, RegExpFlag flags, tokenStream = dummyTokenStream.ptr(); } - if (!irregexp::ParsePatternSyntax(*tokenStream, alloc, source, flags & UnicodeFlag)) + if (!irregexp::ParsePatternSyntax(*tokenStream, alloc, source, flags & UnicodeFlag, flags & DotAllFlag)) return nullptr; Rooted regexp(cx, RegExpAlloc(cx)); @@ -1017,7 +1018,7 @@ RegExpShared::compile(JSContext* cx, HandleAtom pattern, HandleLinearString inpu irregexp::RegExpCompileData data; if (!irregexp::ParsePattern(dummyTokenStream, cx->tempLifoAlloc(), pattern, multiline(), mode == MatchOnly, unicode(), ignoreCase(), - global(), sticky(), &data)) + global(), sticky(), dotall(), &data)) { return false; } diff --git a/js/src/vm/RegExpObject.h b/js/src/vm/RegExpObject.h index f1ea101ed..95c64fa67 100644 --- a/js/src/vm/RegExpObject.h +++ b/js/src/vm/RegExpObject.h @@ -53,16 +53,18 @@ enum RegExpFlag MultilineFlag = 0x04, StickyFlag = 0x08, UnicodeFlag = 0x10, + DotAllFlag = 0x20, NoFlags = 0x00, - AllFlags = 0x1f + AllFlags = 0x3f }; static_assert(IgnoreCaseFlag == REGEXP_IGNORECASE_FLAG && GlobalFlag == REGEXP_GLOBAL_FLAG && MultilineFlag == REGEXP_MULTILINE_FLAG && StickyFlag == REGEXP_STICKY_FLAG && - UnicodeFlag == REGEXP_UNICODE_FLAG, + UnicodeFlag == REGEXP_UNICODE_FLAG && + DotAllFlag == REGEXP_DOTALL_FLAG, "Flag values should be in sync with self-hosted JS"); enum RegExpRunStatus @@ -193,6 +195,7 @@ class RegExpShared bool multiline() const { return flags & MultilineFlag; } bool sticky() const { return flags & StickyFlag; } bool unicode() const { return flags & UnicodeFlag; } + bool dotall() const { return flags & DotAllFlag; } bool isCompiled(CompilationMode mode, bool latin1, ForceByteCodeEnum force = DontForceByteCode) const { @@ -480,6 +483,7 @@ class RegExpObject : public NativeObject bool multiline() const { return getFlags() & MultilineFlag; } bool sticky() const { return getFlags() & StickyFlag; } bool unicode() const { return getFlags() & UnicodeFlag; } + bool dotall() const { return getFlags() & DotAllFlag; } static bool isOriginalFlagGetter(JSNative native, RegExpFlag* mask); -- cgit v1.2.3 From 0a6ccfaa9a28948a7a8f16fc50c884fff375ef8e Mon Sep 17 00:00:00 2001 From: Gaming4JC Date: Mon, 18 Nov 2019 19:30:45 -0500 Subject: Issue #1284 - Update js/src/builtin/TestingFunctions.cpp for /s (dotAll) regular expression changes This fixes debug builds --- js/src/builtin/TestingFunctions.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'js/src') diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctions.cpp index 072a72b75..b521e2bb3 100644 --- a/js/src/builtin/TestingFunctions.cpp +++ b/js/src/builtin/TestingFunctions.cpp @@ -3975,6 +3975,7 @@ ParseRegExp(JSContext* cx, unsigned argc, Value* vp) flags & MultilineFlag, match_only, flags & UnicodeFlag, flags & IgnoreCaseFlag, flags & GlobalFlag, flags & StickyFlag, + flags & DotAllFlag, &data)) { return false; -- cgit v1.2.3 From 185a9a750878ed1d9705fbd162dbfe9bf2e4ea0c Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Tue, 26 Nov 2019 13:37:09 +0100 Subject: Issue #1302 - Add self-hosted implementation for string regex .matchAll This resolves #1302. --- js/src/builtin/RegExp.cpp | 1 + js/src/builtin/RegExp.js | 132 ++++++++++++++++++++++++++++++++++++ js/src/builtin/SelfHostingDefines.h | 5 ++ js/src/builtin/String.js | 27 ++++++++ js/src/jsapi.h | 3 +- js/src/jsiter.cpp | 57 ++++++++++++++++ js/src/jsiter.h | 6 ++ js/src/jsstr.cpp | 1 + js/src/vm/CommonPropertyNames.h | 1 + js/src/vm/GlobalObject.cpp | 79 +++++++-------------- js/src/vm/GlobalObject.h | 8 +++ js/src/vm/SelfHosting.cpp | 23 +++++++ 12 files changed, 286 insertions(+), 57 deletions(-) (limited to 'js/src') diff --git a/js/src/builtin/RegExp.cpp b/js/src/builtin/RegExp.cpp index b7853d533..55e0c8578 100644 --- a/js/src/builtin/RegExp.cpp +++ b/js/src/builtin/RegExp.cpp @@ -795,6 +795,7 @@ const JSFunctionSpec js::regexp_methods[] = { JS_SELF_HOSTED_FN("exec", "RegExp_prototype_Exec", 1,0), JS_SELF_HOSTED_FN("test", "RegExpTest" , 1,0), JS_SELF_HOSTED_SYM_FN(match, "RegExpMatch", 1,0), + JS_SELF_HOSTED_SYM_FN(matchAll, "RegExpMatchAll", 1, 0), JS_SELF_HOSTED_SYM_FN(replace, "RegExpReplace", 2,0), JS_SELF_HOSTED_SYM_FN(search, "RegExpSearch", 1,0), JS_SELF_HOSTED_SYM_FN(split, "RegExpSplit", 2,0), diff --git a/js/src/builtin/RegExp.js b/js/src/builtin/RegExp.js index 1a2276594..25827743e 100644 --- a/js/src/builtin/RegExp.js +++ b/js/src/builtin/RegExp.js @@ -1031,3 +1031,135 @@ function RegExpSpecies() { return this; } _SetCanonicalName(RegExpSpecies, "get [Symbol.species]"); + +// String.prototype.matchAll proposal. +// +// RegExp.prototype [ @@matchAll ] ( string ) +function RegExpMatchAll(string) { + // Step 1. + var rx = this; + + // Step 2. + if (!IsObject(rx)) + ThrowTypeError(JSMSG_NOT_NONNULL_OBJECT, rx === null ? "null" : typeof rx); + + // Step 3. + var str = ToString(string); + + // Step 4. + var C = SpeciesConstructor(rx, GetBuiltinConstructor("RegExp")); + + // Step 5. + var flags = ToString(rx.flags); + + // Step 2.b.iii; located here because it needs |flags|. + if (!callFunction(std_String_includes, flags, "g")) { + ThrowTypeError(JSMSG_BAD_REGEXP_FLAG, "- matchAll requires g"); + } + + // Step 6. + var matcher = new C(rx, flags); + + // Steps 7-8. + matcher.lastIndex = ToLength(rx.lastIndex); + + // Steps 9-12. + // Note, always global because non-global throws as per + // https://github.com/tc39/ecma262/pull/1716 + var flags = REGEXP_GLOBAL_FLAG | + (callFunction(std_String_includes, flags, "u") ? REGEXP_UNICODE_FLAG : 0); + + // Step 13. + return CreateRegExpStringIterator(matcher, str, flags); +} + +// String.prototype.matchAll proposal. +// +// CreateRegExpStringIterator ( R, S, global, fullUnicode ) +function CreateRegExpStringIterator(regexp, string, flags) { + // Step 1. + assert(typeof string === "string", "|string| is a string value"); + + // Steps 2-3. + assert(typeof flags === "number", "|flags| is a number value"); + + // Steps 4-9. + var iterator = NewRegExpStringIterator(); + UnsafeSetReservedSlot(iterator, REGEXP_STRING_ITERATOR_REGEXP_SLOT, regexp); + UnsafeSetReservedSlot(iterator, REGEXP_STRING_ITERATOR_STRING_SLOT, string); + UnsafeSetReservedSlot(iterator, REGEXP_STRING_ITERATOR_FLAGS_SLOT, flags | 0); + UnsafeSetReservedSlot(iterator, REGEXP_STRING_ITERATOR_DONE_SLOT, false); + + // Step 10. + return iterator; +} + +// String.prototype.matchAll proposal. +// +// %RegExpStringIteratorPrototype%.next ( ) +function RegExpStringIteratorNext() { + // Steps 1-3. + var obj; + if (!IsObject(this) || (obj = GuardToRegExpStringIterator(this)) === null) { + return callFunction(CallRegExpStringIteratorMethodIfWrapped, this, + "RegExpStringIteratorNext"); + } + + var result = { value: undefined, done: false }; + + // Step 4. + var done = UnsafeGetReservedSlot(obj, REGEXP_STRING_ITERATOR_DONE_SLOT); + if (done) { + result.done = true; + return result; + } + + // Step 5. + var regexp = UnsafeGetObjectFromReservedSlot(obj, REGEXP_STRING_ITERATOR_REGEXP_SLOT); + + // Step 6. + var string = UnsafeGetStringFromReservedSlot(obj, REGEXP_STRING_ITERATOR_STRING_SLOT); + + // Steps 7-8. + var flags = UnsafeGetInt32FromReservedSlot(obj, REGEXP_STRING_ITERATOR_FLAGS_SLOT); + var global = !!(flags & REGEXP_GLOBAL_FLAG); + var fullUnicode = !!(flags & REGEXP_UNICODE_FLAG); + + // Step 9. + var match = RegExpExec(regexp, string, false); + + // Step 10. + if (match === null) { + // Step 10.a. + UnsafeSetReservedSlot(obj, REGEXP_STRING_ITERATOR_DONE_SLOT, true); + + // Step 10.b. + result.done = true; + return result; + } + + // Step 11.a. + if (global) { + // Step 11.a.i. + var matchStr = ToString(match[0]); + + // Step 11.a.ii. + if (matchStr.length === 0) { + // Step 11.a.ii.1. + var thisIndex = ToLength(regexp.lastIndex); + + // Step 11.a.ii.2. + var nextIndex = fullUnicode ? AdvanceStringIndex(string, thisIndex) : thisIndex + 1; + + // Step 11.a.ii.3. + regexp.lastIndex = nextIndex; + } + } else { + // Step 11.b.i. + UnsafeSetReservedSlot(obj, REGEXP_STRING_ITERATOR_DONE_SLOT, true); + } + + // Steps 11.a.iii and 11.b.ii. + result.value = match; + return result; +} diff --git a/js/src/builtin/SelfHostingDefines.h b/js/src/builtin/SelfHostingDefines.h index 6512810ca..117ac7ffd 100644 --- a/js/src/builtin/SelfHostingDefines.h +++ b/js/src/builtin/SelfHostingDefines.h @@ -92,6 +92,11 @@ #define REGEXP_UNICODE_FLAG 0x10 #define REGEXP_DOTALL_FLAG 0x20 +#define REGEXP_STRING_ITERATOR_REGEXP_SLOT 0 +#define REGEXP_STRING_ITERATOR_STRING_SLOT 1 +#define REGEXP_STRING_ITERATOR_FLAGS_SLOT 2 +#define REGEXP_STRING_ITERATOR_DONE_SLOT 3 + #define MODULE_OBJECT_ENVIRONMENT_SLOT 2 #define MODULE_STATE_FAILED 0 diff --git a/js/src/builtin/String.js b/js/src/builtin/String.js index f830b1aa2..d07ec6127 100644 --- a/js/src/builtin/String.js +++ b/js/src/builtin/String.js @@ -63,6 +63,33 @@ function String_generic_match(thisValue, regexp) { return callFunction(String_match, thisValue, regexp); } +// String.prototype.matchAll proposal. +// +// String.prototype.matchAll ( regexp ) +function String_matchAll(regexp) { + // Step 1. + RequireObjectCoercible(this); + + // Step 2. + if (regexp !== undefined && regexp !== null) { + // Step 2.a. + var matcher = GetMethod(regexp, std_matchAll); + + // Step 2.b. + if (matcher !== undefined) + return callContentFunction(matcher, regexp, this); + } + + // Step 3. + var string = ToString(this); + + // Step 4. + var rx = RegExpCreate(regexp, "g"); + + // Step 5. + return callContentFunction(GetMethod(rx, std_matchAll), rx, string); +} + /** * A helper function implementing the logic for both String.prototype.padStart * and String.prototype.padEnd as described in ES7 Draft March 29, 2016 diff --git a/js/src/jsapi.h b/js/src/jsapi.h index 1a69b1513..4dad68e6e 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -5087,7 +5087,8 @@ GetSymbolDescription(HandleSymbol symbol); macro(split) \ macro(toPrimitive) \ macro(toStringTag) \ - macro(unscopables) + macro(unscopables) \ + macro(matchAll) enum class SymbolCode : uint32_t { // There is one SymbolCode for each well-known symbol. diff --git a/js/src/jsiter.cpp b/js/src/jsiter.cpp index 3e222ca6f..c4da86bdb 100644 --- a/js/src/jsiter.cpp +++ b/js/src/jsiter.cpp @@ -24,6 +24,7 @@ #include "jstypes.h" #include "jsutil.h" +#include "builtin/SelfHostingDefines.h" #include "ds/Sort.h" #include "gc/Marking.h" #include "js/Proxy.h" @@ -1135,6 +1136,38 @@ static const JSFunctionSpec string_iterator_methods[] = { JS_FS_END }; +static const Class RegExpStringIteratorPrototypeClass = { + "RegExp String Iterator", + 0 +}; + +enum { + RegExpStringIteratorSlotRegExp, + RegExpStringIteratorSlotString, + RegExpStringIteratorSlotFlags, + RegExpStringIteratorSlotDone, + RegExpStringIteratorSlotCount +}; + +static_assert(RegExpStringIteratorSlotRegExp == REGEXP_STRING_ITERATOR_REGEXP_SLOT, + "RegExpStringIteratorSlotRegExp must match self-hosting define for regexp slot."); +static_assert(RegExpStringIteratorSlotString == REGEXP_STRING_ITERATOR_STRING_SLOT, + "RegExpStringIteratorSlotString must match self-hosting define for string slot."); +static_assert(RegExpStringIteratorSlotFlags == REGEXP_STRING_ITERATOR_FLAGS_SLOT, + "RegExpStringIteratorSlotFlags must match self-hosting define for flags slot."); +static_assert(RegExpStringIteratorSlotDone == REGEXP_STRING_ITERATOR_DONE_SLOT, + "RegExpStringIteratorSlotDone must match self-hosting define for done slot."); + +const Class RegExpStringIteratorObject::class_ = { + "RegExp String Iterator", + JSCLASS_HAS_RESERVED_SLOTS(RegExpStringIteratorSlotCount) +}; + +static const JSFunctionSpec regexp_string_iterator_methods[] = { + JS_SELF_HOSTED_FN("next", "RegExpStringIteratorNext", 0, 0), + JS_FS_END +}; + JSObject* js::ValueToIterator(JSContext* cx, unsigned flags, HandleValue vp) { @@ -1541,6 +1574,30 @@ GlobalObject::initStringIteratorProto(JSContext* cx, Handle globa return true; } +/* static */ bool +GlobalObject::initRegExpStringIteratorProto(JSContext* cx, Handle global) +{ + if (global->getReservedSlot(REGEXP_STRING_ITERATOR_PROTO).isObject()) + return true; + + RootedObject iteratorProto(cx, GlobalObject::getOrCreateIteratorPrototype(cx, global)); + if (!iteratorProto) + return false; + + const Class* cls = &RegExpStringIteratorPrototypeClass; + RootedObject proto(cx, GlobalObject::createBlankPrototypeInheriting(cx, global, cls, + iteratorProto)); + if (!proto || + !DefinePropertiesAndFunctions(cx, proto, nullptr, regexp_string_iterator_methods) || + !DefineToStringTag(cx, proto, cx->names().RegExpStringIterator)) + { + return false; + } + + global->setReservedSlot(REGEXP_STRING_ITERATOR_PROTO, ObjectValue(*proto)); + return true; +} + JSObject* js::InitLegacyIteratorClass(JSContext* cx, HandleObject obj) { diff --git a/js/src/jsiter.h b/js/src/jsiter.h index a3035ddd0..52eb045c5 100644 --- a/js/src/jsiter.h +++ b/js/src/jsiter.h @@ -151,6 +151,12 @@ class StringIteratorObject : public JSObject static const Class class_; }; +class RegExpStringIteratorObject : public JSObject +{ + public: + static const Class class_; +}; + bool GetIterator(JSContext* cx, HandleObject obj, unsigned flags, MutableHandleObject objp); diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp index 74f61b87d..3964ab84e 100644 --- a/js/src/jsstr.cpp +++ b/js/src/jsstr.cpp @@ -2584,6 +2584,7 @@ static const JSFunctionSpec string_methods[] = { /* Perl-ish methods (search is actually Python-esque). */ JS_SELF_HOSTED_FN("match", "String_match", 1,0), + JS_SELF_HOSTED_FN("matchAll", "String_matchAll", 1,0), JS_SELF_HOSTED_FN("search", "String_search", 1,0), JS_SELF_HOSTED_FN("replace", "String_replace", 2,0), JS_SELF_HOSTED_FN("split", "String_split", 2,0), diff --git a/js/src/vm/CommonPropertyNames.h b/js/src/vm/CommonPropertyNames.h index 4ae49d577..99cb02e58 100644 --- a/js/src/vm/CommonPropertyNames.h +++ b/js/src/vm/CommonPropertyNames.h @@ -282,6 +282,7 @@ macro(RegExpFlagsGetter, RegExpFlagsGetter, "RegExpFlagsGetter") \ macro(RegExpMatcher, RegExpMatcher, "RegExpMatcher") \ macro(RegExpSearcher, RegExpSearcher, "RegExpSearcher") \ + macro(RegExpStringIterator, RegExpStringIterator, "RegExp String Iterator") \ macro(RegExpTester, RegExpTester, "RegExpTester") \ macro(RegExp_prototype_Exec, RegExp_prototype_Exec, "RegExp_prototype_Exec") \ macro(Reify, Reify, "Reify") \ diff --git a/js/src/vm/GlobalObject.cpp b/js/src/vm/GlobalObject.cpp index 85707e1c6..013208f66 100644 --- a/js/src/vm/GlobalObject.cpp +++ b/js/src/vm/GlobalObject.cpp @@ -468,62 +468,29 @@ GlobalObject::initSelfHostingBuiltins(JSContext* cx, Handle globa return false; } - RootedValue std_isConcatSpreadable(cx); - std_isConcatSpreadable.setSymbol(cx->wellKnownSymbols().get(JS::SymbolCode::isConcatSpreadable)); - if (!JS_DefineProperty(cx, global, "std_isConcatSpreadable", std_isConcatSpreadable, - JSPROP_PERMANENT | JSPROP_READONLY)) - { - return false; - } - - // Define a top-level property 'std_iterator' with the name of the method - // used by for-of loops to create an iterator. - RootedValue std_iterator(cx); - std_iterator.setSymbol(cx->wellKnownSymbols().get(JS::SymbolCode::iterator)); - if (!JS_DefineProperty(cx, global, "std_iterator", std_iterator, - JSPROP_PERMANENT | JSPROP_READONLY)) - { - return false; - } - - RootedValue std_match(cx); - std_match.setSymbol(cx->wellKnownSymbols().get(JS::SymbolCode::match)); - if (!JS_DefineProperty(cx, global, "std_match", std_match, - JSPROP_PERMANENT | JSPROP_READONLY)) - { - return false; - } - - RootedValue std_replace(cx); - std_replace.setSymbol(cx->wellKnownSymbols().get(JS::SymbolCode::replace)); - if (!JS_DefineProperty(cx, global, "std_replace", std_replace, - JSPROP_PERMANENT | JSPROP_READONLY)) - { - return false; - } - - RootedValue std_search(cx); - std_search.setSymbol(cx->wellKnownSymbols().get(JS::SymbolCode::search)); - if (!JS_DefineProperty(cx, global, "std_search", std_search, - JSPROP_PERMANENT | JSPROP_READONLY)) - { - return false; - } - - RootedValue std_species(cx); - std_species.setSymbol(cx->wellKnownSymbols().get(JS::SymbolCode::species)); - if (!JS_DefineProperty(cx, global, "std_species", std_species, - JSPROP_PERMANENT | JSPROP_READONLY)) - { - return false; - } - - RootedValue std_split(cx); - std_split.setSymbol(cx->wellKnownSymbols().get(JS::SymbolCode::split)); - if (!JS_DefineProperty(cx, global, "std_split", std_split, - JSPROP_PERMANENT | JSPROP_READONLY)) - { - return false; + struct SymbolAndName { + JS::SymbolCode code; + const char* name; + }; + + SymbolAndName wellKnownSymbols[] = { + {JS::SymbolCode::isConcatSpreadable, "std_isConcatSpreadable"}, + {JS::SymbolCode::iterator, "std_iterator"}, + {JS::SymbolCode::match, "std_match"}, + {JS::SymbolCode::matchAll, "std_matchAll"}, + {JS::SymbolCode::replace, "std_replace"}, + {JS::SymbolCode::search, "std_search"}, + {JS::SymbolCode::species, "std_species"}, + {JS::SymbolCode::split, "std_split"}, + }; + + RootedValue symVal(cx); + for (const auto& sym : wellKnownSymbols) { + symVal.setSymbol(cx->wellKnownSymbols().get(sym.code)); + if (!JS_DefineProperty(cx, global, sym.name, symVal, + JSPROP_PERMANENT | JSPROP_READONLY)) { + return false; + } } return InitBareBuiltinCtor(cx, global, JSProto_Array) && diff --git a/js/src/vm/GlobalObject.h b/js/src/vm/GlobalObject.h index 5aacfc5dc..9179abbb7 100644 --- a/js/src/vm/GlobalObject.h +++ b/js/src/vm/GlobalObject.h @@ -93,6 +93,7 @@ class GlobalObject : public NativeObject ITERATOR_PROTO, ARRAY_ITERATOR_PROTO, STRING_ITERATOR_PROTO, + REGEXP_STRING_ITERATOR_PROTO, LEGACY_GENERATOR_OBJECT_PROTO, STAR_GENERATOR_OBJECT_PROTO, STAR_GENERATOR_FUNCTION_PROTO, @@ -582,6 +583,12 @@ class GlobalObject : public NativeObject initStringIteratorProto)); } + static NativeObject* + getOrCreateRegExpStringIteratorPrototype(JSContext* cx, Handle global) { + return MaybeNativeObject(getOrCreateObject(cx, global, REGEXP_STRING_ITERATOR_PROTO, + initRegExpStringIteratorProto)); + } + static NativeObject* getOrCreateLegacyGeneratorObjectPrototype(JSContext* cx, Handle global) { return MaybeNativeObject(getOrCreateObject(cx, global, LEGACY_GENERATOR_OBJECT_PROTO, @@ -767,6 +774,7 @@ class GlobalObject : public NativeObject static bool initIteratorProto(JSContext* cx, Handle global); static bool initArrayIteratorProto(JSContext* cx, Handle global); static bool initStringIteratorProto(JSContext* cx, Handle global); + static bool initRegExpStringIteratorProto(JSContext* cx, Handle global); // Implemented in vm/GeneratorObject.cpp. static bool initLegacyGeneratorProto(JSContext* cx, Handle global); diff --git a/js/src/vm/SelfHosting.cpp b/js/src/vm/SelfHosting.cpp index 833410465..ffd707b14 100644 --- a/js/src/vm/SelfHosting.cpp +++ b/js/src/vm/SelfHosting.cpp @@ -856,6 +856,24 @@ intrinsic_NewStringIterator(JSContext* cx, unsigned argc, Value* vp) return true; } +static bool +intrinsic_NewRegExpStringIterator(JSContext* cx, unsigned argc, Value* vp) +{ + CallArgs args = CallArgsFromVp(argc, vp); + MOZ_ASSERT(args.length() == 0); + + RootedObject proto(cx, GlobalObject::getOrCreateRegExpStringIteratorPrototype(cx, cx->global())); + if (!proto) + return false; + + JSObject* obj = NewObjectWithGivenProto(cx, &RegExpStringIteratorObject::class_, proto); + if (!obj) + return false; + + args.rval().setObject(*obj); + return true; +} + static bool intrinsic_SetCanonicalName(JSContext* cx, unsigned argc, Value* vp) { @@ -2288,6 +2306,8 @@ static const JSFunctionSpec intrinsic_functions[] = { JS_INLINABLE_FN("GuardToStringIterator", intrinsic_GuardToBuiltin, 1,0, IntrinsicGuardToStringIterator), + JS_FN("GuardToRegExpStringIterator", + intrinsic_GuardToBuiltin, 1,0), JS_FN("_CreateMapIterationResultPair", intrinsic_CreateMapIterationResultPair, 0, 0), JS_INLINABLE_FN("_GetNextMapEntryForIterator", intrinsic_GetNextMapEntryForIterator, 2,0, @@ -2305,6 +2325,9 @@ static const JSFunctionSpec intrinsic_functions[] = { JS_FN("NewStringIterator", intrinsic_NewStringIterator, 0,0), JS_FN("CallStringIteratorMethodIfWrapped", CallNonGenericSelfhostedMethod>, 2,0), + JS_FN("NewRegExpStringIterator", intrinsic_NewRegExpStringIterator, 0,0), + JS_FN("CallRegExpStringIteratorMethodIfWrapped", + CallNonGenericSelfhostedMethod>, 2,0), JS_FN("IsStarGeneratorObject", intrinsic_IsInstanceOfBuiltin, 1,0), -- cgit v1.2.3 From d88f471cbcf9f6c8682b6a0c152622b66708ac5b Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Sat, 30 Nov 2019 00:46:07 +0100 Subject: Issue #1302 followup - Add spec-compliance checks/errors - Check for undefined/null regex flags (because...) - Make it throw a typeerror instead of syntax error on non-global - Generalize JS error messages for these checks. --- js/src/builtin/RegExp.js | 7 +++++-- js/src/js.msg | 2 ++ 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'js/src') diff --git a/js/src/builtin/RegExp.js b/js/src/builtin/RegExp.js index 25827743e..91212066c 100644 --- a/js/src/builtin/RegExp.js +++ b/js/src/builtin/RegExp.js @@ -1042,6 +1042,9 @@ function RegExpMatchAll(string) { // Step 2. if (!IsObject(rx)) ThrowTypeError(JSMSG_NOT_NONNULL_OBJECT, rx === null ? "null" : typeof rx); + + if (rx.flags === undefined || rx.flags === null) + ThrowTypeError(JSMSG_FLAGS_UNDEFINED_OR_NULL); // Step 3. var str = ToString(string); @@ -1052,9 +1055,9 @@ function RegExpMatchAll(string) { // Step 5. var flags = ToString(rx.flags); - // Step 2.b.iii; located here because it needs |flags|. + // Step 2.b.iii; located here because it needs to check |flags|. if (!callFunction(std_String_includes, flags, "g")) { - ThrowTypeError(JSMSG_BAD_REGEXP_FLAG, "- matchAll requires g"); + ThrowTypeError(JSMSG_REQUIRES_GLOBAL_REGEXP, "matchAll"); } // Step 6. diff --git a/js/src/js.msg b/js/src/js.msg index 1612c831d..e2d923bc4 100644 --- a/js/src/js.msg +++ b/js/src/js.msg @@ -132,6 +132,8 @@ MSG_DEF(JSMSG_INVALID_NORMALIZE_FORM, 0, JSEXN_RANGEERR, "form must be one of ' MSG_DEF(JSMSG_NEGATIVE_REPETITION_COUNT, 0, JSEXN_RANGEERR, "repeat count must be non-negative") MSG_DEF(JSMSG_NOT_A_CODEPOINT, 1, JSEXN_RANGEERR, "{0} is not a valid code point") MSG_DEF(JSMSG_RESULTING_STRING_TOO_LARGE, 0, JSEXN_RANGEERR, "repeat count must be less than infinity and not overflow maximum string size") +MSG_DEF(JSMSG_FLAGS_UNDEFINED_OR_NULL, 0, JSEXN_TYPEERR, "'flags' property must neither be undefined nor null") +MSG_DEF(JSMSG_REQUIRES_GLOBAL_REGEXP, 1, JSEXN_TYPEERR, "{0} must be called with a global RegExp") // Number MSG_DEF(JSMSG_BAD_RADIX, 0, JSEXN_RANGEERR, "radix must be an integer at least 2 and no greater than 36") -- cgit v1.2.3 From cffb44547ae7997e5eaf71c644bd626eeb3bba00 Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Sat, 11 Jan 2020 13:09:17 +0100 Subject: Simplify some alias sets in IonMonkey. --- js/src/jit/AliasAnalysisShared.cpp | 4 ++-- js/src/jit/MIR.h | 9 --------- 2 files changed, 2 insertions(+), 11 deletions(-) (limited to 'js/src') diff --git a/js/src/jit/AliasAnalysisShared.cpp b/js/src/jit/AliasAnalysisShared.cpp index 0f0d4a66a..400626b33 100644 --- a/js/src/jit/AliasAnalysisShared.cpp +++ b/js/src/jit/AliasAnalysisShared.cpp @@ -86,8 +86,6 @@ GetObject(const MDefinition* ins) case MDefinition::Op_SetInitializedLength: case MDefinition::Op_ArrayLength: case MDefinition::Op_SetArrayLength: - case MDefinition::Op_StoreElementHole: - case MDefinition::Op_FallibleStoreElement: case MDefinition::Op_TypedObjectDescr: case MDefinition::Op_Slots: case MDefinition::Op_Elements: @@ -143,6 +141,8 @@ GetObject(const MDefinition* ins) case MDefinition::Op_WasmStoreGlobalVar: case MDefinition::Op_ArrayJoin: case MDefinition::Op_ArraySlice: + case MDefinition::Op_StoreElementHole: + case MDefinition::Op_FallibleStoreElement: return nullptr; default: #ifdef DEBUG diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h index 6c376d528..7b0ed65f2 100644 --- a/js/src/jit/MIR.h +++ b/js/src/jit/MIR.h @@ -9460,12 +9460,6 @@ class MStoreElementHole TRIVIAL_NEW_WRAPPERS NAMED_OPERANDS((0, object), (1, elements), (2, index), (3, value)) - AliasSet getAliasSet() const override { - // StoreElementHole can update the initialized length, the array length - // or reallocate obj->elements. - return AliasSet::Store(AliasSet::ObjectFields | AliasSet::Element); - } - ALLOW_CLONE(MStoreElementHole) }; @@ -9496,9 +9490,6 @@ class MFallibleStoreElement TRIVIAL_NEW_WRAPPERS NAMED_OPERANDS((0, object), (1, elements), (2, index), (3, value)) - AliasSet getAliasSet() const override { - return AliasSet::Store(AliasSet::ObjectFields | AliasSet::Element); - } bool strict() const { return strict_; } -- cgit v1.2.3