Exemplo n.º 1
0
void StackVisitor::readInlinedFrame(CallFrame* callFrame, CodeOrigin* codeOrigin)
{
    ASSERT(codeOrigin);

    int frameOffset = inlinedFrameOffset(codeOrigin);
    bool isInlined = !!frameOffset;
    if (isInlined) {
        InlineCallFrame* inlineCallFrame = codeOrigin->inlineCallFrame;

        m_frame.m_callFrame = callFrame;
        m_frame.m_inlineCallFrame = inlineCallFrame;
        m_frame.m_argumentCountIncludingThis = inlineCallFrame->arguments.size();
        m_frame.m_codeBlock = inlineCallFrame->baselineCodeBlock();
        m_frame.m_bytecodeOffset = codeOrigin->bytecodeIndex;

        JSFunction* callee = inlineCallFrame->calleeForCallFrame(callFrame);
        m_frame.m_scope = callee->scope();
        m_frame.m_callee = callee;
        ASSERT(m_frame.scope());
        ASSERT(m_frame.callee());

        // The callerFrame just needs to be non-null to indicate that we
        // haven't reached the last frame yet. Setting it to the root
        // frame (i.e. the callFrame that this inlined frame is called from)
        // would work just fine.
        m_frame.m_callerFrame = callFrame;
        return;
    }

    readNonInlinedFrame(callFrame, codeOrigin);
}
Exemplo n.º 2
0
CallFrame* CallFrame::trueCallerFrameSlow()
{
    // this -> The callee; this is either an inlined callee in which case it already has
    //    a pointer to the true caller. Otherwise it contains current PC in the machine
    //    caller.
    //
    // machineCaller -> The caller according to the machine, which may be zero or
    //    more frames above the true caller due to inlining.
    //
    // trueCaller -> The real caller.
    
    // Am I an inline call frame? If so, we're done.
    if (isInlineCallFrame())
        return callerFrame();
    
    // I am a machine call frame, so the question is: is my caller a machine call frame
    // that has inlines or a machine call frame that doesn't?
    CallFrame* machineCaller = callerFrame()->removeHostCallFrameFlag();
    if (!machineCaller)
        return 0;
    ASSERT(!machineCaller->isInlineCallFrame());
    if (!machineCaller->codeBlock() || !machineCaller->codeBlock()->hasCodeOrigins())
        return machineCaller; // No inlining, so machineCaller == trueCaller
    
    // Figure out where the caller frame would have gone relative to the machine
    // caller, and rematerialize it. Do so for the entire inline stack.
    
    CodeOrigin codeOrigin = machineCaller->codeBlock()->codeOriginForReturn(returnPC());
    
    for (InlineCallFrame* inlineCallFrame = codeOrigin.inlineCallFrame; inlineCallFrame;) {
        InlineCallFrame* nextInlineCallFrame = inlineCallFrame = inlineCallFrame->caller.inlineCallFrame;
        
        CallFrame* inlinedCaller = machineCaller + inlineCallFrame->stackOffset;
        
        JSObject* callee = machineCaller->registers()[inlineCallFrame->calleeVR].function();
        JSCell* calleeAsFunctionCell = getJSFunction(callee);
        ASSERT(calleeAsFunctionCell);
        JSFunction* calleeAsFunction = asFunction(calleeAsFunctionCell);
        
        // Fill in the inlinedCaller
        inlinedCaller->setCodeBlock(machineCaller->codeBlock());
        
        inlinedCaller->setScopeChain(calleeAsFunction->scope());
        if (nextInlineCallFrame)
            inlinedCaller->setCallerFrame(machineCaller + nextInlineCallFrame->stackOffset);
        else
            inlinedCaller->setCallerFrame(machineCaller);
        
        inlinedCaller->setInlineCallFrame(inlineCallFrame);
        inlinedCaller->setArgumentCountIncludingThis(inlineCallFrame->numArgumentsIncludingThis);
        inlinedCaller->setCallee(callee);
        
        inlineCallFrame = nextInlineCallFrame;
    }
    
    return machineCaller + codeOrigin.inlineCallFrame->stackOffset;
}
Exemplo n.º 3
0
void Debugger::recompileAllJSFunctions(JSGlobalData* globalData)
{
    // If JavaScript is running, it's not safe to recompile, since we'll end
    // up throwing away code that is live on the stack.
    ASSERT(!globalData->dynamicGlobalObject);
    if (globalData->dynamicGlobalObject)
        return;

    typedef HashSet<FunctionExecutable*> FunctionExecutableSet;
    typedef HashMap<SourceProvider*, ExecState*> SourceProviderMap;

    FunctionExecutableSet functionExecutables;
    SourceProviderMap sourceProviders;

    LiveObjectIterator it = globalData->heap.primaryHeapBegin();
    LiveObjectIterator heapEnd = globalData->heap.primaryHeapEnd();
    for ( ; it != heapEnd; ++it) {
        if (!(*it)->inherits(&JSFunction::info))
            continue;

        JSFunction* function = asFunction(*it);
        if (function->executable()->isHostFunction())
            continue;

        FunctionExecutable* executable = function->jsExecutable();

        // Check if the function is already in the set - if so,
        // we've already retranslated it, nothing to do here.
        if (!functionExecutables.add(executable).second)
            continue;

        ExecState* exec = function->scope().globalObject()->JSGlobalObject::globalExec();
        executable->recompile(exec);
        if (function->scope().globalObject()->debugger() == this)
            sourceProviders.add(executable->source().provider(), exec);
    }

    // Call sourceParsed() after reparsing all functions because it will execute
    // JavaScript in the inspector.
    SourceProviderMap::const_iterator end = sourceProviders.end();
    for (SourceProviderMap::const_iterator iter = sourceProviders.begin(); iter != end; ++iter)
        sourceParsed(iter->second, SourceCode(iter->first), -1, UString());
}
void JavaScriptDebugServer::recompileAllJSFunctions(Timer<JavaScriptDebugServer>*)
{
    JSLock lock(false);
    JSGlobalData* globalData = JSDOMWindow::commonJSGlobalData();

    // If JavaScript is running, it's not safe to recompile, since we'll end
    // up throwing away code that is live on the stack.
    ASSERT(!globalData->dynamicGlobalObject);
    if (globalData->dynamicGlobalObject)
        return;

    Vector<ProtectedPtr<JSFunction> > functions;
    Heap::iterator heapEnd = globalData->heap.primaryHeapEnd();
    for (Heap::iterator it = globalData->heap.primaryHeapBegin(); it != heapEnd; ++it) {
        if ((*it)->isObject(&JSFunction::info))
            functions.append(static_cast<JSFunction*>(*it));
    }

    typedef HashMap<RefPtr<FunctionBodyNode>, RefPtr<FunctionBodyNode> > FunctionBodyMap;
    typedef HashMap<SourceProvider*, ExecState*> SourceProviderMap;

    FunctionBodyMap functionBodies;
    SourceProviderMap sourceProviders;

    size_t size = functions.size();
    for (size_t i = 0; i < size; ++i) {
        JSFunction* function = functions[i];

        FunctionBodyNode* oldBody = function->body();
        pair<FunctionBodyMap::iterator, bool> result = functionBodies.add(oldBody, 0);
        if (!result.second) {
            function->setBody(result.first->second.get());
            continue;
        }

        ExecState* exec = function->scope().globalObject()->JSGlobalObject::globalExec();
        const SourceCode& sourceCode = oldBody->source();

        RefPtr<FunctionBodyNode> newBody = globalData->parser->parse<FunctionBodyNode>(exec, 0, sourceCode);
        ASSERT(newBody);
        newBody->finishParsing(oldBody->copyParameters(), oldBody->parameterCount());

        result.first->second = newBody;
        function->setBody(newBody.release());

        if (hasListeners())
            sourceProviders.add(sourceCode.provider(), exec);
    }

    // Call sourceParsed() after reparsing all functions because it will execute
    // JavaScript in the inspector.
    SourceProviderMap::const_iterator end = sourceProviders.end();
    for (SourceProviderMap::const_iterator iter = sourceProviders.begin(); iter != end; ++iter)
        sourceParsed((*iter).second, SourceCode((*iter).first), -1, 0);
}
Exemplo n.º 5
0
CallType JSFunction::getCallData(JSCell* cell, CallData& callData)
{
    JSFunction* thisObject = jsCast<JSFunction*>(cell);
    if (thisObject->isHostFunction()) {
        callData.native.function = thisObject->nativeFunction();
        return CallTypeHost;
    }
    callData.js.functionExecutable = thisObject->jsExecutable();
    callData.js.scope = thisObject->scope();
    return CallTypeJS;
}
Exemplo n.º 6
0
// ECMA 13.2.2 [[Construct]]
ConstructType JSFunction::getConstructData(JSCell* cell, ConstructData& constructData)
{
    JSFunction* thisObject = jsCast<JSFunction*>(cell);
    if (thisObject->isHostFunction()) {
        constructData.native.function = thisObject->nativeConstructor();
        return ConstructTypeHost;
    }
    constructData.js.functionExecutable = thisObject->jsExecutable();
    constructData.js.scope = thisObject->scope();
    return ConstructTypeJS;
}
Exemplo n.º 7
0
void JSLazyEventListener::parseCode() const
{
    if (m_parsed)
        return;

    if (m_globalObject->scriptExecutionContext()->isDocument()) {
        JSDOMWindow* window = static_cast<JSDOMWindow*>(m_globalObject);
        Frame* frame = window->impl()->frame();
        if (!frame)
            return;
        // FIXME: Is this check needed for non-Document contexts?
        ScriptController* script = frame->script();
        if (!script->isEnabled() || script->isPaused())
            return;
    }

    m_parsed = true;

    ExecState* exec = m_globalObject->globalExec();

    MarkedArgumentBuffer args;
    UString sourceURL(m_globalObject->scriptExecutionContext()->url().string());
    args.append(jsNontrivialString(exec, m_eventParameterName));
    args.append(jsString(exec, m_code));

    // FIXME: Passing the document's URL to construct is not always correct, since this event listener might
    // have been added with setAttribute from a script, and we should pass String() in that case.
    m_jsFunction = constructFunction(exec, args, Identifier(exec, m_functionName), sourceURL, m_lineNumber); // FIXME: is globalExec ok?

    JSFunction* listenerAsFunction = static_cast<JSFunction*>(m_jsFunction);

    if (exec->hadException()) {
        exec->clearException();

        // failed to parse, so let's just make this listener a no-op
        m_jsFunction = 0;
    } else if (m_originalNode) {
        // Add the event's home element to the scope
        // (and the document, and the form - see JSHTMLElement::eventHandlerScope)
        ScopeChain scope = listenerAsFunction->scope();

        JSValue thisObj = toJS(exec, m_originalNode);
        if (thisObj.isObject()) {
            static_cast<JSNode*>(asObject(thisObj))->pushEventHandlerScope(exec, scope);
            listenerAsFunction->setScope(scope);
        }
    }

    // Since we only parse once, there's no need to keep data used for parsing around anymore.
    m_functionName = String();
    m_code = String();
    m_eventParameterName = String();
}
Exemplo n.º 8
0
void JSLazyEventListener::parseCode() const
{
    if (m_parsed)
        return;
    m_parsed = true;

    Frame* frame = window()->impl()->frame();
    if (frame && frame->script()->isEnabled()) {
        ExecState* exec = window()->globalExec();

        JSLock lock(false);
        ArgList args;

        UString sourceURL(frame->loader()->url().string());
        args.append(eventParameterName());
        args.append(jsString(exec, m_code));

        // FIXME: Passing the document's URL to construct is not always correct, since this event listener might
        // have been added with setAttribute from a script, and we should pass String() in that case.
        m_listener = constructFunction(exec, args, Identifier(exec, m_functionName), sourceURL, m_lineNumber); // FIXME: is globalExec ok?

        JSFunction* listenerAsFunction = static_cast<JSFunction*>(m_listener.get());

        if (exec->hadException()) {
            exec->clearException();

            // failed to parse, so let's just make this listener a no-op
            m_listener = 0;
        } else if (m_originalNode) {
            // Add the event's home element to the scope
            // (and the document, and the form - see JSHTMLElement::eventHandlerScope)
            ScopeChain scope = listenerAsFunction->scope();

            JSValue* thisObj = toJS(exec, m_originalNode);
            if (thisObj->isObject()) {
                static_cast<JSEventTargetNode*>(thisObj)->pushEventHandlerScope(exec, scope);
                listenerAsFunction->setScope(scope);
            }
        }
    }

    // no more need to keep the unparsed code around
    m_functionName = String();
    m_code = String();

    if (m_listener) {
        JSDOMWindow::ListenersMap& listeners = isHTMLEventListener()
            ? window()->jsHTMLEventListeners() : window()->jsEventListeners();
        listeners.set(m_listener, const_cast<JSLazyEventListener*>(this));
    }
}
Exemplo n.º 9
0
JSCell* DFG_OPERATION operationNewFunctionExpression(ExecState* exec, JSCell* functionExecutableAsCell)
{
    ASSERT(functionExecutableAsCell->inherits(&FunctionExecutable::s_info));
    FunctionExecutable* functionExecutable =
        static_cast<FunctionExecutable*>(functionExecutableAsCell);
    JSFunction *function = functionExecutable->make(exec, exec->scopeChain());
    if (!functionExecutable->name().isNull()) {
        JSStaticScopeObject* functionScopeObject =
            JSStaticScopeObject::create(
                exec, functionExecutable->name(), function, ReadOnly | DontDelete);
        function->setScope(exec->globalData(), function->scope()->push(functionScopeObject));
    }
    return function;
}
Exemplo n.º 10
0
inline void* linkFor(ExecState* execCallee, ReturnAddressPtr returnAddress, CodeSpecializationKind kind)
{
    ExecState* exec = execCallee->callerFrame();
    JSGlobalData* globalData = &exec->globalData();
    JSValue calleeAsValue = execCallee->calleeAsValue();
    JSCell* calleeAsFunctionCell = getJSFunction(calleeAsValue);
    if (!calleeAsFunctionCell)
        return handleHostCall(execCallee, calleeAsValue, kind);
    JSFunction* callee = asFunction(calleeAsFunctionCell);
    ExecutableBase* executable = callee->executable();
    
    MacroAssemblerCodePtr codePtr;
    CodeBlock* codeBlock = 0;
    if (executable->isHostFunction())
        codePtr = executable->generatedJITCodeFor(kind).addressForCall();
    else {
        execCallee->setScopeChain(callee->scope());
        FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
        JSObject* error = functionExecutable->compileFor(execCallee, callee->scope(), kind);
        if (error) {
            globalData->exception = createStackOverflowError(exec);
            return 0;
        }
        codeBlock = &functionExecutable->generatedBytecodeFor(kind);
        if (execCallee->argumentCountIncludingThis() == static_cast<size_t>(codeBlock->m_numParameters))
            codePtr = functionExecutable->generatedJITCodeFor(kind).addressForCall();
        else
            codePtr = functionExecutable->generatedJITCodeWithArityCheckFor(kind);
    }
    CallLinkInfo& callLinkInfo = exec->codeBlock()->getCallLinkInfo(returnAddress);
    if (!callLinkInfo.seenOnce())
        callLinkInfo.setSeen();
    else
        dfgLinkFor(execCallee, callLinkInfo, codeBlock, callee, codePtr, kind);
    return codePtr.executableAddress();
}
Exemplo n.º 11
0
JSCell* DFG_OPERATION operationCreateThis(ExecState* exec, JSCell* prototype)
{
    JSFunction* constructor = asFunction(exec->callee());
    
#if !ASSERT_DISABLED
    ConstructData constructData;
    ASSERT(constructor->methodTable()->getConstructData(constructor, constructData) == ConstructTypeJS);
#endif
    
    JSGlobalData& globalData = exec->globalData();
    
    Structure* structure;
    if (prototype->isObject())
        structure = asObject(prototype)->inheritorID(globalData);
    else
        structure = constructor->scope()->globalObject->emptyObjectStructure();
    
    return constructEmptyObject(exec, structure);
}
Exemplo n.º 12
0
inline void* virtualFor(ExecState* execCallee, CodeSpecializationKind kind)
{
    ExecState* exec = execCallee->callerFrame();
    JSValue calleeAsValue = execCallee->calleeAsValue();
    JSCell* calleeAsFunctionCell = getJSFunction(calleeAsValue);
    if (UNLIKELY(!calleeAsFunctionCell))
        return handleHostCall(execCallee, calleeAsValue, kind);
    
    JSFunction* function = asFunction(calleeAsFunctionCell);
    execCallee->setScopeChain(function->scopeUnchecked());
    ExecutableBase* executable = function->executable();
    if (UNLIKELY(!executable->hasJITCodeFor(kind))) {
        FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
        JSObject* error = functionExecutable->compileFor(execCallee, function->scope(), kind);
        if (error) {
            exec->globalData().exception = error;
            return 0;
        }
    }
    return executable->generatedJITCodeWithArityCheckFor(kind).executableAddress();
}
Exemplo n.º 13
0
inline char* linkFor(ExecState* execCallee, CodeSpecializationKind kind)
{
    ExecState* exec = execCallee->callerFrame();
    VM* vm = &exec->vm();
    NativeCallFrameTracer tracer(vm, exec);
    
    JSValue calleeAsValue = execCallee->calleeAsValue();
    JSCell* calleeAsFunctionCell = getJSFunction(calleeAsValue);
    if (!calleeAsFunctionCell)
        return reinterpret_cast<char*>(handleHostCall(execCallee, calleeAsValue, kind));

    JSFunction* callee = jsCast<JSFunction*>(calleeAsFunctionCell);
    execCallee->setScope(callee->scopeUnchecked());
    ExecutableBase* executable = callee->executable();

    MacroAssemblerCodePtr codePtr;
    CodeBlock* codeBlock = 0;
    if (executable->isHostFunction())
        codePtr = executable->generatedJITCodeFor(kind)->addressForCall();
    else {
        FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
        JSObject* error = functionExecutable->prepareForExecution(execCallee, callee->scope(), kind);
        if (error) {
            vm->throwException(exec, createStackOverflowError(exec));
            return reinterpret_cast<char*>(vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress());
        }
        codeBlock = functionExecutable->codeBlockFor(kind);
        if (execCallee->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters()))
            codePtr = functionExecutable->generatedJITCodeWithArityCheckFor(kind);
        else
            codePtr = functionExecutable->generatedJITCodeFor(kind)->addressForCall();
    }
    CallLinkInfo& callLinkInfo = exec->codeBlock()->getCallLinkInfo(execCallee->returnPC());
    if (!callLinkInfo.seenOnce())
        callLinkInfo.setSeen();
    else
        linkFor(execCallee, callLinkInfo, codeBlock, callee, codePtr, kind);
    return reinterpret_cast<char*>(codePtr.executableAddress());
}
Exemplo n.º 14
0
inline char* virtualForWithFunction(ExecState* execCallee, CodeSpecializationKind kind, JSCell*& calleeAsFunctionCell)
{
    ExecState* exec = execCallee->callerFrame();
    VM* vm = &exec->vm();
    NativeCallFrameTracer tracer(vm, exec);

    JSValue calleeAsValue = execCallee->calleeAsValue();
    calleeAsFunctionCell = getJSFunction(calleeAsValue);
    if (UNLIKELY(!calleeAsFunctionCell))
        return reinterpret_cast<char*>(handleHostCall(execCallee, calleeAsValue, kind));
    
    JSFunction* function = jsCast<JSFunction*>(calleeAsFunctionCell);
    execCallee->setScope(function->scopeUnchecked());
    ExecutableBase* executable = function->executable();
    if (UNLIKELY(!executable->hasJITCodeFor(kind))) {
        FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
        JSObject* error = functionExecutable->prepareForExecution(execCallee, function->scope(), kind);
        if (error) {
            exec->vm().throwException(execCallee, error);
            return reinterpret_cast<char*>(vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress());
        }
    }
    return reinterpret_cast<char*>(executable->generatedJITCodeWithArityCheckFor(kind).executableAddress());
}
Exemplo n.º 15
0
CallFrame* CallFrame::trueCallFrame(AbstractPC pc)
{
    // Am I an inline call frame? If so, we're done.
    if (isInlineCallFrame())
        return this;
    
    // If I don't have a code block, then I'm not DFG code, so I'm the true call frame.
    CodeBlock* machineCodeBlock = codeBlock();
    if (!machineCodeBlock)
        return this;
    
    // If the code block does not have any code origins, then there was no inlining, so
    // I'm done.
    if (!machineCodeBlock->hasCodeOrigins())
        return this;
    
    // At this point the PC must be due either to the DFG, or it must be unset.
    ASSERT(pc.hasJITReturnAddress() || !pc);
    
    // Try to determine the CodeOrigin. If we don't have a pc set then the only way
    // that this makes sense is if the CodeOrigin index was set in the call frame.
    // FIXME: Note that you will see "Not currently in inlined code" comments below.
    // Currently, we do not record code origins for code that is not inlined, because
    // the only thing that we use code origins for is determining the inline stack.
    // But in the future, we'll want to use this same functionality (having a code
    // origin mapping for any calls out of JIT code) to determine the PC at any point
    // in the stack even if not in inlined code. When that happens, the code below
    // will have to change the way it detects the presence of inlining: it will always
    // get a code origin, but sometimes, that code origin will not have an inline call
    // frame. In that case, this method should bail and return this.
    CodeOrigin codeOrigin;
    if (pc.isSet()) {
        ReturnAddressPtr currentReturnPC = pc.jitReturnAddress();
        
        bool hasCodeOrigin = machineCodeBlock->codeOriginForReturn(currentReturnPC, codeOrigin);
        ASSERT_UNUSED(hasCodeOrigin, hasCodeOrigin);
    } else {
        unsigned index = codeOriginIndexForDFG();
        codeOrigin = machineCodeBlock->codeOrigin(index);
    }

    if (!codeOrigin.inlineCallFrame)
        return this; // Not currently in inlined code.
    
    for (InlineCallFrame* inlineCallFrame = codeOrigin.inlineCallFrame; inlineCallFrame;) {
        InlineCallFrame* nextInlineCallFrame = inlineCallFrame->caller.inlineCallFrame;
        
        CallFrame* inlinedCaller = this + inlineCallFrame->stackOffset;
        
        JSFunction* calleeAsFunction = inlineCallFrame->callee.get();
        
        // Fill in the inlinedCaller
        inlinedCaller->setCodeBlock(machineCodeBlock);
        
        inlinedCaller->setScopeChain(calleeAsFunction->scope());
        if (nextInlineCallFrame)
            inlinedCaller->setCallerFrame(this + nextInlineCallFrame->stackOffset);
        else
            inlinedCaller->setCallerFrame(this);
        
        inlinedCaller->setInlineCallFrame(inlineCallFrame);
        inlinedCaller->setArgumentCountIncludingThis(inlineCallFrame->arguments.size());
        inlinedCaller->setCallee(calleeAsFunction);
        
        inlineCallFrame = nextInlineCallFrame;
    }
    
    return this + codeOrigin.inlineCallFrame->stackOffset;
}
Exemplo n.º 16
0
JSObject* JSLazyEventListener::initializeJSFunction(ScriptExecutionContext* executionContext) const
{
    ASSERT(executionContext);
    ASSERT(executionContext->isDocument());
    if (!executionContext)
        return 0;

    Frame* frame = static_cast<Document*>(executionContext)->frame();
    if (!frame)
        return 0;

    ScriptController* scriptController = frame->script();
    if (!scriptController->canExecuteScripts(AboutToExecuteScript))
        return 0;

    JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(executionContext, isolatedWorld());
    if (!globalObject)
        return 0;

    if (executionContext->isDocument()) {
        JSDOMWindow* window = static_cast<JSDOMWindow*>(globalObject);
        Frame* frame = window->impl()->frame();
        if (!frame)
            return 0;
        // FIXME: Is this check needed for non-Document contexts?
        ScriptController* script = frame->script();
        if (!script->canExecuteScripts(AboutToExecuteScript) || script->isPaused())
            return 0;
    }

    ExecState* exec = globalObject->globalExec();

    MarkedArgumentBuffer args;
    args.append(jsNontrivialString(exec, stringToUString(m_eventParameterName)));
    args.append(jsString(exec, m_code));

    JSObject* jsFunction = constructFunction(exec, args, Identifier(exec, stringToUString(m_functionName)), stringToUString(m_sourceURL), m_lineNumber); // FIXME: is globalExec ok?
    if (exec->hadException()) {
        exec->clearException();
        return 0;
    }

    JSFunction* listenerAsFunction = static_cast<JSFunction*>(jsFunction);
    if (m_originalNode) {
        if (!wrapper()) {
            // Ensure that 'node' has a JavaScript wrapper to mark the event listener we're creating.
            JSLock lock(SilenceAssertionsOnly);
            // FIXME: Should pass the global object associated with the node
            setWrapper(asObject(toJS(globalObject->globalExec(), globalObject, m_originalNode)));
        }

        // Add the event's home element to the scope
        // (and the document, and the form - see JSHTMLElement::eventHandlerScope)
        ScopeChain scope = listenerAsFunction->scope();
        static_cast<JSNode*>(wrapper())->pushEventHandlerScope(exec, scope);
        listenerAsFunction->setScope(scope);
    }

    // Since we only parse once, there's no need to keep data used for parsing around anymore.
    m_functionName = String();
    m_code = String();
    m_eventParameterName = String();
    m_sourceURL = String();
    return jsFunction;
}
Exemplo n.º 17
0
void JSLazyEventListener::parseCode(ScriptExecutionContext* executionContext) const
{
    ASSERT(executionContext);
    ASSERT(executionContext->isDocument());
    if (!executionContext)
        return;

    if (m_parsed)
        return;

    Frame* frame = static_cast<Document*>(executionContext)->frame();
    if (!frame)
        return;

    ScriptController* scriptController = frame->script();
    if (!scriptController->isEnabled())
        return;

    JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(executionContext);
    if (!globalObject)
        return;

    // Ensure that 'node' has a JavaScript wrapper to mark the event listener we're creating.
    if (m_originalNode) {
        JSLock lock(SilenceAssertionsOnly);
        // FIXME: Should pass the global object associated with the node
        toJS(globalObject->globalExec(), globalObject, m_originalNode);
    }

    if (executionContext->isDocument()) {
        JSDOMWindow* window = static_cast<JSDOMWindow*>(globalObject);
        Frame* frame = window->impl()->frame();
        if (!frame)
            return;
        // FIXME: Is this check needed for non-Document contexts?
        ScriptController* script = frame->script();
        if (!script->isEnabled() || script->isPaused())
            return;
    }

    m_parsed = true;

    ExecState* exec = globalObject->globalExec();

    MarkedArgumentBuffer args;
    args.append(jsNontrivialString(exec, m_eventParameterName));
    args.append(jsString(exec, m_code));

    m_jsFunction = constructFunction(exec, args, Identifier(exec, m_functionName), m_sourceURL, m_lineNumber); // FIXME: is globalExec ok?

    JSFunction* listenerAsFunction = static_cast<JSFunction*>(m_jsFunction);

    if (exec->hadException()) {
        exec->clearException();

        // failed to parse, so let's just make this listener a no-op
        m_jsFunction = 0;
    } else if (m_originalNode) {
        // Add the event's home element to the scope
        // (and the document, and the form - see JSHTMLElement::eventHandlerScope)
        ScopeChain scope = listenerAsFunction->scope();

        JSValue thisObj = toJS(exec, globalObject, m_originalNode);
        if (thisObj.isObject()) {
            static_cast<JSNode*>(asObject(thisObj))->pushEventHandlerScope(exec, scope);
            listenerAsFunction->setScope(scope);
        }
    }

    // Since we only parse once, there's no need to keep data used for parsing around anymore.
    m_functionName = String();
    m_code = String();
    m_eventParameterName = String();
    m_sourceURL = String();
}
Exemplo n.º 18
0
JSObject* JSLazyEventListener::initializeJSFunction(ScriptExecutionContext* executionContext) const
{
    ASSERT(executionContext);
    ASSERT(executionContext->isDocument());
    if (!executionContext)
        return 0;

    Document* document = static_cast<Document*>(executionContext);

    if (!document->frame())
        return 0;

    if (!document->contentSecurityPolicy()->allowInlineEventHandlers())
        return 0;

    ScriptController* script = document->frame()->script();
    if (!script->canExecuteScripts(AboutToExecuteScript) || script->isPaused())
        return 0;

    JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(executionContext, isolatedWorld());
    if (!globalObject)
        return 0;

    ExecState* exec = globalObject->globalExec();

    MarkedArgumentBuffer args;
    args.append(jsNontrivialString(exec, stringToUString(m_eventParameterName)));
    args.append(jsString(exec, m_code));

    JSObject* jsFunction = constructFunctionSkippingEvalEnabledCheck(exec, exec->lexicalGlobalObject(), args, Identifier(exec, stringToUString(m_functionName)), stringToUString(m_sourceURL), m_position); // FIXME: is globalExec ok?
    if (exec->hadException()) {
        reportCurrentException(exec);
        exec->clearException();
        return 0;
    }

    JSFunction* listenerAsFunction = jsCast<JSFunction*>(jsFunction);
    if (m_originalNode) {
        if (!wrapper()) {
            // Ensure that 'node' has a JavaScript wrapper to mark the event listener we're creating.
            JSLock lock(SilenceAssertionsOnly);
            // FIXME: Should pass the global object associated with the node
            setWrapper(exec->globalData(), asObject(toJS(exec, globalObject, m_originalNode)));
        }

        // Add the event's home element to the scope
        // (and the document, and the form - see JSHTMLElement::eventHandlerScope)
        listenerAsFunction->setScope(exec->globalData(), jsCast<JSNode*>(wrapper())->pushEventHandlerScope(exec, listenerAsFunction->scope()));
    }

    // Since we only parse once, there's no need to keep data used for parsing around anymore.
    m_functionName = String();
    m_code = String();
    m_eventParameterName = String();
    m_sourceURL = String();
    return jsFunction;
}
Exemplo n.º 19
0
JSObject* JSLazyEventListener::initializeJSFunction(ScriptExecutionContext* executionContext) const
{
    ASSERT(is<Document>(executionContext));
    if (!executionContext)
        return nullptr;

    ASSERT(!m_code.isNull());
    ASSERT(!m_eventParameterName.isNull());
    if (m_code.isNull() || m_eventParameterName.isNull())
        return nullptr;

    Document& document = downcast<Document>(*executionContext);

    if (!document.frame())
        return nullptr;

    if (!document.contentSecurityPolicy()->allowInlineEventHandlers(m_sourceURL, m_sourcePosition.m_line))
        return nullptr;

    ScriptController& script = document.frame()->script();
    if (!script.canExecuteScripts(AboutToExecuteScript) || script.isPaused())
        return nullptr;

    JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(executionContext, isolatedWorld());
    if (!globalObject)
        return nullptr;

    VM& vm = globalObject->vm();
    JSLockHolder lock(vm);
    auto scope = DECLARE_CATCH_SCOPE(vm);
    ExecState* exec = globalObject->globalExec();

    MarkedArgumentBuffer args;
    args.append(jsNontrivialString(exec, m_eventParameterName));
    args.append(jsStringWithCache(exec, m_code));

    // We want all errors to refer back to the line on which our attribute was
    // declared, regardless of any newlines in our JavaScript source text.
    int overrideLineNumber = m_sourcePosition.m_line.oneBasedInt();

    JSObject* jsFunction = constructFunctionSkippingEvalEnabledCheck(
        exec, exec->lexicalGlobalObject(), args, Identifier::fromString(exec, m_functionName),
        m_sourceURL, m_sourcePosition, overrideLineNumber);

    if (UNLIKELY(scope.exception())) {
        reportCurrentException(exec);
        scope.clearException();
        return nullptr;
    }

    JSFunction* listenerAsFunction = jsCast<JSFunction*>(jsFunction);

    if (m_originalNode) {
        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
            setWrapper(vm, asObject(toJS(exec, globalObject, *m_originalNode)));
        }

        // Add the event's home element to the scope
        // (and the document, and the form - see JSHTMLElement::eventHandlerScope)
        listenerAsFunction->setScope(vm, jsCast<JSNode*>(wrapper())->pushEventHandlerScope(exec, listenerAsFunction->scope()));
    }
    return jsFunction;
}