Index: Source/bindings/core/v8/PrivateScriptRunner.cpp |
diff --git a/Source/bindings/core/v8/PrivateScriptRunner.cpp b/Source/bindings/core/v8/PrivateScriptRunner.cpp |
index c78bdb8191d17161974503dc0b4498aabb0f0880..41e6ffcbc8232899c3c3c16f075b7a466834bce3 100644 |
--- a/Source/bindings/core/v8/PrivateScriptRunner.cpp |
+++ b/Source/bindings/core/v8/PrivateScriptRunner.cpp |
@@ -18,17 +18,47 @@ |
namespace blink { |
-#define LOG_ERROR_ALWAYS(...) WTFReportError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, __VA_ARGS__) |
+static void dumpV8Message(v8::Handle<v8::Message> message) |
+{ |
+ if (message.IsEmpty()) |
+ return; |
+ |
+ // FIXME: How can we get a resource name when an exception is thrown by DOM attributes/methods |
+ // implemented in private scripts? In that case, currently ResourceName() returns an empty handle. |
haraken
2014/08/13 12:37:57
Actually I couldn't figure out a way to get a reso
|
+ v8::Handle<v8::Value> resourceName = message->GetScriptOrigin().ResourceName(); |
+ String fileName = "Unknown JavaScript file"; |
+ if (!resourceName.IsEmpty() && resourceName->IsString()) |
+ fileName = toCoreString(v8::Handle<v8::String>::Cast(resourceName)); |
+ int lineNumber = message->GetLineNumber(); |
+ v8::Handle<v8::String> errorMessage = message->Get(); |
+ fprintf(stderr, "%s (line %d): %s\n", fileName.utf8().data(), lineNumber, toCoreString(errorMessage).utf8().data()); |
+} |
+ |
+static void dumpJSError(String exceptionName, v8::Handle<v8::Message> message) |
+{ |
+ // FIXME: Set a ScriptOrigin of the private script and print a more informative message. |
+#ifndef NDEBUG |
+ fprintf(stderr, "Private script throws an exception: %s\n", exceptionName.utf8().data()); |
+ dumpV8Message(message); |
+#endif |
+} |
-static v8::Handle<v8::Value> compileAndRunInternalScript(v8::Isolate* isolate, String className, const unsigned char* source, size_t size) |
+static v8::Handle<v8::Value> compileAndRunPrivateScript(v8::Isolate* isolate, String className, const unsigned char* source, size_t size) |
{ |
v8::TryCatch block; |
String sourceString(reinterpret_cast<const char*>(source), size); |
- v8::Handle<v8::Value> result = V8ScriptRunner::compileAndRunInternalScript(v8String(isolate, sourceString), isolate); |
+ String fileName = className + ".js"; |
+ v8::Handle<v8::Script> script = V8ScriptRunner::compileScript(v8String(isolate, sourceString), fileName, TextPosition::minimumPosition(), 0, isolate, NotSharableCrossOrigin, V8CacheOptionsOff); |
if (block.HasCaught()) { |
- LOG_ERROR_ALWAYS("Private script error: Compile failed. (Class name = %s)\n", className.utf8().data()); |
- if (!block.Message().IsEmpty()) |
- LOG_ERROR_ALWAYS("%s\n", toCoreString(block.Message()->Get()).utf8().data()); |
+ fprintf(stderr, "Private script error: Compile failed. (Class name = %s)\n", className.utf8().data()); |
+ dumpV8Message(block.Message()); |
+ RELEASE_ASSERT_NOT_REACHED(); |
+ } |
+ |
+ v8::Handle<v8::Value> result = V8ScriptRunner::runCompiledInternalScript(script, isolate); |
+ if (block.HasCaught()) { |
+ fprintf(stderr, "Private script error: installClass() failed. (Class name = %s)\n", className.utf8().data()); |
+ dumpV8Message(block.Message()); |
RELEASE_ASSERT_NOT_REACHED(); |
} |
return result; |
@@ -38,15 +68,15 @@ static v8::Handle<v8::Value> compileAndRunInternalScript(v8::Isolate* isolate, S |
// 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 compilePrivateScript(v8::Isolate* isolate, String className) |
+static void installPrivateScript(v8::Isolate* isolate, String dependencyClassName) |
{ |
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].dependencyClassName) { |
- compileAndRunInternalScript(isolate, className, kPrivateScriptSourcesForTesting[index].source, kPrivateScriptSourcesForTesting[index].size); |
+ if (dependencyClassName == kPrivateScriptSourcesForTesting[index].dependencyClassName) { |
+ compileAndRunPrivateScript(isolate, kPrivateScriptSourcesForTesting[index].className, kPrivateScriptSourcesForTesting[index].source, kPrivateScriptSourcesForTesting[index].size); |
compiledScriptCount++; |
} |
} |
@@ -55,19 +85,19 @@ static void compilePrivateScript(v8::Isolate* isolate, String className) |
// |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].dependencyClassName) { |
- compileAndRunInternalScript(isolate, className, kPrivateScriptSources[index].source, kPrivateScriptSources[index].size); |
+ if (dependencyClassName == kPrivateScriptSources[index].dependencyClassName) { |
+ compileAndRunPrivateScript(isolate, kPrivateScriptSourcesForTesting[index].className, kPrivateScriptSources[index].source, kPrivateScriptSources[index].size); |
Jens Widell
2014/08/13 14:09:34
Ah, shouldn't be *ForTesting here.
haraken
2014/08/13 14:10:36
Yes, fixed :)
|
compiledScriptCount++; |
} |
} |
if (!compiledScriptCount) { |
- LOG_ERROR_ALWAYS("Private script error: Target source code was not found. (Class name = %s)\n", className.utf8().data()); |
+ fprintf(stderr, "Private script error: Target source code was not found. (Class name = %s)\n", dependencyClassName.utf8().data()); |
RELEASE_ASSERT_NOT_REACHED(); |
} |
} |
-static v8::Handle<v8::Value> compilePrivateScriptRunner(v8::Isolate* isolate) |
+static v8::Handle<v8::Value> installPrivateScriptRunner(v8::Isolate* isolate) |
{ |
const String className = "PrivateScriptRunner"; |
size_t index; |
@@ -78,10 +108,10 @@ static v8::Handle<v8::Value> compilePrivateScriptRunner(v8::Isolate* isolate) |
break; |
} |
if (index == WTF_ARRAY_LENGTH(kPrivateScriptSources)) { |
- LOG_ERROR_ALWAYS("Private script error: Target source code was not found. (Class name = %s)\n", className.utf8().data()); |
+ fprintf(stderr, "Private script error: Target source code was not found. (Class name = %s)\n", className.utf8().data()); |
RELEASE_ASSERT_NOT_REACHED(); |
} |
- return compileAndRunInternalScript(isolate, className, kPrivateScriptSources[index].source, kPrivateScriptSources[index].size); |
+ return compileAndRunPrivateScript(isolate, className, kPrivateScriptSources[index].source, kPrivateScriptSources[index].size); |
} |
static v8::Handle<v8::Object> classObjectOfPrivateScript(ScriptState* scriptState, String className) |
@@ -93,13 +123,13 @@ static v8::Handle<v8::Object> classObjectOfPrivateScript(ScriptState* scriptStat |
if (compiledClass.IsEmpty()) { |
v8::Handle<v8::Value> installedClasses = scriptState->perContextData()->compiledPrivateScript("PrivateScriptRunner"); |
if (installedClasses.IsEmpty()) { |
- installedClasses = compilePrivateScriptRunner(isolate); |
+ installedClasses = installPrivateScriptRunner(isolate); |
scriptState->perContextData()->setCompiledPrivateScript("PrivateScriptRunner", installedClasses); |
} |
RELEASE_ASSERT(!installedClasses.IsEmpty()); |
RELEASE_ASSERT(installedClasses->IsObject()); |
- compilePrivateScript(isolate, className); |
+ installPrivateScript(isolate, className); |
compiledClass = v8::Handle<v8::Object>::Cast(installedClasses)->Get(v8String(isolate, className)); |
RELEASE_ASSERT(!compiledClass.IsEmpty()); |
RELEASE_ASSERT(compiledClass->IsObject()); |
@@ -122,9 +152,8 @@ static void initializeHolderIfNeeded(ScriptState* scriptState, v8::Handle<v8::Ob |
v8::TryCatch block; |
V8ScriptRunner::callFunction(v8::Handle<v8::Function>::Cast(initializeFunction), scriptState->executionContext(), holder, 0, 0, isolate); |
if (block.HasCaught()) { |
- LOG_ERROR_ALWAYS("Private script error: Object constructor threw an exception.\n"); |
- if (!block.Message().IsEmpty()) |
- LOG_ERROR_ALWAYS("%s\n", toCoreString(block.Message()->Get()).utf8().data()); |
+ fprintf(stderr, "Private script error: Object constructor threw an exception.\n"); |
+ dumpV8Message(block.Message()); |
RELEASE_ASSERT_NOT_REACHED(); |
} |
} |
@@ -163,12 +192,12 @@ v8::Handle<v8::Value> PrivateScriptRunner::runDOMAttributeGetter(ScriptState* sc |
v8::Handle<v8::Object> classObject = classObjectOfPrivateScript(scriptState, className); |
v8::Handle<v8::Value> descriptor = classObject->GetOwnPropertyDescriptor(v8String(scriptState->isolate(), attributeName)); |
if (descriptor.IsEmpty() || !descriptor->IsObject()) { |
- LOG_ERROR_ALWAYS("Private script error: Target DOM attribute getter was not found. (Class name = %s, Attribute name = %s)\n", className.utf8().data(), attributeName.utf8().data()); |
+ fprintf(stderr, "Private script error: Target DOM attribute getter was not found. (Class name = %s, Attribute name = %s)\n", className.utf8().data(), attributeName.utf8().data()); |
RELEASE_ASSERT_NOT_REACHED(); |
} |
v8::Handle<v8::Value> getter = v8::Handle<v8::Object>::Cast(descriptor)->Get(v8String(scriptState->isolate(), "get")); |
if (getter.IsEmpty() || !getter->IsFunction()) { |
- LOG_ERROR_ALWAYS("Private script error: Target DOM attribute getter was not found. (Class name = %s, Attribute name = %s)\n", className.utf8().data(), attributeName.utf8().data()); |
+ fprintf(stderr, "Private script error: Target DOM attribute getter was not found. (Class name = %s, Attribute name = %s)\n", className.utf8().data(), attributeName.utf8().data()); |
RELEASE_ASSERT_NOT_REACHED(); |
} |
initializeHolderIfNeeded(scriptState, classObject, holder); |
@@ -180,12 +209,12 @@ void PrivateScriptRunner::runDOMAttributeSetter(ScriptState* scriptState, String |
v8::Handle<v8::Object> classObject = classObjectOfPrivateScript(scriptState, className); |
v8::Handle<v8::Value> descriptor = classObject->GetOwnPropertyDescriptor(v8String(scriptState->isolate(), attributeName)); |
if (descriptor.IsEmpty() || !descriptor->IsObject()) { |
- LOG_ERROR_ALWAYS("Private script error: Target DOM attribute setter was not found. (Class name = %s, Attribute name = %s)\n", className.utf8().data(), attributeName.utf8().data()); |
+ fprintf(stderr, "Private script error: Target DOM attribute setter was not found. (Class name = %s, Attribute name = %s)\n", className.utf8().data(), attributeName.utf8().data()); |
RELEASE_ASSERT_NOT_REACHED(); |
} |
v8::Handle<v8::Value> setter = v8::Handle<v8::Object>::Cast(descriptor)->Get(v8String(scriptState->isolate(), "set")); |
if (setter.IsEmpty() || !setter->IsFunction()) { |
- LOG_ERROR_ALWAYS("Private script error: Target DOM attribute setter was not found. (Class name = %s, Attribute name = %s)\n", className.utf8().data(), attributeName.utf8().data()); |
+ fprintf(stderr, "Private script error: Target DOM attribute setter was not found. (Class name = %s, Attribute name = %s)\n", className.utf8().data(), attributeName.utf8().data()); |
RELEASE_ASSERT_NOT_REACHED(); |
} |
initializeHolderIfNeeded(scriptState, classObject, holder); |
@@ -198,23 +227,13 @@ v8::Handle<v8::Value> PrivateScriptRunner::runDOMMethod(ScriptState* scriptState |
v8::Handle<v8::Object> classObject = classObjectOfPrivateScript(scriptState, className); |
v8::Handle<v8::Value> method = classObject->Get(v8String(scriptState->isolate(), methodName)); |
if (method.IsEmpty() || !method->IsFunction()) { |
- LOG_ERROR_ALWAYS("Private script error: Target DOM method was not found. (Class name = %s, Method name = %s)\n", className.utf8().data(), methodName.utf8().data()); |
+ fprintf(stderr, "Private script error: Target DOM method was not found. (Class name = %s, Method name = %s)\n", className.utf8().data(), methodName.utf8().data()); |
RELEASE_ASSERT_NOT_REACHED(); |
} |
initializeHolderIfNeeded(scriptState, classObject, holder); |
return V8ScriptRunner::callFunction(v8::Handle<v8::Function>::Cast(method), scriptState->executionContext(), holder, argc, argv, scriptState->isolate()); |
} |
-static void dumpJSError(String exceptionName, String message) |
-{ |
- // FIXME: Set a ScriptOrigin of the private script and print a more informative message. |
-#ifndef NDEBUG |
- fprintf(stderr, "Private script throws an exception: %s\n", exceptionName.utf8().data()); |
- if (!message.isEmpty()) |
- fprintf(stderr, "%s\n", message.utf8().data()); |
-#endif |
-} |
- |
bool PrivateScriptRunner::rethrowExceptionInPrivateScript(v8::Isolate* isolate, ExceptionState& exceptionState, v8::TryCatch& block) |
{ |
v8::Handle<v8::Value> exception = block.Exception(); |
@@ -225,59 +244,49 @@ bool PrivateScriptRunner::rethrowExceptionInPrivateScript(v8::Isolate* isolate, |
v8::Handle<v8::Value> name = exceptionObject->Get(v8String(isolate, "name")); |
if (name.IsEmpty() || !name->IsString()) |
return false; |
+ |
+ v8::Handle<v8::Message> tryCatchMessage = block.Message(); |
+ v8::Handle<v8::Value> message = exceptionObject->Get(v8String(isolate, "message")); |
+ String messageString; |
+ if (!message.IsEmpty() && message->IsString()) |
+ messageString = toCoreString(v8::Handle<v8::String>::Cast(message)); |
+ |
String exceptionName = toCoreString(v8::Handle<v8::String>::Cast(name)); |
if (exceptionName == "DOMExceptionInPrivateScript") { |
- v8::Handle<v8::Value> v8Message = exceptionObject->Get(v8String(isolate, "message")); |
- RELEASE_ASSERT(!v8Message.IsEmpty() && v8Message->IsString()); |
v8::Handle<v8::Value> code = exceptionObject->Get(v8String(isolate, "code")); |
RELEASE_ASSERT(!code.IsEmpty() && code->IsInt32()); |
- exceptionState.throwDOMException(toInt32(code), toCoreString(v8::Handle<v8::String>::Cast(v8Message))); |
+ exceptionState.throwDOMException(toInt32(code), messageString); |
exceptionState.throwIfNeeded(); |
return true; |
} |
if (exceptionName == "Error") { |
- v8::Handle<v8::Value> v8Message = exceptionObject->Get(v8String(isolate, "message")); |
- RELEASE_ASSERT(!v8Message.IsEmpty() && v8Message->IsString()); |
- String message = toCoreString(v8::Handle<v8::String>::Cast(v8Message)); |
- exceptionState.throwDOMException(V8GeneralError, message); |
+ exceptionState.throwDOMException(V8GeneralError, messageString); |
exceptionState.throwIfNeeded(); |
- dumpJSError(exceptionName, message); |
+ dumpJSError(exceptionName, tryCatchMessage); |
return true; |
} |
if (exceptionName == "TypeError") { |
- v8::Handle<v8::Value> v8Message = exceptionObject->Get(v8String(isolate, "message")); |
- RELEASE_ASSERT(!v8Message.IsEmpty() && v8Message->IsString()); |
- String message = toCoreString(v8::Handle<v8::String>::Cast(v8Message)); |
- exceptionState.throwDOMException(V8TypeError, message); |
+ exceptionState.throwDOMException(V8TypeError, messageString); |
exceptionState.throwIfNeeded(); |
- dumpJSError(exceptionName, message); |
+ dumpJSError(exceptionName, tryCatchMessage); |
return true; |
} |
if (exceptionName == "RangeError") { |
- v8::Handle<v8::Value> v8Message = exceptionObject->Get(v8String(isolate, "message")); |
- RELEASE_ASSERT(!v8Message.IsEmpty() && v8Message->IsString()); |
- String message = toCoreString(v8::Handle<v8::String>::Cast(v8Message)); |
- exceptionState.throwDOMException(V8RangeError, message); |
+ exceptionState.throwDOMException(V8RangeError, messageString); |
exceptionState.throwIfNeeded(); |
- dumpJSError(exceptionName, message); |
+ dumpJSError(exceptionName, tryCatchMessage); |
return true; |
} |
if (exceptionName == "SyntaxError") { |
- v8::Handle<v8::Value> v8Message = exceptionObject->Get(v8String(isolate, "message")); |
- RELEASE_ASSERT(!v8Message.IsEmpty() && v8Message->IsString()); |
- String message = toCoreString(v8::Handle<v8::String>::Cast(v8Message)); |
- exceptionState.throwDOMException(V8SyntaxError, message); |
+ exceptionState.throwDOMException(V8SyntaxError, messageString); |
exceptionState.throwIfNeeded(); |
- dumpJSError(exceptionName, message); |
+ dumpJSError(exceptionName, tryCatchMessage); |
return true; |
} |
if (exceptionName == "ReferenceError") { |
- v8::Handle<v8::Value> v8Message = exceptionObject->Get(v8String(isolate, "message")); |
- RELEASE_ASSERT(!v8Message.IsEmpty() && v8Message->IsString()); |
- String message = toCoreString(v8::Handle<v8::String>::Cast(v8Message)); |
- exceptionState.throwDOMException(V8ReferenceError, message); |
+ exceptionState.throwDOMException(V8ReferenceError, messageString); |
exceptionState.throwIfNeeded(); |
- dumpJSError(exceptionName, message); |
+ dumpJSError(exceptionName, tryCatchMessage); |
return true; |
} |
return false; |