Index: third_party/WebKit/Source/bindings/core/v8/V8ThrowDOMException.cpp |
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8ThrowDOMException.cpp b/third_party/WebKit/Source/bindings/core/v8/V8ThrowDOMException.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..aa167d7f25eab4b9c707d9835c70a87b61fd1250 |
--- /dev/null |
+++ b/third_party/WebKit/Source/bindings/core/v8/V8ThrowDOMException.cpp |
@@ -0,0 +1,94 @@ |
+// Copyright 2017 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "bindings/core/v8/V8ThrowDOMException.h" |
+ |
+#include "bindings/core/v8/ToV8ForCore.h" |
+#include "bindings/core/v8/V8PrivateProperty.h" |
+#include "bindings/core/v8/V8ThrowException.h" |
+#include "core/dom/DOMException.h" |
+ |
+namespace blink { |
+ |
+namespace { |
+ |
+void DomExceptionStackGetter(v8::Local<v8::Name> name, |
+ const v8::PropertyCallbackInfo<v8::Value>& info) { |
+ v8::Isolate* isolate = info.GetIsolate(); |
+ v8::Local<v8::Value> value; |
+ if (info.Data() |
+ .As<v8::Object>() |
+ ->Get(isolate->GetCurrentContext(), V8AtomicString(isolate, "stack")) |
+ .ToLocal(&value)) |
+ V8SetReturnValue(info, value); |
+} |
+ |
+void DomExceptionStackSetter(v8::Local<v8::Name> name, |
+ v8::Local<v8::Value> value, |
+ const v8::PropertyCallbackInfo<void>& info) { |
+ v8::Maybe<bool> unused = info.Data().As<v8::Object>()->Set( |
+ info.GetIsolate()->GetCurrentContext(), |
+ V8AtomicString(info.GetIsolate(), "stack"), value); |
+ ALLOW_UNUSED_LOCAL(unused); |
+} |
+ |
+} // namespace |
+ |
+v8::Local<v8::Value> V8ThrowDOMException::CreateDOMException( |
+ v8::Isolate* isolate, |
+ ExceptionCode exception_code, |
+ const String& sanitized_message, |
+ const String& unsanitized_message) { |
+ DCHECK_GT(exception_code, 0); |
+ DCHECK(exception_code == kSecurityError || unsanitized_message.IsNull()); |
+ |
+ if (isolate->IsExecutionTerminating()) |
+ return v8::Local<v8::Value>(); |
+ |
+ switch (exception_code) { |
+ case kV8Error: |
+ return V8ThrowException::CreateError(isolate, sanitized_message); |
+ case kV8TypeError: |
+ return V8ThrowException::CreateTypeError(isolate, sanitized_message); |
+ case kV8RangeError: |
+ return V8ThrowException::CreateRangeError(isolate, sanitized_message); |
+ case kV8SyntaxError: |
+ return V8ThrowException::CreateSyntaxError(isolate, sanitized_message); |
+ case kV8ReferenceError: |
+ return V8ThrowException::CreateReferenceError(isolate, sanitized_message); |
+ } |
+ |
+ DOMException* dom_exception = DOMException::Create( |
+ exception_code, sanitized_message, unsanitized_message); |
+ v8::Local<v8::Object> exception_obj = |
+ ToV8(dom_exception, isolate->GetCurrentContext()->Global(), isolate) |
+ .As<v8::Object>(); |
+ // Attach an Error object to the DOMException. This is then lazily used to |
+ // get the stack value. |
+ v8::Local<v8::Value> error = |
+ v8::Exception::Error(V8String(isolate, dom_exception->message())); |
+ exception_obj |
+ ->SetAccessor(isolate->GetCurrentContext(), |
+ V8AtomicString(isolate, "stack"), DomExceptionStackGetter, |
+ DomExceptionStackSetter, error) |
+ .ToChecked(); |
+ |
+ auto private_error = V8PrivateProperty::GetDOMExceptionError(isolate); |
+ private_error.Set(exception_obj, error); |
+ |
+ return exception_obj; |
+} |
+ |
+void V8ThrowDOMException::ThrowDOMException(v8::Isolate* isolate, |
+ ExceptionCode exception_code, |
+ const String& sanitized_message, |
+ const String& unsanitized_message) { |
+ v8::Local<v8::Value> dom_exception = CreateDOMException( |
+ isolate, exception_code, sanitized_message, unsanitized_message); |
+ if (dom_exception.IsEmpty()) |
+ return; |
+ V8ThrowException::ThrowException(isolate, dom_exception); |
+} |
+ |
+} // namespace blink |