Chromium Code Reviews| Index: Source/bindings/v8/ScriptController.cpp |
| diff --git a/Source/bindings/v8/ScriptController.cpp b/Source/bindings/v8/ScriptController.cpp |
| index 6be8d4ad162110a1353ea517e097938f23f494e6..505cce93c550107b648ff0e8714e2c9566f421f8 100644 |
| --- a/Source/bindings/v8/ScriptController.cpp |
| +++ b/Source/bindings/v8/ScriptController.cpp |
| @@ -655,7 +655,7 @@ bool ScriptController::executeScriptIfJavaScriptURL(const KURL& url) |
| // We're still in a frame, so there should be a DocumentLoader. |
| ASSERT(m_frame->document()->loader()); |
| - |
| + |
| // 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()) |
| @@ -674,9 +674,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; |
| @@ -720,4 +723,133 @@ void ScriptController::executeScriptInIsolatedWorld(int worldID, const Vector<Sc |
| } |
| } |
| +static const char preprocessorName[] = "$preprocessor.js"; |
| + |
| +class ScriptController::ScriptPreprocessor { |
| + WTF_MAKE_NONCOPYABLE(ScriptPreprocessor); |
| +public: |
| + ScriptPreprocessor(const String& preprocessorScript, ScriptController* controller) |
| + : m_controller(controller), m_isolate(controller->m_isolate) |
| + { |
| + v8::HandleScope scope(m_isolate); |
| + |
| + v8::Local<v8::Context> context = v8::Context::New(m_isolate); |
|
abarth-chromium
2013/06/07 20:13:45
This CL is not lgtm. Please do not create ad-hoc
|
| + if (context.IsEmpty()) |
| + return; |
| + |
| + v8::Local<v8::Value> preprocessorFunction; |
| + v8::TryCatch tryCatch; |
| + |
| + v8::Context::Scope contextScope(context); |
| + v8::Handle<v8::String> preprocessor = v8String(preprocessorScript, m_isolate); |
| + preprocessorFunction = V8ScriptRunner::compileAndRunInternalScript(preprocessor, m_isolate); |
| + |
| + if (tryCatch.HasCaught()) { |
| + reportException(tryCatch, preprocessorName); |
| + return; |
| + } |
| + |
| + if (preprocessorFunction.IsEmpty()) |
| + m_creationError = "Internal error: The preprocessor outer script gave no value without throwing."; |
| + else if (!preprocessorFunction->IsFunction()) |
| + m_creationError = "The preprocessor must compile to a function."; |
| + |
| + if (!m_creationError.isEmpty()) { |
| + reportErrorMessage(preprocessorName); |
| + return; |
| + } |
| + |
| + m_utilityContext.set(m_isolate, context); |
| + m_preprocessorFunction.set(m_isolate, v8::Handle<v8::Function>::Cast(preprocessorFunction)); |
| + } |
| + |
| + void reportException(const v8::TryCatch& tryCatch, const String& sourceName) |
| + { |
| + v8::Local<v8::Message> message = tryCatch.Message(); |
| + if (!tryCatch.Message().IsEmpty()) |
| + m_creationError = toWebCoreStringWithUndefinedOrNullCheck(message->Get()); |
| + else |
| + m_creationError = "Unknown exception."; |
| + |
| + RefPtr<ScriptCallStack> callStack = createScriptCallStack( |
| + message->GetStackTrace(), ScriptCallStack::maxCallStackSizeToCapture); |
| + |
| + reportErrorMessage(sourceName, message->GetLineNumber(), callStack); |
| + } |
| + |
| + void reportErrorMessage(const String& sourceName, int lineNumber = 1, PassRefPtr<ScriptCallStack> callStack = RefPtr<ScriptCallStack>()) |
| + { |
| + v8::Context::Scope contextScope(m_controller->mainWorldContext()); |
| + getScriptExecutionContext()->reportException(m_creationError, lineNumber, sourceName, callStack); |
| + } |
| + |
| + String preprocessSourceCode(const String& sourceCode, const String& sourceName) |
| + { |
| + v8::HandleScope handleScope(m_isolate); |
| + if (m_preprocessorFunction.isEmpty()) |
| + return sourceCode; |
| + |
| + v8::Local<v8::Context> context = v8::Local<v8::Context>::New(m_utilityContext.newLocal(m_isolate)); |
| + 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; |
| + v8::Handle<v8::Value> resultValue = |
| + V8ScriptRunner::callAsFunction(m_preprocessorFunction.newLocal(m_isolate), context->Global(), 2, argv); |
| + |
| + if (tryCatch.HasCaught()) { |
| + reportException(tryCatch, sourceName); |
| + return sourceCode; |
| + } |
| + |
| + if (resultValue->IsString()) |
| + return toWebCoreStringWithNullCheck(resultValue); |
| + |
| + return sourceCode; |
| + } |
| + |
| + bool hadCreationError() |
| + { |
| + return !m_creationError.isEmpty(); |
| + } |
| + |
| + ~ScriptPreprocessor() |
| + { |
| + } |
| + |
| +private: |
| + ScopedPersistent<v8::Context> m_utilityContext; |
| + String m_preprocessorBody; |
| + ScopedPersistent<v8::Function> m_preprocessorFunction; |
| + ScriptController* m_controller; |
| + v8::Isolate* m_isolate; |
| + String m_creationError; |
| +}; |
| + |
| +void ScriptController::setScriptPreprocessor(const String& preprocessorBody) |
| +{ |
| + // The preprocessor will be created the first time it is needed. |
| + m_scriptPreprocessor.clear(); |
| + m_preprocessorSource = preprocessorBody; |
| +} |
| + |
| +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->hadCreationError()) |
| + return scriptSource; |
| + |
| + return m_scriptPreprocessor->preprocessSourceCode(scriptSource, scriptName); |
| +} |
| + |
| + |
| } // namespace WebCore |