void InspectorAnimationAgent::resolveAnimation(
    ErrorString* errorString,
    const String& animationId,
    std::unique_ptr<v8_inspector::protocol::Runtime::API::RemoteObject>*
        result) {
  blink::Animation* animation = assertAnimation(errorString, animationId);
  if (!animation)
    return;
  if (m_idToAnimationClone.get(animationId))
    animation = m_idToAnimationClone.get(animationId);
  const Element* element = toKeyframeEffect(animation->effect())->target();
  Document* document = element->ownerDocument();
  LocalFrame* frame = document ? document->frame() : nullptr;
  ScriptState* scriptState = frame ? ScriptState::forMainWorld(frame) : nullptr;
  if (!scriptState) {
    *errorString = "Element not associated with a document.";
    return;
  }

  ScriptState::Scope scope(scriptState);
  static const char kAnimationObjectGroup[] = "animation";
  m_v8Session->releaseObjectGroup(
      toV8InspectorStringView(kAnimationObjectGroup));
  *result = m_v8Session->wrapObject(
      scriptState->context(),
      toV8(animation, scriptState->context()->Global(), scriptState->isolate()),
      toV8InspectorStringView(kAnimationObjectGroup));
  if (!*result)
    *errorString = "Element not associated with a document.";
}
void V8InjectedScriptHost::inspectCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
{
    if (info.Length() < 2)
        return;

    InjectedScriptHost* host = V8InjectedScriptHost::unwrap(info.GetIsolate()->GetCurrentContext(), info.Holder());
    ScriptState* scriptState = ScriptState::current(info.GetIsolate());
    ScriptState::Scope scope(scriptState);
    host->inspectImpl(toJSONValue(scriptState->context(), info[0]), toJSONValue(scriptState->context(), info[1]));
}
void injectInternalsObject(v8::Local<v8::Context> context)
{
    ScriptState* scriptState = ScriptState::from(context);
    ScriptState::Scope scope(scriptState);
    v8::Local<v8::Object> global = scriptState->context()->Global();
    ExecutionContext* executionContext = scriptState->executionContext();
    if (executionContext->isDocument()) {
        v8::Local<v8::Value> internals = toV8(Internals::create(toDocument(executionContext)), global, scriptState->isolate());
        ASSERT(!internals.IsEmpty());
        v8CallOrCrash(global->Set(scriptState->context(), v8AtomicString(scriptState->isolate(), Internals::internalsId), internals));
    }
}
// Create a V8 object with an interceptor of NPObjectPropertyGetter.
bool ScriptController::bindToWindowObject(LocalFrame* frame, const String& key, NPObject* object)
{
    ScriptState* scriptState = ScriptState::forMainWorld(frame);
    if (!scriptState->contextIsValid())
        return false;

    ScriptState::Scope scope(scriptState);
    v8::Local<v8::Object> value = createV8ObjectForNPObject(isolate(), object, 0);

    // Attach to the global object.
    return v8CallBoolean(scriptState->context()->Global()->Set(scriptState->context(), v8String(isolate(), key), value));
}
Beispiel #5
0
static void promiseRejectHandler(v8::PromiseRejectMessage data, RejectedPromises& rejectedPromises, const String& fallbackResourceName)
{
    if (data.GetEvent() == v8::kPromiseHandlerAddedAfterReject) {
        rejectedPromises.handlerAdded(data);
        return;
    }

    ASSERT(data.GetEvent() == v8::kPromiseRejectWithNoHandler);

    v8::Local<v8::Promise> promise = data.GetPromise();
    v8::Isolate* isolate = promise->GetIsolate();
    ScriptState* scriptState = ScriptState::current(isolate);

    v8::Local<v8::Value> exception = data.GetValue();
    if (V8DOMWrapper::isWrapper(isolate, exception)) {
        // Try to get the stack & location from a wrapped exception object (e.g. DOMException).
        ASSERT(exception->IsObject());
        v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(exception);
        v8::Local<v8::Value> error = V8HiddenValue::getHiddenValue(scriptState, obj, V8HiddenValue::error(isolate));
        if (!error.IsEmpty())
            exception = error;
    }

    int scriptId = 0;
    int lineNumber = 0;
    int columnNumber = 0;
    String resourceName = fallbackResourceName;
    String errorMessage;
    AccessControlStatus corsStatus = NotSharableCrossOrigin;
    RefPtrWillBeRawPtr<ScriptCallStack> callStack = nullptr;

    v8::Local<v8::Message> message = v8::Exception::CreateMessage(isolate, exception);
    if (!message.IsEmpty()) {
        V8StringResource<> v8ResourceName(message->GetScriptOrigin().ResourceName());
        if (v8ResourceName.prepare())
            resourceName = v8ResourceName;
        scriptId = message->GetScriptOrigin().ScriptID()->Value();
        if (v8Call(message->GetLineNumber(scriptState->context()), lineNumber)
            && v8Call(message->GetStartColumn(scriptState->context()), columnNumber))
            ++columnNumber;
        // message->Get() can be empty here. https://crbug.com/450330
        errorMessage = toCoreStringWithNullCheck(message->Get());
        callStack = extractCallStack(isolate, message, &scriptId);
        if (message->IsSharedCrossOrigin())
            corsStatus = SharableCrossOrigin;
    }

    String messageForConsole = extractMessageForConsole(isolate, data.GetValue());
    if (!messageForConsole.isEmpty())
        errorMessage = "Uncaught " + messageForConsole;

    rejectedPromises.rejectedWithNoHandler(scriptState, data, errorMessage, resourceName, scriptId, lineNumber, columnNumber, callStack, corsStatus);
}
Beispiel #6
0
static void messageHandlerInMainThread(v8::Local<v8::Message> message, v8::Local<v8::Value> data)
{
    ASSERT(isMainThread());
    v8::Isolate* isolate = v8::Isolate::GetCurrent();
    // If called during context initialization, there will be no entered window.
    LocalDOMWindow* enteredWindow = enteredDOMWindow(isolate);
    if (!enteredWindow || !enteredWindow->isCurrentlyDisplayedInFrame())
        return;

    int scriptId = 0;
    RefPtrWillBeRawPtr<ScriptCallStack> callStack = extractCallStack(isolate, message, &scriptId);
    String resourceName = extractResourceName(message, enteredWindow->document());
    AccessControlStatus accessControlStatus = NotSharableCrossOrigin;
    if (message->IsOpaque())
        accessControlStatus = OpaqueResource;
    else if (message->IsSharedCrossOrigin())
        accessControlStatus = SharableCrossOrigin;

    ScriptState* scriptState = ScriptState::current(isolate);
    String errorMessage = toCoreStringWithNullCheck(message->Get());
    int lineNumber = 0;
    int columnNumber = 0;
    if (v8Call(message->GetLineNumber(scriptState->context()), lineNumber)
        && v8Call(message->GetStartColumn(scriptState->context()), columnNumber))
        ++columnNumber;
    RefPtrWillBeRawPtr<ErrorEvent> event = ErrorEvent::create(errorMessage, resourceName, lineNumber, columnNumber, &scriptState->world());

    String messageForConsole = extractMessageForConsole(isolate, data);
    if (!messageForConsole.isEmpty())
        event->setUnsanitizedMessage("Uncaught " + messageForConsole);

    // 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(isolate, event.get(), data, scriptState->context()->Global());
    }

    if (scriptState->world().isPrivateScriptIsolatedWorld()) {
        // We allow a private script to dispatch error events even in a EventDispatchForbiddenScope scope.
        // Without having this ability, it's hard to debug the private script because syntax errors
        // in the private script are not reported to console (the private script just crashes silently).
        // Allowing error events in private scripts is safe because error events don't propagate to
        // other isolated worlds (which means that the error events won't fire any event listeners
        // in user's scripts).
        EventDispatchForbiddenScope::AllowUserAgentEvents allowUserAgentEvents;
        enteredWindow->document()->reportException(event.release(), scriptId, callStack, accessControlStatus);
    } else {
        enteredWindow->document()->reportException(event.release(), scriptId, callStack, accessControlStatus);
    }
}
void V8MessageEvent::dataAttributeGetterCustom(
    const v8::FunctionCallbackInfo<v8::Value>& info) {
  ScriptState* scriptState = ScriptState::current(info.GetIsolate());
  auto privateCachedData =
      V8PrivateProperty::getMessageEventCachedData(info.GetIsolate());
  v8::Local<v8::Value> cachedData =
      privateCachedData.get(scriptState->context(), info.Holder());
  if (!cachedData.IsEmpty()) {
    v8SetReturnValue(info, cachedData);
    return;
  }

  MessageEvent* event = V8MessageEvent::toImpl(info.Holder());

  v8::Local<v8::Value> result;
  switch (event->getDataType()) {
    case MessageEvent::DataTypeScriptValue:
      result = event->dataAsScriptValue().v8ValueFor(scriptState);
      if (result.IsEmpty())
        result = v8::Null(info.GetIsolate());
      break;

    case MessageEvent::DataTypeSerializedScriptValue:
      if (SerializedScriptValue* serializedValue =
              event->dataAsSerializedScriptValue()) {
        MessagePortArray ports = event->ports();
        result = serializedValue->deserialize(info.GetIsolate(), &ports);
      } else {
        result = v8::Null(info.GetIsolate());
      }
      break;

    case MessageEvent::DataTypeString:
      result = v8String(info.GetIsolate(), event->dataAsString());
      break;

    case MessageEvent::DataTypeBlob:
      result = toV8(event->dataAsBlob(), info.Holder(), info.GetIsolate());
      break;

    case MessageEvent::DataTypeArrayBuffer:
      result =
          toV8(event->dataAsArrayBuffer(), info.Holder(), info.GetIsolate());
      break;
  }

  // Store the result as a private value so this callback returns the cached
  // result in future invocations.
  privateCachedData.set(scriptState->context(), info.Holder(), result);
  v8SetReturnValue(info, result);
}
void InspectorAnimationAgent::resolveAnimation(ErrorString* errorString, const String& animationId, RefPtr<TypeBuilder::Runtime::RemoteObject>& result)
{
    Animation* animation = assertAnimation(errorString, animationId);
    if (!animation)
        return;
    if (m_idToAnimationClone.get(animationId))
        animation = m_idToAnimationClone.get(animationId);
    const Element* element = toKeyframeEffect(animation->effect())->target();
    Document* document = element->ownerDocument();
    LocalFrame* frame = document ? document->frame() : nullptr;
    if (!frame) {
        *errorString = "Element not associated with a document.";
        return;
    }

    ScriptState* scriptState = ScriptState::forMainWorld(frame);
    InjectedScript injectedScript = m_injectedScriptManager->injectedScriptFor(scriptState);
    if (injectedScript.isEmpty())
        return;

    ScriptState::Scope scope(scriptState);
    v8::Isolate* isolate = scriptState->isolate();
    ScriptValue scriptValue = ScriptValue(scriptState, toV8(animation, scriptState->context()->Global(), isolate));
    injectedScript.releaseObjectGroup("animation");
    result = injectedScript.wrapObject(scriptValue, "animation");
}
static void messageHandlerInWorker(v8::Local<v8::Message> message, v8::Local<v8::Value> data)
{
    v8::Isolate* isolate = v8::Isolate::GetCurrent();
    V8PerIsolateData* perIsolateData = V8PerIsolateData::from(isolate);

    // During the frame teardown, there may not be a valid context.
    ScriptState* scriptState = ScriptState::current(isolate);
    if (!scriptState->contextIsValid())
        return;

    // Exceptions that occur in error handler should be ignored since in that case
    // WorkerGlobalScope::reportException will send the exception to the worker object.
    if (perIsolateData->isReportingException())
        return;

    perIsolateData->setReportingException(true);

    ExecutionContext* context = scriptState->getExecutionContext();
    std::unique_ptr<SourceLocation> location = SourceLocation::fromMessage(isolate, message, context);
    ErrorEvent* event = ErrorEvent::create(toCoreStringWithNullCheck(message->Get()), std::move(location), &scriptState->world());

    AccessControlStatus corsStatus = message->IsSharedCrossOrigin() ? SharableCrossOrigin : NotSharableCrossOrigin;

    // If execution termination has been triggered as part of constructing
    // the error event from the v8::Message, quietly leave.
    if (!isolate->IsExecutionTerminating()) {
        V8ErrorHandler::storeExceptionOnErrorEventWrapper(scriptState, event, data, scriptState->context()->Global());
        scriptState->getExecutionContext()->reportException(event, corsStatus);
    }

    perIsolateData->setReportingException(false);
}
Beispiel #10
0
void WebDevToolsFrontendImpl::didClearWindowObject(WebLocalFrameImpl* frame)
{
    if (m_webFrame == frame) {
        v8::Isolate* isolate = v8::Isolate::GetCurrent();
        ScriptState* scriptState = ScriptState::forMainWorld(m_webFrame->frame());
        ScriptState::Scope scope(scriptState);

        if (m_devtoolsHost)
            m_devtoolsHost->disconnectClient();
        m_devtoolsHost = DevToolsHost::create(this, m_webFrame->frame());
        v8::Local<v8::Object> global = scriptState->context()->Global();
        v8::Local<v8::Value> devtoolsHostObj = toV8(m_devtoolsHost.get(), global, scriptState->isolate());
        ASSERT(!devtoolsHostObj.IsEmpty());
        global->Set(v8AtomicString(isolate, "DevToolsHost"), devtoolsHostObj);
    }

    if (m_injectedScriptForOrigin.isEmpty())
        return;

    String origin = frame->securityOrigin().toString();
    String script = m_injectedScriptForOrigin.get(origin);
    if (script.isEmpty())
        return;
    static int s_lastScriptId = 0;
    StringBuilder scriptWithId;
    scriptWithId.append(script);
    scriptWithId.append('(');
    scriptWithId.appendNumber(++s_lastScriptId);
    scriptWithId.append(')');
    frame->frame()->script().executeScriptInMainWorld(scriptWithId.toString());
}
Beispiel #11
0
static void messageHandlerInMainThread(v8::Local<v8::Message> message,
                                       v8::Local<v8::Value> data) {
  ASSERT(isMainThread());
  v8::Isolate* isolate = v8::Isolate::GetCurrent();

  if (isolate->GetEnteredContext().IsEmpty())
    return;

  // If called during context initialization, there will be no entered context.
  ScriptState* scriptState = ScriptState::current(isolate);
  if (!scriptState->contextIsValid())
    return;

  ExecutionContext* context = scriptState->getExecutionContext();
  std::unique_ptr<SourceLocation> location =
      SourceLocation::fromMessage(isolate, message, context);

  AccessControlStatus accessControlStatus = NotSharableCrossOrigin;
  if (message->IsOpaque())
    accessControlStatus = OpaqueResource;
  else if (message->IsSharedCrossOrigin())
    accessControlStatus = SharableCrossOrigin;

  ErrorEvent* event =
      ErrorEvent::create(toCoreStringWithNullCheck(message->Get()),
                         std::move(location), &scriptState->world());

  String messageForConsole = extractMessageForConsole(isolate, data);
  if (!messageForConsole.isEmpty())
    event->setUnsanitizedMessage("Uncaught " + messageForConsole);

  // 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?
  if (context->isDocument()) {
    LocalFrame* frame = toDocument(context)->frame();
    if (frame && frame->script().existingWindowProxy(scriptState->world())) {
      V8ErrorHandler::storeExceptionOnErrorEventWrapper(
          scriptState, event, data, scriptState->context()->Global());
    }
  }

  if (scriptState->world().isPrivateScriptIsolatedWorld()) {
    // We allow a private script to dispatch error events even in a
    // EventDispatchForbiddenScope scope.  Without having this ability, it's
    // hard to debug the private script because syntax errors in the private
    // script are not reported to console (the private script just crashes
    // silently).  Allowing error events in private scripts is safe because
    // error events don't propagate to other isolated worlds (which means that
    // the error events won't fire any event listeners in user's scripts).
    EventDispatchForbiddenScope::AllowUserAgentEvents allowUserAgentEvents;
    context->dispatchErrorEvent(event, accessControlStatus);
  } else {
    context->dispatchErrorEvent(event, accessControlStatus);
  }
}
Beispiel #12
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);
}
void injectInternalsObject(v8::Local<v8::Context> context)
{
    ScriptState* scriptState = ScriptState::from(context);
    ScriptState::Scope scope(scriptState);
    v8::Handle<v8::Object> global = scriptState->context()->Global();
    ExecutionContext* executionContext = scriptState->executionContext();
    if (executionContext->isDocument())
        global->Set(v8::String::NewFromUtf8(scriptState->isolate(), Internals::internalsId), toV8(Internals::create(toDocument(executionContext)), global, scriptState->isolate()));
}
Beispiel #14
0
static void promiseRejectHandlerInWorker(v8::PromiseRejectMessage data)
{
    v8::Local<v8::Promise> promise = data.GetPromise();

    // Bail out if called during context initialization.
    v8::Isolate* isolate = promise->GetIsolate();
    ScriptState* scriptState = ScriptState::current(isolate);
    if (!scriptState->contextIsValid())
        return;

    ExecutionContext* executionContext = scriptState->executionContext();
    if (!executionContext)
        return;

    ASSERT(executionContext->isWorkerGlobalScope());
    WorkerScriptController* scriptController = toWorkerGlobalScope(executionContext)->script();
    ASSERT(scriptController);

    if (data.GetEvent() == v8::kPromiseHandlerAddedAfterReject) {
        scriptController->rejectedPromises()->handlerAdded(data);
        return;
    }

    ASSERT(data.GetEvent() == v8::kPromiseRejectWithNoHandler);

    int scriptId = 0;
    int lineNumber = 0;
    int columnNumber = 0;
    String resourceName;
    String errorMessage;

    v8::Local<v8::Message> message = v8::Exception::CreateMessage(data.GetValue());
    if (!message.IsEmpty()) {
        TOSTRING_VOID(V8StringResource<>, resourceName, message->GetScriptOrigin().ResourceName());
        scriptId = message->GetScriptOrigin().ScriptID()->Value();
        if (v8Call(message->GetLineNumber(scriptState->context()), lineNumber)
            && v8Call(message->GetStartColumn(scriptState->context()), columnNumber))
            ++columnNumber;
        // message->Get() can be empty here. https://crbug.com/450330
        errorMessage = toCoreStringWithNullCheck(message->Get());
    }
    scriptController->rejectedPromises()->rejectedWithNoHandler(scriptState, data, errorMessage, resourceName, scriptId, lineNumber, columnNumber, nullptr);
}
Beispiel #15
0
void MainThreadDebugger::exceptionThrown(ExecutionContext* context,
                                         ErrorEvent* event) {
  LocalFrame* frame = nullptr;
  ScriptState* scriptState = nullptr;
  if (context->isDocument()) {
    frame = toDocument(context)->frame();
    if (!frame)
      return;
    scriptState = event->world() ? ScriptState::forWorld(frame, *event->world())
                                 : nullptr;
  } else if (context->isMainThreadWorkletGlobalScope()) {
    frame = toMainThreadWorkletGlobalScope(context)->frame();
    if (!frame)
      return;
    scriptState = toMainThreadWorkletGlobalScope(context)
                      ->scriptController()
                      ->getScriptState();
  } else {
    NOTREACHED();
  }

  frame->console().reportMessageToClient(JSMessageSource, ErrorMessageLevel,
                                         event->messageForConsole(),
                                         event->location());

  const String defaultMessage = "Uncaught";
  if (scriptState && scriptState->contextIsValid()) {
    ScriptState::Scope scope(scriptState);
    v8::Local<v8::Value> exception =
        V8ErrorHandler::loadExceptionFromErrorEventWrapper(
            scriptState, event, scriptState->context()->Global());
    SourceLocation* location = event->location();
    String message = event->messageForConsole();
    String url = location->url();
    v8Inspector()->exceptionThrown(
        scriptState->context(), toV8InspectorStringView(defaultMessage),
        exception, toV8InspectorStringView(message),
        toV8InspectorStringView(url), location->lineNumber(),
        location->columnNumber(), location->takeStackTrace(),
        location->scriptId());
  }
}
Beispiel #16
0
void V8HTMLElement::HTMLConstructor(
    const v8::FunctionCallbackInfo<v8::Value>& info) {
  DCHECK(info.IsConstructCall());

  v8::Isolate* isolate = info.GetIsolate();
  ScriptState* scriptState = ScriptState::current(isolate);

  if (!RuntimeEnabledFeatures::customElementsV1Enabled() ||
      !scriptState->world().isMainWorld()) {
    V8ThrowException::throwTypeError(info.GetIsolate(), "Illegal constructor");
    return;
  }

  LocalDOMWindow* window = scriptState->domWindow();
  ScriptCustomElementDefinition* definition =
      ScriptCustomElementDefinition::forConstructor(
          scriptState, window->customElements(), info.NewTarget());
  if (!definition) {
    V8ThrowException::throwTypeError(isolate, "Illegal constructor");
    return;
  }

  ExceptionState exceptionState(ExceptionState::ConstructionContext,
                                "HTMLElement", info.Holder(), isolate);

  Element* element;
  if (definition->constructionStack().isEmpty()) {
    // This is an element being created with 'new' from script
    element = definition->createElementForConstructor(*window->document());
  } else {
    element = definition->constructionStack().last();
    if (element) {
      // This is an element being upgraded that has called super
      definition->constructionStack().last().clear();
    } else {
      // During upgrade an element has invoked the same constructor
      // before calling 'super' and that invocation has poached the
      // element.
      exceptionState.throwDOMException(InvalidStateError,
                                       "this instance is already constructed");
      return;
    }
  }
  const WrapperTypeInfo* wrapperType = element->wrapperTypeInfo();
  v8::Local<v8::Object> wrapper = V8DOMWrapper::associateObjectWithWrapper(
      isolate, element, wrapperType, info.Holder());
  // If the element had a wrapper, we now update and return that
  // instead.
  v8SetReturnValue(info, wrapper);

  wrapper->SetPrototype(scriptState->context(), definition->prototype())
      .ToChecked();
}
Beispiel #17
0
// Create a V8 object with an interceptor of NPObjectPropertyGetter.
void ScriptController::bindToWindowObject(LocalFrame* frame, const String& key, NPObject* object)
{
    ScriptState* scriptState = ScriptState::forMainWorld(frame);
    if (!scriptState->contextIsValid())
        return;

    ScriptState::Scope scope(scriptState);
    v8::Handle<v8::Object> value = createV8ObjectForNPObject(m_isolate, object, 0);

    // Attach to the global object.
    scriptState->context()->Global()->Set(v8String(m_isolate, key), value);
}
Beispiel #18
0
static void messageHandlerInWorker(v8::Local<v8::Message> message, v8::Local<v8::Value> data)
{
    v8::Isolate* isolate = v8::Isolate::GetCurrent();
    V8PerIsolateData* perIsolateData = V8PerIsolateData::from(isolate);
    // Exceptions that occur in error handler should be ignored since in that case
    // WorkerGlobalScope::reportException will send the exception to the worker object.
    if (perIsolateData->isReportingException())
        return;
    perIsolateData->setReportingException(true);

    ScriptState* scriptState = ScriptState::current(isolate);
    // During the frame teardown, there may not be a valid context.
    if (ExecutionContext* context = scriptState->executionContext()) {
        String errorMessage = toCoreStringWithNullCheck(message->Get());
        TOSTRING_VOID(V8StringResource<>, sourceURL, message->GetScriptOrigin().ResourceName());
        int scriptId = 0;
        RefPtrWillBeRawPtr<ScriptCallStack> callStack = extractCallStack(isolate, message, &scriptId);

        int lineNumber = 0;
        int columnNumber = 0;
        if (v8Call(message->GetLineNumber(scriptState->context()), lineNumber)
            && v8Call(message->GetStartColumn(scriptState->context()), columnNumber))
            ++columnNumber;
        RefPtrWillBeRawPtr<ErrorEvent> event = ErrorEvent::create(errorMessage, sourceURL, lineNumber, columnNumber, &DOMWrapperWorld::current(isolate));
        AccessControlStatus corsStatus = message->IsSharedCrossOrigin() ? SharableCrossOrigin : NotSharableCrossOrigin;

        // If execution termination has been triggered as part of constructing
        // the error event from the v8::Message, quietly leave.
        if (!v8::V8::IsExecutionTerminating(isolate)) {
            V8ErrorHandler::storeExceptionOnErrorEventWrapper(isolate, event.get(), data, scriptState->context()->Global());
            context->reportException(event.release(), scriptId, callStack, corsStatus);
        }
    }

    perIsolateData->setReportingException(false);
}
void AcceptConnectionObserver::responseWasResolved(const ScriptValue& value)
{
    ASSERT(executionContext());
    if (!m_resolver) {
        // TODO(mek): Get rid of this block when observer is only used for
        // service port connect events.
        if (!value.v8Value()->IsTrue()) {
            responseWasRejected();
            return;
        }
        ServiceWorkerGlobalScopeClient::from(executionContext())->didHandleCrossOriginConnectEvent(m_eventID, true);
        m_state = Done;
        return;
    }

    ScriptState* scriptState = m_resolver->scriptState();
    ExceptionState exceptionState(ExceptionState::UnknownContext, nullptr, nullptr, scriptState->context()->Global(), scriptState->isolate());
    ServicePortConnectResponse response = ScriptValue::to<ServicePortConnectResponse>(scriptState->isolate(), value, exceptionState);
    if (exceptionState.hadException()) {
        exceptionState.reject(m_resolver.get());
        m_resolver = nullptr;
        responseWasRejected();
        return;
    }
    if (!response.hasAccept() || !response.accept()) {
        responseWasRejected();
        return;
    }
    WebServicePort webPort;
    webPort.targetUrl = m_targetURL;
    if (response.hasName())
        webPort.name = response.name();
    if (response.hasData()) {
        webPort.data = SerializedScriptValueFactory::instance().create(scriptState->isolate(), response.data(), nullptr, exceptionState)->toWireString();
        if (exceptionState.hadException()) {
            exceptionState.reject(m_resolver.get());
            m_resolver = nullptr;
            responseWasRejected();
            return;
        }
    }
    webPort.id = m_portID;
    ServicePort* port = ServicePort::create(m_collection, webPort);
    m_collection->addPort(port);
    m_resolver->resolve(port);
    m_callbacks->onSuccess(&webPort);
    m_state = Done;
}
Beispiel #20
0
WebDevToolsFrontendImpl::~WebDevToolsFrontendImpl()
{
    if (m_devtoolsHost)
        m_devtoolsHost->disconnectClient();

    if (!m_devtoolsHost || !m_webFrame)
        return;

    v8::Isolate* isolate = v8::Isolate::GetCurrent();
    ScriptState* scriptState = ScriptState::forMainWorld(m_webFrame->frame());
    ScriptState::Scope scope(scriptState);

    v8::Local<v8::Object> global = scriptState->context()->Global();
    global->Delete(v8AtomicString(isolate, "DevToolsHost"));
    m_devtoolsHost = nullptr;
}
Beispiel #21
0
bool _NPN_EvaluateHelper(NPP npp, bool popupsAllowed, NPObject* npObject, NPString* npScript, NPVariant* result)
{
    ScriptForbiddenScope::AllowSuperUnsafeScript thisShouldBeRemoved;

    VOID_TO_NPVARIANT(*result);
    if (!npObject)
        return false;

    V8NPObject* v8NpObject = npObjectToV8NPObject(npObject);
    if (!v8NpObject)
        return false;

    v8::Isolate* isolate = v8::Isolate::GetCurrent();
    ScriptState* scriptState = mainWorldScriptState(isolate, npp, npObject);
    if (!scriptState)
        return false;

    ScriptState::Scope scope(scriptState);
    ExceptionCatcher exceptionCatcher;

    // FIXME: Is this branch still needed after switching to using UserGestureIndicator?
    String filename;
    if (!popupsAllowed)
        filename = "npscript";

    LocalFrame* frame = v8NpObject->rootObject->frame();
    ASSERT(frame);

    String script = String::fromUTF8(npScript->UTF8Characters, npScript->UTF8Length);

    UserGestureIndicator gestureIndicator(popupsAllowed ? DefinitelyProcessingNewUserGesture : PossiblyProcessingUserGesture);
    v8::Local<v8::Value> v8result = frame->script().executeScriptAndReturnValue(scriptState->context(), ScriptSourceCode(script, KURL(ParsedURLString, filename)));

    if (v8result.IsEmpty())
        return false;

    if (_NPN_IsAlive(npObject))
        convertV8ObjectToNPVariant(v8result, npObject, result, isolate);
    return true;
}
ScriptObject InjectedScriptManager::injectWebGLScript(const String& scriptSource, const ScriptObject& glContext)
{
    v8::HandleScope scope;

    ScriptState* inspectedScriptState = glContext.scriptState();
    v8::Local<v8::Context> inspectedContext = inspectedScriptState->context();
    v8::Context::Scope contextScope(inspectedContext);

    v8::Local<v8::Object> windowGlobal = inspectedContext->Global();

    v8::Local<v8::Script> script = v8::Script::Compile(v8String(scriptSource));
    V8RecursionScope::MicrotaskSuppression recursionScope;
    v8::Local<v8::Value> v = script->Run();
    ASSERT(!v.IsEmpty());
    ASSERT(v->IsFunction());

    v8::Handle<v8::Value> args[] = {
        glContext.v8Value(),
    };
    v8::Local<v8::Value> injectedScriptValue = v8::Function::Cast(*v)->Call(windowGlobal, 1, args);
    return ScriptObject(inspectedScriptState, v8::Handle<v8::Object>::Cast(injectedScriptValue));
}
void V8LazyEventListener::prepareListenerObject(ExecutionContext* executionContext)
{
    if (!executionContext)
        return;

    // A ScriptState used by the event listener needs to be calculated based on
    // the ExecutionContext that fired the the event listener and the world
    // that installed the event listener.
    v8::HandleScope handleScope(toIsolate(executionContext));
    v8::Local<v8::Context> v8Context = toV8Context(executionContext, world());
    if (v8Context.IsEmpty())
        return;
    ScriptState* scriptState = ScriptState::from(v8Context);
    if (!scriptState->contextIsValid())
        return;

    if (!executionContext->isDocument())
        return;

    if (!toDocument(executionContext)->allowInlineEventHandlers(m_node, this, m_sourceURL, m_position.m_line)) {
        clearListenerObject();
        return;
    }

    if (hasExistingListenerObject())
        return;

    ScriptState::Scope scope(scriptState);

    // FIXME: Remove the following 'with' hack.
    //
    // Nodes other than the document object, when executing inline event
    // handlers push document, form owner, and the target node on the scope chain.
    // We do this by using 'with' statement.
    // See chrome/fast/forms/form-action.html
    //     chrome/fast/forms/selected-index-value.html
    //     base/fast/overflow/onscroll-layer-self-destruct.html
    //
    // Don't use new lines so that lines in the modified handler
    // have the same numbers as in the original code.
    // FIXME: V8 does not allow us to programmatically create object environments so
    //        we have to do this hack! What if m_code escapes to run arbitrary script?
    //
    // Call with 4 arguments instead of 3, pass additional null as the last parameter.
    // By calling the function with 4 arguments, we create a setter on arguments object
    // which would shadow property "3" on the prototype.
    String code = "(function() {"
        "with (this[2]) {"
        "with (this[1]) {"
        "with (this[0]) {"
            "return function(" + m_eventParameterName + ") {" +
                m_code + "\n" // Insert '\n' otherwise //-style comments could break the handler.
            "};"
        "}}}})";

    v8::Local<v8::String> codeExternalString = v8String(isolate(), code);

    v8::Local<v8::Value> result;
    if (!V8ScriptRunner::compileAndRunInternalScript(codeExternalString, isolate(), m_sourceURL, m_position).ToLocal(&result))
        return;

    // Call the outer function to get the inner function.
    if (!result->IsFunction())
        return;
    v8::Local<v8::Function> intermediateFunction = result.As<v8::Function>();

    HTMLFormElement* formElement = 0;
    if (m_node && m_node->isHTMLElement())
        formElement = toHTMLElement(m_node)->formOwner();

    v8::Local<v8::Object> nodeWrapper = toObjectWrapper<Node>(m_node, scriptState);
    v8::Local<v8::Object> formWrapper = toObjectWrapper<HTMLFormElement>(formElement, scriptState);
    v8::Local<v8::Object> documentWrapper = toObjectWrapper<Document>(m_node ? m_node->ownerDocument() : 0, scriptState);

    v8::Local<v8::Object> thisObject = v8::Object::New(isolate());
    if (thisObject.IsEmpty())
        return;
    if (!v8CallBoolean(thisObject->ForceSet(scriptState->context(), v8::Integer::New(isolate(), 0), nodeWrapper)))
        return;
    if (!v8CallBoolean(thisObject->ForceSet(scriptState->context(), v8::Integer::New(isolate(), 1), formWrapper)))
        return;
    if (!v8CallBoolean(thisObject->ForceSet(scriptState->context(), v8::Integer::New(isolate(), 2), documentWrapper)))
        return;

    // FIXME: Remove this code when we stop doing the 'with' hack above.
    v8::Local<v8::Value> innerValue;
    if (!V8ScriptRunner::callInternalFunction(intermediateFunction, thisObject, 0, 0, isolate()).ToLocal(&innerValue) || !innerValue->IsFunction())
        return;

    v8::Local<v8::Function> wrappedFunction = innerValue.As<v8::Function>();

    // Change the toString function on the wrapper function to avoid it
    // returning the source for the actual wrapper function. Instead it
    // returns source for a clean wrapper function with the event
    // argument wrapping the event source code. The reason for this is
    // that some web sites use toString on event functions and eval the
    // source returned (sometimes a RegExp is applied as well) for some
    // other use. That fails miserably if the actual wrapper source is
    // returned.
    v8::Local<v8::Function> toStringFunction = v8::Function::New(isolate(), V8LazyEventListenerToString);
    if (toStringFunction.IsEmpty())
        return;
    String toStringString = "function " + m_functionName + "(" + m_eventParameterName + ") {\n  " + m_code + "\n}";
    V8HiddenValue::setHiddenValue(isolate(), wrappedFunction, V8HiddenValue::toStringString(isolate()), v8String(isolate(), toStringString));
    if (!v8CallBoolean(wrappedFunction->Set(scriptState->context(), v8AtomicString(isolate(), "toString"), toStringFunction)))
        return;
    wrappedFunction->SetName(v8String(isolate(), m_functionName));

    // FIXME: Remove the following comment-outs.
    // See https://bugs.webkit.org/show_bug.cgi?id=85152 for more details.
    //
    // For the time being, we comment out the following code since the
    // second parsing can happen.
    // // 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();

    setListenerObject(wrappedFunction);
}
Beispiel #24
0
// https://html.spec.whatwg.org/multipage/dom.html#html-element-constructors
void V8HTMLConstructor::htmlConstructor(
    const v8::FunctionCallbackInfo<v8::Value>& info,
    const WrapperTypeInfo& wrapperTypeInfo,
    const HTMLElementType elementInterfaceName) {
  TRACE_EVENT0("blink", "HTMLConstructor");
  DCHECK(info.IsConstructCall());

  v8::Isolate* isolate = info.GetIsolate();
  ScriptState* scriptState = ScriptState::current(isolate);
  v8::Local<v8::Value> newTarget = info.NewTarget();

  if (!scriptState->contextIsValid()) {
    V8ThrowException::throwError(isolate, "The context has been destroyed");
    return;
  }

  if (!RuntimeEnabledFeatures::customElementsV1Enabled() ||
      !scriptState->world().isMainWorld()) {
    V8ThrowException::throwTypeError(isolate, "Illegal constructor");
    return;
  }

  // 2. If NewTarget is equal to the active function object, then
  // throw a TypeError and abort these steps.
  v8::Local<v8::Function> activeFunctionObject =
      scriptState->perContextData()->constructorForType(
          &V8HTMLElement::wrapperTypeInfo);
  if (newTarget == activeFunctionObject) {
    V8ThrowException::throwTypeError(isolate, "Illegal constructor");
    return;
  }

  LocalDOMWindow* window = scriptState->domWindow();
  CustomElementRegistry* registry = window->customElements();

  // 3. Let definition be the entry in registry with constructor equal to
  // NewTarget.
  // If there is no such definition, then throw a TypeError and abort these
  // steps.
  ScriptCustomElementDefinition* definition =
      ScriptCustomElementDefinition::forConstructor(scriptState, registry,
                                                    newTarget);
  if (!definition) {
    V8ThrowException::throwTypeError(isolate, "Illegal constructor");
    return;
  }

  const AtomicString& localName = definition->descriptor().localName();
  const AtomicString& name = definition->descriptor().name();

  if (localName == name) {
    // Autonomous custom element
    // 4.1. If the active function object is not HTMLElement, then throw a
    // TypeError
    if (!V8HTMLElement::wrapperTypeInfo.equals(&wrapperTypeInfo)) {
      V8ThrowException::throwTypeError(isolate,
                                       "Illegal constructor: autonomous custom "
                                       "elements must extend HTMLElement");
      return;
    }
  } else {
    // Customized built-in element
    // 5. If local name is not valid for interface, throw TypeError
    if (htmlElementTypeForTag(localName) != elementInterfaceName) {
      V8ThrowException::throwTypeError(isolate,
                                       "Illegal constructor: localName does "
                                       "not match the HTML element interface");
      return;
    }
  }

  ExceptionState exceptionState(isolate, ExceptionState::ConstructionContext,
                                "HTMLElement");
  v8::TryCatch tryCatch(isolate);

  // 6. Let prototype be Get(NewTarget, "prototype"). Rethrow any exceptions.
  v8::Local<v8::Value> prototype;
  v8::Local<v8::String> prototypeString = v8AtomicString(isolate, "prototype");
  if (!v8Call(newTarget.As<v8::Object>()->Get(scriptState->context(),
                                              prototypeString),
              prototype)) {
    return;
  }

  // 7. If Type(prototype) is not Object, then: ...
  if (!prototype->IsObject()) {
    if (V8PerContextData* perContextData = V8PerContextData::from(
            newTarget.As<v8::Object>()->CreationContext())) {
      prototype =
          perContextData->prototypeForType(&V8HTMLElement::wrapperTypeInfo);
    } else {
      V8ThrowException::throwError(isolate, "The context has been destroyed");
      return;
    }
  }

  // 8. If definition's construction stack is empty...
  Element* element;
  if (definition->constructionStack().isEmpty()) {
    // This is an element being created with 'new' from script
    element = definition->createElementForConstructor(*window->document());
  } else {
    element = definition->constructionStack().last();
    if (element) {
      // This is an element being upgraded that has called super
      definition->constructionStack().last().clear();
    } else {
      // During upgrade an element has invoked the same constructor
      // before calling 'super' and that invocation has poached the
      // element.
      exceptionState.throwDOMException(InvalidStateError,
                                       "this instance is already constructed");
      return;
    }
  }
  const WrapperTypeInfo* wrapperType = element->wrapperTypeInfo();
  v8::Local<v8::Object> wrapper = V8DOMWrapper::associateObjectWithWrapper(
      isolate, element, wrapperType, info.Holder());
  // If the element had a wrapper, we now update and return that
  // instead.
  v8SetReturnValue(info, wrapper);

  // 11. Perform element.[[SetPrototypeOf]](prototype). Rethrow any exceptions.
  // Note: I don't think this prototype set *can* throw exceptions.
  wrapper->SetPrototype(scriptState->context(), prototype.As<v8::Object>())
      .ToChecked();
}
Beispiel #25
0
v8::Local<v8::Context> MainThreadDebugger::ensureDefaultContextInGroup(
    int contextGroupId) {
  LocalFrame* frame = WeakIdentifierMap<LocalFrame>::lookup(contextGroupId);
  ScriptState* scriptState = frame ? ScriptState::forMainWorld(frame) : nullptr;
  return scriptState ? scriptState->context() : v8::Local<v8::Context>();
}
Beispiel #26
0
Page* InspectorOverlay::overlayPage() {
  if (m_overlayPage)
    return m_overlayPage.get();

  ScriptForbiddenScope::AllowUserAgentScript allowScript;

  DEFINE_STATIC_LOCAL(FrameLoaderClient, dummyFrameLoaderClient,
                      (EmptyFrameLoaderClient::create()));
  Page::PageClients pageClients;
  fillWithEmptyClients(pageClients);
  DCHECK(!m_overlayChromeClient);
  m_overlayChromeClient = InspectorOverlayChromeClient::create(
      m_frameImpl->frame()->host()->chromeClient(), *this);
  pageClients.chromeClient = m_overlayChromeClient.get();
  m_overlayPage = Page::create(pageClients);

  Settings& settings = m_frameImpl->frame()->host()->settings();
  Settings& overlaySettings = m_overlayPage->settings();

  overlaySettings.genericFontFamilySettings().updateStandard(
      settings.genericFontFamilySettings().standard());
  overlaySettings.genericFontFamilySettings().updateSerif(
      settings.genericFontFamilySettings().serif());
  overlaySettings.genericFontFamilySettings().updateSansSerif(
      settings.genericFontFamilySettings().sansSerif());
  overlaySettings.genericFontFamilySettings().updateCursive(
      settings.genericFontFamilySettings().cursive());
  overlaySettings.genericFontFamilySettings().updateFantasy(
      settings.genericFontFamilySettings().fantasy());
  overlaySettings.genericFontFamilySettings().updatePictograph(
      settings.genericFontFamilySettings().pictograph());
  overlaySettings.setMinimumFontSize(settings.minimumFontSize());
  overlaySettings.setMinimumLogicalFontSize(settings.minimumLogicalFontSize());
  overlaySettings.setScriptEnabled(true);
  overlaySettings.setPluginsEnabled(false);
  overlaySettings.setLoadsImagesAutomatically(true);
  // FIXME: http://crbug.com/363843. Inspector should probably create its
  // own graphics layers and attach them to the tree rather than going
  // through some non-composited paint function.
  overlaySettings.setAcceleratedCompositingEnabled(false);

  LocalFrame* frame = LocalFrame::create(&dummyFrameLoaderClient,
                                         &m_overlayPage->frameHost(), 0);
  frame->setView(FrameView::create(*frame));
  frame->init();
  FrameLoader& loader = frame->loader();
  frame->view()->setCanHaveScrollbars(false);
  frame->view()->setTransparent(true);

  const WebData& overlayPageHTMLResource =
      Platform::current()->loadResource("InspectorOverlayPage.html");
  RefPtr<SharedBuffer> data = SharedBuffer::create(
      overlayPageHTMLResource.data(), overlayPageHTMLResource.size());
  loader.load(FrameLoadRequest(
      0, blankURL(), SubstituteData(data, "text/html", "UTF-8", KURL(),
                                    ForceSynchronousLoad)));
  v8::Isolate* isolate = toIsolate(frame);
  ScriptState* scriptState = ScriptState::forMainWorld(frame);
  DCHECK(scriptState);
  ScriptState::Scope scope(scriptState);
  v8::Local<v8::Object> global = scriptState->context()->Global();
  v8::Local<v8::Value> overlayHostObj =
      toV8(m_overlayHost.get(), global, isolate);
  DCHECK(!overlayHostObj.IsEmpty());
  global
      ->Set(scriptState->context(),
            v8AtomicString(isolate, "InspectorOverlayHost"), overlayHostObj)
      .ToChecked();

#if OS(WIN)
  evaluateInOverlay("setPlatform", "windows");
#elif OS(MACOSX)
  evaluateInOverlay("setPlatform", "mac");
#elif OS(POSIX)
  evaluateInOverlay("setPlatform", "linux");
#endif

  return m_overlayPage.get();
}
void V8LazyEventListener::prepareListenerObject(ExecutionContext* executionContext)
{
    if (!executionContext)
        return;

    // A ScriptState used by the event listener needs to be calculated based on
    // the ExecutionContext that fired the the event listener and the world
    // that installed the event listener.
    v8::HandleScope handleScope(toIsolate(executionContext));
    v8::Local<v8::Context> v8Context = toV8Context(executionContext, world());
    if (v8Context.IsEmpty())
        return;
    ScriptState* scriptState = ScriptState::from(v8Context);
    if (!scriptState->contextIsValid())
        return;

    if (!executionContext->isDocument())
        return;

    if (!toDocument(executionContext)->allowInlineEventHandlers(m_node, this, m_sourceURL, m_position.m_line)) {
        clearListenerObject();
        return;
    }

    if (hasExistingListenerObject())
        return;

    ScriptState::Scope scope(scriptState);

    // Nodes other than the document object, when executing inline event
    // handlers push document, form owner, and the target node on the scope chain.
    // We do this by using 'with' statement.
    // See fast/forms/form-action.html
    //     fast/forms/selected-index-value.html
    //     fast/overflow/onscroll-layer-self-destruct.html
    HTMLFormElement* formElement = 0;
    if (m_node && m_node->isHTMLElement())
        formElement = toHTMLElement(m_node)->formOwner();

    v8::Local<v8::Object> scopes[3];

    scopes[2] = toObjectWrapper<Node>(m_node, scriptState);
    scopes[1] = toObjectWrapper<HTMLFormElement>(formElement, scriptState);
    scopes[0] = toObjectWrapper<Document>(m_node ? m_node->ownerDocument() : 0, scriptState);

    v8::Local<v8::String> parameterName = v8String(isolate(), m_eventParameterName);
    v8::ScriptOrigin origin(
        v8String(isolate(), m_sourceURL),
        v8::Integer::New(isolate(), m_position.m_line.zeroBasedInt()),
        v8::Integer::New(isolate(), m_position.m_column.zeroBasedInt()),
        v8::True(isolate()),
        v8::Local<v8::Integer>(),
        v8::True(isolate()));
    v8::ScriptCompiler::Source source(v8String(isolate(), m_code), origin);

    v8::Local<v8::Function> wrappedFunction;
    {
        // JavaScript compilation error shouldn't be reported as a runtime
        // exception because we're not running any program code.  Instead,
        // it should be reported as an ErrorEvent.
        v8::TryCatch block(isolate());
        wrappedFunction = v8::ScriptCompiler::CompileFunctionInContext(isolate(), &source, v8Context, 1, &parameterName, 3, scopes);
        if (block.HasCaught()) {
            fireErrorEvent(v8Context, executionContext, block.Message());
            return;
        }
    }

    // Change the toString function on the wrapper function to avoid it
    // returning the source for the actual wrapper function. Instead it
    // returns source for a clean wrapper function with the event
    // argument wrapping the event source code. The reason for this is
    // that some web sites use toString on event functions and eval the
    // source returned (sometimes a RegExp is applied as well) for some
    // other use. That fails miserably if the actual wrapper source is
    // returned.
    v8::Local<v8::Function> toStringFunction = v8::Function::New(isolate(), V8LazyEventListenerToString);
    if (toStringFunction.IsEmpty())
        return;
    String toStringString = "function " + m_functionName + "(" + m_eventParameterName + ") {\n  " + m_code + "\n}";
    V8HiddenValue::setHiddenValue(scriptState, wrappedFunction, V8HiddenValue::toStringString(isolate()), v8String(isolate(), toStringString));
    if (!v8CallBoolean(wrappedFunction->Set(scriptState->context(), v8AtomicString(isolate(), "toString"), toStringFunction)))
        return;
    wrappedFunction->SetName(v8String(isolate(), m_functionName));

    // FIXME: Remove the following comment-outs.
    // See https://bugs.webkit.org/show_bug.cgi?id=85152 for more details.
    //
    // For the time being, we comment out the following code since the
    // second parsing can happen.
    // // 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();
    setListenerObject(wrappedFunction, scriptState);
}
void WebDevToolsFrontendImpl::windowObjectCleared()
{
    v8::Isolate* isolate = v8::Isolate::GetCurrent();
    Page* page = m_webViewImpl->page();
    ASSERT(page->mainFrame());
    ScriptState* scriptState = ScriptState::forMainWorld(page->deprecatedLocalMainFrame());
    ScriptState::Scope scope(scriptState);

    if (m_frontendHost)
        m_frontendHost->disconnectClient();
    m_frontendHost = InspectorFrontendHost::create(this, page);
    v8::Handle<v8::Object> global = scriptState->context()->Global();
    v8::Handle<v8::Value> frontendHostObj = toV8(m_frontendHost.get(), global, scriptState->isolate());

    global->Set(v8::String::NewFromUtf8(isolate, "InspectorFrontendHost"), frontendHostObj);
    ScriptController* scriptController = page->mainFrame() ? &page->deprecatedLocalMainFrame()->script() : 0;
    if (scriptController) {
        String installAdditionalAPI =
            "" // Wrap messages that go to embedder.
            "(function(host, methodEntries) {"
            "    host._lastCallId = 0;"
            "    host._callbacks = [];"
            "    host.embedderMessageAck = function(id, error)"
            "    {"
            "        var callback = host._callbacks[id];"
            "        delete host._callbacks[id];"
            "        if (callback)"
            "            callback(error);"
            "    };"
            "    function dispatch(methodName, argumentCount)"
            "    {"
            "        var callId = ++host._lastCallId;"
            "        var argsArray = Array.prototype.slice.call(arguments, 2);"
            "        var callback = argsArray[argsArray.length - 1];"
            "        if (typeof callback === \"function\") {"
            "            argsArray.pop();"
            "            host._callbacks[callId] = callback;"
            "        }"
            "        var message = { \"id\": callId, \"method\": methodName };"
            "        argsArray = argsArray.slice(0, argumentCount);"
            "        if (argsArray.length)"
            "            message.params = argsArray;"
            "        host.sendMessageToEmbedder(JSON.stringify(message));"
            "    };"
            "    methodEntries.forEach(function(methodEntry) { host[methodEntry[0]] = dispatch.bind(null, methodEntry[0], methodEntry[1]); });"
            "})(InspectorFrontendHost,"
            "    [['addFileSystem', 0],"
            "     ['append', 2],"
            "     ['bringToFront', 0],"
            "     ['closeWindow', 0],"
            "     ['indexPath', 2],"
            "     ['inspectElementCompleted', 0],"
            "     ['inspectedURLChanged', 1],"
            "     ['moveWindowBy', 2],"
            "     ['openInNewTab', 1],"
            "     ['openUrlOnRemoteDeviceAndInspect', 2],"
            "     ['removeFileSystem', 1],"
            "     ['requestFileSystems', 0],"
            "     ['resetZoom', 0],"
            "     ['save', 3],"
            "     ['searchInPath', 3],"
            "     ['setDeviceCountUpdatesEnabled', 1],"
            "     ['setDevicesUpdatesEnabled', 1],"
            "     ['setWhitelistedShortcuts', 1],"
            "     ['setContentsResizingStrategy', 2],"
            "     ['setInspectedPageBounds', 1],"
            "     ['setIsDocked', 1],"
            "     ['stopIndexing', 1],"
            "     ['zoomIn', 0],"
            "     ['zoomOut', 0]]);"
            ""
            "" // Support for legacy front-ends (<M34). Do not add items here.
            "InspectorFrontendHost.requestSetDockSide = function(dockSide)"
            "{"
            "    InspectorFrontendHost.setIsDocked(dockSide !== \"undocked\");"
            "};"
            "InspectorFrontendHost.supportsFileSystems = function() { return true; };"
            ""
            "" // Support for legacy front-ends (<M28). Do not add items here.
            "InspectorFrontendHost.canInspectWorkers = function() { return true; };"
            "InspectorFrontendHost.canSaveAs = function() { return true; };"
            "InspectorFrontendHost.canSave = function() { return true; };"
            "InspectorFrontendHost.loaded = function() {};"
            "InspectorFrontendHost.hiddenPanels = function() { return ""; };"
            "InspectorFrontendHost.localizedStringsURL = function() { return ""; };"
            "InspectorFrontendHost.close = function(url) { };";
        scriptController->executeScriptInMainWorld(installAdditionalAPI, ScriptController::ExecuteScriptWhenScriptsDisabled);
    }
}