Skip to content
Permalink
Browse files
[JSC] WeakMap / WeakSet constructor should accept symbols
https://bugs.webkit.org/show_bug.cgi?id=247997
rdar://102440538

Reviewed by Alexey Shvayka.

This patch fixes missing handling of symbols in WeakMap / WeakSet constructors.

* JSTests/stress/weak-map-constructor-symbol.js: Added.
(shouldBe):
(shouldThrow):
* JSTests/stress/weak-set-constructor-symbol.js: Added.
(shouldBe):
(shouldThrow):
(test.set shouldThrow):
* Source/JavaScriptCore/runtime/WeakMapConstructor.cpp:
(JSC::JSC_DEFINE_HOST_FUNCTION):
* Source/JavaScriptCore/runtime/WeakMapPrototype.cpp:
(JSC::JSC_DEFINE_HOST_FUNCTION):
* Source/JavaScriptCore/runtime/WeakSetConstructor.cpp:
(JSC::JSC_DEFINE_HOST_FUNCTION):
* Source/JavaScriptCore/runtime/WeakSetPrototype.cpp:
(JSC::JSC_DEFINE_HOST_FUNCTION):

Canonical link: https://commits.webkit.org/256758@main
  • Loading branch information
Constellation committed Nov 17, 2022
1 parent e015c58 commit dd4f45d5e334782e7e809d3a28be5d1f04bd2f5a
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 8 deletions.
@@ -0,0 +1,34 @@
function shouldBe(actual, expected) {
if (actual !== expected)
throw new Error('bad value: ' + actual);
}

function shouldThrow(func, errorMessage) {
var errorThrown = false;
var error = null;
try {
func();
} catch (e) {
errorThrown = true;
error = e;
}
if (!errorThrown)
throw new Error('not thrown');
if (String(error) !== errorMessage)
throw new Error(`bad error: ${String(error)}`);
}

function test() {
var symbol = Symbol("Hello");
var map = new WeakMap([
[ symbol, 42 ]
]);
shouldBe(map.get(symbol), 42);
shouldThrow(() => {
var registered = Symbol.for("Hello");
new WeakMap([ [ registered, 42 ] ]);
}, `TypeError: WeakMap keys must be objects or non-registered symbols`);
}

for (var i = 0; i < 1e4; ++i)
test();
@@ -0,0 +1,34 @@
function shouldBe(actual, expected) {
if (actual !== expected)
throw new Error('bad value: ' + actual);
}

function shouldThrow(func, errorMessage) {
var errorThrown = false;
var error = null;
try {
func();
} catch (e) {
errorThrown = true;
error = e;
}
if (!errorThrown)
throw new Error('not thrown');
if (String(error) !== errorMessage)
throw new Error(`bad error: ${String(error)}`);
}

function test() {
var symbol = Symbol("Hello");
var set = new WeakSet([
symbol
]);
shouldBe(set.has(symbol), true);
shouldThrow(() => {
var registered = Symbol.for("Hello");
new WeakSet([ registered ]);
}, `TypeError: WeakSet values must be objects or non-registered symbols`);
}

for (var i = 0; i < 1e4; ++i)
test();
@@ -96,10 +96,11 @@ JSC_DEFINE_HOST_FUNCTION(constructWeakMap, (JSGlobalObject* globalObject, CallFr
RETURN_IF_EXCEPTION(scope, void());

if (canPerformFastSet) {
if (key.isObject())
weakMap->set(vm, asObject(key), value);
else
if (UNLIKELY(!canBeHeldWeakly(key))) {
throwTypeError(asObject(adderFunction)->globalObject(), scope, WeakMapInvalidKeyError);
return;
}
weakMap->set(vm, key.asCell(), value);
return;
}

@@ -114,7 +114,7 @@ JSC_DEFINE_HOST_FUNCTION(protoFuncWeakMapSet, (JSGlobalObject* globalObject, Cal
return JSValue::encode(jsUndefined());
JSValue key = callFrame->argument(0);
if (UNLIKELY(!canBeHeldWeakly(key)))
return JSValue::encode(throwTypeError(globalObject, scope, WeakMapInvalidKeyError));
return throwVMTypeError(globalObject, scope, WeakMapInvalidKeyError);
map->set(vm, key.asCell(), callFrame->argument(1));
return JSValue::encode(callFrame->thisValue());
}
@@ -83,10 +83,11 @@ JSC_DEFINE_HOST_FUNCTION(constructWeakSet, (JSGlobalObject* globalObject, CallFr
scope.release();
forEachInIterable(globalObject, iterable, [&](VM&, JSGlobalObject* globalObject, JSValue nextValue) {
if (canPerformFastAdd) {
if (nextValue.isObject())
weakSet->add(vm, asObject(nextValue));
else
if (UNLIKELY(!canBeHeldWeakly(nextValue))) {
throwTypeError(asObject(adderFunction)->globalObject(), scope, WeakSetInvalidValueError);
return;
}
weakSet->add(vm, nextValue.asCell());
return;
}

@@ -103,7 +103,7 @@ JSC_DEFINE_HOST_FUNCTION(protoFuncWeakSetAdd, (JSGlobalObject* globalObject, Cal
return JSValue::encode(jsUndefined());
JSValue key = callFrame->argument(0);
if (UNLIKELY(!canBeHeldWeakly(key)))
return JSValue::encode(throwTypeError(globalObject, scope, WeakSetInvalidValueError));
return throwVMTypeError(globalObject, scope, WeakSetInvalidValueError);
set->add(vm, key.asCell());
return JSValue::encode(callFrame->thisValue());
}

0 comments on commit dd4f45d

Please sign in to comment.