Diff
Modified: trunk/JSTests/ChangeLog (242990 => 242991)
--- trunk/JSTests/ChangeLog 2019-03-15 05:45:07 UTC (rev 242990)
+++ trunk/JSTests/ChangeLog 2019-03-15 05:56:24 UTC (rev 242991)
@@ -1,3 +1,14 @@
+2019-03-14 Yusuke Suzuki <[email protected]>
+
+ [JSC] Retain PrivateName of Symbol before passing it to operations potentially incurring GC
+ https://bugs.webkit.org/show_bug.cgi?id=195791
+ <rdar://problem/48806130>
+
+ Reviewed by Mark Lam.
+
+ * stress/symbol-is-destructed-before-refing-underlying-symbol-impl.js: Added.
+ (foo):
+
2019-03-14 Saam barati <[email protected]>
We can't remove code after ForceOSRExit until after FixupPhase
Added: trunk/JSTests/stress/symbol-is-destructed-before-refing-underlying-symbol-impl.js (0 => 242991)
--- trunk/JSTests/stress/symbol-is-destructed-before-refing-underlying-symbol-impl.js (rev 0)
+++ trunk/JSTests/stress/symbol-is-destructed-before-refing-underlying-symbol-impl.js 2019-03-15 05:56:24 UTC (rev 242991)
@@ -0,0 +1,13 @@
+//@ skip if $buildType == "debug"
+//@ slow!
+//@ runDefault("--collectContinuously=1", "--slowPathAllocsBetweenGCs=100")
+
+function foo(a) {
+ a[Symbol()] = 1;
+}
+noInline(foo);
+
+for (let i = 0; i < 3e7; i++) {
+ let a = {};
+ foo(a);
+}
Modified: trunk/Source/_javascript_Core/ChangeLog (242990 => 242991)
--- trunk/Source/_javascript_Core/ChangeLog 2019-03-15 05:45:07 UTC (rev 242990)
+++ trunk/Source/_javascript_Core/ChangeLog 2019-03-15 05:56:24 UTC (rev 242991)
@@ -1,5 +1,66 @@
2019-03-14 Yusuke Suzuki <[email protected]>
+ [JSC] Retain PrivateName of Symbol before passing it to operations potentially incurring GC
+ https://bugs.webkit.org/show_bug.cgi?id=195791
+ <rdar://problem/48806130>
+
+ Reviewed by Mark Lam.
+
+ Consider the following example:
+
+ void putByVal(JSObject*, PropertyName propertyName, ...);
+
+ putByVal(object, symbol->privateName(), ...);
+
+ PropertyName does not retain the passed UniquedStringImpl*. It just holds the pointer to UniquedStringImpl*.
+ It means that since `Symbol::privateName()` returns `const PrivateName&` instead of `PrivateName`, putByVal
+ and its caller does not retain UniquedStringImpl* held in PropertyName. The problem happens when the putByVal
+ incurs GC, and when the `symbol` is missing in the conservative GC scan. The underlying UniquedStringImpl* of
+ PropertyName can be accidentally destroyed in the middle of the putByVal operation. We should retain PrivateName
+ before passing it to operations which takes it as PropertyName.
+
+ 1. We use the code pattern like this.
+
+ auto propertyName = symbol->privateName();
+ someOperation(..., propertyName);
+
+ This pattern is well aligned to existing `JSValue::toPropertyKey(exec)` and `JSString::toIdentifier(exec)` code patterns.
+
+ auto propertyName = value.toPropertyKey(exec);
+ RETURN_IF_EXCEPTION(scope, { });
+ someOperation(..., propertyName);
+
+ 2. We change `Symbol::privateName()` to returning `PrivateName` instead of `const PrivateName&` to avoid
+ potential dangerous use cases. This is OK because the code using `Symbol::privateName()` is not a critical path,
+ and they typically need to retain PrivateName.
+
+ 3. We audit similar functions `toPropertyKey(exec)` and `toIdentifier(exec)` for needed but missing exception checks.
+ BTW, these functions are safe to the problem fixed in this patch since they return `Identifier` instead
+ of `const Identifier&`.
+
+ Mark and Robin investigated and offered important data to understand what went wrong. And figured out the reason behind
+ the mysterious behavior shown in the data, and now, we confirm that this is the right fix for this bug.
+
+ * dfg/DFGOperations.cpp:
+ * jit/JITOperations.cpp:
+ (JSC::tryGetByValOptimize):
+ * runtime/JSFunction.cpp:
+ (JSC::JSFunction::setFunctionName):
+ * runtime/JSModuleLoader.cpp:
+ (JSC::printableModuleKey):
+ * runtime/JSONObject.cpp:
+ (JSC::Stringifier::Stringifier):
+ * runtime/Symbol.cpp:
+ (JSC::Symbol::descriptiveString const):
+ (JSC::Symbol::description const):
+ * runtime/Symbol.h:
+ * runtime/SymbolConstructor.cpp:
+ (JSC::symbolConstructorKeyFor):
+ * tools/JSDollarVM.cpp:
+ (JSC::functionGetGetterSetter):
+
+2019-03-14 Yusuke Suzuki <[email protected]>
+
REGRESSION(r242841): Fix conservative DFG OSR entry validation to accept values which will be stored in AnyInt / Double flush formats
https://bugs.webkit.org/show_bug.cgi?id=195752
Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (242990 => 242991)
--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp 2019-03-15 05:45:07 UTC (rev 242990)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp 2019-03-15 05:56:24 UTC (rev 242991)
@@ -770,7 +770,8 @@
VM& vm = exec->vm();
NativeCallFrameTracer tracer(&vm, exec);
- return JSValue::encode(getByValObject(exec, vm, asObject(base), asSymbol(symbol)->privateName()));
+ auto propertyName = asSymbol(symbol)->privateName();
+ return JSValue::encode(getByValObject(exec, vm, asObject(base), propertyName));
}
void JIT_OPERATION operationPutByValStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
@@ -826,7 +827,8 @@
VM& vm = exec->vm();
NativeCallFrameTracer tracer(&vm, exec);
- putByValCellInternal<true, false>(exec, vm, cell, asSymbol(symbol)->privateName(), JSValue::decode(encodedValue));
+ auto propertyName = asSymbol(symbol)->privateName();
+ putByValCellInternal<true, false>(exec, vm, cell, propertyName, JSValue::decode(encodedValue));
}
void JIT_OPERATION operationPutByValCellSymbolNonStrict(ExecState* exec, JSCell* cell, JSCell* symbol, EncodedJSValue encodedValue)
@@ -834,7 +836,8 @@
VM& vm = exec->vm();
NativeCallFrameTracer tracer(&vm, exec);
- putByValCellInternal<false, false>(exec, vm, cell, asSymbol(symbol)->privateName(), JSValue::decode(encodedValue));
+ auto propertyName = asSymbol(symbol)->privateName();
+ putByValCellInternal<false, false>(exec, vm, cell, propertyName, JSValue::decode(encodedValue));
}
void JIT_OPERATION operationPutByValBeyondArrayBoundsStrict(ExecState* exec, JSObject* object, int32_t index, EncodedJSValue encodedValue)
@@ -986,7 +989,8 @@
VM& vm = exec->vm();
NativeCallFrameTracer tracer(&vm, exec);
- putByValCellInternal<true, true>(exec, vm, cell, asSymbol(symbol)->privateName(), JSValue::decode(encodedValue));
+ auto propertyName = asSymbol(symbol)->privateName();
+ putByValCellInternal<true, true>(exec, vm, cell, propertyName, JSValue::decode(encodedValue));
}
void JIT_OPERATION operationPutByValDirectCellSymbolNonStrict(ExecState* exec, JSCell* cell, JSCell* symbol, EncodedJSValue encodedValue)
@@ -994,7 +998,8 @@
VM& vm = exec->vm();
NativeCallFrameTracer tracer(&vm, exec);
- putByValCellInternal<false, true>(exec, vm, cell, asSymbol(symbol)->privateName(), JSValue::decode(encodedValue));
+ auto propertyName = asSymbol(symbol)->privateName();
+ putByValCellInternal<false, true>(exec, vm, cell, propertyName, JSValue::decode(encodedValue));
}
void JIT_OPERATION operationPutByValDirectBeyondArrayBoundsStrict(ExecState* exec, JSObject* object, int32_t index, EncodedJSValue encodedValue)
@@ -2054,10 +2059,12 @@
return result;
}
-EncodedJSValue JIT_OPERATION operationHasGenericProperty(ExecState* exec, EncodedJSValue encodedBaseValue, JSCell* propertyName)
+EncodedJSValue JIT_OPERATION operationHasGenericProperty(ExecState* exec, EncodedJSValue encodedBaseValue, JSCell* property)
{
VM& vm = exec->vm();
NativeCallFrameTracer tracer(&vm, exec);
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
JSValue baseValue = JSValue::decode(encodedBaseValue);
if (baseValue.isUndefinedOrNull())
return JSValue::encode(jsBoolean(false));
@@ -2065,7 +2072,9 @@
JSObject* base = baseValue.toObject(exec);
if (!base)
return JSValue::encode(JSValue());
- return JSValue::encode(jsBoolean(base->hasPropertyGeneric(exec, asString(propertyName)->toIdentifier(exec), PropertySlot::InternalMethodType::GetOwnProperty)));
+ auto propertyName = asString(property)->toIdentifier(exec);
+ RETURN_IF_EXCEPTION(scope, { });
+ RELEASE_AND_RETURN(scope, JSValue::encode(jsBoolean(base->hasPropertyGeneric(exec, propertyName, PropertySlot::InternalMethodType::GetOwnProperty))));
}
size_t JIT_OPERATION operationHasIndexedPropertyByInt(ExecState* exec, JSCell* baseCell, int32_t subscript, int32_t internalMethodType)
Modified: trunk/Source/_javascript_Core/jit/JITOperations.cpp (242990 => 242991)
--- trunk/Source/_javascript_Core/jit/JITOperations.cpp 2019-03-15 05:45:07 UTC (rev 242990)
+++ trunk/Source/_javascript_Core/jit/JITOperations.cpp 2019-03-15 05:56:24 UTC (rev 242991)
@@ -720,6 +720,7 @@
OptimizationResult optimizationResult = OptimizationResult::NotOptimized;
VM& vm = exec->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
if (baseValue.isObject() && isCopyOnWrite(baseValue.getObject()->indexingMode()))
return OptimizationResult::GiveUp;
@@ -750,6 +751,7 @@
if (baseValue.isObject() && isStringOrSymbol(subscript)) {
const Identifier propertyName = subscript.toPropertyKey(exec);
+ RETURN_IF_EXCEPTION(scope, OptimizationResult::GiveUp);
if (subscript.isSymbol() || !parseIndex(propertyName)) {
ASSERT(exec->bytecodeOffset());
ASSERT(!byValInfo->stubRoutine);
@@ -790,16 +792,19 @@
{
VM& vm = exec->vm();
NativeCallFrameTracer tracer(&vm, exec);
+ auto scope = DECLARE_THROW_SCOPE(vm);
JSValue baseValue = JSValue::decode(encodedBaseValue);
JSValue subscript = JSValue::decode(encodedSubscript);
JSValue value = JSValue::decode(encodedValue);
- if (tryPutByValOptimize(exec, baseValue, subscript, byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS)) == OptimizationResult::GiveUp) {
+ OptimizationResult result = tryPutByValOptimize(exec, baseValue, subscript, byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS));
+ RETURN_IF_EXCEPTION(scope, void());
+ if (result == OptimizationResult::GiveUp) {
// Don't ever try to optimize.
byValInfo->tookSlowPath = true;
ctiPatchCallByReturnAddress(ReturnAddressPtr(OUR_RETURN_ADDRESS), operationPutByValGeneric);
}
- putByVal(exec, baseValue, subscript, value, byValInfo);
+ RELEASE_AND_RETURN(scope, putByVal(exec, baseValue, subscript, value, byValInfo));
}
static OptimizationResult tryDirectPutByValOptimize(ExecState* exec, JSObject* object, JSValue subscript, ByValInfo* byValInfo, ReturnAddressPtr returnAddress)
@@ -808,6 +813,7 @@
OptimizationResult optimizationResult = OptimizationResult::NotOptimized;
VM& vm = exec->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
if (subscript.isInt32()) {
ASSERT(exec->bytecodeOffset());
@@ -832,6 +838,7 @@
optimizationResult = OptimizationResult::GiveUp;
} else if (isStringOrSymbol(subscript)) {
const Identifier propertyName = subscript.toPropertyKey(exec);
+ RETURN_IF_EXCEPTION(scope, OptimizationResult::GiveUp);
if (subscript.isSymbol() || !parseIndex(propertyName)) {
ASSERT(exec->bytecodeOffset());
ASSERT(!byValInfo->stubRoutine);
@@ -872,6 +879,7 @@
{
VM& vm = exec->vm();
NativeCallFrameTracer tracer(&vm, exec);
+ auto scope = DECLARE_THROW_SCOPE(vm);
JSValue baseValue = JSValue::decode(encodedBaseValue);
JSValue subscript = JSValue::decode(encodedSubscript);
@@ -878,13 +886,15 @@
JSValue value = JSValue::decode(encodedValue);
RELEASE_ASSERT(baseValue.isObject());
JSObject* object = asObject(baseValue);
- if (tryDirectPutByValOptimize(exec, object, subscript, byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS)) == OptimizationResult::GiveUp) {
+ OptimizationResult result = tryDirectPutByValOptimize(exec, object, subscript, byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS));
+ RETURN_IF_EXCEPTION(scope, void());
+ if (result == OptimizationResult::GiveUp) {
// Don't ever try to optimize.
byValInfo->tookSlowPath = true;
ctiPatchCallByReturnAddress(ReturnAddressPtr(OUR_RETURN_ADDRESS), operationDirectPutByValGeneric);
}
- directPutByVal(exec, object, subscript, value, byValInfo);
+ RELEASE_AND_RETURN(scope, directPutByVal(exec, object, subscript, value, byValInfo));
}
void JIT_OPERATION operationPutByValGeneric(ExecState* exec, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, ByValInfo* byValInfo)
@@ -1873,6 +1883,7 @@
OptimizationResult optimizationResult = OptimizationResult::NotOptimized;
VM& vm = exec->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
if (baseValue.isObject() && subscript.isInt32()) {
JSObject* object = asObject(baseValue);
@@ -1903,6 +1914,7 @@
if (baseValue.isObject() && isStringOrSymbol(subscript)) {
const Identifier propertyName = subscript.toPropertyKey(exec);
+ RETURN_IF_EXCEPTION(scope, OptimizationResult::GiveUp);
if (subscript.isSymbol() || !parseIndex(propertyName)) {
ASSERT(exec->bytecodeOffset());
ASSERT(!byValInfo->stubRoutine);
@@ -1956,17 +1968,20 @@
{
VM& vm = exec->vm();
NativeCallFrameTracer tracer(&vm, exec);
+ auto scope = DECLARE_THROW_SCOPE(vm);
JSValue baseValue = JSValue::decode(encodedBase);
JSValue subscript = JSValue::decode(encodedSubscript);
ReturnAddressPtr returnAddress = ReturnAddressPtr(OUR_RETURN_ADDRESS);
- if (tryGetByValOptimize(exec, baseValue, subscript, byValInfo, returnAddress) == OptimizationResult::GiveUp) {
+ OptimizationResult result = tryGetByValOptimize(exec, baseValue, subscript, byValInfo, returnAddress);
+ RETURN_IF_EXCEPTION(scope, { });
+ if (result == OptimizationResult::GiveUp) {
// Don't ever try to optimize.
byValInfo->tookSlowPath = true;
ctiPatchCallByReturnAddress(returnAddress, operationGetByValGeneric);
}
- return JSValue::encode(getByVal(exec, baseValue, subscript, byValInfo, returnAddress));
+ RELEASE_AND_RETURN(scope, JSValue::encode(getByVal(exec, baseValue, subscript, byValInfo, returnAddress)));
}
EncodedJSValue JIT_OPERATION operationHasIndexedPropertyDefault(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ByValInfo* byValInfo)
Modified: trunk/Source/_javascript_Core/runtime/JSFunction.cpp (242990 => 242991)
--- trunk/Source/_javascript_Core/runtime/JSFunction.cpp 2019-03-15 05:45:07 UTC (rev 242990)
+++ trunk/Source/_javascript_Core/runtime/JSFunction.cpp 2019-03-15 05:56:24 UTC (rev 242991)
@@ -669,7 +669,8 @@
ASSERT(jsExecutable()->ecmaName().isNull());
String name;
if (value.isSymbol()) {
- SymbolImpl& uid = asSymbol(value)->privateName().uid();
+ PrivateName privateName = asSymbol(value)->privateName();
+ SymbolImpl& uid = privateName.uid();
if (uid.isNullSymbol())
name = emptyString();
else
Modified: trunk/Source/_javascript_Core/runtime/JSModuleLoader.cpp (242990 => 242991)
--- trunk/Source/_javascript_Core/runtime/JSModuleLoader.cpp 2019-03-15 05:45:07 UTC (rev 242990)
+++ trunk/Source/_javascript_Core/runtime/JSModuleLoader.cpp 2019-03-15 05:56:24 UTC (rev 242991)
@@ -116,8 +116,12 @@
static String printableModuleKey(ExecState* exec, JSValue key)
{
VM& vm = exec->vm();
- if (key.isString() || key.isSymbol())
- return key.toPropertyKey(exec).impl();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+ if (key.isString() || key.isSymbol()) {
+ auto propertyName = key.toPropertyKey(exec);
+ scope.assertNoException(); // This is OK since this function is just for debugging purpose.
+ return propertyName.impl();
+ }
return vm.propertyNames->emptyIdentifier.impl();
}
Modified: trunk/Source/_javascript_Core/runtime/JSONObject.cpp (242990 => 242991)
--- trunk/Source/_javascript_Core/runtime/JSONObject.cpp 2019-03-15 05:45:07 UTC (rev 242990)
+++ trunk/Source/_javascript_Core/runtime/JSONObject.cpp 2019-03-15 05:56:24 UTC (rev 242991)
@@ -247,8 +247,11 @@
continue;
} else if (!name.isNumber() && !name.isString())
continue;
- m_arrayReplacerPropertyNames.add(name.toString(exec)->toIdentifier(exec));
+ JSString* propertyNameString = name.toString(exec);
RETURN_IF_EXCEPTION(scope, );
+ auto propertyName = propertyNameString->toIdentifier(exec);
+ RETURN_IF_EXCEPTION(scope, );
+ m_arrayReplacerPropertyNames.add(WTFMove(propertyName));
}
}
}
Modified: trunk/Source/_javascript_Core/runtime/Symbol.cpp (242990 => 242991)
--- trunk/Source/_javascript_Core/runtime/Symbol.cpp 2019-03-15 05:45:07 UTC (rev 242990)
+++ trunk/Source/_javascript_Core/runtime/Symbol.cpp 2019-03-15 05:56:24 UTC (rev 242991)
@@ -100,12 +100,12 @@
String Symbol::descriptiveString() const
{
- return makeString("Symbol(", String(privateName().uid()), ')');
+ return makeString("Symbol(", String(m_privateName.uid()), ')');
}
String Symbol::description() const
{
- auto& uid = privateName().uid();
+ auto& uid = m_privateName.uid();
return uid.isNullSymbol() ? String() : uid;
}
Modified: trunk/Source/_javascript_Core/runtime/Symbol.h (242990 => 242991)
--- trunk/Source/_javascript_Core/runtime/Symbol.h 2019-03-15 05:45:07 UTC (rev 242990)
+++ trunk/Source/_javascript_Core/runtime/Symbol.h 2019-03-15 05:56:24 UTC (rev 242991)
@@ -49,7 +49,7 @@
static Symbol* create(ExecState*, JSString* description);
JS_EXPORT_PRIVATE static Symbol* create(VM&, SymbolImpl& uid);
- const PrivateName& privateName() const { return m_privateName; }
+ PrivateName privateName() const { return m_privateName; }
String descriptiveString() const;
String description() const;
Modified: trunk/Source/_javascript_Core/runtime/SymbolConstructor.cpp (242990 => 242991)
--- trunk/Source/_javascript_Core/runtime/SymbolConstructor.cpp 2019-03-15 05:45:07 UTC (rev 242990)
+++ trunk/Source/_javascript_Core/runtime/SymbolConstructor.cpp 2019-03-15 05:56:24 UTC (rev 242991)
@@ -109,7 +109,8 @@
if (!symbolValue.isSymbol())
return JSValue::encode(throwTypeError(exec, scope, SymbolKeyForTypeError));
- SymbolImpl& uid = asSymbol(symbolValue)->privateName().uid();
+ PrivateName privateName = asSymbol(symbolValue)->privateName();
+ SymbolImpl& uid = privateName.uid();
if (!uid.symbolRegistry())
return JSValue::encode(jsUndefined());
Modified: trunk/Source/_javascript_Core/tools/JSDollarVM.cpp (242990 => 242991)
--- trunk/Source/_javascript_Core/tools/JSDollarVM.cpp 2019-03-15 05:45:07 UTC (rev 242990)
+++ trunk/Source/_javascript_Core/tools/JSDollarVM.cpp 2019-03-15 05:56:24 UTC (rev 242991)
@@ -2103,6 +2103,9 @@
static EncodedJSValue JSC_HOST_CALL functionGetGetterSetter(ExecState* exec)
{
+ VM& vm = exec->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
JSValue value = exec->argument(0);
if (!value.isObject())
return JSValue::encode(jsUndefined());
@@ -2111,8 +2114,11 @@
if (!property.isString())
return JSValue::encode(jsUndefined());
+ auto propertyName = asString(property)->toIdentifier(exec);
+ RETURN_IF_EXCEPTION(scope, { });
+
PropertySlot slot(value, PropertySlot::InternalMethodType::VMInquiry);
- value.getPropertySlot(exec, asString(property)->toIdentifier(exec), slot);
+ value.getPropertySlot(exec, propertyName, slot);
JSValue result;
if (slot.isCacheableGetter())
Modified: trunk/Source/WebCore/ChangeLog (242990 => 242991)
--- trunk/Source/WebCore/ChangeLog 2019-03-15 05:45:07 UTC (rev 242990)
+++ trunk/Source/WebCore/ChangeLog 2019-03-15 05:56:24 UTC (rev 242991)
@@ -1,3 +1,14 @@
+2019-03-14 Yusuke Suzuki <[email protected]>
+
+ [JSC] Retain PrivateName of Symbol before passing it to operations potentially incurring GC
+ https://bugs.webkit.org/show_bug.cgi?id=195791
+ <rdar://problem/48806130>
+
+ Reviewed by Mark Lam.
+
+ * bindings/js/ScriptController.cpp:
+ (WebCore::ScriptController::setupModuleScriptHandlers):
+
2019-03-14 Brent Fulgham <[email protected]>
Move CoreCrypto SPI declarations to an appropriate PAL/spi header
Modified: trunk/Source/WebCore/bindings/js/ScriptController.cpp (242990 => 242991)
--- trunk/Source/WebCore/bindings/js/ScriptController.cpp 2019-03-15 05:45:07 UTC (rev 242990)
+++ trunk/Source/WebCore/bindings/js/ScriptController.cpp 2019-03-15 05:56:24 UTC (rev 242991)
@@ -278,8 +278,11 @@
RefPtr<LoadableModuleScript> moduleScript(&moduleScriptRef);
- auto& fulfillHandler = *JSNativeStdFunction::create(state.vm(), proxy.window(), 1, String(), [moduleScript](ExecState* exec) {
+ auto& fulfillHandler = *JSNativeStdFunction::create(state.vm(), proxy.window(), 1, String(), [moduleScript](ExecState* exec) -> JSC::EncodedJSValue {
+ VM& vm = exec->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
Identifier moduleKey = jsValueToModuleKey(exec, exec->argument(0));
+ RETURN_IF_EXCEPTION(scope, { });
moduleScript->notifyLoadCompleted(*moduleKey.impl());
return JSValue::encode(jsUndefined());
});