Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(83)

Side by Side Diff: Source/bindings/v8/custom/V8PromiseCustom.cpp

Issue 18113004: Implement Promise.prototype.then and Promise.prototype.catch (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « Source/bindings/v8/custom/V8PromiseCustom.h ('k') | Source/core/dom/Promise.idl » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « Source/bindings/v8/custom/V8PromiseCustom.h ('k') | Source/core/dom/Promise.idl » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698