Bug 1198352 - Handle cross-compartment WeakSets. r=Waldo
authorTom Schuster <evilpies@gmail.com>
Wed, 21 Oct 2015 21:05:26 +0200
changeset 268889 dc1467aff5e45fc7e31eb08969265c3ec1c72798
parent 268797 26c5929a5a7e97e45126d7596b3fc3b3f9f9e549
child 268890 b031fc40cf45213e29c085292568a22ef9d5621c
push id29566
push usercbook@mozilla.com
push dateThu, 22 Oct 2015 09:45:32 +0000
treeherdermozilla-central@76bd0c01d72e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersWaldo
bugs1198352
milestone44.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1198352 - Handle cross-compartment WeakSets. r=Waldo
js/src/builtin/WeakSet.js
js/src/jit-test/tests/collections/WeakSet-clear.js
js/src/jit-test/tests/collections/WeakSet-delete.js
js/src/vm/SelfHosting.cpp
--- a/js/src/builtin/WeakSet.js
+++ b/js/src/builtin/WeakSet.js
@@ -2,17 +2,17 @@
  * 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/. */
 
 // 23.4.3.1
 function WeakSet_add(value) {
     // Steps 1-3.
     var S = this;
     if (!IsObject(S) || !IsWeakSet(S))
-        ThrowTypeError(JSMSG_INCOMPATIBLE_PROTO, "WeakSet", "add", typeof S);
+        return callFunction(CallWeakSetMethodIfWrapped, this, value, "WeakSet_add");
 
     // Step 4.,6.
     let entries = UnsafeGetReservedSlot(this, WEAKSET_MAP_SLOT);
     if (!entries)
         ThrowTypeError(JSMSG_INCOMPATIBLE_PROTO, "WeakSet", "add", typeof S);
 
     // Step 5.
     if (!IsObject(value))
@@ -25,17 +25,17 @@ function WeakSet_add(value) {
     return S;
 }
 
 // 23.4.3.2
 function WeakSet_clear() {
     // Step 1-3.
     var S = this;
     if (!IsObject(S) || !IsWeakSet(S))
-        ThrowTypeError(JSMSG_INCOMPATIBLE_PROTO, "WeakSet", "clear", typeof S);
+        return callFunction(CallWeakSetMethodIfWrapped, this, "WeakSet_clear");
 
     // Step 4.
     let entries = UnsafeGetReservedSlot(this, WEAKSET_MAP_SLOT);
     if (!entries)
         ThrowTypeError(JSMSG_INCOMPATIBLE_PROTO, "WeakSet", "clear", typeof S);
 
     // Step 5.
     callFunction(std_WeakMap_clear, entries);
@@ -44,17 +44,17 @@ function WeakSet_clear() {
     return undefined;
 }
 
 // 23.4.3.4
 function WeakSet_delete(value) {
     // Steps 1-3.
     var S = this;
     if (!IsObject(S) || !IsWeakSet(S))
-        ThrowTypeError(JSMSG_INCOMPATIBLE_PROTO, "WeakSet", "delete", typeof S);
+        return callFunction(CallWeakSetMethodIfWrapped, this, value, "WeakSet_delete");
 
     // Step 4.,6.
     let entries = UnsafeGetReservedSlot(this, WEAKSET_MAP_SLOT);
     if (!entries)
         ThrowTypeError(JSMSG_INCOMPATIBLE_PROTO, "WeakSet", "delete", typeof S);
 
     // Step 5.
     if (!IsObject(value))
@@ -64,17 +64,17 @@ function WeakSet_delete(value) {
     return callFunction(std_WeakMap_delete, entries, value);
 }
 
 // 23.4.3.5
 function WeakSet_has(value) {
     // Steps 1-3.
     var S = this;
     if (!IsObject(S) || !IsWeakSet(S))
-        ThrowTypeError(JSMSG_INCOMPATIBLE_PROTO, "WeakSet", "has", typeof S);
+        return callFunction(CallWeakSetMethodIfWrapped, this, value, "WeakSet_has");
 
     // Step 4-5.
     let entries = UnsafeGetReservedSlot(this, WEAKSET_MAP_SLOT);
     if (!entries)
         ThrowTypeError(JSMSG_INCOMPATIBLE_PROTO, "WeakSet", "has", typeof S);
 
     // Step 6.
     if (!IsObject(value))
--- a/js/src/jit-test/tests/collections/WeakSet-clear.js
+++ b/js/src/jit-test/tests/collections/WeakSet-clear.js
@@ -35,8 +35,16 @@ ws.add(value);
 value = null;
 ws.clear();
 gc();
 var value2 = {};
 ws.add(value2);
 value2 = null;
 gc();
 ws.clear();
+
+// Clearing a cross-compartment WeakSet with a live value
+ws = new (newGlobal().WeakSet);
+value = {};
+WeakSet.prototype.add.call(ws, value);
+assertEq(WeakSet.prototype.has.call(ws, value), true);
+WeakSet.prototype.clear.call(ws);
+assertEq(WeakSet.prototype.has.call(ws, value), false);
--- a/js/src/jit-test/tests/collections/WeakSet-delete.js
+++ b/js/src/jit-test/tests/collections/WeakSet-delete.js
@@ -24,8 +24,16 @@ assertEq(ws.add(value), ws);
 assertEq(ws.has(value), true);
 assertEq(ws.delete(value), true);
 assertEq(ws.has(value), false);
 assertEq(ws.delete(value), false);
 assertEq(ws.has(value), false);
 
 // Delete primitive
 assertEq(ws.delete(15), false);
+
+// Delete with cross-compartment WeakSet
+ws = new (newGlobal().WeakSet);
+WeakSet.prototype.add.call(ws, value);
+assertEq(WeakSet.prototype.has.call(ws, value), true);
+assertEq(WeakSet.prototype.delete.call(ws, value), true);
+assertEq(WeakSet.prototype.has.call(ws, value), false);
+assertEq(WeakSet.prototype.delete.call(ws, value), false);
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -1657,16 +1657,18 @@ static const JSFunctionSpec intrinsic_fu
           CallNonGenericSelfhostedMethod<Is<TypedArrayObject>>, 2, 0),
 
     JS_FN("CallLegacyGeneratorMethodIfWrapped",
           CallNonGenericSelfhostedMethod<Is<LegacyGeneratorObject>>, 2, 0),
     JS_FN("CallStarGeneratorMethodIfWrapped",
           CallNonGenericSelfhostedMethod<Is<StarGeneratorObject>>, 2, 0),
 
     JS_FN("IsWeakSet",               intrinsic_IsWeakSet,               1,0),
+    JS_FN("CallWeakSetMethodIfWrapped",
+          CallNonGenericSelfhostedMethod<Is<WeakSetObject>>, 2, 0),
 
     // See builtin/TypedObject.h for descriptors of the typedobj functions.
     JS_FN("NewOpaqueTypedObject",           js::NewOpaqueTypedObject, 1, 0),
     JS_FN("NewDerivedTypedObject",          js::NewDerivedTypedObject, 3, 0),
     JS_FN("TypedObjectBuffer",              TypedObject::GetBuffer, 1, 0),
     JS_FN("TypedObjectByteOffset",          TypedObject::GetByteOffset, 1, 0),
     JS_FN("AttachTypedObject",              js::AttachTypedObject, 3, 0),
     JS_FN("TypedObjectIsAttached",          js::TypedObjectIsAttached, 1, 0),