diff --git a/Source/JavaScriptCore/API/APICallbackFunction.h b/Source/JavaScriptCore/API/APICallbackFunction.h index 616924b97942e..388b7e6f6c979 100644 --- a/Source/JavaScriptCore/API/APICallbackFunction.h +++ b/Source/JavaScriptCore/API/APICallbackFunction.h @@ -124,7 +124,9 @@ EncodedJSValue APICallbackFunction::constructImpl(JSGlobalObject* globalObject, return JSValue::encode(newObject); } - return JSValue::encode(toJS(JSObjectMake(ctx, jsCast(callee)->classRef(), nullptr))); + auto* callbackConstructor = jsCast(callee); + JSC::EnsureStillAliveScope ensureCallbackConstructor(callbackConstructor); + return JSValue::encode(toJS(JSObjectMake(ctx, callbackConstructor->classRef(), nullptr))); } } // namespace JSC diff --git a/Source/JavaScriptCore/API/JSCallbackObjectFunctions.h b/Source/JavaScriptCore/API/JSCallbackObjectFunctions.h index 41b5e7fb0b26f..4ac98230a4afe 100644 --- a/Source/JavaScriptCore/API/JSCallbackObjectFunctions.h +++ b/Source/JavaScriptCore/API/JSCallbackObjectFunctions.h @@ -147,10 +147,11 @@ bool JSCallbackObject::getOwnPropertySlot(JSObject* object, JSGlobalObje auto scope = DECLARE_THROW_SCOPE(vm); JSCallbackObject* thisObject = jsCast(object); + JSC::EnsureStillAliveScope ensureThisObject(thisObject); JSContextRef ctx = toRef(globalObject); JSObjectRef thisRef = toRef(jsCast(thisObject)); RefPtr propertyNameRef; - + if (StringImpl* name = propertyName.uid()) { unsigned attributes = PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum; for (JSClassRef jsClass = thisObject->classRef(); jsClass; jsClass = jsClass->parentClass) { @@ -267,6 +268,7 @@ bool JSCallbackObject::put(JSCell* cell, JSGlobalObject* globalObject, P auto scope = DECLARE_THROW_SCOPE(vm); JSCallbackObject* thisObject = jsCast(cell); + JSC::EnsureStillAliveScope ensureThisObject(thisObject); JSContextRef ctx = toRef(globalObject); JSObjectRef thisRef = toRef(jsCast(thisObject)); RefPtr propertyNameRef; @@ -397,10 +399,11 @@ bool JSCallbackObject::deleteProperty(JSCell* cell, JSGlobalObject* glob auto scope = DECLARE_THROW_SCOPE(vm); JSCallbackObject* thisObject = jsCast(cell); + JSC::EnsureStillAliveScope ensureThisObject(thisObject); JSContextRef ctx = toRef(globalObject); JSObjectRef thisRef = toRef(jsCast(thisObject)); RefPtr propertyNameRef; - + if (StringImpl* name = propertyName.uid()) { for (JSClassRef jsClass = thisObject->classRef(); jsClass; jsClass = jsClass->parentClass) { if (JSObjectDeletePropertyCallback deleteProperty = jsClass->deleteProperty) { diff --git a/Source/JavaScriptCore/API/JSObjectRef.cpp b/Source/JavaScriptCore/API/JSObjectRef.cpp index fddf672c17b1d..17cd8c3fb6fb0 100644 --- a/Source/JavaScriptCore/API/JSObjectRef.cpp +++ b/Source/JavaScriptCore/API/JSObjectRef.cpp @@ -83,6 +83,7 @@ JSObjectRef JSObjectMake(JSContextRef ctx, JSClassRef jsClass, void* data) return nullptr; } JSGlobalObject* globalObject = toJS(ctx); + JSC::EnsureStillAliveScope ensureGlobalObject(globalObject); VM& vm = globalObject->vm(); JSLockHolder locker(vm); @@ -115,6 +116,7 @@ JSObjectRef JSObjectMakeConstructor(JSContextRef ctx, JSClassRef jsClass, JSObje return nullptr; } JSGlobalObject* globalObject = toJS(ctx); + JSC::EnsureStillAliveScope ensureGlobalObject(globalObject); VM& vm = globalObject->vm(); JSLockHolder locker(vm); diff --git a/Source/JavaScriptCore/API/JSValueRef.cpp b/Source/JavaScriptCore/API/JSValueRef.cpp index 0f2372ae8cc6d..99b9211cbf8f3 100644 --- a/Source/JavaScriptCore/API/JSValueRef.cpp +++ b/Source/JavaScriptCore/API/JSValueRef.cpp @@ -285,6 +285,7 @@ bool JSValueIsInstanceOfConstructor(JSContextRef ctx, JSValueRef value, JSObject JSValue jsValue = toJS(globalObject, value); JSObject* jsConstructor = toJS(constructor); + JSC::EnsureStillAliveScope ensureJsConstructor(jsConstructor); if (!jsConstructor->structure()->typeInfo().implementsHasInstance()) return false; bool result = jsConstructor->hasInstance(globalObject, jsValue); // false if an exception is thrown diff --git a/Source/JavaScriptCore/API/glib/JSCWrapperMap.cpp b/Source/JavaScriptCore/API/glib/JSCWrapperMap.cpp index b83e2edcd78d4..b0811a3e97d71 100644 --- a/Source/JavaScriptCore/API/glib/JSCWrapperMap.cpp +++ b/Source/JavaScriptCore/API/glib/JSCWrapperMap.cpp @@ -80,6 +80,7 @@ JSObject* WrapperMap::createJSWrapper(JSGlobalContextRef jsContext, JSClassRef j { ASSERT(toJSGlobalObject(jsContext)->wrapperMap() == this); JSGlobalObject* globalObject = toJS(jsContext); + JSC::EnsureStillAliveScope ensureGlobalObject(globalObject); VM& vm = globalObject->vm(); JSLockHolder locker(vm); auto* object = JSC::JSCallbackObject::create(globalObject, globalObject->glibWrapperObjectStructure(), jsClass, nullptr); @@ -99,6 +100,7 @@ JSGlobalContextRef WrapperMap::createContextWithJSWrapper(JSContextGroupRef jsGr Ref vm(*toJS(jsGroup)); JSLockHolder locker(vm.ptr()); auto* globalObject = JSCallbackObject::create(vm.get(), jsClass, JSCallbackObject::createStructure(vm.get(), nullptr, jsNull())); + JSC::EnsureStillAliveScope ensureGlobalObject(globalObject); if (wrappedObject) { globalObject->setWrappedObject(new JSC::JSCGLibWrapperObject(wrappedObject, destroyFunction)); m_cachedJSWrappers->set(wrappedObject, globalObject); diff --git a/Source/JavaScriptCore/bytecode/ObjectPropertyConditionSet.cpp b/Source/JavaScriptCore/bytecode/ObjectPropertyConditionSet.cpp index 7c351fa796cd2..835c3747a387e 100644 --- a/Source/JavaScriptCore/bytecode/ObjectPropertyConditionSet.cpp +++ b/Source/JavaScriptCore/bytecode/ObjectPropertyConditionSet.cpp @@ -301,6 +301,7 @@ ObjectPropertyConditionSet generateConditions(JSGlobalObject* globalObject, Stru } JSObject* object = jsCast(value); + JSC::EnsureStillAliveScope ensureObject(object); structure = object->structure(); if (structure->isDictionary()) { diff --git a/Source/JavaScriptCore/bytecode/Repatch.cpp b/Source/JavaScriptCore/bytecode/Repatch.cpp index b91555ea812f6..9edafd09fc007 100644 --- a/Source/JavaScriptCore/bytecode/Repatch.cpp +++ b/Source/JavaScriptCore/bytecode/Repatch.cpp @@ -500,6 +500,7 @@ static InlineCacheAction tryCacheGetBy(JSGlobalObject* globalObject, CodeBlock* JSFunction* getter = nullptr; if (slot.isCacheableGetter()) getter = jsDynamicCast(slot.getterSetter()->getter()); + JSC::EnsureStillAliveScope ensureGetter(getter); std::optional domAttribute; if (slot.isCacheableCustom() && slot.domAttribute()) diff --git a/Source/JavaScriptCore/debugger/DebuggerScope.cpp b/Source/JavaScriptCore/debugger/DebuggerScope.cpp index 04c0e1755f7c3..31d4804832c86 100644 --- a/Source/JavaScriptCore/debugger/DebuggerScope.cpp +++ b/Source/JavaScriptCore/debugger/DebuggerScope.cpp @@ -74,6 +74,7 @@ bool DebuggerScope::getOwnPropertySlot(JSObject* object, JSGlobalObject* globalO if (!scope->isValid()) return false; JSObject* thisObject = JSScope::objectAtScope(scope->jsScope()); + JSC::EnsureStillAliveScope ensureThisObject(thisObject); slot.setThisValue(JSValue(thisObject)); // By default, JSObject::getPropertySlot() will look in the DebuggerScope's prototype @@ -105,6 +106,7 @@ bool DebuggerScope::put(JSCell* cell, JSGlobalObject* globalObject, PropertyName if (!scope->isValid()) return false; JSObject* thisObject = JSScope::objectAtScope(scope->jsScope()); + JSC::EnsureStillAliveScope ensureThisObject(thisObject); slot.setThisValue(JSValue(thisObject)); return thisObject->methodTable()->put(thisObject, globalObject, propertyName, value, slot); } @@ -116,6 +118,7 @@ bool DebuggerScope::deleteProperty(JSCell* cell, JSGlobalObject* globalObject, P if (!scope->isValid()) return false; JSObject* thisObject = JSScope::objectAtScope(scope->jsScope()); + JSC::EnsureStillAliveScope ensureThisObject(thisObject); return thisObject->methodTable()->deleteProperty(thisObject, globalObject, propertyName, slot); } @@ -126,6 +129,7 @@ void DebuggerScope::getOwnPropertyNames(JSObject* object, JSGlobalObject* global if (!scope->isValid()) return; JSObject* thisObject = JSScope::objectAtScope(scope->jsScope()); + JSC::EnsureStillAliveScope ensureThisObject(thisObject); thisObject->getPropertyNames(globalObject, propertyNames, mode); } @@ -136,6 +140,7 @@ bool DebuggerScope::defineOwnProperty(JSObject* object, JSGlobalObject* globalOb if (!scope->isValid()) return false; JSObject* thisObject = JSScope::objectAtScope(scope->jsScope()); + JSC::EnsureStillAliveScope ensureThisObject(thisObject); return thisObject->methodTable()->defineOwnProperty(thisObject, globalObject, propertyName, descriptor, shouldThrow); } @@ -233,6 +238,7 @@ JSValue DebuggerScope::caughtValue(JSGlobalObject* globalObject) const { ASSERT(isCatchScope()); JSLexicalEnvironment* catchEnvironment = jsCast(m_scope.get()); + JSC::EnsureStillAliveScope ensureCatchEnvironment(catchEnvironment); SymbolTable* catchSymbolTable = catchEnvironment->symbolTable(); RELEASE_ASSERT(catchSymbolTable->size() == 1); PropertyName errorName(catchSymbolTable->begin(catchSymbolTable->m_lock)->key.get()); diff --git a/Source/JavaScriptCore/inspector/JSInjectedScriptHost.cpp b/Source/JavaScriptCore/inspector/JSInjectedScriptHost.cpp index 8ef0244f0edc5..67294ac4e7118 100644 --- a/Source/JavaScriptCore/inspector/JSInjectedScriptHost.cpp +++ b/Source/JavaScriptCore/inspector/JSInjectedScriptHost.cpp @@ -547,14 +547,18 @@ static JSObject* cloneArrayIteratorObject(JSGlobalObject* globalObject, VM& vm, static JSObject* cloneMapIteratorObject(JSGlobalObject* globalObject, VM& vm, JSMapIterator* iteratorObject) { - JSMapIterator* clone = JSMapIterator::create(vm, globalObject->mapIteratorStructure(), jsCast(iteratorObject->iteratedObject()), iteratorObject->kind()); + JSMap* iteratedMap = jsCast(iteratorObject->iteratedObject()); + JSC::EnsureStillAliveScope ensureIteratedMap(iteratedMap); + JSMapIterator* clone = JSMapIterator::create(vm, globalObject->mapIteratorStructure(), iteratedMap, iteratorObject->kind()); clone->internalField(JSMapIterator::Field::MapBucket).set(vm, clone, iteratorObject->internalField(JSMapIterator::Field::MapBucket).get()); return clone; } static JSObject* cloneSetIteratorObject(JSGlobalObject* globalObject, VM& vm, JSSetIterator* iteratorObject) { - JSSetIterator* clone = JSSetIterator::create(vm, globalObject->setIteratorStructure(), jsCast(iteratorObject->iteratedObject()), iteratorObject->kind()); + JSSet* iteratedSet = jsCast(iteratorObject->iteratedObject()); + JSC::EnsureStillAliveScope ensureIteratedSet(iteratedSet); + JSSetIterator* clone = JSSetIterator::create(vm, globalObject->setIteratorStructure(), iteratedSet, iteratorObject->kind()); clone->internalField(JSSetIterator::Field::SetBucket).set(vm, clone, iteratorObject->internalField(JSSetIterator::Field::SetBucket).get()); return clone; } @@ -584,10 +588,14 @@ JSValue JSInjectedScriptHost::iteratorEntries(JSGlobalObject* globalObject, Call iterator = cloneArrayIteratorObject(globalObject, vm, arrayIterator); } } else if (auto* mapIterator = jsDynamicCast(iteratorObject)) { - if (jsCast(mapIterator->iteratedObject())->isIteratorProtocolFastAndNonObservable()) + JSMap* iteratedMap = jsCast(mapIterator->iteratedObject()); + JSC::EnsureStillAliveScope ensureIteratedMap(iteratedMap); + if (iteratedMap->isIteratorProtocolFastAndNonObservable()) iterator = cloneMapIteratorObject(globalObject, vm, mapIterator); } else if (auto* setIterator = jsDynamicCast(iteratorObject)) { - if (jsCast(setIterator->iteratedObject())->isIteratorProtocolFastAndNonObservable()) + JSSet* iteratedSet = jsCast(setIterator->iteratedObject()); + JSC::EnsureStillAliveScope ensureIteratedSet(iteratedSet); + if (iteratedSet->isIteratorProtocolFastAndNonObservable()) iterator = cloneSetIteratorObject(globalObject, vm, setIterator); } } diff --git a/Source/JavaScriptCore/interpreter/Interpreter.cpp b/Source/JavaScriptCore/interpreter/Interpreter.cpp index daf8a026a8c05..e7299d9cf08d1 100644 --- a/Source/JavaScriptCore/interpreter/Interpreter.cpp +++ b/Source/JavaScriptCore/interpreter/Interpreter.cpp @@ -189,6 +189,7 @@ unsigned sizeOfVarargs(JSGlobalObject* globalObject, JSValue arguments, uint32_t } JSCell* cell = arguments.asCell(); + JSC::EnsureStillAliveScope ensureCell(cell); unsigned length; switch (cell->type()) { case DirectArgumentsType: @@ -260,6 +261,7 @@ void loadVarargs(JSGlobalObject* globalObject, JSValue* firstElementDest, JSValu VM& vm = globalObject->vm(); auto scope = DECLARE_THROW_SCOPE(vm); JSCell* cell = arguments.asCell(); + JSC::EnsureStillAliveScope ensureCell(cell); switch (cell->type()) { case DirectArgumentsType: diff --git a/Source/JavaScriptCore/jit/JITOperations.cpp b/Source/JavaScriptCore/jit/JITOperations.cpp index f12a348b387bd..03900b64c8252 100644 --- a/Source/JavaScriptCore/jit/JITOperations.cpp +++ b/Source/JavaScriptCore/jit/JITOperations.cpp @@ -734,11 +734,12 @@ JSC_DEFINE_JIT_OPERATION(operationPutByIdStrict, void, (JSGlobalObject* globalOb stubInfo->tookSlowPath = true; JSValue baseValue = JSValue::decode(encodedBase); + JSC::EnsureStillAliveScope ensureBase(baseValue); CacheableIdentifier identifier = CacheableIdentifier::createFromRawBits(rawCacheableIdentifier); Identifier ident = Identifier::fromUid(vm, identifier.uid()); PutPropertySlot slot(baseValue, true, callFrame->codeBlock()->putByIdContext()); baseValue.putInline(globalObject, ident, JSValue::decode(encodedValue), slot); - + LOG_IC((ICEvent::OperationPutByIdStrict, baseValue.classInfoOrNull(), ident, slot.base() == baseValue)); } @@ -753,6 +754,7 @@ JSC_DEFINE_JIT_OPERATION(operationPutByIdNonStrict, void, (JSGlobalObject* globa stubInfo->tookSlowPath = true; JSValue baseValue = JSValue::decode(encodedBase); + JSC::EnsureStillAliveScope ensureBase(baseValue); CacheableIdentifier identifier = CacheableIdentifier::createFromRawBits(rawCacheableIdentifier); Identifier ident = Identifier::fromUid(vm, identifier.uid()); PutPropertySlot slot(baseValue, false, callFrame->codeBlock()->putByIdContext()); @@ -772,10 +774,12 @@ JSC_DEFINE_JIT_OPERATION(operationPutByIdDirectStrict, void, (JSGlobalObject* gl stubInfo->tookSlowPath = true; JSValue baseValue = JSValue::decode(encodedBase); + JSObject* baseObject = asObject(baseValue); + JSC::EnsureStillAliveScope ensureBase(baseObject); CacheableIdentifier identifier = CacheableIdentifier::createFromRawBits(rawCacheableIdentifier); Identifier ident = Identifier::fromUid(vm, identifier.uid()); PutPropertySlot slot(baseValue, true, callFrame->codeBlock()->putByIdContext()); - CommonSlowPaths::putDirectWithReify(vm, globalObject, asObject(baseValue), ident, JSValue::decode(encodedValue), slot); + CommonSlowPaths::putDirectWithReify(vm, globalObject, baseObject, ident, JSValue::decode(encodedValue), slot); LOG_IC((ICEvent::OperationPutByIdDirectStrict, baseValue.classInfoOrNull(), ident, slot.base() == baseValue)); } @@ -791,10 +795,12 @@ JSC_DEFINE_JIT_OPERATION(operationPutByIdDirectNonStrict, void, (JSGlobalObject* stubInfo->tookSlowPath = true; JSValue baseValue = JSValue::decode(encodedBase); + JSObject* baseObject = asObject(baseValue); + JSC::EnsureStillAliveScope ensureBase(baseObject); CacheableIdentifier identifier = CacheableIdentifier::createFromRawBits(rawCacheableIdentifier); Identifier ident = Identifier::fromUid(vm, identifier.uid()); PutPropertySlot slot(baseValue, false, callFrame->codeBlock()->putByIdContext()); - CommonSlowPaths::putDirectWithReify(vm, globalObject, asObject(baseValue), ident, JSValue::decode(encodedValue), slot); + CommonSlowPaths::putDirectWithReify(vm, globalObject, baseObject, ident, JSValue::decode(encodedValue), slot); LOG_IC((ICEvent::OperationPutByIdDirectNonStrict, baseValue.classInfoOrNull(), ident, slot.base() == baseValue)); } @@ -814,6 +820,7 @@ JSC_DEFINE_JIT_OPERATION(operationPutByIdStrictOptimize, void, (JSGlobalObject* JSValue value = JSValue::decode(encodedValue); JSValue baseValue = JSValue::decode(encodedBase); + JSC::EnsureStillAliveScope ensureBase(baseValue); CodeBlock* codeBlock = callFrame->codeBlock(); PutPropertySlot slot(baseValue, true, codeBlock->putByIdContext()); @@ -846,6 +853,7 @@ JSC_DEFINE_JIT_OPERATION(operationPutByIdNonStrictOptimize, void, (JSGlobalObjec JSValue value = JSValue::decode(encodedValue); JSValue baseValue = JSValue::decode(encodedBase); + JSC::EnsureStillAliveScope ensureBase(baseValue); CodeBlock* codeBlock = callFrame->codeBlock(); PutPropertySlot slot(baseValue, false, codeBlock->putByIdContext()); @@ -878,6 +886,7 @@ JSC_DEFINE_JIT_OPERATION(operationPutByIdDirectStrictOptimize, void, (JSGlobalOb JSValue value = JSValue::decode(encodedValue); JSObject* baseObject = asObject(JSValue::decode(encodedBase)); + JSC::EnsureStillAliveScope ensureBase(baseObject); CodeBlock* codeBlock = callFrame->codeBlock(); PutPropertySlot slot(baseObject, true, codeBlock->putByIdContext()); Structure* structure = nullptr; @@ -909,6 +918,7 @@ JSC_DEFINE_JIT_OPERATION(operationPutByIdDirectNonStrictOptimize, void, (JSGloba JSValue value = JSValue::decode(encodedValue); JSObject* baseObject = asObject(JSValue::decode(encodedBase)); + JSC::EnsureStillAliveScope ensureBase(baseObject); CodeBlock* codeBlock = callFrame->codeBlock(); PutPropertySlot slot(baseObject, false, codeBlock->putByIdContext()); Structure* structure = nullptr; @@ -1073,6 +1083,7 @@ static void putByVal(JSGlobalObject* globalObject, JSValue baseValue, JSValue su scope.release(); PutPropertySlot slot(baseValue, ecmaMode.isStrict()); + JSC::EnsureStillAliveScope ensureBase(baseValue); baseValue.putInline(globalObject, property, value, slot); } @@ -1201,6 +1212,7 @@ static ALWAYS_INLINE void directPutByValOptimize(JSGlobalObject* globalObject, C RELEASE_ASSERT(baseValue.isObject()); JSObject* baseObject = asObject(baseValue); + JSC::EnsureStillAliveScope ensureBase(baseObject); if (!isCopyOnWrite(baseObject->indexingMode()) && subscript.isInt32()) { Structure* structure = baseObject->structure(); @@ -1302,13 +1314,15 @@ JSC_DEFINE_JIT_OPERATION(operationDirectPutByValStrictGeneric, void, (JSGlobalOb JITOperationPrologueCallFrameTracer tracer(vm, callFrame); JSValue baseValue = JSValue::decode(encodedBaseValue); + JSObject* baseObject = asObject(baseValue); + JSC::EnsureStillAliveScope ensureBase(baseObject); JSValue subscript = JSValue::decode(encodedSubscript); JSValue value = JSValue::decode(encodedValue); RELEASE_ASSERT(baseValue.isObject()); stubInfo->tookSlowPath = true; - directPutByVal(globalObject, asObject(baseValue), subscript, value, profile, ECMAMode::strict()); + directPutByVal(globalObject, baseObject, subscript, value, profile, ECMAMode::strict()); } JSC_DEFINE_JIT_OPERATION(operationDirectPutByValNonStrictGeneric, void, (JSGlobalObject* globalObject, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, StructureStubInfo* stubInfo, ArrayProfile* profile)) @@ -1318,13 +1332,15 @@ JSC_DEFINE_JIT_OPERATION(operationDirectPutByValNonStrictGeneric, void, (JSGloba JITOperationPrologueCallFrameTracer tracer(vm, callFrame); JSValue baseValue = JSValue::decode(encodedBaseValue); + JSObject* baseObject = asObject(baseValue); + JSC::EnsureStillAliveScope ensureBase(baseObject); JSValue subscript = JSValue::decode(encodedSubscript); JSValue value = JSValue::decode(encodedValue); RELEASE_ASSERT(baseValue.isObject()); stubInfo->tookSlowPath = true; - directPutByVal(globalObject, asObject(baseValue), subscript, value, profile, ECMAMode::sloppy()); + directPutByVal(globalObject, baseObject, subscript, value, profile, ECMAMode::sloppy()); } JSC_DEFINE_JIT_OPERATION(operationSetPrivateBrandOptimize, void, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue encodedBaseValue, EncodedJSValue encodedBrand)) diff --git a/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp b/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp index d31f9cde5de29..c54543aa2573a 100644 --- a/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp +++ b/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp @@ -1463,7 +1463,9 @@ LLINT_SLOW_PATH_DECL(slow_path_in_by_id) if (!baseValue.isObject()) LLINT_THROW(createInvalidInParameterError(globalObject, baseValue)); - LLINT_RETURN(jsBoolean(asObject(baseValue)->hasProperty(globalObject, codeBlock->identifier(bytecode.m_property)))); + JSObject* baseObject = asObject(baseValue); + JSC::EnsureStillAliveScope ensureBase(baseObject); + LLINT_RETURN(jsBoolean(baseObject->hasProperty(globalObject, codeBlock->identifier(bytecode.m_property)))); } LLINT_SLOW_PATH_DECL(slow_path_in_by_val) @@ -1483,12 +1485,14 @@ LLINT_SLOW_PATH_DECL(slow_path_has_private_name) if (!baseValue.isObject()) LLINT_THROW(createInvalidInParameterError(globalObject, baseValue)); + JSObject* baseObject = asObject(baseValue); + JSC::EnsureStillAliveScope ensureBase(baseObject); auto propertyValue = getOperand(callFrame, bytecode.m_property); ASSERT(propertyValue.isSymbol()); auto property = propertyValue.toPropertyKey(globalObject); LLINT_CHECK_EXCEPTION(); - LLINT_RETURN(jsBoolean(asObject(baseValue)->hasPrivateField(globalObject, property))); + LLINT_RETURN(jsBoolean(baseObject->hasPrivateField(globalObject, property))); } LLINT_SLOW_PATH_DECL(slow_path_has_private_brand) @@ -1500,7 +1504,9 @@ LLINT_SLOW_PATH_DECL(slow_path_has_private_brand) if (!baseValue.isObject()) LLINT_THROW(createInvalidInParameterError(globalObject, baseValue)); - LLINT_RETURN(jsBoolean(asObject(baseValue)->hasPrivateBrand(globalObject, getOperand(callFrame, bytecode.m_brand)))); + JSObject* baseObject = asObject(baseValue); + JSC::EnsureStillAliveScope ensureBase(baseObject); + LLINT_RETURN(jsBoolean(baseObject->hasPrivateBrand(globalObject, getOperand(callFrame, bytecode.m_brand)))); } LLINT_SLOW_PATH_DECL(slow_path_put_getter_by_id) @@ -1514,8 +1520,10 @@ LLINT_SLOW_PATH_DECL(slow_path_put_getter_by_id) JSValue getter = getNonConstantOperand(callFrame, bytecode.m_accessor); ASSERT(getter.isObject()); + JSObject* getterObject = asObject(getter); + JSC::EnsureStillAliveScope ensureGetter(getterObject); - baseObj->putGetter(globalObject, codeBlock->identifier(bytecode.m_property), asObject(getter), options); + baseObj->putGetter(globalObject, codeBlock->identifier(bytecode.m_property), getterObject, options); LLINT_END(); } @@ -1530,8 +1538,10 @@ LLINT_SLOW_PATH_DECL(slow_path_put_setter_by_id) JSValue setter = getNonConstantOperand(callFrame, bytecode.m_accessor); ASSERT(setter.isObject()); + JSObject* setterObject = asObject(setter); + JSC::EnsureStillAliveScope ensureSetter(setterObject); - baseObj->putSetter(globalObject, codeBlock->identifier(bytecode.m_property), asObject(setter), options); + baseObj->putSetter(globalObject, codeBlock->identifier(bytecode.m_property), setterObject, options); LLINT_END(); } @@ -1563,11 +1573,13 @@ LLINT_SLOW_PATH_DECL(slow_path_put_getter_by_val) JSValue getter = getNonConstantOperand(callFrame, bytecode.m_accessor); ASSERT(getter.isObject()); + JSObject* getterObject = asObject(getter); + JSC::EnsureStillAliveScope ensureGetter(getterObject); auto property = subscript.toPropertyKey(globalObject); LLINT_CHECK_EXCEPTION(); - baseObj->putGetter(globalObject, property, asObject(getter), options); + baseObj->putGetter(globalObject, property, getterObject, options); LLINT_END(); } @@ -1583,11 +1595,13 @@ LLINT_SLOW_PATH_DECL(slow_path_put_setter_by_val) JSValue setter = getNonConstantOperand(callFrame, bytecode.m_accessor); ASSERT(setter.isObject()); + JSObject* setterObject = asObject(setter); + JSC::EnsureStillAliveScope ensureSetter(setterObject); auto property = subscript.toPropertyKey(globalObject); LLINT_CHECK_EXCEPTION(); - baseObj->putSetter(globalObject, property, asObject(setter), options); + baseObj->putSetter(globalObject, property, setterObject, options); LLINT_END(); } diff --git a/Source/JavaScriptCore/parser/ParserArena.cpp b/Source/JavaScriptCore/parser/ParserArena.cpp index 7917ed9ed6b92..e5779b00bb90b 100644 --- a/Source/JavaScriptCore/parser/ParserArena.cpp +++ b/Source/JavaScriptCore/parser/ParserArena.cpp @@ -111,6 +111,7 @@ const Identifier* IdentifierArena::makeBigIntDecimalIdentifier(VM& vm, const Ide #endif heapBigInt = bigInt.asHeapBigInt(); + JSC::EnsureStillAliveScope ensureHeapBigInt(heapBigInt); m_identifiers.append(Identifier::fromString(vm, JSBigInt::tryGetString(vm, heapBigInt, 10))); return &m_identifiers.last(); } diff --git a/Source/JavaScriptCore/runtime/GetterSetter.cpp b/Source/JavaScriptCore/runtime/GetterSetter.cpp index af48b6afaac46..6076607666c1d 100644 --- a/Source/JavaScriptCore/runtime/GetterSetter.cpp +++ b/Source/JavaScriptCore/runtime/GetterSetter.cpp @@ -55,6 +55,7 @@ JSValue GetterSetter::callGetter(JSGlobalObject* globalObject, JSValue thisValue RETURN_IF_EXCEPTION(scope, scope.exception()->value()); JSObject* getter = this->getter(); + JSC::EnsureStillAliveScope ensureGetter(getter); auto callData = JSC::getCallData(getter); RELEASE_AND_RETURN(scope, call(globalObject, getter, callData, thisValue, ArgList())); @@ -66,6 +67,7 @@ bool GetterSetter::callSetter(JSGlobalObject* globalObject, JSValue thisValue, J auto scope = DECLARE_THROW_SCOPE(vm); JSObject* setter = this->setter(); + JSC::EnsureStillAliveScope ensureSetter(setter); if (setter->type() == NullSetterFunctionType) return typeError(globalObject, scope, shouldThrow, ReadonlyPropertyWriteError); diff --git a/Source/JavaScriptCore/runtime/ObjectConstructor.cpp b/Source/JavaScriptCore/runtime/ObjectConstructor.cpp index aa2bab67d1fc2..c4e87aca85d33 100644 --- a/Source/JavaScriptCore/runtime/ObjectConstructor.cpp +++ b/Source/JavaScriptCore/runtime/ObjectConstructor.cpp @@ -474,6 +474,7 @@ bool toPropertyDescriptor(JSGlobalObject* globalObject, JSValue in, PropertyDesc return false; } JSObject* description = asObject(in); + JSC::EnsureStillAliveScope ensureDescription(description); bool hasProperty = description->hasProperty(globalObject, vm.propertyNames->enumerable); EXCEPTION_ASSERT(!scope.exception() || !hasProperty); diff --git a/Source/JavaScriptCore/runtime/RegExpConstructor.cpp b/Source/JavaScriptCore/runtime/RegExpConstructor.cpp index 0a7b3b5a2414f..5980879cd3e34 100644 --- a/Source/JavaScriptCore/runtime/RegExpConstructor.cpp +++ b/Source/JavaScriptCore/runtime/RegExpConstructor.cpp @@ -263,7 +263,9 @@ JSObject* constructRegExp(JSGlobalObject* globalObject, const ArgList& args, JS } if (isPatternRegExp) { - RegExp* regExp = jsCast(patternArg)->regExp(); + auto* regExpObj = jsCast(patternArg); + JSC::EnsureStillAliveScope ensureRegExpObj(regExpObj); + RegExp* regExp = regExpObj->regExp(); Structure* structure = getRegExpStructure(globalObject, newTarget); RETURN_IF_EXCEPTION(scope, nullptr); diff --git a/Source/JavaScriptCore/runtime/ShadowRealmPrototype.cpp b/Source/JavaScriptCore/runtime/ShadowRealmPrototype.cpp index 7b6c36d9d9ceb..1fe7e0ba06734 100644 --- a/Source/JavaScriptCore/runtime/ShadowRealmPrototype.cpp +++ b/Source/JavaScriptCore/runtime/ShadowRealmPrototype.cpp @@ -78,6 +78,7 @@ JSC_DEFINE_HOST_FUNCTION(importInRealm, (JSGlobalObject* globalObject, CallFrame RETURN_IF_EXCEPTION(scope, { }); JSGlobalObject* realmGlobalObject = thisRealm->globalObject(); + JSC::EnsureStillAliveScope ensureRealmGlobalObject(realmGlobalObject); auto* internalPromise = realmGlobalObject->moduleLoader()->importModule(realmGlobalObject, specifier, jsUndefined(), sourceOrigin); RETURN_IF_EXCEPTION(scope, JSValue::encode(promise->rejectWithCaughtException(realmGlobalObject, scope))); diff --git a/Source/JavaScriptCore/runtime/WeakMapConstructor.cpp b/Source/JavaScriptCore/runtime/WeakMapConstructor.cpp index f82841210a44e..061e3fbeb8ff8 100644 --- a/Source/JavaScriptCore/runtime/WeakMapConstructor.cpp +++ b/Source/JavaScriptCore/runtime/WeakMapConstructor.cpp @@ -98,8 +98,11 @@ JSC_DEFINE_HOST_FUNCTION(constructWeakMap, (JSGlobalObject* globalObject, CallFr if (canPerformFastSet) { if (key.isObject()) weakMap->set(vm, asObject(key), value); - else - throwTypeError(asObject(adderFunction)->globalObject(), scope, WeakMapInvalidKeyError); + else { + auto* adderObj = asObject(adderFunction); + JSC::EnsureStillAliveScope ensureAdder(adderObj); + throwTypeError(adderObj->globalObject(), scope, WeakMapInvalidKeyError); + } return; } diff --git a/Source/JavaScriptCore/runtime/WeakSetConstructor.cpp b/Source/JavaScriptCore/runtime/WeakSetConstructor.cpp index 41cf831dc90b3..12a174cbaf179 100644 --- a/Source/JavaScriptCore/runtime/WeakSetConstructor.cpp +++ b/Source/JavaScriptCore/runtime/WeakSetConstructor.cpp @@ -85,8 +85,11 @@ JSC_DEFINE_HOST_FUNCTION(constructWeakSet, (JSGlobalObject* globalObject, CallFr if (canPerformFastAdd) { if (nextValue.isObject()) weakSet->add(vm, asObject(nextValue)); - else - throwTypeError(asObject(adderFunction)->globalObject(), scope, WeakSetInvalidValueError); + else { + auto* adderObj = asObject(adderFunction); + JSC::EnsureStillAliveScope ensureAdder(adderObj); + throwTypeError(adderObj->globalObject(), scope, WeakSetInvalidValueError); + } return; } diff --git a/Source/JavaScriptCore/tools/JSDollarVM.cpp b/Source/JavaScriptCore/tools/JSDollarVM.cpp index 660dec9cb92c1..74819a8e1465d 100644 --- a/Source/JavaScriptCore/tools/JSDollarVM.cpp +++ b/Source/JavaScriptCore/tools/JSDollarVM.cpp @@ -554,6 +554,7 @@ JSC_DEFINE_CUSTOM_GETTER(customGetterValueGetter, (JSGlobalObject* globalObject, CustomGetter* thisObject = jsDynamicCast(JSValue::decode(thisValue)); if (!thisObject) return throwVMTypeError(globalObject, scope); + JSC::EnsureStillAliveScope ensureThisObject(thisObject); bool shouldThrow = thisObject->get(globalObject, PropertyName(Identifier::fromString(vm, "shouldThrow"_s))).toBoolean(globalObject); RETURN_IF_EXCEPTION(scope, encodedJSValue()); if (shouldThrow) @@ -570,6 +571,7 @@ JSC_DEFINE_CUSTOM_GETTER(customGetterAcessorGetter, (JSGlobalObject* globalObjec JSObject* thisObject = jsDynamicCast(JSValue::decode(thisValue)); if (!thisObject) return throwVMTypeError(globalObject, scope); + JSC::EnsureStillAliveScope ensureThisObject(thisObject); bool shouldThrow = thisObject->get(globalObject, PropertyName(Identifier::fromString(vm, "shouldThrow"_s))).toBoolean(globalObject); RETURN_IF_EXCEPTION(scope, encodedJSValue()); if (shouldThrow) diff --git a/Source/JavaScriptCore/wasm/js/JSWebAssemblyMemory.cpp b/Source/JavaScriptCore/wasm/js/JSWebAssemblyMemory.cpp index 0877ff2059379..a72a86b3fd2ae 100644 --- a/Source/JavaScriptCore/wasm/js/JSWebAssemblyMemory.cpp +++ b/Source/JavaScriptCore/wasm/js/JSWebAssemblyMemory.cpp @@ -111,6 +111,7 @@ JSArrayBuffer* JSWebAssemblyMemory::buffer(JSGlobalObject* globalObject) if (m_memory->sharingMode() == Wasm::MemorySharingMode::Shared) m_buffer->makeShared(); auto* arrayBuffer = JSArrayBuffer::create(vm, globalObject->arrayBufferStructure(m_buffer->sharingMode()), m_buffer.get()); + JSC::EnsureStillAliveScope ensureArrayBuffer(arrayBuffer); if (m_memory->sharingMode() == Wasm::MemorySharingMode::Shared) { objectConstructorFreeze(globalObject, arrayBuffer); RETURN_IF_EXCEPTION(throwScope, { }); diff --git a/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp b/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp index cbedddc8efef8..9848e539dc9e0 100644 --- a/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp +++ b/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp @@ -564,6 +564,7 @@ void WebAssemblyModuleRecord::initializeExports(JSGlobalObject* globalObject) // Let exports be a list of (string, JS value) pairs that is mapped from each external value e in instance.exports as follows: // https://webassembly.github.io/spec/js-api/index.html#create-an-exports-object JSObject* exportsObject = constructEmptyObject(vm, globalObject->nullPrototypeObjectStructure()); + JSC::EnsureStillAliveScope ensureExportsObject(exportsObject); JSModuleEnvironment* moduleEnvironment = this->moduleEnvironment(); for (const auto& exp : moduleInformation.exports) { JSValue exportedValue; diff --git a/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransform.cpp b/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransform.cpp index 1bba4e75951d7..f7c2a6f6db58c 100644 --- a/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransform.cpp +++ b/Source/WebCore/Modules/mediastream/RTCRtpSFrameTransform.cpp @@ -220,6 +220,7 @@ ExceptionOr RTCRtpSFrameTransform::createStreams() if (!globalObject) return Exception { InvalidStateError }; + JSC::EnsureStillAliveScope ensureGlobal(globalObject); m_readableStreamSource = SimpleReadableStreamSource::create(); auto readable = ReadableStream::create(*globalObject, m_readableStreamSource.copyRef()); if (readable.hasException()) diff --git a/Source/WebCore/bindings/js/JSCustomElementInterface.cpp b/Source/WebCore/bindings/js/JSCustomElementInterface.cpp index 0915fe4aee69b..7a4f01a3229b5 100644 --- a/Source/WebCore/bindings/js/JSCustomElementInterface.cpp +++ b/Source/WebCore/bindings/js/JSCustomElementInterface.cpp @@ -261,6 +261,7 @@ void JSCustomElementInterface::invokeCallback(Element& element, JSObject* callba JSGlobalObject* lexicalGlobalObject = globalObject; JSObject* jsElement = asObject(toJS(lexicalGlobalObject, globalObject, element)); + JSC::EnsureStillAliveScope ensureJsElement(jsElement); auto callData = JSC::getCallData(callback); ASSERT(callData.type != CallData::Type::None); diff --git a/Source/WebCore/bindings/js/JSDOMPromiseDeferred.h b/Source/WebCore/bindings/js/JSDOMPromiseDeferred.h index ef851d8dc359e..0ffea0f182fe0 100644 --- a/Source/WebCore/bindings/js/JSDOMPromiseDeferred.h +++ b/Source/WebCore/bindings/js/JSDOMPromiseDeferred.h @@ -67,6 +67,7 @@ class DeferredPromise : public DOMGuarded { ASSERT(globalObject()); JSC::JSGlobalObject* lexicalGlobalObject = globalObject(); JSC::JSLockHolder locker(lexicalGlobalObject); + JSC::EnsureStillAliveScope ensureLexicalGlobalObject(lexicalGlobalObject); resolve(*lexicalGlobalObject, toJS(*lexicalGlobalObject, *globalObject(), std::forward(value))); } @@ -104,6 +105,7 @@ class DeferredPromise : public DOMGuarded { ASSERT(globalObject()); JSC::JSGlobalObject* lexicalGlobalObject = globalObject(); JSC::JSLockHolder locker(lexicalGlobalObject); + JSC::EnsureStillAliveScope ensureLexicalGlobalObject(lexicalGlobalObject); resolve(*lexicalGlobalObject, toJSNewlyCreated(*lexicalGlobalObject, *globalObject(), std::forward(value))); } @@ -117,6 +119,7 @@ class DeferredPromise : public DOMGuarded { ASSERT(globalObject()); auto* lexicalGlobalObject = globalObject(); JSC::JSLockHolder locker(lexicalGlobalObject); + JSC::EnsureStillAliveScope ensureLexicalGlobalObject(lexicalGlobalObject); resolve(*lexicalGlobalObject, toJSNewlyCreated(*lexicalGlobalObject, *globalObject(), createValue(*globalObject()->scriptExecutionContext()))); } @@ -130,6 +133,7 @@ class DeferredPromise : public DOMGuarded { ASSERT(globalObject()); JSC::JSGlobalObject* lexicalGlobalObject = globalObject(); JSC::JSLockHolder locker(lexicalGlobalObject); + JSC::EnsureStillAliveScope ensureLexicalGlobalObject(lexicalGlobalObject); reject(*lexicalGlobalObject, toJS(*lexicalGlobalObject, *globalObject(), std::forward(value)), rejectAsHandled); } @@ -150,6 +154,7 @@ class DeferredPromise : public DOMGuarded { auto* lexicalGlobalObject = globalObject(); JSC::VM& vm = lexicalGlobalObject->vm(); JSC::JSLockHolder locker(vm); + JSC::EnsureStillAliveScope ensureLexicalGlobalObject(lexicalGlobalObject); auto scope = DECLARE_CATCH_SCOPE(vm); resolve(*lexicalGlobalObject, callback(*globalObject())); if (UNLIKELY(scope.exception())) @@ -167,6 +172,7 @@ class DeferredPromise : public DOMGuarded { auto* lexicalGlobalObject = globalObject(); JSC::VM& vm = lexicalGlobalObject->vm(); JSC::JSLockHolder locker(vm); + JSC::EnsureStillAliveScope ensureLexicalGlobalObject(lexicalGlobalObject); auto scope = DECLARE_CATCH_SCOPE(vm); reject(*lexicalGlobalObject, callback(*globalObject()), rejectAsHandled); if (UNLIKELY(scope.exception())) diff --git a/Source/WebCore/bindings/js/JSDOMWrapperCache.h b/Source/WebCore/bindings/js/JSDOMWrapperCache.h index fa1d516a0b35f..018a71ade804a 100644 --- a/Source/WebCore/bindings/js/JSDOMWrapperCache.h +++ b/Source/WebCore/bindings/js/JSDOMWrapperCache.h @@ -185,6 +185,7 @@ template inline auto createWrapper(JSDOMGlobalObj { using WrapperClass = typename JSDOMWrapperConverterTraits::WrapperClass; + JSC::EnsureStillAliveScope ensureGlobalObject(globalObject); ASSERT(!getCachedWrapper(globalObject->world(), domObject)); auto* domObjectPtr = domObject.ptr(); auto* wrapper = WrapperClass::create(getDOMStructure(globalObject->vm(), *globalObject), globalObject, WTFMove(domObject)); @@ -201,6 +202,8 @@ template inline JSC::JSValue wrap(JSC::JSGlobalObject* lexica { if (auto* wrapper = getCachedWrapper(globalObject->world(), domObject)) return wrapper; + JSC::EnsureStillAliveScope ensureLexicalGlobalObject(lexicalGlobalObject); + JSC::EnsureStillAliveScope ensureGlobalObject(globalObject); return toJSNewlyCreated(lexicalGlobalObject, globalObject, Ref(domObject)); } diff --git a/Source/WebCore/bindings/js/JSDocumentCustom.cpp b/Source/WebCore/bindings/js/JSDocumentCustom.cpp index 151f750ba5999..dac590d5c0704 100644 --- a/Source/WebCore/bindings/js/JSDocumentCustom.cpp +++ b/Source/WebCore/bindings/js/JSDocumentCustom.cpp @@ -60,6 +60,7 @@ JSObject* cachedDocumentWrapper(JSGlobalObject& lexicalGlobalObject, JSDOMGlobal auto* documentGlobalObject = toJSDOMGlobalObject(lexicalGlobalObject.vm(), toJS(&lexicalGlobalObject, *window)); if (!documentGlobalObject) return nullptr; + JSC::EnsureStillAliveScope ensureDocumentGlobalObject(documentGlobalObject); // Creating a wrapper for domWindow might have created a wrapper for document as well. return getCachedWrapper(documentGlobalObject->world(), document); diff --git a/Source/WebCore/bindings/js/JSErrorHandler.cpp b/Source/WebCore/bindings/js/JSErrorHandler.cpp index bdf52807d99a1..110eaed592352 100644 --- a/Source/WebCore/bindings/js/JSErrorHandler.cpp +++ b/Source/WebCore/bindings/js/JSErrorHandler.cpp @@ -80,6 +80,12 @@ void JSErrorHandler::handleEvent(ScriptExecutionContext& scriptExecutionContext, if (!globalObject) return; + // Prevent the compiler from keeping jsFunction or globalObject only in caller-saved + // registers across GC allocation points below. On ARM 32-bit, conservative stack + // scanning only sees callee-saved registers and stack-spilled values. + JSC::EnsureStillAliveScope ensureJSFunction(jsFunction); + JSC::EnsureStillAliveScope ensureGlobalObject(globalObject); + auto callData = JSC::getCallData(jsFunction); if (callData.type != CallData::Type::None) { Ref protectedThis(*this); diff --git a/Source/WebCore/bindings/js/JSEventListener.cpp b/Source/WebCore/bindings/js/JSEventListener.cpp index a57a7dd7a14eb..02316de7db730 100644 --- a/Source/WebCore/bindings/js/JSEventListener.cpp +++ b/Source/WebCore/bindings/js/JSEventListener.cpp @@ -184,6 +184,15 @@ void JSEventListener::handleEvent(ScriptExecutionContext& scriptExecutionContext JSValue handleEventFunction = jsFunction; + // Prevent the compiler from keeping jsFunction, globalObject, or lexicalGlobalObject + // only in caller-saved registers across GC allocation points below (toJS calls, property + // accesses, etc.). On ARM 32-bit, conservative stack scanning only sees callee-saved + // registers and stack-spilled values. Without these, a GC triggered by e.g. toJS() at + // line 213/220 could miss these cells, collect them, and corrupt the heap. + EnsureStillAliveScope ensureJSFunction(jsFunction); + EnsureStillAliveScope ensureGlobalObject(globalObject); + EnsureStillAliveScope ensureLexicalGlobalObject(lexicalGlobalObject); + Ref protectedThis { *this }; auto callData = JSC::getCallData(handleEventFunction); diff --git a/Source/WebCore/bindings/js/JSHTMLElementCustom.cpp b/Source/WebCore/bindings/js/JSHTMLElementCustom.cpp index 8ef9cf537d8e9..d175ff29d5b00 100644 --- a/Source/WebCore/bindings/js/JSHTMLElementCustom.cpp +++ b/Source/WebCore/bindings/js/JSHTMLElementCustom.cpp @@ -105,6 +105,7 @@ EncodedJSValue constructJSHTMLElement(JSGlobalObject* lexicalGlobalObject, CallF RETURN_IF_EXCEPTION(scope, encodedJSValue()); JSObject* elementWrapperObject = asObject(elementWrapperValue); + JSC::EnsureStillAliveScope ensureElementWrapperObject(elementWrapperObject); JSObject::setPrototype(elementWrapperObject, lexicalGlobalObject, newPrototype, true /* shouldThrowIfCantSet */); RETURN_IF_EXCEPTION(scope, encodedJSValue()); @@ -124,14 +125,21 @@ JSScope* JSHTMLElement::pushEventHandlerScope(JSGlobalObject* lexicalGlobalObjec // https://bugs.webkit.org/show_bug.cgi?id=134932 VM& vm = lexicalGlobalObject->vm(); - scope = JSWithScope::create(vm, lexicalGlobalObject, scope, asObject(toJS(lexicalGlobalObject, globalObject(), element.document()))); + auto* docWrapper = asObject(toJS(lexicalGlobalObject, globalObject(), element.document())); + JSC::EnsureStillAliveScope ensureDocWrapper(docWrapper); + scope = JSWithScope::create(vm, lexicalGlobalObject, scope, docWrapper); // The form is next, searched before the document, but after the element itself. - if (HTMLFormElement* form = element.form()) - scope = JSWithScope::create(vm, lexicalGlobalObject, scope, asObject(toJS(lexicalGlobalObject, globalObject(), *form))); + if (HTMLFormElement* form = element.form()) { + auto* formWrapper = asObject(toJS(lexicalGlobalObject, globalObject(), *form)); + JSC::EnsureStillAliveScope ensureFormWrapper(formWrapper); + scope = JSWithScope::create(vm, lexicalGlobalObject, scope, formWrapper); + } // The element is on top, searched first. - return JSWithScope::create(vm, lexicalGlobalObject, scope, asObject(toJS(lexicalGlobalObject, globalObject(), element))); + auto* elementWrapper = asObject(toJS(lexicalGlobalObject, globalObject(), element)); + JSC::EnsureStillAliveScope ensureElementWrapper(elementWrapper); + return JSWithScope::create(vm, lexicalGlobalObject, scope, elementWrapper); } JSValue toJS(JSGlobalObject*, JSDOMGlobalObject* globalObject, HTMLElement& element) diff --git a/Source/WebCore/bindings/js/JSLazyEventListener.cpp b/Source/WebCore/bindings/js/JSLazyEventListener.cpp index b029cacf19912..e6e66da80e792 100644 --- a/Source/WebCore/bindings/js/JSLazyEventListener.cpp +++ b/Source/WebCore/bindings/js/JSLazyEventListener.cpp @@ -177,7 +177,9 @@ JSObject* JSLazyEventListener::initializeJSFunction(ScriptExecutionContext& exec if (!wrapper()) { // Ensure that 'node' has a JavaScript wrapper to mark the event listener we're creating. // FIXME: Should pass the global object associated with the node - setWrapperWhenInitializingJSFunction(vm, asObject(toJS(lexicalGlobalObject, globalObject, *m_originalNode))); + auto* nodeWrapper = asObject(toJS(lexicalGlobalObject, globalObject, *m_originalNode)); + JSC::EnsureStillAliveScope ensureNodeWrapper(nodeWrapper); + setWrapperWhenInitializingJSFunction(vm, nodeWrapper); } // Add the event's home element to the scope diff --git a/Source/WebCore/bindings/js/JSPopStateEventCustom.cpp b/Source/WebCore/bindings/js/JSPopStateEventCustom.cpp index 302ecd412e923..c938df6a89266 100644 --- a/Source/WebCore/bindings/js/JSPopStateEventCustom.cpp +++ b/Source/WebCore/bindings/js/JSPopStateEventCustom.cpp @@ -85,6 +85,7 @@ JSValue JSPopStateEvent::state(JSGlobalObject& lexicalGlobalObject) const if (isSameState) { JSHistory* jsHistory = jsCast(toJS(&lexicalGlobalObject, globalObject(), *history).asCell()); + JSC::EnsureStillAliveScope ensureJsHistory(jsHistory); result = jsHistory->state(lexicalGlobalObject); } else result = event.serializedState()->deserialize(lexicalGlobalObject, globalObject()); diff --git a/Source/WebCore/bindings/js/SerializedScriptValue.cpp b/Source/WebCore/bindings/js/SerializedScriptValue.cpp index 5897e1066512f..8b364316c9925 100644 --- a/Source/WebCore/bindings/js/SerializedScriptValue.cpp +++ b/Source/WebCore/bindings/js/SerializedScriptValue.cpp @@ -2042,6 +2042,7 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in) if (inputObjectStack.size() > maximumFilterRecursion) return SerializationReturnCode::StackOverflowError; JSMap* inMap = jsCast(inValue); + JSC::EnsureStillAliveScope ensureInMap(inMap); if (!startMap(inMap)) break; JSMapIterator* iterator = JSMapIterator::create(vm, m_lexicalGlobalObject->mapIteratorStructure(), inMap, IterationKind::Entries); @@ -2088,6 +2089,7 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in) if (inputObjectStack.size() > maximumFilterRecursion) return SerializationReturnCode::StackOverflowError; JSSet* inSet = jsCast(inValue); + JSC::EnsureStillAliveScope ensureInSet(inSet); if (!startSet(inSet)) break; JSSetIterator* iterator = JSSetIterator::create(vm, m_lexicalGlobalObject->setIteratorStructure(), inSet, IterationKind::Keys); @@ -3985,6 +3987,7 @@ DeserializationResult CloneDeserializer::deserialize() if (outputObjectStack.size() > maximumFilterRecursion) return std::make_pair(JSValue(), SerializationReturnCode::StackOverflowError); JSObject* outObject = constructEmptyObject(m_lexicalGlobalObject, m_globalObject->objectPrototype()); + JSC::EnsureStillAliveScope ensureOutObject(outObject); m_gcBuffer.appendWithCrashOnOverflow(outObject); outputObjectStack.append(outObject); } @@ -4020,6 +4023,7 @@ DeserializationResult CloneDeserializer::deserialize() if (outputObjectStack.size() > maximumFilterRecursion) return std::make_pair(JSValue(), SerializationReturnCode::StackOverflowError); JSMap* map = JSMap::create(m_lexicalGlobalObject->vm(), m_globalObject->mapStructure()); + JSC::EnsureStillAliveScope ensureMap(map); m_gcBuffer.appendWithCrashOnOverflow(map); outputObjectStack.append(map); mapStack.append(map); @@ -4049,6 +4053,7 @@ DeserializationResult CloneDeserializer::deserialize() if (outputObjectStack.size() > maximumFilterRecursion) return std::make_pair(JSValue(), SerializationReturnCode::StackOverflowError); JSSet* set = JSSet::create(m_lexicalGlobalObject->vm(), m_globalObject->setStructure()); + JSC::EnsureStillAliveScope ensureSet(set); m_gcBuffer.appendWithCrashOnOverflow(set); outputObjectStack.append(set); setStack.append(set); diff --git a/Source/WebCore/crypto/SubtleCrypto.cpp b/Source/WebCore/crypto/SubtleCrypto.cpp index 824a5014ea272..d872943dcfae3 100644 --- a/Source/WebCore/crypto/SubtleCrypto.cpp +++ b/Source/WebCore/crypto/SubtleCrypto.cpp @@ -244,6 +244,7 @@ static ExceptionOr> normalizeCryptoAl JSValue nameValue = value.get()->get(&state, Identifier::fromString(vm, "name"_s)); JSValue publicValue = value.get()->get(&state, Identifier::fromString(vm, "public"_s)); JSObject* newValue = constructEmptyObject(&state); + JSC::EnsureStillAliveScope ensureNewValue(newValue); newValue->putDirect(vm, Identifier::fromString(vm, "name"_s), nameValue); newValue->putDirect(vm, Identifier::fromString(vm, "publicKey"_s), publicValue); diff --git a/Source/WebCore/html/CustomPaintImage.cpp b/Source/WebCore/html/CustomPaintImage.cpp index bf29dd90ff581..691c6211bb24b 100644 --- a/Source/WebCore/html/CustomPaintImage.cpp +++ b/Source/WebCore/html/CustomPaintImage.cpp @@ -163,6 +163,7 @@ ImageDrawResult CustomPaintImage::doCustomPaint(GraphicsContext& destContext, co auto& vm = paintConstructor.getObject()->vm(); JSC::JSLockHolder lock(vm); + JSC::EnsureStillAliveScope ensurePaintConstructor(paintConstructor.asCell()); auto scope = DECLARE_THROW_SCOPE(vm); auto& globalObject = *paintConstructor.getObject()->globalObject(); diff --git a/Source/WebCore/html/PDFDocument.cpp b/Source/WebCore/html/PDFDocument.cpp index cce0a7c38d428..12524e5de5634 100644 --- a/Source/WebCore/html/PDFDocument.cpp +++ b/Source/WebCore/html/PDFDocument.cpp @@ -191,6 +191,7 @@ void PDFDocument::sendPDFArrayBuffer() auto globalObject = this->globalObject(); auto& vm = globalObject->vm(); + JSC::EnsureStillAliveScope ensureGlobalObject(globalObject); JSLockHolder lock(vm); auto callData = JSC::getCallData(openFunction); diff --git a/Source/WebCore/inspector/CommandLineAPIHost.cpp b/Source/WebCore/inspector/CommandLineAPIHost.cpp index a13d66e4ad9fd..2c8467a53b6b6 100644 --- a/Source/WebCore/inspector/CommandLineAPIHost.cpp +++ b/Source/WebCore/inspector/CommandLineAPIHost.cpp @@ -194,6 +194,7 @@ JSValue CommandLineAPIHost::wrapper(JSGlobalObject* exec, JSDOMGlobalObject* glo return value; JSObject* prototype = JSCommandLineAPIHost::createPrototype(exec->vm(), *globalObject); + JSC::EnsureStillAliveScope ensurePrototype(prototype); Structure* structure = JSCommandLineAPIHost::createStructure(exec->vm(), globalObject, prototype); JSCommandLineAPIHost* commandLineAPIHost = JSCommandLineAPIHost::create(structure, globalObject, Ref { *this }); m_wrappers.addWrapper(globalObject, commandLineAPIHost); diff --git a/Source/WebCore/inspector/WebInjectedScriptHost.cpp b/Source/WebCore/inspector/WebInjectedScriptHost.cpp index 520a30970215c..64b841653eb11 100644 --- a/Source/WebCore/inspector/WebInjectedScriptHost.cpp +++ b/Source/WebCore/inspector/WebInjectedScriptHost.cpp @@ -95,7 +95,9 @@ static JSObject* objectForPaymentItem(VM& vm, JSGlobalObject* exec, const Paymen { auto* object = constructEmptyObject(exec); object->putDirect(vm, Identifier::fromString(vm, "label"_s), jsString(vm, paymentItem.label)); - object->putDirect(vm, Identifier::fromString(vm, "amount"_s), objectForPaymentCurrencyAmount(vm, exec, paymentItem.amount)); + auto* amount = objectForPaymentCurrencyAmount(vm, exec, paymentItem.amount); + JSC::EnsureStillAliveScope ensureAmount(amount); + object->putDirect(vm, Identifier::fromString(vm, "amount"_s), amount); object->putDirect(vm, Identifier::fromString(vm, "pending"_s), jsBoolean(paymentItem.pending)); return object; } @@ -105,7 +107,9 @@ static JSObject* objectForPaymentShippingOption(VM& vm, JSGlobalObject* exec, co auto* object = constructEmptyObject(exec); object->putDirect(vm, Identifier::fromString(vm, "id"_s), jsString(vm, paymentShippingOption.id)); object->putDirect(vm, Identifier::fromString(vm, "label"_s), jsString(vm, paymentShippingOption.label)); - object->putDirect(vm, Identifier::fromString(vm, "amount"_s), objectForPaymentCurrencyAmount(vm, exec, paymentShippingOption.amount)); + auto* amount = objectForPaymentCurrencyAmount(vm, exec, paymentShippingOption.amount); + JSC::EnsureStillAliveScope ensureAmount(amount); + object->putDirect(vm, Identifier::fromString(vm, "amount"_s), amount); object->putDirect(vm, Identifier::fromString(vm, "selected"_s), jsBoolean(paymentShippingOption.selected)); return object; } @@ -114,12 +118,19 @@ static JSObject* objectForPaymentDetailsModifier(VM& vm, JSGlobalObject* exec, c { auto* object = constructEmptyObject(exec); object->putDirect(vm, Identifier::fromString(vm, "supportedMethods"_s), jsString(vm, modifier.supportedMethods)); - if (modifier.total) - object->putDirect(vm, Identifier::fromString(vm, "total"_s), objectForPaymentItem(vm, exec, *modifier.total)); + if (modifier.total) { + auto* total = objectForPaymentItem(vm, exec, *modifier.total); + JSC::EnsureStillAliveScope ensureTotal(total); + object->putDirect(vm, Identifier::fromString(vm, "total"_s), total); + } if (!modifier.additionalDisplayItems.isEmpty()) { auto* additionalDisplayItems = constructEmptyArray(exec, nullptr); - for (unsigned i = 0; i < modifier.additionalDisplayItems.size(); ++i) - additionalDisplayItems->putDirectIndex(exec, i, objectForPaymentItem(vm, exec, modifier.additionalDisplayItems[i])); + JSC::EnsureStillAliveScope ensureAdditionalDisplayItems(additionalDisplayItems); + for (unsigned i = 0; i < modifier.additionalDisplayItems.size(); ++i) { + auto* item = objectForPaymentItem(vm, exec, modifier.additionalDisplayItems[i]); + JSC::EnsureStillAliveScope ensureItem(item); + additionalDisplayItems->putDirectIndex(exec, i, item); + } object->putDirect(vm, Identifier::fromString(vm, "additionalDisplayItems"_s), additionalDisplayItems); } return object; @@ -129,23 +140,39 @@ static JSObject* objectForPaymentDetails(VM& vm, JSGlobalObject* exec, const Pay { auto* object = constructEmptyObject(exec); object->putDirect(vm, Identifier::fromString(vm, "id"_s), jsString(vm, paymentDetails.id)); - object->putDirect(vm, Identifier::fromString(vm, "total"_s), objectForPaymentItem(vm, exec, paymentDetails.total)); + { + auto* total = objectForPaymentItem(vm, exec, paymentDetails.total); + JSC::EnsureStillAliveScope ensureTotal(total); + object->putDirect(vm, Identifier::fromString(vm, "total"_s), total); + } if (paymentDetails.displayItems) { auto* displayItems = constructEmptyArray(exec, nullptr); - for (unsigned i = 0; i < paymentDetails.displayItems->size(); ++i) - displayItems->putDirectIndex(exec, i, objectForPaymentItem(vm, exec, paymentDetails.displayItems->at(i))); + JSC::EnsureStillAliveScope ensureDisplayItems(displayItems); + for (unsigned i = 0; i < paymentDetails.displayItems->size(); ++i) { + auto* item = objectForPaymentItem(vm, exec, paymentDetails.displayItems->at(i)); + JSC::EnsureStillAliveScope ensureItem(item); + displayItems->putDirectIndex(exec, i, item); + } object->putDirect(vm, Identifier::fromString(vm, "displayItems"_s), displayItems); } if (paymentDetails.shippingOptions) { auto* shippingOptions = constructEmptyArray(exec, nullptr); - for (unsigned i = 0; i < paymentDetails.shippingOptions->size(); ++i) - shippingOptions->putDirectIndex(exec, i, objectForPaymentShippingOption(vm, exec, paymentDetails.shippingOptions->at(i))); + JSC::EnsureStillAliveScope ensureShippingOptions(shippingOptions); + for (unsigned i = 0; i < paymentDetails.shippingOptions->size(); ++i) { + auto* option = objectForPaymentShippingOption(vm, exec, paymentDetails.shippingOptions->at(i)); + JSC::EnsureStillAliveScope ensureOption(option); + shippingOptions->putDirectIndex(exec, i, option); + } object->putDirect(vm, Identifier::fromString(vm, "shippingOptions"_s), shippingOptions); } if (paymentDetails.modifiers) { auto* modifiers = constructEmptyArray(exec, nullptr); - for (unsigned i = 0; i < paymentDetails.modifiers->size(); ++i) - modifiers->putDirectIndex(exec, i, objectForPaymentDetailsModifier(vm, exec, paymentDetails.modifiers->at(i))); + JSC::EnsureStillAliveScope ensureModifiers(modifiers); + for (unsigned i = 0; i < paymentDetails.modifiers->size(); ++i) { + auto* modifier = objectForPaymentDetailsModifier(vm, exec, paymentDetails.modifiers->at(i)); + JSC::EnsureStillAliveScope ensureModifier(modifier); + modifiers->putDirectIndex(exec, i, modifier); + } object->putDirect(vm, Identifier::fromString(vm, "modifiers"_s), modifiers); } return object; diff --git a/Source/WebCore/testing/Internals.cpp b/Source/WebCore/testing/Internals.cpp index cad9428421394..5bec793a2435c 100644 --- a/Source/WebCore/testing/Internals.cpp +++ b/Source/WebCore/testing/Internals.cpp @@ -2483,8 +2483,11 @@ String Internals::parserMetaData(JSC::JSValue code) GetCallerCodeBlockFunctor iter; callFrame->iterate(vm, iter); executable = iter.codeBlock()->ownerExecutable(); - } else if (code.isCallable()) - executable = JSC::jsCast(code.toObject(globalObject))->jsExecutable(); + } else if (code.isCallable()) { + JSFunction* codeFunction = JSC::jsCast(code.toObject(globalObject)); + JSC::EnsureStillAliveScope ensureCodeFunction(codeFunction); + executable = codeFunction->jsExecutable(); + } else return String(); @@ -5200,7 +5203,9 @@ RefPtr Internals::observeGC(JSC::JSValue value) { if (!value.isObject()) return nullptr; - return GCObservation::create(asObject(value)); + JSC::JSObject* object = asObject(value); + JSC::EnsureStillAliveScope ensureObject(object); + return GCObservation::create(object); } void Internals::setUserInterfaceLayoutDirection(UserInterfaceLayoutDirection userInterfaceLayoutDirection) diff --git a/Source/WebCore/workers/WorkerOrWorkletScriptController.cpp b/Source/WebCore/workers/WorkerOrWorkletScriptController.cpp index 5afb2accfb8a1..5320ce566bc4d 100644 --- a/Source/WebCore/workers/WorkerOrWorkletScriptController.cpp +++ b/Source/WebCore/workers/WorkerOrWorkletScriptController.cpp @@ -305,6 +305,7 @@ bool WorkerOrWorkletScriptController::loadModuleSynchronously(WorkerScriptFetche auto scope = DECLARE_CATCH_SCOPE(vm); if (errorValue.isObject()) { auto* object = JSC::asObject(errorValue); + JSC::EnsureStillAliveScope ensureObject(object); if (JSValue failureKindValue = object->getDirect(vm, builtinNames(vm).failureKindPrivateName())) { // This is host propagated error in the module loader pipeline. switch (static_cast(failureKindValue.asInt32())) { @@ -480,6 +481,7 @@ void WorkerOrWorkletScriptController::loadAndEvaluateModule(const URL& moduleURL JSValue errorValue = callFrame->argument(0); if (errorValue.isObject()) { auto* object = JSC::asObject(errorValue); + JSC::EnsureStillAliveScope ensureObject(object); if (JSValue failureKindValue = object->getDirect(vm, builtinNames(vm).failureKindPrivateName())) { auto catchScope = DECLARE_CATCH_SCOPE(vm); String message = retrieveErrorMessageWithoutName(*globalObject, vm, object, catchScope); @@ -496,6 +498,7 @@ void WorkerOrWorkletScriptController::loadAndEvaluateModule(const URL& moduleURL } if (object->inherits()) { auto* error = jsCast(object); + JSC::EnsureStillAliveScope ensureError(error); switch (error->errorType()) { case ErrorType::TypeError: { auto catchScope = DECLARE_CATCH_SCOPE(vm); diff --git a/Source/WebCore/workers/service/ServiceWorkerRegistration.cpp b/Source/WebCore/workers/service/ServiceWorkerRegistration.cpp index 99a6c34171d2c..680f6ed0284b3 100644 --- a/Source/WebCore/workers/service/ServiceWorkerRegistration.cpp +++ b/Source/WebCore/workers/service/ServiceWorkerRegistration.cpp @@ -312,7 +312,9 @@ void ServiceWorkerRegistration::showNotification(ScriptExecutionContext& context if (auto* serviceWorkerGlobalScope = dynamicDowncast(context)) { if (auto* pushEvent = serviceWorkerGlobalScope->pushEvent()) { auto& globalObject = *JSC::jsCast(promise->globalObject()); - auto& jsPromise = *JSC::jsCast(promise->promise()); + auto* jsPromisePtr = JSC::jsCast(promise->promise()); + JSC::EnsureStillAliveScope ensureJSPromise(jsPromisePtr); + auto& jsPromise = *jsPromisePtr; pushEvent->waitUntil(DOMPromise::create(globalObject, jsPromise)); } }