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

Unified Diff: Source/bindings/v8/ScriptController.cpp

Issue 13575004: Apply script preprocessor to Web page scripts only. (Closed) Base URL: https://chromium.googlesource.com/external/WebKit_trimmed.git@master
Patch Set: rebase Created 7 years, 5 months 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: Source/bindings/v8/ScriptController.cpp
diff --git a/Source/bindings/v8/ScriptController.cpp b/Source/bindings/v8/ScriptController.cpp
index d0085c4491eaa9b9bec14c81ea736845f5adc1c2..a3fdcde2a26bb269fb951da0c551d77bbf29ff07 100644
--- a/Source/bindings/v8/ScriptController.cpp
+++ b/Source/bindings/v8/ScriptController.cpp
@@ -668,7 +668,7 @@ bool ScriptController::executeScriptIfJavaScriptURL(const KURL& url)
if (!locationChangeBefore && m_frame->navigationScheduler()->locationChangePending())
return true;
-
+
// DocumentWriter::replaceDocument can cause the DocumentLoader to get deref'ed and possible destroyed,
// so protect it with a RefPtr.
if (RefPtr<DocumentLoader> loader = m_frame->document()->loader())
@@ -687,9 +687,12 @@ ScriptValue ScriptController::executeScriptInMainWorld(const ScriptSourceCode& s
if (v8Context.IsEmpty())
return ScriptValue();
+ String processedString = m_frame->script()->preprocess(sourceCode.source(), sourceURL);
+ ScriptSourceCode processedSourceCode(processedString, sourceCode.url(), sourceCode.startPosition());
+
v8::Context::Scope scope(v8Context);
RefPtr<Frame> protect(m_frame);
- v8::Local<v8::Value> object = compileAndRunScript(sourceCode);
+ v8::Local<v8::Value> object = compileAndRunScript(processedSourceCode);
m_sourceURL = savedSourceURL;
@@ -733,4 +736,117 @@ void ScriptController::executeScriptInIsolatedWorld(int worldID, const Vector<Sc
}
}
+class ScriptController::ScriptPreprocessor {
+ WTF_MAKE_NONCOPYABLE(ScriptPreprocessor);
+public:
+ ScriptPreprocessor(const String& preprocessorScript, ScriptController* controller)
+ : m_controller(controller), m_isolate(controller->m_isolate)
abarth-chromium 2013/07/08 23:57:08 The correct style is to use separate lines for eac
johnjbarton 2013/07/09 22:44:54 Done.
+ {
+ v8::HandleScope scope(m_isolate);
abarth-chromium 2013/07/08 23:57:08 Is it safe to hold the isolate across call stacks?
johnjbarton 2013/07/09 22:44:54 ScriptController holds an isolate so I guess it is
+
+ v8::TryCatch tryCatch;
+ tryCatch.SetVerbose(true);
+ ScriptSourceCode preprocessor(preprocessorScript);
+ Vector<ScriptSourceCode> sources;
+ sources.append(preprocessor);
+ Vector<ScriptValue> scriptResults;
+ controller->executeScriptInIsolatedWorld(ScriptPreprocessorIsolatedWorldId, sources, 0, &scriptResults);
+
+ ScriptValue preprocessorFunction = scriptResults[0];
abarth-chromium 2013/07/08 23:57:08 What if scriptResults is empty ?
johnjbarton 2013/07/09 22:44:54 executeScriptInIsolatedWorld maps sources onto scr
+ if (!preprocessorFunction.isFunction()) {
+ v8::Context::Scope contextScope(m_controller->mainWorldContext());
+ String notAFunction = String("The preprocessor must compile to a function.");
+ String preprocessorName = String("reloadPreprocessorOptionSource.js");
+ getScriptExecutionContext()->reportException(notAFunction, 1, preprocessorName, RefPtr<ScriptCallStack>());
+ return;
abarth-chromium 2013/07/08 23:57:08 I don't understand what you're trying to do there.
johnjbarton 2013/07/09 22:44:54 Done.
+ }
+
+ m_preprocessorFunction.set(m_isolate, v8::Handle<v8::Function>::Cast(preprocessorFunction.v8Value()));
+ }
+
+ String preprocessSourceCode(const String& sourceCode, const String& sourceName)
+ {
+ v8::HandleScope handleScope(m_isolate);
+ if (m_preprocessorFunction.isEmpty())
+ return sourceCode;
abarth-chromium 2013/07/08 23:57:08 You can do this before creating the handleScope
johnjbarton 2013/07/09 22:44:54 Done, pls recheck the new location.
+
+ RefPtr<DOMWrapperWorld> world = DOMWrapperWorld::ensureIsolatedWorld(ScriptPreprocessorIsolatedWorldId, 0);
+ V8WindowShell* isolatedWorldShell = m_controller->windowShell(world.get());
+
+ if (!isolatedWorldShell->isContextInitialized())
+ return sourceCode;
abarth-chromium 2013/07/08 23:57:08 When does this happy? How can m_preprocessorFunct
johnjbarton 2013/07/09 22:44:54 Done.
+
+ v8::Local<v8::Context> context = isolatedWorldShell->context();
+ v8::Context::Scope contextScope(context);
+ v8::Handle<v8::String> sourceCodeString = v8String(sourceCode, m_isolate);
+ v8::Handle<v8::String> sourceNameString = v8String(sourceName, m_isolate);
+ v8::Handle<v8::Value> argv[] = { sourceCodeString, sourceNameString };
+
+ v8::TryCatch tryCatch;
+ tryCatch.SetVerbose(true);
+ m_isPreprocessing = true;
abarth-chromium 2013/07/08 23:57:08 Please use TemporaryChange to make sure we handle
johnjbarton 2013/07/09 22:44:54 Done.
+ v8::Handle<v8::Value> resultValue =
+ V8ScriptRunner::callAsFunction(m_preprocessorFunction.newLocal(m_isolate), context->Global(), 2, argv);
abarth-chromium 2013/07/08 23:57:08 2 -> WTF_ARRAY_LENGTH
johnjbarton 2013/07/09 22:44:54 Done.
+ m_isPreprocessing = false;
+
+ if (!resultValue.IsEmpty() && resultValue->IsString())
+ return toWebCoreStringWithNullCheck(resultValue);
+
+ return sourceCode;
+ }
+
+ bool hasPreprocessorFunction()
+ {
+ return !m_preprocessorFunction.isEmpty();
+ }
+
+ bool isPreprocessing()
+ {
+ return m_isPreprocessing;
+ }
+
+ ~ScriptPreprocessor()
+ {
+ }
abarth-chromium 2013/07/08 23:57:08 The compiler will generate this function for you.
+
+private:
+ String m_preprocessorBody;
+ ScopedPersistent<v8::Function> m_preprocessorFunction;
abarth-chromium 2013/07/08 23:57:08 Does this leak memory?
johnjbarton 2013/07/09 22:44:54 Destructing the ScriptPreprocessor destructs the m
+ ScriptController* m_controller;
+ v8::Isolate* m_isolate;
+ bool m_isPreprocessing;
+};
+
+bool ScriptController::hasScriptPreprocessor()
+{
+ return m_scriptPreprocessor && m_scriptPreprocessor->hasPreprocessorFunction();
+}
+
+bool ScriptController::isScriptPreprocessing()
+{
+ return hasScriptPreprocessor() && m_scriptPreprocessor->isPreprocessing();
+}
+
+void ScriptController::setScriptPreprocessor(const String& preprocessorBody)
+{
+ // The preprocessor will be created the first time it is needed.
+ m_scriptPreprocessor.clear();
+ m_preprocessorSource = preprocessorBody;
abarth-chromium 2013/07/08 23:57:08 Why not store m_preprocessorSource in m_scriptPrep
johnjbarton 2013/07/09 22:44:54 At this point in the page setup the debugger has n
+}
+
+String ScriptController::preprocess(const String& scriptSource, const String& scriptName)
+{
+ if (m_preprocessorSource.isEmpty())
+ return scriptSource;
+
+ if (!m_scriptPreprocessor)
+ m_scriptPreprocessor = adoptPtr(new ScriptPreprocessor(m_preprocessorSource, this));
+
+ if (!m_scriptPreprocessor->hasPreprocessorFunction())
+ return scriptSource;
+
+ return m_scriptPreprocessor->preprocessSourceCode(scriptSource, scriptName);
abarth-chromium 2013/07/08 23:57:08 Don't we need to clear the m_scriptPreprocessor on
johnjbarton 2013/07/09 22:44:54 We clear the m_scriptPreprocessor whenever PageDeb
+}
+
+
} // namespace WebCore

Powered by Google App Engine
This is Rietveld 408576698