| Index: third_party/WebKit/Source/bindings/core/v8/PrivateScriptRunner.cpp
|
| diff --git a/third_party/WebKit/Source/bindings/core/v8/PrivateScriptRunner.cpp b/third_party/WebKit/Source/bindings/core/v8/PrivateScriptRunner.cpp
|
| deleted file mode 100644
|
| index 5b75d8d6f9c8aabf5eb58789ffaea67ce1c03087..0000000000000000000000000000000000000000
|
| --- a/third_party/WebKit/Source/bindings/core/v8/PrivateScriptRunner.cpp
|
| +++ /dev/null
|
| @@ -1,490 +0,0 @@
|
| -// Copyright 2014 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "bindings/core/v8/PrivateScriptRunner.h"
|
| -
|
| -#include "bindings/core/v8/DOMWrapperWorld.h"
|
| -#include "bindings/core/v8/ExceptionState.h"
|
| -#include "bindings/core/v8/V8Binding.h"
|
| -#include "bindings/core/v8/V8PerContextData.h"
|
| -#include "bindings/core/v8/V8PrivateProperty.h"
|
| -#include "bindings/core/v8/V8ScriptRunner.h"
|
| -#include "core/PrivateScriptSources.h"
|
| -#ifndef NDEBUG
|
| -#include "core/PrivateScriptSourcesForTesting.h"
|
| -#endif
|
| -#include "core/dom/Document.h"
|
| -#include "core/dom/ExceptionCode.h"
|
| -#include "platform/PlatformResourceLoader.h"
|
| -
|
| -namespace blink {
|
| -
|
| -static void dumpV8Message(v8::Local<v8::Context> context,
|
| - v8::Local<v8::Message> message) {
|
| - if (message.IsEmpty())
|
| - return;
|
| -
|
| - // FIXME: GetScriptOrigin() and GetLineNumber() return empty handles
|
| - // when they are called at the first time if V8 has a pending exception.
|
| - // So we need to call twice to get a correct ScriptOrigin and line number.
|
| - // This is a bug of V8.
|
| - message->GetScriptOrigin();
|
| - v8::Maybe<int> unused = message->GetLineNumber(context);
|
| - ALLOW_UNUSED_LOCAL(unused);
|
| -
|
| - v8::Local<v8::Value> resourceName = message->GetScriptOrigin().ResourceName();
|
| - String fileName = "Unknown JavaScript file";
|
| - if (!resourceName.IsEmpty() && resourceName->IsString())
|
| - fileName = toCoreString(v8::Local<v8::String>::Cast(resourceName));
|
| - int lineNumber = 0;
|
| - v8Call(message->GetLineNumber(context), lineNumber);
|
| - v8::Local<v8::String> errorMessage = message->Get();
|
| - fprintf(stderr, "%s (line %d): %s\n", fileName.utf8().data(), lineNumber,
|
| - toCoreString(errorMessage).utf8().data());
|
| -}
|
| -
|
| -static void importFunction(const v8::FunctionCallbackInfo<v8::Value>& args);
|
| -
|
| -static v8::Local<v8::Value> compileAndRunPrivateScript(ScriptState* scriptState,
|
| - String scriptClassName,
|
| - const char* source,
|
| - size_t size) {
|
| - v8::Isolate* isolate = scriptState->isolate();
|
| - v8::TryCatch block(isolate);
|
| - String sourceString(source, size);
|
| - String fileName = scriptClassName + ".js";
|
| -
|
| - v8::Local<v8::Context> context = scriptState->context();
|
| - v8::Local<v8::Object> global = context->Global();
|
| - v8::Local<v8::String> key = v8String(isolate, "privateScriptController");
|
| -
|
| - if (global->HasOwnProperty(context, key).ToChecked()) {
|
| - v8::Local<v8::Value> privateScriptController =
|
| - global->Get(context, key).ToLocalChecked();
|
| - CHECK(privateScriptController->IsObject());
|
| - v8::Local<v8::Object> privateScriptControllerObject =
|
| - privateScriptController.As<v8::Object>();
|
| - v8::Local<v8::Value> importFunctionValue =
|
| - privateScriptControllerObject->Get(context, v8String(isolate, "import"))
|
| - .ToLocalChecked();
|
| - if (importFunctionValue->IsUndefined()) {
|
| - v8::Local<v8::Function> function;
|
| - // This is a memory leak, FunctionTemplates are eternal.
|
| - if (!v8::FunctionTemplate::New(isolate, importFunction)
|
| - ->GetFunction(context)
|
| - .ToLocal(&function) ||
|
| - !v8CallBoolean(privateScriptControllerObject->Set(
|
| - context, v8String(isolate, "import"), function))) {
|
| - dumpV8Message(context, block.Message());
|
| - LOG(FATAL)
|
| - << "Private script error: Setting import function failed. (Class "
|
| - "name = "
|
| - << scriptClassName.utf8().data() << ")";
|
| - }
|
| - }
|
| - }
|
| -
|
| - v8::Local<v8::Script> script;
|
| - if (!v8Call(V8ScriptRunner::compileScript(
|
| - v8String(isolate, sourceString), fileName, String(),
|
| - TextPosition::minimumPosition(), isolate, nullptr, nullptr,
|
| - nullptr, NotSharableCrossOrigin),
|
| - script, block)) {
|
| - dumpV8Message(context, block.Message());
|
| - LOG(FATAL) << "Private script error: Compile failed. (Class name = "
|
| - << scriptClassName.utf8().data() << ")";
|
| - }
|
| -
|
| - v8::Local<v8::Value> result;
|
| - if (!v8Call(V8ScriptRunner::runCompiledInternalScript(isolate, script),
|
| - result, block)) {
|
| - dumpV8Message(context, block.Message());
|
| - LOG(FATAL) << "Private script error: installClass() failed. (Class name = "
|
| - << scriptClassName.utf8().data() << ")";
|
| - }
|
| - return result;
|
| -}
|
| -
|
| -// Private scripts can use privateScriptController.import(bundledResource,
|
| -// compileAndRunScript) to import dependent resources.
|
| -// |bundledResource| is a string resource name.
|
| -// |compileAndRunScript| optional boolean representing if the javascript should
|
| -// be executed. Default: true.
|
| -void importFunction(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
| - v8::Isolate* isolate = args.GetIsolate();
|
| - RELEASE_ASSERT(isolate && (args.Length() >= 1));
|
| - String resourceFileName = toCoreString(
|
| - args[0]->ToString(isolate->GetCurrentContext()).ToLocalChecked());
|
| - String resourceData =
|
| - loadResourceAsASCIIString(resourceFileName.utf8().data());
|
| - RELEASE_ASSERT(resourceData.length());
|
| - bool compileAndRunScript = true;
|
| - if (args.Length() == 2) {
|
| - RELEASE_ASSERT(args[1]->IsBoolean());
|
| - compileAndRunScript = args[1].As<v8::Boolean>()->Value();
|
| - }
|
| -
|
| - if (resourceFileName.endsWith(".js") && compileAndRunScript)
|
| - compileAndRunPrivateScript(
|
| - ScriptState::current(isolate), resourceFileName.replace(".js", ""),
|
| - resourceData.utf8().data(), resourceData.length());
|
| - args.GetReturnValue().Set(v8String(isolate, resourceData));
|
| -}
|
| -
|
| -// FIXME: If we have X.js, XPartial-1.js and XPartial-2.js, currently all of the
|
| -// JS files are compiled when any of the JS files is requested. Ideally we
|
| -// should avoid compiling unrelated JS files. For example, if a method in
|
| -// XPartial-1.js is requested, we just need to compile X.js and XPartial-1.js,
|
| -// and don't need to compile XPartial-2.js.
|
| -static void installPrivateScript(v8::Isolate* isolate, String className) {
|
| - ScriptState* scriptState = ScriptState::current(isolate);
|
| - int compiledScriptCount = 0;
|
| -// |kPrivateScriptSourcesForTesting| is defined in V8PrivateScriptSources.h,
|
| -// which is auto-generated by make_private_script_source.py.
|
| -#ifndef NDEBUG
|
| - for (size_t index = 0;
|
| - index < WTF_ARRAY_LENGTH(kPrivateScriptSourcesForTesting); index++) {
|
| - if (className == kPrivateScriptSourcesForTesting[index].className) {
|
| - compileAndRunPrivateScript(
|
| - scriptState, kPrivateScriptSourcesForTesting[index].scriptClassName,
|
| - kPrivateScriptSourcesForTesting[index].source,
|
| - kPrivateScriptSourcesForTesting[index].size);
|
| - compiledScriptCount++;
|
| - }
|
| - }
|
| -#endif
|
| -
|
| - // |kPrivateScriptSources| is defined in V8PrivateScriptSources.h, which is
|
| - // auto-generated by make_private_script_source.py.
|
| - for (size_t index = 0; index < WTF_ARRAY_LENGTH(kPrivateScriptSources);
|
| - index++) {
|
| - if (className == kPrivateScriptSources[index].className) {
|
| - String resourceData =
|
| - loadResourceAsASCIIString(kPrivateScriptSources[index].resourceFile);
|
| - compileAndRunPrivateScript(
|
| - scriptState, kPrivateScriptSources[index].scriptClassName,
|
| - resourceData.utf8().data(), resourceData.length());
|
| - compiledScriptCount++;
|
| - }
|
| - }
|
| -
|
| - if (!compiledScriptCount) {
|
| - LOG(FATAL)
|
| - << "Private script error: Target source code was not found. (Class "
|
| - "name = "
|
| - << className.utf8().data() << ")";
|
| - }
|
| -}
|
| -
|
| -static v8::Local<v8::Value> installPrivateScriptRunner(v8::Isolate* isolate) {
|
| - const String className = "PrivateScriptRunner";
|
| - size_t index;
|
| - // |kPrivateScriptSources| is defined in V8PrivateScriptSources.h, which is
|
| - // auto-generated by make_private_script_source.py.
|
| - for (index = 0; index < WTF_ARRAY_LENGTH(kPrivateScriptSources); index++) {
|
| - if (className == kPrivateScriptSources[index].className)
|
| - break;
|
| - }
|
| - if (index == WTF_ARRAY_LENGTH(kPrivateScriptSources)) {
|
| - LOG(FATAL)
|
| - << "Private script error: Target source code was not found. (Class "
|
| - "name = "
|
| - << className.utf8().data() << ")";
|
| - }
|
| - String resourceData =
|
| - loadResourceAsASCIIString(kPrivateScriptSources[index].resourceFile);
|
| - return compileAndRunPrivateScript(ScriptState::current(isolate), className,
|
| - resourceData.utf8().data(),
|
| - resourceData.length());
|
| -}
|
| -
|
| -static v8::Local<v8::Object> classObjectOfPrivateScript(
|
| - ScriptState* scriptState,
|
| - String className) {
|
| - ASSERT(scriptState->perContextData());
|
| - ASSERT(scriptState->getExecutionContext());
|
| - v8::Isolate* isolate = scriptState->isolate();
|
| - v8::Local<v8::Value> compiledClass =
|
| - scriptState->perContextData()->compiledPrivateScript(className);
|
| - if (compiledClass.IsEmpty()) {
|
| - v8::Local<v8::Value> installedClasses =
|
| - scriptState->perContextData()->compiledPrivateScript(
|
| - "PrivateScriptRunner");
|
| - if (installedClasses.IsEmpty()) {
|
| - installedClasses = installPrivateScriptRunner(isolate);
|
| - scriptState->perContextData()->setCompiledPrivateScript(
|
| - "PrivateScriptRunner", installedClasses);
|
| - }
|
| - RELEASE_ASSERT(!installedClasses.IsEmpty());
|
| - RELEASE_ASSERT(installedClasses->IsObject());
|
| -
|
| - installPrivateScript(isolate, className);
|
| - compiledClass =
|
| - v8::Local<v8::Object>::Cast(installedClasses)
|
| - ->Get(scriptState->context(), v8String(isolate, className))
|
| - .ToLocalChecked();
|
| - RELEASE_ASSERT(compiledClass->IsObject());
|
| - scriptState->perContextData()->setCompiledPrivateScript(className,
|
| - compiledClass);
|
| - }
|
| - return v8::Local<v8::Object>::Cast(compiledClass);
|
| -}
|
| -
|
| -static void initializeHolderIfNeeded(ScriptState* scriptState,
|
| - v8::Local<v8::Object> classObject,
|
| - v8::Local<v8::Value> holder) {
|
| - RELEASE_ASSERT(!holder.IsEmpty());
|
| - RELEASE_ASSERT(holder->IsObject());
|
| - v8::Local<v8::Object> holderObject = v8::Local<v8::Object>::Cast(holder);
|
| - v8::Isolate* isolate = scriptState->isolate();
|
| - v8::Local<v8::Context> context = scriptState->context();
|
| - auto privateIsInitialized =
|
| - V8PrivateProperty::getPrivateScriptRunnerIsInitialized(isolate);
|
| - if (privateIsInitialized.hasValue(context, holderObject))
|
| - return; // Already initialized.
|
| -
|
| - v8::TryCatch block(isolate);
|
| - v8::Local<v8::Value> initializeFunction;
|
| - if (classObject->Get(scriptState->context(), v8String(isolate, "initialize"))
|
| - .ToLocal(&initializeFunction) &&
|
| - initializeFunction->IsFunction()) {
|
| - v8::TryCatch block(isolate);
|
| - v8::Local<v8::Value> result;
|
| - if (!V8ScriptRunner::callInternalFunction(
|
| - v8::Local<v8::Function>::Cast(initializeFunction), holder, 0, 0,
|
| - isolate)
|
| - .ToLocal(&result)) {
|
| - dumpV8Message(context, block.Message());
|
| - LOG(FATAL)
|
| - << "Private script error: Object constructor threw an exception.";
|
| - }
|
| - }
|
| -
|
| - // Inject the prototype object of the private script into the prototype chain
|
| - // of the holder object. This is necessary to let the holder object use
|
| - // properties defined on the prototype object of the private script. (e.g., if
|
| - // the prototype object has |foo|, the holder object should be able to use it
|
| - // with |this.foo|.)
|
| - if (classObject->GetPrototype() != holderObject->GetPrototype()) {
|
| - if (!v8CallBoolean(
|
| - classObject->SetPrototype(context, holderObject->GetPrototype()))) {
|
| - dumpV8Message(context, block.Message());
|
| - LOG(FATAL) << "Private script error: SetPrototype failed.";
|
| - }
|
| - }
|
| - if (!v8CallBoolean(holderObject->SetPrototype(context, classObject))) {
|
| - dumpV8Message(context, block.Message());
|
| - LOG(FATAL) << "Private script error: SetPrototype failed.";
|
| - }
|
| -
|
| - privateIsInitialized.set(context, holderObject, v8Boolean(true, isolate));
|
| -}
|
| -
|
| -v8::Local<v8::Value> PrivateScriptRunner::installClassIfNeeded(
|
| - Document* document,
|
| - String className) {
|
| - if (!document->contextDocument()->frame())
|
| - return v8::Local<v8::Value>();
|
| -
|
| - v8::HandleScope handleScope(toIsolate(document));
|
| - ScriptState* scriptState =
|
| - ScriptState::forWorld(document->contextDocument()->frame(),
|
| - DOMWrapperWorld::privateScriptIsolatedWorld());
|
| - if (!scriptState)
|
| - return v8::Local<v8::Value>();
|
| -
|
| - ScriptState::Scope scope(scriptState);
|
| - return classObjectOfPrivateScript(scriptState, className);
|
| -}
|
| -
|
| -namespace {
|
| -
|
| -void rethrowExceptionInPrivateScript(v8::Isolate* isolate,
|
| - v8::TryCatch& block,
|
| - ScriptState* scriptStateInUserScript,
|
| - ExceptionState::ContextType errorContext,
|
| - const char* propertyName,
|
| - const char* interfaceName) {
|
| - v8::Local<v8::Context> context = scriptStateInUserScript->context();
|
| - v8::Local<v8::Value> exception = block.Exception();
|
| - RELEASE_ASSERT(!exception.IsEmpty() && exception->IsObject());
|
| -
|
| - v8::Local<v8::Object> exceptionObject =
|
| - v8::Local<v8::Object>::Cast(exception);
|
| - v8::Local<v8::Value> name =
|
| - exceptionObject->Get(context, v8String(isolate, "name")).ToLocalChecked();
|
| - RELEASE_ASSERT(name->IsString());
|
| -
|
| - v8::Local<v8::Message> tryCatchMessage = block.Message();
|
| - v8::Local<v8::Value> message;
|
| - String messageString;
|
| - if (exceptionObject->Get(context, v8String(isolate, "message"))
|
| - .ToLocal(&message) &&
|
| - message->IsString())
|
| - messageString = toCoreString(v8::Local<v8::String>::Cast(message));
|
| -
|
| - String exceptionName = toCoreString(v8::Local<v8::String>::Cast(name));
|
| - if (exceptionName == "PrivateScriptException") {
|
| - v8::Local<v8::Value> code =
|
| - exceptionObject->Get(context, v8String(isolate, "code"))
|
| - .ToLocalChecked();
|
| - RELEASE_ASSERT(code->IsInt32());
|
| - int exceptionCode = code.As<v8::Int32>()->Value();
|
| - ScriptState::Scope scope(scriptStateInUserScript);
|
| - ExceptionState exceptionState(scriptStateInUserScript->isolate(),
|
| - errorContext, interfaceName, propertyName);
|
| - exceptionState.throwDOMException(exceptionCode, messageString);
|
| - return;
|
| - }
|
| -
|
| - // Standard JS errors thrown by a private script are treated as real errors
|
| - // of the private script and crash the renderer, except for a stack overflow
|
| - // error. A stack overflow error can happen in a valid private script
|
| - // if user's script can create a recursion that involves the private script.
|
| - if (exceptionName == "RangeError" &&
|
| - messageString.contains("Maximum call stack size exceeded")) {
|
| - ScriptState::Scope scope(scriptStateInUserScript);
|
| - ExceptionState exceptionState(scriptStateInUserScript->isolate(),
|
| - errorContext, interfaceName, propertyName);
|
| - exceptionState.throwDOMException(V8RangeError, messageString);
|
| - return;
|
| - }
|
| -
|
| - dumpV8Message(context, tryCatchMessage);
|
| - LOG(FATAL) << "Private script error: " << exceptionName.utf8().data()
|
| - << " was thrown.";
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -v8::Local<v8::Value> PrivateScriptRunner::runDOMAttributeGetter(
|
| - ScriptState* scriptState,
|
| - ScriptState* scriptStateInUserScript,
|
| - const char* className,
|
| - const char* attributeName,
|
| - v8::Local<v8::Value> holder) {
|
| - v8::Isolate* isolate = scriptState->isolate();
|
| - v8::Local<v8::Object> classObject =
|
| - classObjectOfPrivateScript(scriptState, className);
|
| - v8::Local<v8::Value> descriptor;
|
| - if (!classObject
|
| - ->GetOwnPropertyDescriptor(scriptState->context(),
|
| - v8String(isolate, attributeName))
|
| - .ToLocal(&descriptor) ||
|
| - !descriptor->IsObject()) {
|
| - LOG(FATAL)
|
| - << "Private script error: Target DOM attribute getter was not found. "
|
| - "(Class name = "
|
| - << className << ", Attribute name = " << attributeName << ")";
|
| - }
|
| - v8::Local<v8::Value> getter;
|
| - if (!v8::Local<v8::Object>::Cast(descriptor)
|
| - ->Get(scriptState->context(), v8String(isolate, "get"))
|
| - .ToLocal(&getter) ||
|
| - !getter->IsFunction()) {
|
| - LOG(FATAL)
|
| - << "Private script error: Target DOM attribute getter was not found. "
|
| - "(Class name = "
|
| - << className << ", Attribute name = " << attributeName << ")";
|
| - }
|
| - initializeHolderIfNeeded(scriptState, classObject, holder);
|
| - v8::TryCatch block(isolate);
|
| - v8::Local<v8::Value> result;
|
| - if (!V8ScriptRunner::callInternalFunction(
|
| - v8::Local<v8::Function>::Cast(getter), holder, 0, 0, isolate)
|
| - .ToLocal(&result)) {
|
| - rethrowExceptionInPrivateScript(isolate, block, scriptStateInUserScript,
|
| - ExceptionState::GetterContext,
|
| - attributeName, className);
|
| - block.ReThrow();
|
| - return v8::Local<v8::Value>();
|
| - }
|
| - return result;
|
| -}
|
| -
|
| -bool PrivateScriptRunner::runDOMAttributeSetter(
|
| - ScriptState* scriptState,
|
| - ScriptState* scriptStateInUserScript,
|
| - const char* className,
|
| - const char* attributeName,
|
| - v8::Local<v8::Value> holder,
|
| - v8::Local<v8::Value> v8Value) {
|
| - v8::Isolate* isolate = scriptState->isolate();
|
| - v8::Local<v8::Object> classObject =
|
| - classObjectOfPrivateScript(scriptState, className);
|
| - v8::Local<v8::Value> descriptor;
|
| - if (!classObject
|
| - ->GetOwnPropertyDescriptor(scriptState->context(),
|
| - v8String(isolate, attributeName))
|
| - .ToLocal(&descriptor) ||
|
| - !descriptor->IsObject()) {
|
| - LOG(FATAL)
|
| - << "Private script error: Target DOM attribute setter was not found. "
|
| - "(Class name = "
|
| - << className << ", Attribute name = " << attributeName << ")";
|
| - }
|
| - v8::Local<v8::Value> setter;
|
| - if (!v8::Local<v8::Object>::Cast(descriptor)
|
| - ->Get(scriptState->context(), v8String(isolate, "set"))
|
| - .ToLocal(&setter) ||
|
| - !setter->IsFunction()) {
|
| - LOG(FATAL) << "Private script error: Target DOM attribute setter was not "
|
| - "found. (Class name = "
|
| - << className << ", Attribute name = " << attributeName << ")";
|
| - }
|
| - initializeHolderIfNeeded(scriptState, classObject, holder);
|
| - v8::Local<v8::Value> argv[] = {v8Value};
|
| - v8::TryCatch block(isolate);
|
| - v8::Local<v8::Value> result;
|
| - if (!V8ScriptRunner::callInternalFunction(
|
| - v8::Local<v8::Function>::Cast(setter), holder,
|
| - WTF_ARRAY_LENGTH(argv), argv, isolate)
|
| - .ToLocal(&result)) {
|
| - rethrowExceptionInPrivateScript(isolate, block, scriptStateInUserScript,
|
| - ExceptionState::SetterContext,
|
| - attributeName, className);
|
| - block.ReThrow();
|
| - return false;
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -v8::Local<v8::Value> PrivateScriptRunner::runDOMMethod(
|
| - ScriptState* scriptState,
|
| - ScriptState* scriptStateInUserScript,
|
| - const char* className,
|
| - const char* methodName,
|
| - v8::Local<v8::Value> holder,
|
| - int argc,
|
| - v8::Local<v8::Value> argv[]) {
|
| - v8::Local<v8::Object> classObject =
|
| - classObjectOfPrivateScript(scriptState, className);
|
| - v8::Local<v8::Value> method;
|
| - if (!classObject
|
| - ->Get(scriptState->context(),
|
| - v8String(scriptState->isolate(), methodName))
|
| - .ToLocal(&method) ||
|
| - !method->IsFunction()) {
|
| - LOG(FATAL)
|
| - << "Private script error: Target DOM method was not found. (Class "
|
| - "name = "
|
| - << className << ", Method name = " << methodName << ")";
|
| - }
|
| - initializeHolderIfNeeded(scriptState, classObject, holder);
|
| - v8::TryCatch block(scriptState->isolate());
|
| - v8::Local<v8::Value> result;
|
| - if (!V8ScriptRunner::callInternalFunction(
|
| - v8::Local<v8::Function>::Cast(method), holder, argc, argv,
|
| - scriptState->isolate())
|
| - .ToLocal(&result)) {
|
| - rethrowExceptionInPrivateScript(
|
| - scriptState->isolate(), block, scriptStateInUserScript,
|
| - ExceptionState::ExecutionContext, methodName, className);
|
| - block.ReThrow();
|
| - return v8::Local<v8::Value>();
|
| - }
|
| - return result;
|
| -}
|
| -
|
| -} // namespace blink
|
|
|