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(args.GetIsolate()); | |
abarth-chromium
2013/07/03 18:30:23
Seems like you can just pass |isolate|
yhirano
2013/07/04 01:12:16
Done.
| |
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 |