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..1eab79649545c655bef63679b2a8fd6cecfde372 100644 |
| --- a/Source/bindings/v8/ScriptController.cpp |
| +++ b/Source/bindings/v8/ScriptController.cpp |
| @@ -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,134 @@ void ScriptController::executeScriptInIsolatedWorld(int worldID, const Vector<Sc |
| } |
| } |
| +static const String preprocessorName = "$preprocessor.js"; |
|
abarth-chromium
2013/06/04 06:50:23
This will create a static initializer, which isn't
johnjbarton
2013/06/04 18:41:22
Done.
|
| + |
| +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/04 06:50:23
Hum... I usually push back on calls to v8::Contex
johnjbarton
2013/06/04 18:41:22
I don't know what to do here: what context shall I
|
| + if (context.IsEmpty()) |
| + return; |
| + |
| + v8::Local<v8::Value> preprocessorFunction; |
| + v8::TryCatch tryCatch; |
| + |
| + v8::Context::Scope contextScope(context); |
| + v8::Handle<v8::String> preprocessor = v8::String::New(preprocessorScript.utf8().data(), preprocessorScript.utf8().length()); |
|
abarth-chromium
2013/06/04 06:50:23
This isn't the right way to create v8 string from
johnjbarton
2013/06/04 18:41:22
Done.
|
| + 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.get()); |
|
abarth-chromium
2013/06/04 06:50:23
I think we have a new pattern for this sort of cod
johnjbarton
2013/06/04 18:41:22
I've changed this code and I will ask Marja to rev
|
| + v8::Context::Scope contextScope(context); |
| + |
| + v8::Handle<v8::String> sourceCodeString = v8::String::New(sourceCode.utf8().data(), sourceCode.utf8().length()); |
| + |
| + v8::Handle<v8::String> sourceNameString = v8::String::New(sourceName.utf8().data(), sourceName.utf8().length()); |
| + 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()) { |
| + v8::String::Utf8Value utf8Value(resultValue); |
| + return String::fromUTF8(*utf8Value, utf8Value.length()); |
|
abarth-chromium
2013/06/04 06:50:23
This isn't the way we create WTFStrings from v8::S
johnjbarton
2013/06/04 18:41:22
Done.
|
| + } |
| + 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 |