예제 #1
0
bool NPJSObject::hasMethod(NPIdentifier methodName)
{
    IdentifierRep* identifierRep = static_cast<IdentifierRep*>(methodName);

    if (!identifierRep->isString())
        return false;

    ExecState* exec = m_objectMap->globalExec();
    if (!exec)
        return false;

    JSLockHolder lock(exec);

    JSValue value = m_jsObject->get(exec, identifierFromIdentifierRep(exec, identifierRep));    
    exec->clearException();

    CallData callData;
    return getCallData(value, callData) != CallType::None;
}
예제 #2
0
EncodedJSValue JSC_HOST_CALL objectProtoFuncDefineSetter(ExecState* exec)
{
    JSObject* thisObject = exec->thisValue().toThis(exec, StrictMode).toObject(exec);
    if (exec->hadException())
        return JSValue::encode(jsUndefined());

    JSValue set = exec->argument(1);
    CallData callData;
    if (getCallData(set, callData) == CallTypeNone)
        return throwVMError(exec, createTypeError(exec, ASCIILiteral("invalid setter usage")));

    PropertyDescriptor descriptor;
    descriptor.setSetter(set);
    descriptor.setEnumerable(true);
    descriptor.setConfigurable(true);
    thisObject->methodTable(exec->vm())->defineOwnProperty(thisObject, exec, exec->argument(0).toString(exec)->toIdentifier(exec), descriptor, false);

    return JSValue::encode(jsUndefined());
}
예제 #3
0
// 15.2.4.3 Object.prototype.toLocaleString()
EncodedJSValue JSC_HOST_CALL objectProtoFuncToLocaleString(ExecState* exec)
{
    // 1. Let O be the result of calling ToObject passing the this value as the argument.
    JSObject* object = exec->thisValue().toThis(exec, StrictMode).toObject(exec);
    if (exec->hadException())
        return JSValue::encode(jsUndefined());

    // 2. Let toString be the result of calling the [[Get]] internal method of O passing "toString" as the argument.
    JSValue toString = object->get(exec, exec->propertyNames().toString);

    // 3. If IsCallable(toString) is false, throw a TypeError exception.
    CallData callData;
    CallType callType = getCallData(toString, callData);
    if (callType == CallTypeNone)
        return JSValue::encode(jsUndefined());

    // 4. Return the result of calling the [[Call]] internal method of toString passing O as the this value and no arguments.
    return JSValue::encode(call(exec, toString, callType, callData, object, exec->emptyList()));
}
예제 #4
0
EncodedJSValue JSC_HOST_CALL boundThisNoArgsFunctionCall(ExecState* exec)
{
    JSBoundFunction* boundFunction = jsCast<JSBoundFunction*>(exec->jsCallee());

    MarkedArgumentBuffer args;
    for (unsigned i = 0; i < exec->argumentCount(); ++i)
        args.append(exec->uncheckedArgument(i));

    JSFunction* targetFunction = jsCast<JSFunction*>(boundFunction->targetFunction());
    ExecutableBase* executable = targetFunction->executable();
    if (executable->hasJITCodeForCall()) {
        // Force the executable to cache its arity entrypoint.
        executable->entrypointFor(CodeForCall, MustCheckArity);
    }
    CallData callData;
    CallType callType = getCallData(targetFunction, callData);
    ASSERT(callType != CallType::None);
    return JSValue::encode(call(exec, targetFunction, callType, callData, boundFunction->boundThis(), args));
}
예제 #5
0
ScriptValue ScriptCallback::call(bool& hadException)
{
    JSLock lock(SilenceAssertionsOnly);

    CallData callData;
    CallType callType = getCallData(m_function.jsValue(), callData);
    if (callType == CallTypeNone)
        return ScriptValue();

    JSValue result = JSC::call(m_exec, m_function.jsValue(), callType, callData, m_function.jsValue(), m_arguments);
    hadException = m_exec->hadException();

    if (hadException) {
        reportException(m_exec, m_exec->exception());
        return ScriptValue();
    }

    return ScriptValue(result);
}
예제 #6
0
void iteratorClose(ExecState* exec, JSValue iterator)
{
    Exception* exception = nullptr;
    if (exec->hadException()) {
        exception = exec->exception();
        exec->clearException();
    }
    JSValue returnFunction = iterator.get(exec, exec->vm().propertyNames->returnKeyword);
    if (exec->hadException())
        return;

    if (returnFunction.isUndefined()) {
        if (exception)
            exec->vm().throwException(exec, exception);
        return;
    }

    CallData returnFunctionCallData;
    CallType returnFunctionCallType = getCallData(returnFunction, returnFunctionCallData);
    if (returnFunctionCallType == CallTypeNone) {
        if (exception)
            exec->vm().throwException(exec, exception);
        else
            throwTypeError(exec);
        return;
    }

    MarkedArgumentBuffer returnFunctionArguments;
    JSValue innerResult = call(exec, returnFunction, returnFunctionCallType, returnFunctionCallData, iterator, returnFunctionArguments);

    if (exception) {
        exec->vm().throwException(exec, exception);
        return;
    }

    if (exec->hadException())
        return;

    if (!innerResult.isObject()) {
        throwTypeError(exec, ASCIILiteral("Iterator result interface is not an object."));
        return;
    }
}
EncodedJSValue JSC_HOST_CALL boundFunctionCall(ExecState* exec)
{
    JSBoundFunction* boundFunction = jsCast<JSBoundFunction*>(exec->callee());

    ASSERT(isJSArray(boundFunction->boundArgs())); // Currently this is true!
    JSArray* boundArgs = asArray(boundFunction->boundArgs());

    MarkedArgumentBuffer args;
    for (unsigned i = 0; i < boundArgs->length(); ++i)
        args.append(boundArgs->getIndexQuickly(i));
    for (unsigned i = 0; i < exec->argumentCount(); ++i)
        args.append(exec->uncheckedArgument(i));

    JSObject* targetFunction = boundFunction->targetFunction();
    CallData callData;
    CallType callType = getCallData(targetFunction, callData);
    ASSERT(callType != CallTypeNone);
    return JSValue::encode(call(exec, targetFunction, callType, callData, boundFunction->boundThis(), args));
}
예제 #8
0
void JSMutationCallback::call(const Vector<RefPtr<MutationRecord> >& mutations, MutationObserver* observer)
{
    if (!canInvokeCallback())
        return;

    RefPtr<JSMutationCallback> protect(this);

    JSLockHolder lock(m_isolatedWorld->vm());

    if (!m_callback)
        return;

    JSValue callback = m_callback.get();
    CallData callData;
    CallType callType = getCallData(callback, callData);
    if (callType == CallTypeNone) {
        ASSERT_NOT_REACHED();
        return;
    }

    ScriptExecutionContext* context = scriptExecutionContext();
    if (!context)
        return;
    ASSERT(context->isDocument());

    JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(context, m_isolatedWorld.get());
    ExecState* exec = globalObject->globalExec();

    JSValue jsObserver = toJS(exec, globalObject, observer);

    MarkedArgumentBuffer args;
    args.append(jsArray(exec, globalObject, mutations));
    args.append(jsObserver);

    InspectorInstrumentationCookie cookie = JSMainThreadExecState::instrumentFunctionCall(context, callType, callData);

    JSMainThreadExecState::call(exec, callback, callType, callData, jsObserver, args);

    InspectorInstrumentation::didCallFunction(cookie);

    if (exec->hadException())
        reportCurrentException(exec);
}
// 15.3.4.5 Function.prototype.bind (thisArg [, arg1 [, arg2, ...]])
EncodedJSValue JSC_HOST_CALL functionProtoFuncBind(ExecState* exec)
{
    JSGlobalObject* globalObject = exec->callee()->globalObject();

    // Let Target be the this value.
    JSValue target = exec->hostThisValue();

    // If IsCallable(Target) is false, throw a TypeError exception.
    CallData callData;
    CallType callType = getCallData(target, callData);
    if (callType == CallTypeNone)
        return throwVMTypeError(exec);
    // Primitive values are not callable.
    ASSERT(target.isObject());
    JSObject* targetObject = asObject(target);

    // Let A be a new (possibly empty) internal list of all of the argument values provided after thisArg (arg1, arg2 etc), in order.
    size_t numBoundArgs = exec->argumentCount() > 1 ? exec->argumentCount() - 1 : 0;
    JSArray* boundArgs = JSArray::tryCreateUninitialized(exec->globalData(), globalObject->arrayStructure(), numBoundArgs);
    if (!boundArgs)
        return JSValue::encode(throwOutOfMemoryError(exec));

    for (size_t i = 0; i < numBoundArgs; ++i)
        boundArgs->initializeIndex(exec->globalData(), i, exec->argument(i + 1));
    boundArgs->completeInitialization(numBoundArgs);

    // If the [[Class]] internal property of Target is "Function", then ...
    // Else set the length own property of F to 0.
    unsigned length = 0;
    if (targetObject->inherits(&JSFunction::s_info)) {
        ASSERT(target.get(exec, exec->propertyNames().length).isNumber());
        // a. Let L be the length property of Target minus the length of A.
        // b. Set the length own property of F to either 0 or L, whichever is larger.
        unsigned targetLength = (unsigned)target.get(exec, exec->propertyNames().length).asNumber();
        if (targetLength > numBoundArgs)
            length = targetLength - numBoundArgs;
    }

    Identifier name(exec, target.get(exec, exec->propertyNames().name).toString(exec)->value(exec));

    return JSValue::encode(JSBoundFunction::create(exec, globalObject, targetObject, exec->argument(0), boundArgs, length, name));
}
예제 #10
0
bool NPJSObject::invoke(ExecState* exec, JSGlobalObject* globalObject, JSValue function, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result)
{
    CallData callData;
    CallType callType = getCallData(function, callData);
    if (callType == CallTypeNone)
        return false;

    // Convert the passed in arguments.
    MarkedArgumentBuffer argumentList;
    for (uint32_t i = 0; i < argumentCount; ++i)
        argumentList.append(m_objectMap->convertNPVariantToJSValue(exec, globalObject, arguments[i]));

    JSValue value = JSC::call(exec, function, callType, callData, m_jsObject->methodTable()->toThisObject(m_jsObject.get(), exec), argumentList);

    // Convert and return the result of the function call.
    m_objectMap->convertJSValueToNPVariant(exec, value, *result);
    exec->clearException();
    
    return true;
}
예제 #11
0
JSValue JSCallbackData::invokeCallback(MarkedArgumentBuffer& args, bool* raisedException)
{
    ASSERT(callback());
    ASSERT(globalObject());

    ExecState* exec = globalObject()->globalExec();
    JSValue function = callback()->get(exec, Identifier(exec, "handleEvent"));

    CallData callData;
    CallType callType = getCallData(function, callData);
    if (callType == CallTypeNone) {
        callType = callback()->methodTable()->getCallData(callback(), callData);
        if (callType == CallTypeNone)
            return JSValue();
        function = callback();
    }
    
    globalObject()->globalData().timeoutChecker.start();
    ScriptExecutionContext* context = globalObject()->scriptExecutionContext();
    // We will fail to get the context if the frame has been detached.
    if (!context)
        return JSValue();

    bool contextIsDocument = context->isDocument();
    JSValue result = contextIsDocument
        ? JSMainThreadExecState::call(exec, function, callType, callData, callback(), args)
        : JSC::call(exec, function, callType, callData, callback(), args);
    globalObject()->globalData().timeoutChecker.stop();

    if (contextIsDocument)
        Document::updateStyleForAllDocuments();

    if (exec->hadException()) {
        reportCurrentException(exec);
        if (raisedException)
            *raisedException = true;
        return result;
    }
    
    return result;
}
예제 #12
0
static ALWAYS_INLINE JSValue callDefaultValueFunction(ExecState* exec, const JSObject* object, const Identifier& propertyName)
{
    JSValue function = object->get(exec, propertyName);
    CallData callData;
    CallType callType = getCallData(function, callData);
    if (callType == CallTypeNone)
        return exec->exception();

    // Prevent "toString" and "valueOf" from observing execution if an exception
    // is pending.
    if (exec->hadException())
        return exec->exception();

    JSValue result = call(exec, function, callType, callData, const_cast<JSObject*>(object), exec->emptyList());
    ASSERT(!result.isGetterSetter());
    if (exec->hadException())
        return exec->exception();
    if (result.isObject())
        return JSValue();
    return result;
}
예제 #13
0
EncodedJSValue JSC_HOST_CALL dateProtoFuncToJSON(ExecState* exec)
{
    JSValue thisValue = exec->thisValue();
    JSObject* object = jsCast<JSObject*>(thisValue.toThis(exec, NotStrictMode));
    if (exec->hadException())
        return JSValue::encode(jsNull());
    
    JSValue toISOValue = object->get(exec, exec->vm().propertyNames->toISOString);
    if (exec->hadException())
        return JSValue::encode(jsNull());

    CallData callData;
    CallType callType = getCallData(toISOValue, callData);
    if (callType == CallTypeNone)
        return throwVMError(exec, createTypeError(exec, ASCIILiteral("toISOString is not a function")));

    JSValue result = call(exec, asObject(toISOValue), callType, callData, object, exec->emptyList());
    if (exec->hadException())
        return JSValue::encode(jsNull());
    if (result.isObject())
        return throwVMError(exec, createTypeError(exec, ASCIILiteral("toISOString did not return a primitive value")));
    return JSValue::encode(result);
}
예제 #14
0
JSValue iteratorNext(ExecState* exec, JSValue iterator, JSValue value)
{
    JSValue nextFunction = iterator.get(exec, exec->vm().propertyNames->next);
    if (exec->hadException())
        return jsUndefined();

    CallData nextFunctionCallData;
    CallType nextFunctionCallType = getCallData(nextFunction, nextFunctionCallData);
    if (nextFunctionCallType == CallType::None)
        return throwTypeError(exec);

    MarkedArgumentBuffer nextFunctionArguments;
    if (!value.isEmpty())
        nextFunctionArguments.append(value);
    JSValue result = call(exec, nextFunction, nextFunctionCallType, nextFunctionCallData, iterator, nextFunctionArguments);
    if (exec->hadException())
        return jsUndefined();

    if (!result.isObject())
        return throwTypeError(exec, ASCIILiteral("Iterator result interface is not an object."));

    return result;
}
예제 #15
0
bool NPJSObject::invoke(ExecState* exec, JSGlobalObject* globalObject, JSValue function, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result)
{
    VM& vm = exec->vm();
    auto scope = DECLARE_CATCH_SCOPE(vm);

    CallData callData;
    CallType callType = getCallData(function, callData);
    if (callType == CallType::None)
        return false;

    // Convert the passed in arguments.
    MarkedArgumentBuffer argumentList;
    for (uint32_t i = 0; i < argumentCount; ++i)
        argumentList.append(m_objectMap->convertNPVariantToJSValue(exec, globalObject, arguments[i]));

    JSValue value = JSC::call(exec, function, callType, callData, m_jsObject.get(), argumentList);

    // Convert and return the result of the function call.
    m_objectMap->convertJSValueToNPVariant(exec, value, *result);
    scope.clearException();
    
    return true;
}
static EncodedJSValue JSC_HOST_CALL constructPromise(ExecState* exec)
{
    if (!exec->argumentCount())
        return throwVMError(exec, createTypeError(exec, "Expected at least one argument"));

    JSValue function = exec->argument(0);

    CallData callData;
    CallType callType = getCallData(function, callData);
    if (callType == CallTypeNone)
        return throwVMError(exec, createTypeError(exec, "Expected function as as first argument"));

    JSGlobalObject* globalObject = asInternalFunction(exec->callee())->globalObject();
    
    // 1. Let promise be a new promise.
    JSPromise* promise = JSPromise::createWithResolver(exec->vm(), globalObject);

    // 2. Let resolver be promise's associated resolver.
    JSPromiseResolver* resolver = promise->resolver();

    // 3. Set init's callback this value to promise.
    // 4. Invoke init with resolver passed as parameter.
    MarkedArgumentBuffer initArguments;
    initArguments.append(resolver);
    call(exec, function, callType, callData, promise, initArguments);

    // 5. If init threw an exception, catch it, and then, if resolver's resolved flag
    //    is unset, run resolver's reject with the thrown exception as argument.
    if (exec->hadException()) {
        JSValue exception = exec->exception();
        exec->clearException();

        resolver->rejectIfNotResolved(exec, exception);
    }

    return JSValue::encode(promise);
}
예제 #17
0
EncodedJSValue JSC_HOST_CALL mapProtoFuncForEach(CallFrame* callFrame)
{
    JSMap* map = getMap(callFrame, callFrame->thisValue());
    if (!map)
        return JSValue::encode(jsUndefined());
    JSValue callBack = callFrame->argument(0);
    CallData callData;
    CallType callType = getCallData(callBack, callData);
    if (callType == CallTypeNone)
        return JSValue::encode(throwTypeError(callFrame, WTF::ASCIILiteral("Map.prototype.forEach called without callback")));
    JSValue thisValue = callFrame->argument(1);
    VM* vm = &callFrame->vm();
    JSMapIterator* iterator = JSMapIterator::create(*vm, callFrame->callee()->globalObject()->mapIteratorStructure(), map, MapIterateKeyValue);
    JSValue key, value;
    if (callType == CallTypeJS) {
        JSFunction* function = jsCast<JSFunction*>(callBack);
        CachedCall cachedCall(callFrame, function, 3);
        while (iterator->nextKeyValue(key, value) && !vm->exception()) {
            cachedCall.setThis(thisValue);
            cachedCall.setArgument(0, value);
            cachedCall.setArgument(1, key);
            cachedCall.setArgument(2, map);
            cachedCall.call();
        }
        iterator->finish();
    } else {
        while (iterator->nextKeyValue(key, value) && !vm->exception()) {
            MarkedArgumentBuffer args;
            args.append(value);
            args.append(key);
            args.append(map);
            JSC::call(callFrame, callBack, callType, callData, thisValue, args);
        }
        iterator->finish();
    }
    return JSValue::encode(jsUndefined());
}
EncodedJSValue JSC_HOST_CALL JSPromisePrototypeFuncCatch(ExecState* exec)
{
    JSPromise* thisObject = jsDynamicCast<JSPromise*>(exec->thisValue());
    if (!thisObject)
        return throwVMError(exec, createTypeError(exec, "Receiver of catch must be a Promise"));
    
    JSValue rejectCallback = exec->argument(0);
    if (!rejectCallback.isUndefined()) {
        CallData callData;
        CallType callType = getCallData(rejectCallback, callData);
        if (callType == CallTypeNone)
            return throwVMError(exec, createTypeError(exec, "Expected function or undefined as as first argument"));
    }

    JSFunction* callee = jsCast<JSFunction*>(exec->callee());
    JSGlobalObject* globalObject = callee->globalObject();

    // 1. Let promise be a new promise.
    JSPromise* promise = JSPromise::createWithResolver(exec->vm(), globalObject);

    // 2. Let resolver be promise's associated resolver.
    JSPromiseResolver* resolver = promise->resolver();

    // 3. Let fulfillCallback be a new promise callback for resolver and its fulfill algorithm.
    InternalFunction* fulfillWrapper = JSPromiseCallback::create(exec, globalObject, globalObject->promiseCallbackStructure(), resolver, JSPromiseCallback::Fulfill);

    // 4. Let rejectWrapper be a promise wrapper callback for resolver and rejectCallback if rejectCallback is
    //    not omitted and a promise callback for resolver and its reject algorithm otherwise.
    InternalFunction* rejectWrapper = wrapCallback(exec, globalObject, rejectCallback, resolver, JSPromiseCallback::Reject);

    // 5. Append fulfillWrapper and rejectWrapper to the context object.
    thisObject->appendCallbacks(exec, fulfillWrapper, rejectWrapper);

    // 6. Return promise.
    return JSValue::encode(promise);
}
예제 #19
0
ScriptObject InjectedScriptHost::createInjectedScript(const String& source, ScriptState* scriptState, long id)
{
    SourceCode sourceCode = makeSource(stringToUString(source));
    JSLock lock(SilenceAssertionsOnly);
    JSDOMGlobalObject* globalObject = static_cast<JSDOMGlobalObject*>(scriptState->lexicalGlobalObject());
    JSValue globalThisValue = scriptState->globalThisValue();
    Completion comp = JSMainThreadExecState::evaluate(scriptState, globalObject->globalScopeChain(), sourceCode, globalThisValue);
    if (comp.complType() != JSC::Normal && comp.complType() != JSC::ReturnValue)
        return ScriptObject();
    JSValue functionValue = comp.value();
    CallData callData;
    CallType callType = getCallData(functionValue, callData);
    if (callType == CallTypeNone)
        return ScriptObject();

    MarkedArgumentBuffer args;
    args.append(toJS(scriptState, globalObject, this));
    args.append(globalThisValue);
    args.append(jsNumber(id));
    JSValue result = JSC::call(scriptState, functionValue, callType, callData, globalThisValue, args);
    if (result.isObject())
        return ScriptObject(scriptState, result.getObject());
    return ScriptObject();
}
예제 #20
0
JSValue iteratorNext(ExecState* exec, JSValue iterator, JSValue value)
{
    VM& vm = exec->vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    JSValue nextFunction = iterator.get(exec, vm.propertyNames->next);
    RETURN_IF_EXCEPTION(scope, JSValue());

    CallData nextFunctionCallData;
    CallType nextFunctionCallType = getCallData(nextFunction, nextFunctionCallData);
    if (nextFunctionCallType == CallType::None)
        return throwTypeError(exec, scope);

    MarkedArgumentBuffer nextFunctionArguments;
    if (!value.isEmpty())
        nextFunctionArguments.append(value);
    JSValue result = call(exec, nextFunction, nextFunctionCallType, nextFunctionCallData, iterator, nextFunctionArguments);
    RETURN_IF_EXCEPTION(scope, JSValue());

    if (!result.isObject())
        return throwTypeError(exec, scope, ASCIILiteral("Iterator result interface is not an object."));

    return result;
}
예제 #21
0
static JSValue performPromiseAll(ExecState* exec, JSValue iterator, JSValue C, JSPromiseDeferred* deferred)
{
    JSObject* thisObject = asObject(C);
    VM& vm = exec->vm();

    // 6. Let 'values' be the result of calling ArrayCreate(0).
    JSArray* values = constructEmptyArray(exec, nullptr, thisObject->globalObject());

    // 7. Let 'countdownHolder' be Record { [[Countdown]]: 0 }.
    NumberObject* countdownHolder = constructNumber(exec, thisObject->globalObject(), JSValue(0));

    // 8. Let 'index' be 0.
    unsigned index = 0;

    // 9. Repeat.
    do {
        // i. Let 'next' be the result of calling IteratorStep(iterator).
        JSValue next = iteratorStep(exec, iterator);
        if (exec->hadException())
            return jsUndefined();

        // iii. If 'next' is false,
        if (next.isFalse()) {
            // a. If 'index' is 0,
            if (!index) {
                // a. Let 'resolveResult' be the result of calling the [[Call]] internal method
                //    of deferred.[[Resolve]] with undefined as thisArgument and a List containing
                //    values as argumentsList.
                performDeferredResolve(exec, deferred, values);

                // b. ReturnIfAbrupt(resolveResult).
                if (exec->hadException())
                    return jsUndefined();
            }

            // b. Return deferred.[[Promise]].
            return deferred->promise();
        }

        // iv. Let 'nextValue' be the result of calling IteratorValue(next).
        // v. RejectIfAbrupt(nextValue, deferred).
        JSValue nextValue = iteratorValue(exec, next);
        if (exec->hadException())
            return jsUndefined();

        values->push(exec, jsUndefined());

        // vi. Let 'nextPromise' be the result of calling Invoke(C, "resolve", (nextValue)).
        JSValue resolveFunction = C.get(exec, vm.propertyNames->resolve);
        if (exec->hadException())
            return jsUndefined();

        CallData resolveFunctionCallData;
        CallType resolveFunctionCallType = getCallData(resolveFunction, resolveFunctionCallData);
        if (resolveFunctionCallType == CallTypeNone) {
            throwTypeError(exec);
            return jsUndefined();
        }

        MarkedArgumentBuffer resolveFunctionArguments;
        resolveFunctionArguments.append(nextValue);
        JSValue nextPromise = call(exec, resolveFunction, resolveFunctionCallType, resolveFunctionCallData, C, resolveFunctionArguments);

        // vii. RejectIfAbrupt(nextPromise, deferred).
        if (exec->hadException())
            return jsUndefined();

        // viii. Let 'countdownFunction' be a new built-in function object as defined in Promise.all Countdown Functions.
        JSFunction* countdownFunction = createPromiseAllCountdownFunction(vm, thisObject->globalObject());

        // ix. Set the [[Index]] internal slot of 'countdownFunction' to 'index'.
        countdownFunction->putDirect(vm, vm.propertyNames->indexPrivateName, JSValue(index));

        // x. Set the [[Values]] internal slot of 'countdownFunction' to 'values'.
        countdownFunction->putDirect(vm, vm.propertyNames->valuesPrivateName, values);

        // xi. Set the [[Deferred]] internal slot of 'countdownFunction' to 'deferred'.
        countdownFunction->putDirect(vm, vm.propertyNames->deferredPrivateName, deferred);

        // xii. Set the [[CountdownHolder]] internal slot of 'countdownFunction' to 'countdownHolder'.
        countdownFunction->putDirect(vm, vm.propertyNames->countdownHolderPrivateName, countdownHolder);

        // xiii. Let 'result' be the result of calling Invoke(nextPromise, "then", (countdownFunction, deferred.[[Reject]])).
        JSValue thenFunction = nextPromise.get(exec, vm.propertyNames->then);
        if (exec->hadException())
            return jsUndefined();

        CallData thenFunctionCallData;
        CallType thenFunctionCallType = getCallData(thenFunction, thenFunctionCallData);
        if (thenFunctionCallType == CallTypeNone) {
            throwTypeError(exec);
            return jsUndefined();
        }

        MarkedArgumentBuffer thenFunctionArguments;
        thenFunctionArguments.append(countdownFunction);
        thenFunctionArguments.append(deferred->reject());

        call(exec, thenFunction, thenFunctionCallType, thenFunctionCallData, nextPromise, thenFunctionArguments);

        // xiv. RejectIfAbrupt(result, deferred).
        if (exec->hadException())
            return jsUndefined();

        // xv. Set index to index + 1.
        index++;

        // xvi. Set countdownHolder.[[Countdown]] to countdownHolder.[[Countdown]] + 1.
        uint32_t newCountdownValue = countdownHolder->internalValue().asUInt32() + 1;
        countdownHolder->setInternalValue(vm, JSValue(newCountdownValue));
    } while (true);
    ASSERT_NOT_REACHED();
    return jsUndefined();
}
// ES5 8.10.5 ToPropertyDescriptor
static bool toPropertyDescriptor(ExecState* exec, JSValue in, PropertyDescriptor& desc)
{
    if (!in.isObject()) {
        throwError(exec, createTypeError(exec, ASCIILiteral("Property description must be an object.")));
        return false;
    }
    JSObject* description = asObject(in);

    PropertySlot enumerableSlot(description);
    if (description->getPropertySlot(exec, exec->propertyNames().enumerable, enumerableSlot)) {
        desc.setEnumerable(enumerableSlot.getValue(exec, exec->propertyNames().enumerable).toBoolean(exec));
        if (exec->hadException())
            return false;
    }

    PropertySlot configurableSlot(description);
    if (description->getPropertySlot(exec, exec->propertyNames().configurable, configurableSlot)) {
        desc.setConfigurable(configurableSlot.getValue(exec, exec->propertyNames().configurable).toBoolean(exec));
        if (exec->hadException())
            return false;
    }

    JSValue value;
    PropertySlot valueSlot(description);
    if (description->getPropertySlot(exec, exec->propertyNames().value, valueSlot)) {
        desc.setValue(valueSlot.getValue(exec, exec->propertyNames().value));
        if (exec->hadException())
            return false;
    }

    PropertySlot writableSlot(description);
    if (description->getPropertySlot(exec, exec->propertyNames().writable, writableSlot)) {
        desc.setWritable(writableSlot.getValue(exec, exec->propertyNames().writable).toBoolean(exec));
        if (exec->hadException())
            return false;
    }

    PropertySlot getSlot(description);
    if (description->getPropertySlot(exec, exec->propertyNames().get, getSlot)) {
        JSValue get = getSlot.getValue(exec, exec->propertyNames().get);
        if (exec->hadException())
            return false;
        if (!get.isUndefined()) {
            CallData callData;
            if (getCallData(get, callData) == CallTypeNone) {
                throwError(exec, createTypeError(exec, ASCIILiteral("Getter must be a function.")));
                return false;
            }
        }
        desc.setGetter(get);
    }

    PropertySlot setSlot(description);
    if (description->getPropertySlot(exec, exec->propertyNames().set, setSlot)) {
        JSValue set = setSlot.getValue(exec, exec->propertyNames().set);
        if (exec->hadException())
            return false;
        if (!set.isUndefined()) {
            CallData callData;
            if (getCallData(set, callData) == CallTypeNone) {
                throwError(exec, createTypeError(exec, ASCIILiteral("Setter must be a function.")));
                return false;
            }
        }
        desc.setSetter(set);
    }

    if (!desc.isAccessorDescriptor())
        return true;

    if (desc.value()) {
        throwError(exec, createTypeError(exec, ASCIILiteral("Invalid property.  'value' present on property with getter or setter.")));
        return false;
    }

    if (desc.writablePresent()) {
        throwError(exec, createTypeError(exec, ASCIILiteral("Invalid property.  'writable' present on property with getter or setter.")));
        return false;
    }
    return true;
}
예제 #23
0
static inline JSValue callFunction(ExecState& exec, JSValue jsFunction, JSValue thisValue, const ArgList& arguments)
{
    CallData callData;
    CallType callType = getCallData(jsFunction, callData);
    return call(&exec, jsFunction, callType, callData, thisValue, arguments);
}
예제 #24
0
static EncodedJSValue JSC_HOST_CALL constructMap(ExecState* exec)
{
    JSValue prototype = JSValue();
    JSValue newTarget = exec->newTarget();

    if (newTarget != exec->callee())
        prototype = newTarget.get(exec, exec->propertyNames().prototype);

    JSGlobalObject* globalObject = asInternalFunction(exec->callee())->globalObject();
    Structure* mapStructure = Structure::createSubclassStructure(exec->vm(), globalObject->mapStructure(), prototype);
    JSMap* map = JSMap::create(exec, mapStructure);
    JSValue iterable = exec->argument(0);
    if (iterable.isUndefinedOrNull())
        return JSValue::encode(map);

    JSValue adderFunction = map->JSObject::get(exec, exec->propertyNames().set);
    if (exec->hadException())
        return JSValue::encode(jsUndefined());

    CallData adderFunctionCallData;
    CallType adderFunctionCallType = getCallData(adderFunction, adderFunctionCallData);
    if (adderFunctionCallType == CallTypeNone)
        return JSValue::encode(throwTypeError(exec));

    JSValue iteratorFunction = iterable.get(exec, exec->propertyNames().iteratorSymbol);
    if (exec->hadException())
        return JSValue::encode(jsUndefined());

    CallData iteratorFunctionCallData;
    CallType iteratorFunctionCallType = getCallData(iteratorFunction, iteratorFunctionCallData);
    if (iteratorFunctionCallType == CallTypeNone)
        return JSValue::encode(throwTypeError(exec));

    ArgList iteratorFunctionArguments;
    JSValue iterator = call(exec, iteratorFunction, iteratorFunctionCallType, iteratorFunctionCallData, iterable, iteratorFunctionArguments);
    if (exec->hadException())
        return JSValue::encode(jsUndefined());

    if (!iterator.isObject())
        return JSValue::encode(throwTypeError(exec));

    while (true) {
        JSValue next = iteratorStep(exec, iterator);
        if (exec->hadException())
            return JSValue::encode(jsUndefined());

        if (next.isFalse())
            return JSValue::encode(map);

        JSValue nextItem = iteratorValue(exec, next);
        if (exec->hadException())
            return JSValue::encode(jsUndefined());

        if (!nextItem.isObject()) {
            throwTypeError(exec);
            iteratorClose(exec, iterator);
            return JSValue::encode(jsUndefined());
        }

        JSValue key = nextItem.get(exec, 0);
        if (exec->hadException()) {
            iteratorClose(exec, iterator);
            return JSValue::encode(jsUndefined());
        }

        JSValue value = nextItem.get(exec, 1);
        if (exec->hadException()) {
            iteratorClose(exec, iterator);
            return JSValue::encode(jsUndefined());
        }

        MarkedArgumentBuffer arguments;
        arguments.append(key);
        arguments.append(value);
        call(exec, adderFunction, adderFunctionCallType, adderFunctionCallData, map, arguments);
        if (exec->hadException()) {
            iteratorClose(exec, iterator);
            return JSValue::encode(jsUndefined());
        }
    }
    RELEASE_ASSERT_NOT_REACHED();
    return JSValue::encode(map);
}
예제 #25
0
bool ScriptValue::isFunction() const
{
    CallData callData;
    return getCallData(m_value.get(), callData) != CallTypeNone;
}
static EncodedJSValue JSC_HOST_CALL promiseResolutionHandlerFunction(ExecState* exec)
{
    JSValue x = exec->argument(0);
    VM& vm = exec->vm();
    JSObject* F = exec->callee();

    // 1. Let 'promise' be the value of F's [[Promise]] internal slot
    JSPromise* promise = jsCast<JSPromise*>(F->get(exec, vm.propertyNames->promisePrivateName));

    // 2. Let 'fulfillmentHandler' be the value of F's [[FulfillmentHandler]] internal slot.
    JSValue fulfillmentHandler = F->get(exec, vm.propertyNames->fulfillmentHandlerPrivateName);
    
    // 3. Let 'rejectionHandler' be the value of F's [[RejectionHandler]] internal slot.
    JSValue rejectionHandler = F->get(exec, vm.propertyNames->rejectionHandlerPrivateName);
    
    // 4. If SameValue(x, promise) is true,
    if (sameValue(exec, x, promise)) {
        // i. Let 'selfResolutionError' be a newly-created TypeError object.
        JSObject* selfResolutionError = createTypeError(exec, ASCIILiteral("Resolve a promise with itself"));
        // ii. Return the result of calling the [[Call]] internal method of rejectionHandler with
        //     undefined as thisArgument and a List containing selfResolutionError as argumentsList.
        CallData rejectCallData;
        CallType rejectCallType = getCallData(rejectionHandler, rejectCallData);
        ASSERT(rejectCallType != CallTypeNone);

        MarkedArgumentBuffer rejectArguments;
        rejectArguments.append(selfResolutionError);

        return JSValue::encode(call(exec, rejectionHandler, rejectCallType, rejectCallData, jsUndefined(), rejectArguments));
    }

    // 5. Let 'C' be the value of promise's [[PromiseConstructor]] internal slot.
    JSValue C = promise->constructor();

    // 6. Let 'deferred' be the result of calling GetDeferred(C)
    JSValue deferredValue = createJSPromiseDeferredFromConstructor(exec, C);

    // 7. ReturnIfAbrupt(deferred).
    if (exec->hadException())
        return JSValue::encode(jsUndefined());

    JSPromiseDeferred* deferred = jsCast<JSPromiseDeferred*>(deferredValue);

    // 8. Let 'updateResult' be the result of calling UpdateDeferredFromPotentialThenable(x, deferred).
    ThenableStatus updateResult = updateDeferredFromPotentialThenable(exec, x, deferred);

    // 9. ReturnIfAbrupt(updateResult).
    if (exec->hadException())
        return JSValue::encode(jsUndefined());

    // 10. If 'updateResult' is not "not a thenable", return the result of calling
    //     Invoke(deferred.[[Promise]], "then", (fulfillmentHandler, rejectionHandler)).
    // NOTE: Invoke does not seem to be defined anywhere, so I am guessing here.
    if (updateResult != NotAThenable) {
        JSObject* deferredPromise = deferred->promise();
    
        JSValue thenValue = deferredPromise->get(exec, exec->vm().propertyNames->then);
        if (exec->hadException())
            return JSValue::encode(jsUndefined());

        CallData thenCallData;
        CallType thenCallType = getCallData(thenValue, thenCallData);
        if (thenCallType == CallTypeNone)
            return JSValue::encode(throwTypeError(exec));

        MarkedArgumentBuffer arguments;
        arguments.append(fulfillmentHandler);
        arguments.append(rejectionHandler);

        return JSValue::encode(call(exec, thenValue, thenCallType, thenCallData, deferredPromise, arguments));
    }
    
    // 11. Return the result of calling the [[Call]] internal method of fulfillmentHandler
    //     with undefined as thisArgument and a List containing x as argumentsList.
    CallData fulfillmentHandlerCallData;
    CallType fulfillmentHandlerCallType = getCallData(fulfillmentHandler, fulfillmentHandlerCallData);
    ASSERT(fulfillmentHandlerCallType != CallTypeNone);
    
    MarkedArgumentBuffer fulfillmentHandlerArguments;
    fulfillmentHandlerArguments.append(x);

    return JSValue::encode(call(exec, fulfillmentHandler, fulfillmentHandlerCallType, fulfillmentHandlerCallData, jsUndefined(), fulfillmentHandlerArguments));
}
예제 #27
0
void JSEventListener::handleEvent(ScriptExecutionContext* scriptExecutionContext, Event* event)
{
    ASSERT(scriptExecutionContext);
    if (!scriptExecutionContext || scriptExecutionContext->isJSExecutionForbidden())
        return;

    JSLock lock(SilenceAssertionsOnly);

    JSObject* jsFunction = this->jsFunction(scriptExecutionContext);
    if (!jsFunction)
        return;

    JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(scriptExecutionContext, m_isolatedWorld.get());
    if (!globalObject)
        return;

    if (scriptExecutionContext->isDocument()) {
        JSDOMWindow* window = static_cast<JSDOMWindow*>(globalObject);
        Frame* frame = window->impl()->frame();
        if (!frame)
            return;
        // The window must still be active in its frame. See <https://bugs.webkit.org/show_bug.cgi?id=21921>.
        // FIXME: A better fix for this may be to change DOMWindow::frame() to not return a frame the detached window used to be in.
        if (frame->domWindow() != window->impl())
            return;
        // FIXME: Is this check needed for other contexts?
        ScriptController* script = frame->script();
        if (!script->canExecuteScripts(AboutToExecuteScript) || script->isPaused())
            return;
    }

    ExecState* exec = globalObject->globalExec();
    JSValue handleEventFunction = jsFunction;

    CallData callData;
    CallType callType = getCallData(handleEventFunction, callData);
    // If jsFunction is not actually a function, see if it implements the EventListener interface and use that
    if (callType == CallTypeNone) {
        handleEventFunction = jsFunction->get(exec, Identifier(exec, "handleEvent"));
        callType = getCallData(handleEventFunction, callData);
    }

    if (callType != CallTypeNone) {
        RefPtr<JSEventListener> protect(this);

        MarkedArgumentBuffer args;
        args.append(toJS(exec, globalObject, event));

        Event* savedEvent = globalObject->currentEvent();
        globalObject->setCurrentEvent(event);

        JSGlobalData& globalData = globalObject->globalData();
        DynamicGlobalObjectScope globalObjectScope(globalData, globalData.dynamicGlobalObject ? globalData.dynamicGlobalObject : globalObject);

        globalData.timeoutChecker.start();
        JSValue thisValue = handleEventFunction == jsFunction ? toJS(exec, globalObject, event->currentTarget()) : jsFunction;
        JSValue retval = scriptExecutionContext->isDocument()
                         ? JSMainThreadExecState::call(exec, handleEventFunction, callType, callData, thisValue, args)
                         : JSC::call(exec, handleEventFunction, callType, callData, thisValue, args);
        globalData.timeoutChecker.stop();

        globalObject->setCurrentEvent(savedEvent);

#if ENABLE(WORKERS)
        if (scriptExecutionContext->isWorkerContext()) {
            bool terminatorCausedException = (exec->hadException() && isTerminatedExecutionException(exec->exception()));
            if (terminatorCausedException || globalData.terminator.shouldTerminate())
                static_cast<WorkerContext*>(scriptExecutionContext)->script()->forbidExecution();
        }
#endif

        if (exec->hadException()) {
            event->target()->uncaughtExceptionInEventHandler();
            reportCurrentException(exec);
        } else {
            if (!retval.isUndefinedOrNull() && event->storesResultAsString())
                event->storeResult(ustringToString(retval.toString(exec)->value(exec)));
            if (m_isAttribute) {
                if (retval.isFalse())
                    event->preventDefault();
            }
        }
    }
}
예제 #28
0
static void performPromiseRaceLoop(ExecState* exec, JSValue iterator, JSPromiseDeferred* deferred, JSValue C)
{
    // 6. Repeat
    do {
        // i. Let 'next' be the result of calling IteratorStep(iterator).
        JSValue next = iteratorStep(exec, iterator);

        // ii. RejectIfAbrupt(next, deferred).
        if (exec->hadException())
            return;

        // iii. If 'next' is false, return deferred.[[Promise]].
        if (next.isFalse())
            return;

        // iv. Let 'nextValue' be the result of calling IteratorValue(next).
        // v. RejectIfAbrupt(nextValue, deferred).
        JSValue nextValue = iteratorValue(exec, next);
        if (exec->hadException())
            return;

        // vi. Let 'nextPromise' be the result of calling Invoke(C, "resolve", (nextValue)).
        JSValue resolveFunction = C.get(exec, exec->vm().propertyNames->resolve);
        if (exec->hadException())
            return;

        CallData resolveFunctionCallData;
        CallType resolveFunctionCallType = getCallData(resolveFunction, resolveFunctionCallData);
        if (resolveFunctionCallType == CallTypeNone) {
            throwTypeError(exec);
            return;
        }

        MarkedArgumentBuffer resolveFunctionArguments;
        resolveFunctionArguments.append(nextValue);
        JSValue nextPromise = call(exec, resolveFunction, resolveFunctionCallType, resolveFunctionCallData, C, resolveFunctionArguments);

        // vii. RejectIfAbrupt(nextPromise, deferred).
        if (exec->hadException())
            return;

        // viii. Let 'result' be the result of calling Invoke(nextPromise, "then", (deferred.[[Resolve]], deferred.[[Reject]])).
        JSValue thenFunction = nextPromise.get(exec, exec->vm().propertyNames->then);
        if (exec->hadException())
            return;

        CallData thenFunctionCallData;
        CallType thenFunctionCallType = getCallData(thenFunction, thenFunctionCallData);
        if (thenFunctionCallType == CallTypeNone) {
            throwTypeError(exec);
            return;
        }

        MarkedArgumentBuffer thenFunctionArguments;
        thenFunctionArguments.append(deferred->resolve());
        thenFunctionArguments.append(deferred->reject());

        call(exec, thenFunction, thenFunctionCallType, thenFunctionCallData, nextPromise, thenFunctionArguments);

        // ix. RejectIfAbrupt(result, deferred).
        if (exec->hadException())
            return;
    } while (true);
}
예제 #29
0
void JSEventListener::handleEvent(ScriptExecutionContext* scriptExecutionContext, Event* event)
{
    ASSERT(scriptExecutionContext);
    if (!scriptExecutionContext || scriptExecutionContext->isJSExecutionForbidden())
        return;

    JSLockHolder lock(scriptExecutionContext->vm());

    JSObject* jsFunction = this->jsFunction(scriptExecutionContext);
    if (!jsFunction)
        return;

    JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(scriptExecutionContext, *m_isolatedWorld);
    if (!globalObject)
        return;

    if (scriptExecutionContext->isDocument()) {
        JSDOMWindow* window = jsCast<JSDOMWindow*>(globalObject);
        if (!window->impl().isCurrentlyDisplayedInFrame())
            return;
        // FIXME: Is this check needed for other contexts?
        ScriptController& script = window->impl().frame()->script();
        if (!script.canExecuteScripts(AboutToExecuteScript) || script.isPaused())
            return;
    }

    ExecState* exec = globalObject->globalExec();
    JSValue handleEventFunction = jsFunction;

    CallData callData;
    CallType callType = getCallData(handleEventFunction, callData);
    // If jsFunction is not actually a function, see if it implements the EventListener interface and use that
    if (callType == CallTypeNone) {
        handleEventFunction = jsFunction->get(exec, Identifier::fromString(exec, "handleEvent"));
        callType = getCallData(handleEventFunction, callData);
    }

    if (callType != CallTypeNone) {
        Ref<JSEventListener> protect(*this);

        MarkedArgumentBuffer args;
        args.append(toJS(exec, globalObject, event));

        Event* savedEvent = globalObject->currentEvent();
        globalObject->setCurrentEvent(event);

        VM& vm = globalObject->vm();
        VMEntryScope entryScope(vm, vm.entryScope ? vm.entryScope->globalObject() : globalObject);

        InspectorInstrumentationCookie cookie = JSMainThreadExecState::instrumentFunctionCall(scriptExecutionContext, callType, callData);

        JSValue thisValue = handleEventFunction == jsFunction ? toJS(exec, globalObject, event->currentTarget()) : jsFunction;
        NakedPtr<Exception> exception;
        JSValue retval = scriptExecutionContext->isDocument()
            ? JSMainThreadExecState::call(exec, handleEventFunction, callType, callData, thisValue, args, exception)
            : JSC::call(exec, handleEventFunction, callType, callData, thisValue, args, exception);

        InspectorInstrumentation::didCallFunction(cookie, scriptExecutionContext);

        globalObject->setCurrentEvent(savedEvent);

        if (is<WorkerGlobalScope>(*scriptExecutionContext)) {
            bool terminatorCausedException = (exec->hadException() && isTerminatedExecutionException(exec->exception()));
            if (terminatorCausedException || (vm.watchdog && vm.watchdog->didFire()))
                downcast<WorkerGlobalScope>(*scriptExecutionContext).script()->forbidExecution();
        }

        if (exception) {
            event->target()->uncaughtExceptionInEventHandler();
            reportException(exec, exception);
        } else {
            if (!retval.isUndefinedOrNull() && is<BeforeUnloadEvent>(*event))
                downcast<BeforeUnloadEvent>(*event).setReturnValue(retval.toString(exec)->value(exec));
            if (m_isAttribute) {
                if (retval.isFalse())
                    event->preventDefault();
            }
        }
    }
}
예제 #30
0
void JSEventListener::handleEvent(ScriptExecutionContext* scriptExecutionContext, Event* event)
{
    ASSERT(scriptExecutionContext);
    if (!scriptExecutionContext || scriptExecutionContext->isJSExecutionForbidden())
        return;

    VM& vm = scriptExecutionContext->vm();
    JSLockHolder lock(vm);
    auto scope = DECLARE_CATCH_SCOPE(vm);
    // See https://dom.spec.whatwg.org/#dispatching-events spec on calling handleEvent.
    // "If this throws an exception, report the exception." It should not propagate the
    // exception.

    JSObject* jsFunction = this->jsFunction(scriptExecutionContext);
    if (!jsFunction)
        return;

    JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(scriptExecutionContext, *m_isolatedWorld);
    if (!globalObject)
        return;

    if (scriptExecutionContext->isDocument()) {
        JSDOMWindow* window = jsCast<JSDOMWindow*>(globalObject);
        if (!window->wrapped().isCurrentlyDisplayedInFrame())
            return;
        if (wasCreatedFromMarkup() && !scriptExecutionContext->contentSecurityPolicy()->allowInlineEventHandlers(sourceURL(), sourcePosition().m_line))
            return;
        // FIXME: Is this check needed for other contexts?
        ScriptController& script = window->wrapped().frame()->script();
        if (!script.canExecuteScripts(AboutToExecuteScript) || script.isPaused())
            return;
    }

    ExecState* exec = globalObject->globalExec();
    JSValue handleEventFunction = jsFunction;

    CallData callData;
    CallType callType = getCallData(handleEventFunction, callData);
    // If jsFunction is not actually a function, see if it implements the EventListener interface and use that
    if (callType == CallType::None) {
        handleEventFunction = jsFunction->get(exec, Identifier::fromString(exec, "handleEvent"));
        if (UNLIKELY(scope.exception())) {
            auto* exception = scope.exception();
            scope.clearException();

            event->target()->uncaughtExceptionInEventHandler();
            reportException(exec, exception);
            return;
        }
        callType = getCallData(handleEventFunction, callData);
    }

    if (callType != CallType::None) {
        Ref<JSEventListener> protectedThis(*this);

        MarkedArgumentBuffer args;
        args.append(toJS(exec, globalObject, event));

        Event* savedEvent = globalObject->currentEvent();
        globalObject->setCurrentEvent(event);

        VMEntryScope entryScope(vm, vm.entryScope ? vm.entryScope->globalObject() : globalObject);

        InspectorInstrumentationCookie cookie = JSMainThreadExecState::instrumentFunctionCall(scriptExecutionContext, callType, callData);

        JSValue thisValue = handleEventFunction == jsFunction ? toJS(exec, globalObject, event->currentTarget()) : jsFunction;
        NakedPtr<JSC::Exception> exception;
        JSValue retval = scriptExecutionContext->isDocument()
            ? JSMainThreadExecState::profiledCall(exec, JSC::ProfilingReason::Other, handleEventFunction, callType, callData, thisValue, args, exception)
            : JSC::profiledCall(exec, JSC::ProfilingReason::Other, handleEventFunction, callType, callData, thisValue, args, exception);

        InspectorInstrumentation::didCallFunction(cookie, scriptExecutionContext);

        globalObject->setCurrentEvent(savedEvent);

        if (is<WorkerGlobalScope>(*scriptExecutionContext)) {
            auto scriptController = downcast<WorkerGlobalScope>(*scriptExecutionContext).script();
            bool terminatorCausedException = (scope.exception() && isTerminatedExecutionException(scope.exception()));
            if (terminatorCausedException || scriptController->isTerminatingExecution())
                scriptController->forbidExecution();
        }

        if (exception) {
            event->target()->uncaughtExceptionInEventHandler();
            reportException(exec, exception);
        } else {
            if (!retval.isUndefinedOrNull() && is<BeforeUnloadEvent>(*event))
                downcast<BeforeUnloadEvent>(*event).setReturnValue(retval.toWTFString(exec));
            if (m_isAttribute) {
                if (retval.isFalse())
                    event->preventDefault();
            }
        }
    }
}