OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 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 are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
112 v8::Handle<v8::Value> postTask(v8::Handle<v8::Function> callback, v8::Handle<v8:
:Object> receiver, v8::Handle<v8::Value> value, v8::Isolate* isolate) | 112 v8::Handle<v8::Value> postTask(v8::Handle<v8::Function> callback, v8::Handle<v8:
:Object> receiver, v8::Handle<v8::Value> value, v8::Isolate* isolate) |
113 { | 113 { |
114 DOMWindow* window = activeDOMWindow(); | 114 DOMWindow* window = activeDOMWindow(); |
115 ASSERT(window); | 115 ASSERT(window); |
116 Document* document = window->document(); | 116 Document* document = window->document(); |
117 ASSERT(document); | 117 ASSERT(document); |
118 document->postTask(adoptPtr(new PromiseTask(callback, receiver, value))); | 118 document->postTask(adoptPtr(new PromiseTask(callback, receiver, value))); |
119 return v8::Undefined(isolate); | 119 return v8::Undefined(isolate); |
120 } | 120 } |
121 | 121 |
122 // This function must have the resolver as the first argument when called | 122 void wrapperCallback(const v8::FunctionCallbackInfo<v8::Value>& args) |
| 123 { |
| 124 v8::Isolate* isolate = args.GetIsolate(); |
| 125 ASSERT(!args.Data().IsEmpty()); |
| 126 v8::Local<v8::Object> environment = args.Data().As<v8::Object>(); |
| 127 v8::Local<v8::Value> result = v8::Undefined(isolate); |
| 128 if (args.Length() > 0) |
| 129 result = args[0]; |
| 130 |
| 131 v8::Local<v8::Object> promise = environment->GetInternalField(V8PromiseCusto
m::WrapperCallbackEnvironmentPromiseIndex).As<v8::Object>(); |
| 132 v8::Local<v8::Object> resolver = environment->GetInternalField(V8PromiseCust
om::WrapperCallbackEnvironmentPromiseResolverIndex).As<v8::Object>(); |
| 133 v8::Local<v8::Function> callback = environment->GetInternalField(V8PromiseCu
stom::WrapperCallbackEnvironmentCallbackIndex).As<v8::Function>(); |
| 134 |
| 135 v8::Local<v8::Value> argv[] = { |
| 136 result, |
| 137 }; |
| 138 v8::TryCatch trycatch; |
| 139 result = V8ScriptRunner::callFunction(callback, getScriptExecutionContext(),
promise, WTF_ARRAY_LENGTH(argv), argv); |
| 140 if (result.IsEmpty()) { |
| 141 V8PromiseCustom::rejectResolver(resolver, trycatch.Exception(), V8Promis
eCustom::Synchronous, isolate); |
| 142 return; |
| 143 } |
| 144 V8PromiseCustom::resolveResolver(resolver, result, V8PromiseCustom::Synchron
ous, isolate); |
| 145 } |
| 146 |
| 147 v8::Local<v8::Object> wrapperCallbackEnvironment(v8::Handle<v8::Object> promise,
v8::Handle<v8::Object> resolver, v8::Handle<v8::Function> callback) |
| 148 { |
| 149 // FIXME: v8::ObjectTemplate::New should be cached. |
| 150 v8::Local<v8::ObjectTemplate> objectTemplate = v8::ObjectTemplate::New(); |
| 151 objectTemplate->SetInternalFieldCount(V8PromiseCustom::WrapperCallbackEnviro
nmentFieldCount); |
| 152 v8::Local<v8::Object> environment = objectTemplate->NewInstance(); |
| 153 environment->SetInternalField(V8PromiseCustom::WrapperCallbackEnvironmentPro
miseIndex, promise); |
| 154 environment->SetInternalField(V8PromiseCustom::WrapperCallbackEnvironmentPro
miseResolverIndex, resolver); |
| 155 environment->SetInternalField(V8PromiseCustom::WrapperCallbackEnvironmentCal
lbackIndex, callback); |
| 156 return environment; |
| 157 } |
| 158 |
| 159 // This function must have the resolver as the first argument when called. |
123 // See promiseCallback. | 160 // See promiseCallback. |
124 void promiseFulfillCallback(const v8::FunctionCallbackInfo<v8::Value>& args) | 161 void promiseFulfillCallback(const v8::FunctionCallbackInfo<v8::Value>& args) |
125 { | 162 { |
126 v8::Local<v8::Object> resolver; | 163 v8::Local<v8::Object> resolver; |
127 v8::Local<v8::Value> result = v8::Undefined(args.GetIsolate()); | 164 v8::Local<v8::Value> result = v8::Undefined(args.GetIsolate()); |
128 ASSERT(args.Length() > 0); | 165 ASSERT(args.Length() > 0); |
129 resolver = args[0].As<v8::Object>(); | 166 resolver = args[0].As<v8::Object>(); |
130 if (args.Length() > 1) | 167 if (args.Length() > 1) |
131 result = args[1]; | 168 result = args[1]; |
132 | 169 |
133 V8PromiseCustom::fulfillResolver(resolver, result, V8PromiseCustom::Synchron
ous, args.GetIsolate()); | 170 V8PromiseCustom::fulfillResolver(resolver, result, V8PromiseCustom::Synchron
ous, args.GetIsolate()); |
134 } | 171 } |
135 | 172 |
136 // This function must be bound with the resolver as the first argument. | 173 // This function must have the resolver as the first argument when called. |
137 // See promiseCallback. | 174 // See promiseCallback. |
138 void promiseResolveCallback(const v8::FunctionCallbackInfo<v8::Value>& args) | 175 void promiseResolveCallback(const v8::FunctionCallbackInfo<v8::Value>& args) |
139 { | 176 { |
140 v8::Local<v8::Object> resolver; | 177 v8::Local<v8::Object> resolver; |
141 v8::Local<v8::Value> result = v8::Undefined(args.GetIsolate()); | 178 v8::Local<v8::Value> result = v8::Undefined(args.GetIsolate()); |
142 ASSERT(args.Length() > 0); | 179 ASSERT(args.Length() > 0); |
143 resolver = args[0].As<v8::Object>(); | 180 resolver = args[0].As<v8::Object>(); |
144 if (args.Length() > 1) | 181 if (args.Length() > 1) |
145 result = args[1]; | 182 result = args[1]; |
146 | 183 |
147 V8PromiseCustom::resolveResolver(resolver, result, V8PromiseCustom::Synchron
ous, args.GetIsolate()); | 184 V8PromiseCustom::resolveResolver(resolver, result, V8PromiseCustom::Synchron
ous, args.GetIsolate()); |
148 } | 185 } |
149 | 186 |
150 // This function must be bound with the resolver as the first argument. | 187 // This function must have the resolver as the first argument when called. |
151 // See promiseCallback. | 188 // See promiseCallback. |
152 void promiseRejectCallback(const v8::FunctionCallbackInfo<v8::Value>& args) | 189 void promiseRejectCallback(const v8::FunctionCallbackInfo<v8::Value>& args) |
153 { | 190 { |
154 v8::Local<v8::Object> resolver; | 191 v8::Local<v8::Object> resolver; |
155 v8::Local<v8::Value> result = v8::Undefined(args.GetIsolate()); | 192 v8::Local<v8::Value> result = v8::Undefined(args.GetIsolate()); |
156 ASSERT(args.Length() > 0); | 193 ASSERT(args.Length() > 0); |
157 resolver = args[0].As<v8::Object>(); | 194 resolver = args[0].As<v8::Object>(); |
158 if (args.Length() > 1) | 195 if (args.Length() > 1) |
159 result = args[1]; | 196 result = args[1]; |
160 | 197 |
(...skipping 19 matching lines...) Expand all Loading... |
180 // We bind |resolver| to promise{Fulfill, Resolve, Reject}Callback. | 217 // We bind |resolver| to promise{Fulfill, Resolve, Reject}Callback. |
181 // | 218 // |
182 // promiseCallback(result) will be evaluated as | 219 // promiseCallback(result) will be evaluated as |
183 // promiseFulfillCallback(resolver, result), | 220 // promiseFulfillCallback(resolver, result), |
184 // if algorithm is FulfillAlgorithm. | 221 // if algorithm is FulfillAlgorithm. |
185 | 222 |
186 // FIXME: If there is a way to bind an object to a function other than evalu
ate a JavaScript, it will be preferable. | 223 // FIXME: If there is a way to bind an object to a function other than evalu
ate a JavaScript, it will be preferable. |
187 // We should not depend on the global context that user can change, such as
accessing a property, calling a method or so. | 224 // We should not depend on the global context that user can change, such as
accessing a property, calling a method or so. |
188 v8::Local<v8::String> script = v8String("(function(f, v1) { return function(
v2) { return f(v1, v2); }; })", isolate); | 225 v8::Local<v8::String> script = v8String("(function(f, v1) { return function(
v2) { return f(v1, v2); }; })", isolate); |
189 v8::Local<v8::Value> value = V8ScriptRunner::compileAndRunInternalScript(scr
ipt, isolate); | 226 v8::Local<v8::Value> value = V8ScriptRunner::compileAndRunInternalScript(scr
ipt, isolate); |
| 227 ASSERT(!value.IsEmpty()); |
190 | 228 |
191 v8::Local<v8::Value> argv[] = { | 229 v8::Local<v8::Value> argv[] = { |
192 callback, | 230 callback, |
193 resolver, | 231 resolver, |
194 }; | 232 }; |
195 v8::Local<v8::Object> receiver = isolate->GetCurrentContext()->Global(); | 233 v8::Local<v8::Object> receiver = isolate->GetCurrentContext()->Global(); |
196 | 234 |
197 value = V8ScriptRunner::callFunction(value.As<v8::Function>(), getScriptExec
utionContext(), receiver, WTF_ARRAY_LENGTH(argv), argv); | 235 value = V8ScriptRunner::callFunction(value.As<v8::Function>(), getScriptExec
utionContext(), receiver, WTF_ARRAY_LENGTH(argv), argv); |
198 ASSERT(!value.IsEmpty()); | 236 ASSERT(!value.IsEmpty()); |
199 return value.As<v8::Function>(); | 237 return value.As<v8::Function>(); |
(...skipping 28 matching lines...) Expand all Loading... |
228 v8::TryCatch trycatch; | 266 v8::TryCatch trycatch; |
229 if (V8ScriptRunner::callFunction(init, getScriptExecutionContext(), promise,
WTF_ARRAY_LENGTH(argv), argv).IsEmpty()) { | 267 if (V8ScriptRunner::callFunction(init, getScriptExecutionContext(), promise,
WTF_ARRAY_LENGTH(argv), argv).IsEmpty()) { |
230 // An exception is thrown. Reject the promise if its resolved flag is un
set. | 268 // An exception is thrown. Reject the promise if its resolved flag is un
set. |
231 if (!V8PromiseCustom::isInternalDetached(resolver) && V8PromiseCustom::g
etState(V8PromiseCustom::getInternal(resolver)) == V8PromiseCustom::Pending) | 269 if (!V8PromiseCustom::isInternalDetached(resolver) && V8PromiseCustom::g
etState(V8PromiseCustom::getInternal(resolver)) == V8PromiseCustom::Pending) |
232 V8PromiseCustom::rejectResolver(resolver, trycatch.Exception(), V8Pr
omiseCustom::Asynchronous, isolate); | 270 V8PromiseCustom::rejectResolver(resolver, trycatch.Exception(), V8Pr
omiseCustom::Asynchronous, isolate); |
233 } | 271 } |
234 v8SetReturnValue(args, promise); | 272 v8SetReturnValue(args, promise); |
235 return; | 273 return; |
236 } | 274 } |
237 | 275 |
| 276 void V8Promise::thenMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args
) |
| 277 { |
| 278 v8::Isolate* isolate = args.GetIsolate(); |
| 279 v8::Local<v8::Function> fulfillWrapper, rejectWrapper; |
| 280 v8::Local<v8::Object> promise, resolver; |
| 281 V8PromiseCustom::createPromise(args.Holder(), &promise, &resolver, isolate); |
| 282 if (args.Length() > 0 && !args[0]->IsUndefined()) { |
| 283 if (!args[0]->IsFunction()) { |
| 284 v8SetReturnValue(args, throwTypeError("fulfillCallback must be a fun
ction or undefined", isolate)); |
| 285 return; |
| 286 } |
| 287 v8::Local<v8::Object> environment = wrapperCallbackEnvironment(promise,
resolver, args[0].As<v8::Function>()); |
| 288 fulfillWrapper = v8::FunctionTemplate::New(wrapperCallback, environment)
->GetFunction(); |
| 289 } else { |
| 290 fulfillWrapper = promiseCallback(resolver, V8PromiseCustom::FulfillAlgor
ithm, isolate); |
| 291 } |
| 292 if (args.Length() > 1 && !args[1]->IsUndefined()) { |
| 293 if (!args[1]->IsFunction()) { |
| 294 v8SetReturnValue(args, throwTypeError("rejectCallback must be a func
tion or undefined", isolate)); |
| 295 return; |
| 296 } |
| 297 v8::Local<v8::Object> environment = wrapperCallbackEnvironment(promise,
resolver, args[1].As<v8::Function>()); |
| 298 rejectWrapper = v8::FunctionTemplate::New(wrapperCallback, environment)-
>GetFunction(); |
| 299 } else { |
| 300 rejectWrapper = promiseCallback(resolver, V8PromiseCustom::RejectAlgorit
hm, isolate); |
| 301 } |
| 302 V8PromiseCustom::append(args.Holder(), fulfillWrapper, rejectWrapper, isolat
e); |
| 303 v8SetReturnValue(args, promise); |
| 304 } |
| 305 |
| 306 void V8Promise::catchMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& arg
s) |
| 307 { |
| 308 v8::Isolate* isolate = args.GetIsolate(); |
| 309 v8::Local<v8::Function> fulfillWrapper, rejectWrapper; |
| 310 v8::Local<v8::Object> promise, resolver; |
| 311 V8PromiseCustom::createPromise(args.Holder(), &promise, &resolver, isolate); |
| 312 |
| 313 if (args.Length() > 0 && !args[0]->IsUndefined()) { |
| 314 if (!args[0]->IsFunction()) { |
| 315 v8SetReturnValue(args, throwTypeError("rejectCallback must be a func
tion or undefined", isolate)); |
| 316 return; |
| 317 } |
| 318 v8::Local<v8::Object> environment = wrapperCallbackEnvironment(promise,
resolver, args[0].As<v8::Function>()); |
| 319 rejectWrapper = v8::FunctionTemplate::New(wrapperCallback, environment)-
>GetFunction(); |
| 320 } else { |
| 321 rejectWrapper = promiseCallback(resolver, V8PromiseCustom::RejectAlgorit
hm, isolate); |
| 322 } |
| 323 fulfillWrapper = promiseCallback(resolver, V8PromiseCustom::FulfillAlgorithm
, isolate); |
| 324 V8PromiseCustom::append(args.Holder(), fulfillWrapper, rejectWrapper, isolat
e); |
| 325 v8SetReturnValue(args, promise); |
| 326 } |
| 327 |
238 // | 328 // |
239 // -- V8PromiseCustom -- | 329 // -- V8PromiseCustom -- |
240 void V8PromiseCustom::createPromise(v8::Handle<v8::Object> creationContext, v8::
Local<v8::Object>* promise, v8::Local<v8::Object>* resolver, v8::Isolate* isolat
e) | 330 void V8PromiseCustom::createPromise(v8::Handle<v8::Object> creationContext, v8::
Local<v8::Object>* promise, v8::Local<v8::Object>* resolver, v8::Isolate* isolat
e) |
241 { | 331 { |
242 // FIXME: v8::ObjectTemplate::New should be cached. | 332 // FIXME: v8::ObjectTemplate::New should be cached. |
243 v8::Local<v8::ObjectTemplate> internalTemplate = v8::ObjectTemplate::New(); | 333 v8::Local<v8::ObjectTemplate> internalTemplate = v8::ObjectTemplate::New(); |
244 internalTemplate->SetInternalFieldCount(InternalFieldCount); | 334 internalTemplate->SetInternalFieldCount(InternalFieldCount); |
245 v8::Local<v8::Object> internal = internalTemplate->NewInstance(); | 335 v8::Local<v8::Object> internal = internalTemplate->NewInstance(); |
246 *promise = V8DOMWrapper::createWrapper(creationContext, &V8Promise::info, 0,
isolate); | 336 *promise = V8DOMWrapper::createWrapper(creationContext, &V8Promise::info, 0,
isolate); |
247 *resolver = V8DOMWrapper::createWrapper(creationContext, &V8PromiseResolver:
:info, 0, isolate); | 337 *resolver = V8DOMWrapper::createWrapper(creationContext, &V8PromiseResolver:
:info, 0, isolate); |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
391 v8::TryCatch trycatch; | 481 v8::TryCatch trycatch; |
392 v8::Handle<v8::Value> args[] = { result }; | 482 v8::Handle<v8::Value> args[] = { result }; |
393 V8ScriptRunner::callFunction(function, getScriptExecutionContext(), rece
iver, WTF_ARRAY_LENGTH(args), args); | 483 V8ScriptRunner::callFunction(function, getScriptExecutionContext(), rece
iver, WTF_ARRAY_LENGTH(args), args); |
394 } else { | 484 } else { |
395 ASSERT(mode == Asynchronous); | 485 ASSERT(mode == Asynchronous); |
396 postTask(function, receiver, result, isolate); | 486 postTask(function, receiver, result, isolate); |
397 } | 487 } |
398 } | 488 } |
399 | 489 |
400 } // namespace WebCore | 490 } // namespace WebCore |
OLD | NEW |