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) |
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)) { | |
74 scriptState = ScriptState::current(isolate); | |
75 sanitizedCreationContext = scriptState->context()->Global(); | |
76 } | 73 } |
77 | 74 |
78 v8::TryCatch tryCatch(isolate); | 75 DOMException* domException = DOMException::create(exceptionCode, sanitizedMe
ssage, unsanitizedMessage); |
79 | 76 v8::Local<v8::Object> exceptionObj = toV8(domException, isolate->GetCurrentC
ontext()->Global(), isolate).As<v8::Object>(); |
80 DOMException* domException = DOMException::create(ec, sanitizedMessage, unsa
nitizedMessage); | 77 // Attach an Error object to the DOMException. This is then lazily used to |
81 v8::Local<v8::Value> exception = toV8(domException, sanitizedCreationContext
, isolate); | 78 // get the stack value. |
82 | |
83 if (tryCatch.HasCaught()) { | |
84 ASSERT(exception.IsEmpty()); | |
85 return tryCatch.Exception(); | |
86 } | |
87 ASSERT(!exception.IsEmpty()); | |
88 | |
89 // Attach an Error object to the DOMException. This is then lazily used to g
et the stack value. | |
90 v8::Local<v8::Value> error = v8::Exception::Error(v8String(isolate, domExcep
tion->message())); | 79 v8::Local<v8::Value> error = v8::Exception::Error(v8String(isolate, domExcep
tion->message())); |
91 ASSERT(!error.IsEmpty()); | 80 exceptionObj->SetAccessor(isolate->GetCurrentContext(), v8AtomicString(isola
te, "stack"), domExceptionStackGetter, domExceptionStackSetter, error).ToChecked
(); |
92 v8::Local<v8::Object> exceptionObject = exception.As<v8::Object>(); | |
93 exceptionObject->SetAccessor(isolate->GetCurrentContext(), v8AtomicString(is
olate, "stack"), domExceptionStackGetter, domExceptionStackSetter, error).ToChec
ked(); | |
94 | 81 |
95 auto privateError = V8PrivateProperty::getDOMExceptionError(isolate); | 82 auto privateError = V8PrivateProperty::getDOMExceptionError(isolate); |
96 privateError.set(scriptState->context(), exceptionObject, error); | 83 privateError.set(isolate->GetCurrentContext(), exceptionObj, error); |
97 | 84 |
98 return exception; | 85 return exceptionObj; |
99 } | 86 } |
100 | 87 |
101 v8::Local<v8::Value> V8ThrowException::createGeneralError(v8::Isolate* isolate,
const String& message) | 88 #define DEFINE_CREATE_AND_THROW_ERROR_FUNC(blinkErrorType, v8ErrorType, defaultM
essage) \ |
102 { | 89 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)); | 90 { \ |
| 91 return v8::Exception::v8ErrorType(v8String(isolate, message.isNull() ? defau
ltMessage : message)); \ |
| 92 } \ |
| 93 \ |
| 94 void V8ThrowException::throw##blinkErrorType(v8::Isolate* isolate, const String&
message) \ |
| 95 { \ |
| 96 throwException(isolate, create##blinkErrorType(isolate, message)); \ |
104 } | 97 } |
105 | 98 |
106 v8::Local<v8::Value> V8ThrowException::throwGeneralError(v8::Isolate* isolate, c
onst String& message) | 99 DEFINE_CREATE_AND_THROW_ERROR_FUNC(GeneralError, Error, "Error") |
107 { | 100 DEFINE_CREATE_AND_THROW_ERROR_FUNC(RangeError, RangeError, "Range error") |
108 v8::Local<v8::Value> exception = V8ThrowException::createGeneralError(isolat
e, message); | 101 DEFINE_CREATE_AND_THROW_ERROR_FUNC(ReferenceError, ReferenceError, "Reference er
ror") |
109 return V8ThrowException::throwException(exception, isolate); | 102 DEFINE_CREATE_AND_THROW_ERROR_FUNC(SyntaxError, SyntaxError, "Syntax error") |
110 } | 103 DEFINE_CREATE_AND_THROW_ERROR_FUNC(TypeError, TypeError, "Type error") |
111 | 104 |
112 v8::Local<v8::Value> V8ThrowException::createTypeError(v8::Isolate* isolate, con
st String& message) | 105 #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 | 106 |
163 } // namespace blink | 107 } // namespace blink |
OLD | NEW |