Chromium Code Reviews| 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 |