Beispiel #1
0
static void messageHandlerInMainThread(v8::Handle<v8::Message> message, v8::Handle<v8::Value> data)
{
    ASSERT(isMainThread());
    // It's possible that messageHandlerInMainThread() is invoked while we're initializing a window.
    // In that half-baked situation, we don't have a valid context nor a valid world,
    // so just return immediately.
    if (DOMWrapperWorld::windowIsBeingInitialized())
        return;

    v8::Isolate* isolate = v8::Isolate::GetCurrent();
    // If called during context initialization, there will be no entered window.
    LocalDOMWindow* enteredWindow = enteredDOMWindow(isolate);
    if (!enteredWindow)
        return;

    String errorMessage = toCoreString(message->Get());

    v8::Handle<v8::StackTrace> stackTrace = message->GetStackTrace();
    RefPtr<ScriptCallStack> callStack = nullptr;
    int scriptId = message->GetScriptOrigin().ScriptID()->Value();
    // Currently stack trace is only collected when inspector is open.
    if (!stackTrace.IsEmpty() && stackTrace->GetFrameCount() > 0) {
        callStack = createScriptCallStack(stackTrace, ScriptCallStack::maxCallStackSizeToCapture, isolate);
        bool success = false;
        int topScriptId = callStack->at(0).scriptId().toInt(&success);
        if (success && topScriptId == scriptId)
            scriptId = 0;
    } else {
        Vector<ScriptCallFrame> callFrames;
        callStack = ScriptCallStack::create(callFrames);
    }

    v8::Handle<v8::Value> resourceName = message->GetScriptOrigin().ResourceName();
    bool shouldUseDocumentURL = resourceName.IsEmpty() || !resourceName->IsString();
    String resource = shouldUseDocumentURL ? enteredWindow->document()->url() : toCoreString(resourceName.As<v8::String>());

    ScriptState* scriptState = ScriptState::current(isolate);
    RefPtr<ErrorEvent> event = ErrorEvent::create(errorMessage, resource, message->GetLineNumber(), message->GetStartColumn() + 1, &scriptState->world());
    if (V8DOMWrapper::isDOMWrapper(data)) {
        v8::Handle<v8::Object> obj = v8::Handle<v8::Object>::Cast(data);
        const WrapperTypeInfo* type = toWrapperTypeInfo(obj);
        if (V8DOMException::wrapperTypeInfo.isSubclass(type)) {
            DOMException* exception = V8DOMException::toNative(obj);
            if (exception && !exception->messageForConsole().isEmpty())
                event->setUnsanitizedMessage("Uncaught " + exception->toStringForConsole());
        }
    }

    // This method might be called while we're creating a new context. In this case, we
    // avoid storing the exception object, as we can't create a wrapper during context creation.
    // FIXME: Can we even get here during initialization now that we bail out when GetEntered returns an empty handle?
    LocalFrame* frame = enteredWindow->document()->frame();
    if (frame && frame->script().existingWindowProxy(scriptState->world())) {
        V8ErrorHandler::storeExceptionOnErrorEventWrapper(event.get(), data, scriptState->context()->Global(), isolate);
    }

    enteredWindow->document()->reportException(event.release(), scriptId, callStack);
}
static inline void resourceInfo(const v8::Handle<v8::Function> function, String& resourceName, int& lineNumber)
{
    v8::ScriptOrigin origin = function->GetScriptOrigin();
    if (origin.ResourceName().IsEmpty()) {
        resourceName = "undefined";
        lineNumber = 1;
    } else {
        resourceName = toWebCoreString(origin.ResourceName());
        lineNumber = function->GetScriptLineNumber() + 1;
    }
}
Beispiel #3
0
v8::Local<v8::Value> V8Proxy::callFunction(v8::Handle<v8::Function> function, v8::Handle<v8::Object> receiver, int argc, v8::Handle<v8::Value> args[])
{
    /// M: add for systrace
    TRACE_METHOD()
    V8GCController::checkMemoryUsage();
    v8::Local<v8::Value> result;
    {
        if (m_recursion >= kMaxRecursionDepth) {
            v8::Local<v8::String> code = v8::String::New("throw new RangeError('Maximum call stack size exceeded.')");
            if (code.IsEmpty())
                return result;
            v8::Local<v8::Script> script = v8::Script::Compile(code);
            if (script.IsEmpty())
                return result;
            script->Run();
            return result;
        }

        // Evaluating the JavaScript could cause the frame to be deallocated,
        // so we start the keep alive timer here.
        // Frame::keepAlive method adds the ref count of the frame and sets a
        // timer to decrease the ref count. It assumes that the current JavaScript
        // execution finishs before firing the timer.
        m_frame->keepAlive();

        InspectorInstrumentationCookie cookie;
        if (InspectorInstrumentation::hasFrontends()) {
            v8::ScriptOrigin origin = function->GetScriptOrigin();
            String resourceName("undefined");
            int lineNumber = 1;
            if (!origin.ResourceName().IsEmpty()) {
                resourceName = toWebCoreString(origin.ResourceName());
                lineNumber = function->GetScriptLineNumber() + 1;
            }
            cookie = InspectorInstrumentation::willCallFunction(m_frame, resourceName, lineNumber);
        }

        m_recursion++;
        result = function->Call(receiver, argc, args);
        m_recursion--;

        InspectorInstrumentation::didCallFunction(cookie);
    }

    // Release the storage mutex if applicable.
    didLeaveScriptContext();

    if (v8::V8::IsDead())
        handleFatalErrorInV8();

    return result;
}
Beispiel #4
0
static bool resourceInfo(const v8::Handle<v8::Function> function, String& resourceName, int& lineNumber)
{
    v8::ScriptOrigin origin = function->GetScriptOrigin();
    if (origin.ResourceName().IsEmpty()) {
        resourceName = "undefined";
        lineNumber = 1;
    } else {
        V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, stringResourceName, origin.ResourceName(), false);
        resourceName = stringResourceName;
        lineNumber = function->GetScriptLineNumber() + 1;
    }
    return true;
}
Beispiel #5
0
v8::Local<v8::Value> V8Proxy::instrumentedCallFunction(Frame* frame, v8::Handle<v8::Function> function, v8::Handle<v8::Object> receiver, int argc, v8::Handle<v8::Value> args[])
{
    V8GCController::checkMemoryUsage();

    if (V8RecursionScope::recursionLevel() >= kMaxRecursionDepth)
        return handleMaxRecursionDepthExceeded();

    ScriptExecutionContext* context = frame ? frame->document() : 0;

    InspectorInstrumentationCookie cookie;
    if (InspectorInstrumentation::hasFrontends() && context) {
        String resourceName("undefined");
        int lineNumber = 1;
        v8::ScriptOrigin origin = function->GetScriptOrigin();
        if (!origin.ResourceName().IsEmpty()) {
            resourceName = toWebCoreString(origin.ResourceName());
            lineNumber = function->GetScriptLineNumber() + 1;
        }
        cookie = InspectorInstrumentation::willCallFunction(context, resourceName, lineNumber);
    }

    v8::Local<v8::Value> result;
    {
#if PLATFORM(CHROMIUM)
        TRACE_EVENT0("v8", "v8.callFunction");
#endif
        V8RecursionScope recursionScope(context);
        result = function->Call(receiver, argc, args);
    }

    InspectorInstrumentation::didCallFunction(cookie);

    if (v8::V8::IsDead())
        handleFatalErrorInV8();

    return result;
}
v8::Local<v8::Value> V8Proxy::callFunction(v8::Handle<v8::Function> function, v8::Handle<v8::Object> receiver, int argc, v8::Handle<v8::Value> args[])
{
    V8GCController::checkMemoryUsage();
    v8::Local<v8::Value> result;
    {
        V8ConsoleMessage::Scope scope;

        if (m_recursion >= kMaxRecursionDepth) {
            v8::Local<v8::String> code = v8::String::New("throw new RangeError('Maximum call stack size exceeded.')");
            if (code.IsEmpty())
                return result;
            v8::Local<v8::Script> script = v8::Script::Compile(code);
            if (script.IsEmpty())
                return result;
            script->Run();
            return result;
        }

        // Evaluating the JavaScript could cause the frame to be deallocated,
        // so we start the keep alive timer here.
        // Frame::keepAlive method adds the ref count of the frame and sets a
        // timer to decrease the ref count. It assumes that the current JavaScript
        // execution finishs before firing the timer.
        m_frame->keepAlive();

#if ENABLE(INSPECTOR)
        Page* inspectedPage = InspectorTimelineAgent::instanceCount() ? m_frame->page(): 0;
        if (inspectedPage) {
            if (InspectorTimelineAgent* timelineAgent = inspectedPage->inspectorTimelineAgent()) {
                v8::ScriptOrigin origin = function->GetScriptOrigin();
                String resourceName("undefined");
                int lineNumber = 1;
                if (!origin.ResourceName().IsEmpty()) {
                    resourceName = toWebCoreString(origin.ResourceName());
                    lineNumber = function->GetScriptLineNumber() + 1;
                }
                timelineAgent->willCallFunction(resourceName, lineNumber);
            } else
                inspectedPage = 0;
        }
#endif // !ENABLE(INSPECTOR)

        m_recursion++;
        result = function->Call(receiver, argc, args);
        m_recursion--;

#if ENABLE(INSPECTOR)
        if (inspectedPage)
            if (InspectorTimelineAgent* timelineAgent = inspectedPage->inspectorTimelineAgent())
                timelineAgent->didCallFunction();
#endif // !ENABLE(INSPECTOR)

    }

    // Release the storage mutex if applicable.
    didLeaveScriptContext();

    if (v8::V8::IsDead())
        handleFatalErrorInV8();

    return result;
}