Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(108)

Unified Diff: third_party/WebKit/Source/bindings/core/v8/PrivateScriptRunner.cpp

Issue 2571063002: Remove Blink-in-JS (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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

Powered by Google App Engine
This is Rietveld 408576698