Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2009 Google Inc. All rights reserved. | 2 * Copyright (C) 2009 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
| 8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
| 9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
| 10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 26 | 26 |
| 27 #include "bindings/core/v8/BindingSecurity.h" | 27 #include "bindings/core/v8/BindingSecurity.h" |
| 28 #include "bindings/core/v8/V8Binding.h" | 28 #include "bindings/core/v8/V8Binding.h" |
| 29 #include "bindings/core/v8/V8DOMException.h" | 29 #include "bindings/core/v8/V8DOMException.h" |
| 30 #include "bindings/core/v8/V8PrivateProperty.h" | 30 #include "bindings/core/v8/V8PrivateProperty.h" |
| 31 #include "core/dom/DOMException.h" | 31 #include "core/dom/DOMException.h" |
| 32 #include "core/dom/ExceptionCode.h" | 32 #include "core/dom/ExceptionCode.h" |
| 33 | 33 |
| 34 namespace blink { | 34 namespace blink { |
| 35 | 35 |
| 36 static void domExceptionStackGetter(v8::Local<v8::Name> name, const v8::Property CallbackInfo<v8::Value>& info) | 36 namespace { |
| 37 | |
| 38 void domExceptionStackGetter(v8::Local<v8::Name> name, const v8::PropertyCallbac kInfo<v8::Value>& info) | |
| 37 { | 39 { |
| 38 v8::Isolate* isolate = info.GetIsolate(); | 40 v8::Isolate* isolate = info.GetIsolate(); |
| 39 v8::Local<v8::Value> value; | 41 v8::Local<v8::Value> value; |
| 40 if (info.Data().As<v8::Object>()->Get(isolate->GetCurrentContext(), v8Atomic String(isolate, "stack")).ToLocal(&value)) | 42 if (info.Data().As<v8::Object>()->Get(isolate->GetCurrentContext(), v8Atomic String(isolate, "stack")).ToLocal(&value)) |
| 41 v8SetReturnValue(info, value); | 43 v8SetReturnValue(info, value); |
| 42 } | 44 } |
| 43 | 45 |
| 44 static void domExceptionStackSetter(v8::Local<v8::Name> name, v8::Local<v8::Valu e> value, const v8::PropertyCallbackInfo<void>& info) | 46 void domExceptionStackSetter(v8::Local<v8::Name> name, v8::Local<v8::Value> valu e, const v8::PropertyCallbackInfo<void>& info) |
| 45 { | 47 { |
| 46 v8::Maybe<bool> unused = info.Data().As<v8::Object>()->Set(info.GetIsolate() ->GetCurrentContext(), v8AtomicString(info.GetIsolate(), "stack"), value); | 48 v8::Maybe<bool> unused = info.Data().As<v8::Object>()->Set(info.GetIsolate() ->GetCurrentContext(), v8AtomicString(info.GetIsolate(), "stack"), value); |
| 47 ALLOW_UNUSED_LOCAL(unused); | 49 ALLOW_UNUSED_LOCAL(unused); |
| 48 } | 50 } |
| 49 | 51 |
| 50 v8::Local<v8::Value> V8ThrowException::createDOMException(v8::Isolate* isolate, int ec, const String& sanitizedMessage, const String& unsanitizedMessage, const v8::Local<v8::Object>& creationContext) | 52 } // namespace |
| 53 | |
| 54 v8::Local<v8::Value> V8ThrowException::createDOMException(v8::Isolate* isolate, ExceptionCode exceptionCode, const String& sanitizedMessage, const String& unsan itizedMessage) | |
|
haraken
2016/08/09 07:53:50
Just to confirm: Is it guaranteed that the current
Yuki
2016/08/10 03:11:09
I suppose so. There are three use cases of v8::Co
| |
| 51 { | 55 { |
| 52 if (ec <= 0 || isolate->IsExecutionTerminating()) | 56 DCHECK_GT(exceptionCode, 0); |
| 53 return v8Undefined(); | 57 DCHECK(exceptionCode == SecurityError || unsanitizedMessage.isNull()); |
| 54 | 58 |
| 55 ASSERT(ec == SecurityError || unsanitizedMessage.isEmpty()); | 59 if (isolate->IsExecutionTerminating()) |
| 60 return v8::Local<v8::Value>(); | |
| 56 | 61 |
| 57 if (ec == V8GeneralError) | 62 switch (exceptionCode) { |
| 58 return V8ThrowException::createGeneralError(isolate, sanitizedMessage); | 63 case V8GeneralError: |
| 59 if (ec == V8TypeError) | 64 return createGeneralError(isolate, sanitizedMessage); |
| 60 return V8ThrowException::createTypeError(isolate, sanitizedMessage); | 65 case V8TypeError: |
| 61 if (ec == V8RangeError) | 66 return createTypeError(isolate, sanitizedMessage); |
| 62 return V8ThrowException::createRangeError(isolate, sanitizedMessage); | 67 case V8RangeError: |
| 63 if (ec == V8SyntaxError) | 68 return createRangeError(isolate, sanitizedMessage); |
| 64 return V8ThrowException::createSyntaxError(isolate, sanitizedMessage); | 69 case V8SyntaxError: |
| 65 if (ec == V8ReferenceError) | 70 return createSyntaxError(isolate, sanitizedMessage); |
| 66 return V8ThrowException::createReferenceError(isolate, sanitizedMessage) ; | 71 case V8ReferenceError: |
| 67 | 72 return createReferenceError(isolate, sanitizedMessage); |
| 68 v8::Local<v8::Object> sanitizedCreationContext = creationContext; | |
| 69 | |
| 70 // FIXME: Is the current context always the right choice? | |
| 71 ScriptState* scriptState = ScriptState::from(creationContext->CreationContex t()); | |
| 72 Frame* frame = toFrameIfNotDetached(scriptState->context()); | |
| 73 if (!frame || !BindingSecurity::shouldAllowAccessToFrame(isolate, currentDOM Window(isolate), frame, DoNotReportSecurityError)) { | |
|
haraken
2016/08/09 07:53:50
Do you know why we had this security check? This C
Yuki
2016/08/10 03:11:10
The old implementation was creating a new exceptio
haraken
2016/08/10 05:00:33
Makes sense.
| |
| 74 scriptState = ScriptState::current(isolate); | |
| 75 sanitizedCreationContext = scriptState->context()->Global(); | |
| 76 } | 73 } |
| 77 | 74 |
| 78 v8::TryCatch tryCatch(isolate); | 75 v8::TryCatch tryCatch(isolate); |
| 79 | 76 |
| 80 DOMException* domException = DOMException::create(ec, sanitizedMessage, unsa nitizedMessage); | 77 DOMException* domException = DOMException::create(exceptionCode, sanitizedMe ssage, unsanitizedMessage); |
| 81 v8::Local<v8::Value> exception = toV8(domException, sanitizedCreationContext , isolate); | 78 v8::Local<v8::Object> exceptionObj = toV8(domException, isolate->GetCurrentC ontext()->Global(), isolate).As<v8::Object>(); |
| 82 | 79 // Attach an Error object to the DOMException. This is then lazily used to |
| 80 // get the stack value. | |
| 81 v8::Local<v8::Value> error = v8::Exception::Error(v8String(isolate, domExcep tion->message())); | |
| 83 if (tryCatch.HasCaught()) { | 82 if (tryCatch.HasCaught()) { |
|
haraken
2016/08/09 07:53:50
Just help me understand: Who can throw an exceptio
Yuki
2016/08/10 03:11:10
OOM (out of handles or stack) in V8?
Probably the
haraken
2016/08/10 05:00:33
Yeah, let's remove it.
Yuki
2016/08/10 05:45:11
Done.
| |
| 84 ASSERT(exception.IsEmpty()); | |
| 85 return tryCatch.Exception(); | 83 return tryCatch.Exception(); |
| 86 } | 84 } |
| 87 ASSERT(!exception.IsEmpty()); | 85 // |exceptionObj| and |error| must not be empty here because of no |
| 88 | 86 // exception. |
| 89 // Attach an Error object to the DOMException. This is then lazily used to g et the stack value. | 87 if (!v8CallBoolean(exceptionObj->SetAccessor(isolate->GetCurrentContext(), v 8AtomicString(isolate, "stack"), domExceptionStackGetter, domExceptionStackSette r, error))) { |
|
haraken
2016/08/09 07:53:50
Is it possible that the SetAccessor() call fails?
Yuki
2016/08/10 03:11:10
Unlikely.
haraken
2016/08/10 05:00:33
Then let's use ToChecked.
Yuki
2016/08/10 05:45:11
Done.
| |
| 90 v8::Local<v8::Value> error = v8::Exception::Error(v8String(isolate, domExcep tion->message())); | 88 CHECK(tryCatch.HasCaught()); |
| 91 ASSERT(!error.IsEmpty()); | 89 return tryCatch.Exception(); |
| 92 v8::Local<v8::Object> exceptionObject = exception.As<v8::Object>(); | 90 } |
| 93 exceptionObject->SetAccessor(isolate->GetCurrentContext(), v8AtomicString(is olate, "stack"), domExceptionStackGetter, domExceptionStackSetter, error).ToChec ked(); | |
| 94 | 91 |
| 95 auto privateError = V8PrivateProperty::getDOMExceptionError(isolate); | 92 auto privateError = V8PrivateProperty::getDOMExceptionError(isolate); |
| 96 privateError.set(scriptState->context(), exceptionObject, error); | 93 privateError.set(isolate->GetCurrentContext(), exceptionObj, error); |
| 97 | 94 |
| 98 return exception; | 95 return exceptionObj; |
| 99 } | 96 } |
| 100 | 97 |
| 101 v8::Local<v8::Value> V8ThrowException::createGeneralError(v8::Isolate* isolate, const String& message) | 98 #define DEFINE_CREATE_AND_THROW_ERROR_FUNC(blinkErrorType, v8ErrorType, defaultM essage) \ |
| 102 { | 99 v8::Local<v8::Value> V8ThrowException::create##blinkErrorType(v8::Isolate* isola te, const String& message) \ |
| 103 return v8::Exception::Error(v8String(isolate, message.isNull() ? "Error" : m essage)); | 100 { \ |
| 101 return v8::Exception::v8ErrorType(v8String(isolate, message.isNull() ? defau ltMessage : message)); \ | |
| 102 } \ | |
| 103 \ | |
| 104 void V8ThrowException::throw##blinkErrorType(v8::Isolate* isolate, const String& message) \ | |
| 105 { \ | |
| 106 throwException(isolate, create##blinkErrorType(isolate, message)); \ | |
| 104 } | 107 } |
| 105 | 108 |
| 106 v8::Local<v8::Value> V8ThrowException::throwGeneralError(v8::Isolate* isolate, c onst String& message) | 109 DEFINE_CREATE_AND_THROW_ERROR_FUNC(GeneralError, Error, "Error") |
|
haraken
2016/08/09 07:53:50
Shall we rename GeneralError to Error in a follow-
Yuki
2016/08/10 03:11:10
Yes, will do.
| |
| 107 { | 110 DEFINE_CREATE_AND_THROW_ERROR_FUNC(RangeError, RangeError, "Range error") |
| 108 v8::Local<v8::Value> exception = V8ThrowException::createGeneralError(isolat e, message); | 111 DEFINE_CREATE_AND_THROW_ERROR_FUNC(ReferenceError, ReferenceError, "Reference er ror") |
| 109 return V8ThrowException::throwException(exception, isolate); | 112 DEFINE_CREATE_AND_THROW_ERROR_FUNC(SyntaxError, SyntaxError, "Syntax error") |
| 110 } | 113 DEFINE_CREATE_AND_THROW_ERROR_FUNC(TypeError, TypeError, "Type error") |
| 111 | 114 |
| 112 v8::Local<v8::Value> V8ThrowException::createTypeError(v8::Isolate* isolate, con st String& message) | 115 #undef DEFINE_CREATE_AND_THROW_ERROR_FUNC |
| 113 { | |
| 114 return v8::Exception::TypeError(v8String(isolate, message.isNull() ? "Type e rror" : message)); | |
| 115 } | |
| 116 | |
| 117 v8::Local<v8::Value> V8ThrowException::throwTypeError(v8::Isolate* isolate, cons t String& message) | |
| 118 { | |
| 119 v8::Local<v8::Value> exception = V8ThrowException::createTypeError(isolate, message); | |
| 120 return V8ThrowException::throwException(exception, isolate); | |
| 121 } | |
| 122 | |
| 123 v8::Local<v8::Value> V8ThrowException::createRangeError(v8::Isolate* isolate, co nst String& message) | |
| 124 { | |
| 125 return v8::Exception::RangeError(v8String(isolate, message.isNull() ? "Range error" : message)); | |
| 126 } | |
| 127 | |
| 128 v8::Local<v8::Value> V8ThrowException::throwRangeError(v8::Isolate* isolate, con st String& message) | |
| 129 { | |
| 130 v8::Local<v8::Value> exception = V8ThrowException::createRangeError(isolate, message); | |
| 131 return V8ThrowException::throwException(exception, isolate); | |
| 132 } | |
| 133 | |
| 134 v8::Local<v8::Value> V8ThrowException::createSyntaxError(v8::Isolate* isolate, c onst String& message) | |
| 135 { | |
| 136 return v8::Exception::SyntaxError(v8String(isolate, message.isNull() ? "Synt ax error" : message)); | |
| 137 } | |
| 138 | |
| 139 v8::Local<v8::Value> V8ThrowException::throwSyntaxError(v8::Isolate* isolate, co nst String& message) | |
| 140 { | |
| 141 v8::Local<v8::Value> exception = V8ThrowException::createSyntaxError(isolate , message); | |
| 142 return V8ThrowException::throwException(exception, isolate); | |
| 143 } | |
| 144 | |
| 145 v8::Local<v8::Value> V8ThrowException::createReferenceError(v8::Isolate* isolate , const String& message) | |
| 146 { | |
| 147 return v8::Exception::ReferenceError(v8String(isolate, message.isNull() ? "R eference error" : message)); | |
| 148 } | |
| 149 | |
| 150 v8::Local<v8::Value> V8ThrowException::throwReferenceError(v8::Isolate* isolate, const String& message) | |
| 151 { | |
| 152 v8::Local<v8::Value> exception = V8ThrowException::createReferenceError(isol ate, message); | |
| 153 return V8ThrowException::throwException(exception, isolate); | |
| 154 } | |
| 155 | |
| 156 v8::Local<v8::Value> V8ThrowException::throwException(v8::Local<v8::Value> excep tion, v8::Isolate* isolate) | |
| 157 { | |
| 158 if (!isolate->IsExecutionTerminating()) | |
| 159 isolate->ThrowException(exception); | |
| 160 return v8::Undefined(isolate); | |
| 161 } | |
| 162 | 116 |
| 163 } // namespace blink | 117 } // namespace blink |
| OLD | NEW |