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

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

Issue 174073009: [Promise] Avoid crash in stack exhausted circumstance. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Revert the V8Initializer.cpp change: They will be address in another CL. Created 6 years, 9 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 | « no previous file | no next file » | 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 13 matching lines...) Expand all
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */ 29 */
30 30
31 #include "config.h" 31 #include "config.h"
32 #include "bindings/v8/custom/V8PromiseCustom.h" 32 #include "bindings/v8/custom/V8PromiseCustom.h"
33 33
34 #include <v8.h>
35 #include "V8Promise.h" 34 #include "V8Promise.h"
36 #include "bindings/v8/DOMRequestState.h" 35 #include "bindings/v8/DOMRequestState.h"
37 #include "bindings/v8/ScopedPersistent.h" 36 #include "bindings/v8/ScopedPersistent.h"
38 #include "bindings/v8/ScriptFunctionCall.h" 37 #include "bindings/v8/ScriptFunctionCall.h"
39 #include "bindings/v8/ScriptState.h" 38 #include "bindings/v8/ScriptState.h"
40 #include "bindings/v8/V8Binding.h" 39 #include "bindings/v8/V8Binding.h"
41 #include "bindings/v8/V8PerIsolateData.h" 40 #include "bindings/v8/V8PerIsolateData.h"
42 #include "bindings/v8/V8ScriptRunner.h" 41 #include "bindings/v8/V8ScriptRunner.h"
43 #include "bindings/v8/WrapperTypeInfo.h" 42 #include "bindings/v8/WrapperTypeInfo.h"
44 #include "core/dom/Document.h" 43 #include "core/dom/Document.h"
45 #include "core/dom/ExecutionContextTask.h" 44 #include "core/dom/ExecutionContextTask.h"
46 #include "core/frame/DOMWindow.h" 45 #include "core/frame/DOMWindow.h"
47 #include "core/frame/UseCounter.h" 46 #include "core/frame/UseCounter.h"
48 #include "core/inspector/InspectorInstrumentation.h" 47 #include "core/inspector/InspectorInstrumentation.h"
49 #include "core/workers/WorkerGlobalScope.h" 48 #include "core/workers/WorkerGlobalScope.h"
50 #include "platform/Task.h" 49 #include "platform/Task.h"
51 #include "wtf/Deque.h" 50 #include "wtf/Deque.h"
52 #include "wtf/Functional.h" 51 #include "wtf/Functional.h"
53 #include "wtf/Noncopyable.h" 52 #include "wtf/Noncopyable.h"
54 #include "wtf/PassOwnPtr.h" 53 #include "wtf/PassOwnPtr.h"
54 #include <v8.h>
55 55
56 namespace WebCore { 56 namespace WebCore {
57 57
58 namespace { 58 namespace {
59 59
60 v8::Local<v8::ObjectTemplate> cachedObjectTemplate(void* domTemplateKey, int int ernalFieldCount, v8::Isolate* isolate) 60 v8::Local<v8::ObjectTemplate> cachedObjectTemplate(void* domTemplateKey, int int ernalFieldCount, v8::Isolate* isolate)
61 { 61 {
62 V8PerIsolateData* data = V8PerIsolateData::from(isolate); 62 V8PerIsolateData* data = V8PerIsolateData::from(isolate);
63 WrapperWorldType currentWorldType = worldType(isolate); 63 WrapperWorldType currentWorldType = worldType(isolate);
64 v8::Handle<v8::FunctionTemplate> functionDescriptor = data->existingDOMTempl ate(currentWorldType, domTemplateKey); 64 v8::Handle<v8::FunctionTemplate> functionDescriptor = data->existingDOMTempl ate(currentWorldType, domTemplateKey);
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
134 V8PromiseCustom::resolve(promise, results, isolate); 134 V8PromiseCustom::resolve(promise, results, isolate);
135 return; 135 return;
136 } 136 }
137 countdownWrapper->SetInternalField(V8PromiseCustom::PrimitiveWrapperPrimitiv eIndex, v8::Integer::New(isolate, countdown->Value() - 1)); 137 countdownWrapper->SetInternalField(V8PromiseCustom::PrimitiveWrapperPrimitiv eIndex, v8::Integer::New(isolate, countdown->Value() - 1));
138 } 138 }
139 139
140 v8::Local<v8::Object> promiseAllEnvironment(v8::Handle<v8::Object> promise, v8:: Handle<v8::Object> countdownWrapper, int index, v8::Handle<v8::Array> results, v 8::Isolate* isolate) 140 v8::Local<v8::Object> promiseAllEnvironment(v8::Handle<v8::Object> promise, v8:: Handle<v8::Object> countdownWrapper, int index, v8::Handle<v8::Array> results, v 8::Isolate* isolate)
141 { 141 {
142 v8::Local<v8::ObjectTemplate> objectTemplate = promiseAllEnvironmentObjectTe mplate(isolate); 142 v8::Local<v8::ObjectTemplate> objectTemplate = promiseAllEnvironmentObjectTe mplate(isolate);
143 v8::Local<v8::Object> environment = objectTemplate->NewInstance(); 143 v8::Local<v8::Object> environment = objectTemplate->NewInstance();
144 if (environment.IsEmpty())
145 return v8::Local<v8::Object>();
144 146
145 environment->SetInternalField(V8PromiseCustom::PromiseAllEnvironmentPromiseI ndex, promise); 147 environment->SetInternalField(V8PromiseCustom::PromiseAllEnvironmentPromiseI ndex, promise);
146 environment->SetInternalField(V8PromiseCustom::PromiseAllEnvironmentCountdow nIndex, countdownWrapper); 148 environment->SetInternalField(V8PromiseCustom::PromiseAllEnvironmentCountdow nIndex, countdownWrapper);
147 environment->SetInternalField(V8PromiseCustom::PromiseAllEnvironmentIndexInd ex, v8::Integer::New(isolate, index)); 149 environment->SetInternalField(V8PromiseCustom::PromiseAllEnvironmentIndexInd ex, v8::Integer::New(isolate, index));
148 environment->SetInternalField(V8PromiseCustom::PromiseAllEnvironmentResultsI ndex, results); 150 environment->SetInternalField(V8PromiseCustom::PromiseAllEnvironmentResultsI ndex, results);
149 return environment; 151 return environment;
150 } 152 }
151 153
152 // Clear |internal|'s derived array. 154 // Clear |internal|'s derived array.
153 void clearDerived(v8::Handle<v8::Object> internal, v8::Isolate* isolate) 155 void clearDerived(v8::Handle<v8::Object> internal, v8::Isolate* isolate)
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
296 then = originatorValueObject->Get(v8AtomicString(isolate, "then")); 298 then = originatorValueObject->Get(v8AtomicString(isolate, "then"));
297 if (then.IsEmpty()) { 299 if (then.IsEmpty()) {
298 // If calling the [[Get]] internal method threw an exception, catch it a nd run updateDerivedFromReason. 300 // If calling the [[Get]] internal method threw an exception, catch it a nd run updateDerivedFromReason.
299 V8PromiseCustom::updateDerivedFromReason(m_promise.newLocal(isolate), m_ onRejected.newLocal(isolate), trycatch.Exception(), isolate); 301 V8PromiseCustom::updateDerivedFromReason(m_promise.newLocal(isolate), m_ onRejected.newLocal(isolate), trycatch.Exception(), isolate);
300 return; 302 return;
301 } 303 }
302 304
303 if (then->IsFunction()) { 305 if (then->IsFunction()) {
304 ASSERT(then->IsObject()); 306 ASSERT(then->IsObject());
305 v8::Local<v8::Object> coerced = V8PromiseCustom::coerceThenable(originat orValueObject, then.As<v8::Function>(), isolate); 307 v8::Local<v8::Object> coerced = V8PromiseCustom::coerceThenable(originat orValueObject, then.As<v8::Function>(), isolate);
308 // If the stack is exhausted coerced can be empty, but it is impossible
309 // because this function is executed on a fresh stack.
310 ASSERT(!coerced.IsEmpty());
306 V8PromiseCustom::updateDerivedFromPromise(m_promise.newLocal(isolate), m _onFulfilled.newLocal(isolate), m_onRejected.newLocal(isolate), coerced, isolate ); 311 V8PromiseCustom::updateDerivedFromPromise(m_promise.newLocal(isolate), m _onFulfilled.newLocal(isolate), m_onRejected.newLocal(isolate), coerced, isolate );
307 return; 312 return;
308 } 313 }
309 314
310 V8PromiseCustom::updateDerivedFromValue(m_promise.newLocal(isolate), m_onFul filled.newLocal(isolate), originatorValueObject, isolate); 315 V8PromiseCustom::updateDerivedFromValue(m_promise.newLocal(isolate), m_onFul filled.newLocal(isolate), originatorValueObject, isolate);
311 } 316 }
312 317
313 // Since Promises state propagation routines are executed recursively, they caus e 318 // Since Promises state propagation routines are executed recursively, they caus e
314 // stack overflow. 319 // stack overflow.
315 // (e.g. UpdateDerived -> UpdateDerivedFromValue -> SetValue -> 320 // (e.g. UpdateDerived -> UpdateDerivedFromValue -> SetValue ->
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
484 { 489 {
485 v8SetReturnValue(info, v8::Local<v8::Value>()); 490 v8SetReturnValue(info, v8::Local<v8::Value>());
486 v8::Isolate* isolate = info.GetIsolate(); 491 v8::Isolate* isolate = info.GetIsolate();
487 ExecutionContext* executionContext = callingExecutionContext(isolate); 492 ExecutionContext* executionContext = callingExecutionContext(isolate);
488 UseCounter::count(executionContext, UseCounter::PromiseConstructor); 493 UseCounter::count(executionContext, UseCounter::PromiseConstructor);
489 if (!info.Length() || !info[0]->IsFunction()) { 494 if (!info.Length() || !info[0]->IsFunction()) {
490 throwTypeError("Promise constructor takes a function argument", isolate) ; 495 throwTypeError("Promise constructor takes a function argument", isolate) ;
491 return; 496 return;
492 } 497 }
493 v8::Local<v8::Function> init = info[0].As<v8::Function>(); 498 v8::Local<v8::Function> init = info[0].As<v8::Function>();
494 v8::Local<v8::Object> promise = V8PromiseCustom::createPromise(info.Holder() , isolate); 499 V8TRYCATCH_VOID(v8::Local<v8::Object>, promise, V8PromiseCustom::createPromi se(info.Holder(), isolate));
495 v8::Handle<v8::Value> argv[] = { 500 V8TRYCATCH_VOID(v8::Handle<v8::Value>, resolve, createClosure(promiseResolve Callback, promise, isolate));
496 createClosure(promiseResolveCallback, promise, isolate), 501 V8TRYCATCH_VOID(v8::Handle<v8::Value>, reject, createClosure(promiseRejectCa llback, promise, isolate));
497 createClosure(promiseRejectCallback, promise, isolate) 502 v8::Handle<v8::Value> argv[] = { resolve, reject };
498 };
499 v8::TryCatch trycatch; 503 v8::TryCatch trycatch;
500 if (V8ScriptRunner::callFunction(init, currentExecutionContext(isolate), v8: :Undefined(isolate), WTF_ARRAY_LENGTH(argv), argv, isolate).IsEmpty()) { 504 if (V8ScriptRunner::callFunction(init, currentExecutionContext(isolate), v8: :Undefined(isolate), WTF_ARRAY_LENGTH(argv), argv, isolate).IsEmpty()) {
501 // An exception is thrown. Reject the promise if its resolved flag is un set. 505 // An exception is thrown. Reject the promise if its resolved flag is un set.
502 V8PromiseCustom::reject(promise, trycatch.Exception(), isolate); 506 V8PromiseCustom::reject(promise, trycatch.Exception(), isolate);
503 } 507 }
504 v8SetReturnValue(info, promise); 508 v8SetReturnValue(info, promise);
505 return; 509 return;
506 } 510 }
507 511
508 void V8Promise::thenMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info ) 512 void V8Promise::thenMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info )
509 { 513 {
510 v8::Isolate* isolate = info.GetIsolate(); 514 v8::Isolate* isolate = info.GetIsolate();
511 v8::Local<v8::Function> onFulfilled, onRejected; 515 v8::Local<v8::Function> onFulfilled, onRejected;
512 if (info.Length() > 0 && info[0]->IsFunction()) 516 if (info.Length() > 0 && info[0]->IsFunction())
513 onFulfilled = info[0].As<v8::Function>(); 517 onFulfilled = info[0].As<v8::Function>();
514 if (info.Length() > 1 && info[1]->IsFunction()) 518 if (info.Length() > 1 && info[1]->IsFunction())
515 onRejected = info[1].As<v8::Function>(); 519 onRejected = info[1].As<v8::Function>();
516 v8SetReturnValue(info, V8PromiseCustom::then(info.Holder(), onFulfilled, onR ejected, isolate)); 520 V8TRYCATCH_VOID(v8::Local<v8::Value>, newPromise, V8PromiseCustom::then(info .Holder(), onFulfilled, onRejected, isolate));
521 v8SetReturnValue(info, newPromise);
517 } 522 }
518 523
519 void V8Promise::castMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info ) 524 void V8Promise::castMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info )
520 { 525 {
521 v8::Isolate* isolate = info.GetIsolate(); 526 v8::Isolate* isolate = info.GetIsolate();
522 ExecutionContext* executionContext = callingExecutionContext(isolate); 527 ExecutionContext* executionContext = callingExecutionContext(isolate);
523 UseCounter::count(executionContext, UseCounter::PromiseCast); 528 UseCounter::count(executionContext, UseCounter::PromiseCast);
524 v8::Local<v8::Value> result = v8::Undefined(isolate); 529 v8::Local<v8::Value> result = v8::Undefined(isolate);
525 if (info.Length() > 0) 530 if (info.Length() > 0)
526 result = info[0]; 531 result = info[0];
527 532
528 v8SetReturnValue(info, V8PromiseCustom::toPromise(result, isolate)); 533 V8TRYCATCH_VOID(v8::Local<v8::Value>, cast, V8PromiseCustom::toPromise(resul t, isolate));
534 v8SetReturnValue(info, cast);
529 } 535 }
530 536
531 void V8Promise::catchMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& inf o) 537 void V8Promise::catchMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& inf o)
532 { 538 {
533 v8::Isolate* isolate = info.GetIsolate(); 539 v8::Isolate* isolate = info.GetIsolate();
534 v8::Local<v8::Function> onFulfilled, onRejected; 540 v8::Local<v8::Function> onFulfilled, onRejected;
535 541
536 if (info.Length() > 0 && !info[0]->IsUndefined()) { 542 if (info.Length() > 0 && !info[0]->IsUndefined()) {
537 if (!info[0]->IsFunction()) { 543 if (!info[0]->IsFunction()) {
538 v8SetReturnValue(info, throwTypeError("onRejected must be a function or undefined", isolate)); 544 v8SetReturnValue(info, throwTypeError("onRejected must be a function or undefined", isolate));
539 return; 545 return;
540 } 546 }
541 onRejected = info[0].As<v8::Function>(); 547 onRejected = info[0].As<v8::Function>();
542 } 548 }
543 v8SetReturnValue(info, V8PromiseCustom::then(info.Holder(), onFulfilled, onR ejected, isolate)); 549 V8TRYCATCH_VOID(v8::Local<v8::Value>, newPromise, V8PromiseCustom::then(info .Holder(), onFulfilled, onRejected, isolate));
550 v8SetReturnValue(info, newPromise);
544 } 551 }
545 552
546 void V8Promise::resolveMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& i nfo) 553 void V8Promise::resolveMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& i nfo)
547 { 554 {
548 v8::Isolate* isolate = info.GetIsolate(); 555 v8::Isolate* isolate = info.GetIsolate();
549 ExecutionContext* executionContext = callingExecutionContext(isolate); 556 ExecutionContext* executionContext = callingExecutionContext(isolate);
550 UseCounter::count(executionContext, UseCounter::PromiseResolve); 557 UseCounter::count(executionContext, UseCounter::PromiseResolve);
551 v8::Local<v8::Value> result = v8::Undefined(isolate); 558 v8::Local<v8::Value> result = v8::Undefined(isolate);
552 if (info.Length() > 0) 559 if (info.Length() > 0)
553 result = info[0]; 560 result = info[0];
554 561
555 v8::Local<v8::Object> promise = V8PromiseCustom::createPromise(info.Holder() , isolate); 562 V8TRYCATCH_VOID(v8::Local<v8::Object>, promise, V8PromiseCustom::createPromi se(info.Holder(), isolate));
556 V8PromiseCustom::resolve(promise, result, isolate); 563 V8PromiseCustom::resolve(promise, result, isolate);
557 v8SetReturnValue(info, promise); 564 v8SetReturnValue(info, promise);
558 } 565 }
559 566
560 void V8Promise::rejectMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& in fo) 567 void V8Promise::rejectMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& in fo)
561 { 568 {
562 v8::Isolate* isolate = info.GetIsolate(); 569 v8::Isolate* isolate = info.GetIsolate();
563 ExecutionContext* executionContext = callingExecutionContext(isolate); 570 ExecutionContext* executionContext = callingExecutionContext(isolate);
564 UseCounter::count(executionContext, UseCounter::PromiseReject); 571 UseCounter::count(executionContext, UseCounter::PromiseReject);
565 v8::Local<v8::Value> result = v8::Undefined(isolate); 572 v8::Local<v8::Value> result = v8::Undefined(isolate);
566 if (info.Length() > 0) 573 if (info.Length() > 0)
567 result = info[0]; 574 result = info[0];
568 575
569 v8::Local<v8::Object> promise = V8PromiseCustom::createPromise(info.Holder() , isolate); 576 V8TRYCATCH_VOID(v8::Local<v8::Object>, promise, V8PromiseCustom::createPromi se(info.Holder(), isolate));
570 V8PromiseCustom::reject(promise, result, isolate); 577 V8PromiseCustom::reject(promise, result, isolate);
571 v8SetReturnValue(info, promise); 578 v8SetReturnValue(info, promise);
572 } 579 }
573 580
574 void V8Promise::raceMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info ) 581 void V8Promise::raceMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info )
575 { 582 {
576 v8::Isolate* isolate = info.GetIsolate(); 583 v8::Isolate* isolate = info.GetIsolate();
577 v8::Local<v8::Object> promise = V8PromiseCustom::createPromise(info.Holder() , isolate); 584 V8TRYCATCH_VOID(v8::Local<v8::Object>, promise, V8PromiseCustom::createPromi se(info.Holder(), isolate));
578 585
579 if (!info.Length() || !info[0]->IsArray()) { 586 if (!info.Length() || !info[0]->IsArray()) {
580 v8SetReturnValue(info, promise); 587 v8SetReturnValue(info, promise);
581 return; 588 return;
582 } 589 }
583 590
584 // FIXME: Now we limit the iterable type to the Array type. 591 // FIXME: Now we limit the iterable type to the Array type.
585 v8::Local<v8::Array> iterable = info[0].As<v8::Array>(); 592 v8::Local<v8::Array> iterable = info[0].As<v8::Array>();
586 v8::Local<v8::Function> onFulfilled = createClosure(promiseResolveCallback, promise, isolate); 593 V8TRYCATCH_VOID(v8::Local<v8::Function>, onFulfilled, createClosure(promiseR esolveCallback, promise, isolate));
587 v8::Local<v8::Function> onRejected = createClosure(promiseRejectCallback, pr omise, isolate); 594 V8TRYCATCH_VOID(v8::Local<v8::Function>, onRejected, createClosure(promiseRe jectCallback, promise, isolate));
588 595
589 for (unsigned i = 0, length = iterable->Length(); i < length; ++i) { 596 for (unsigned i = 0, length = iterable->Length(); i < length; ++i) {
590 // Array-holes should not be skipped by for-of iteration semantics. 597 // Array-holes should not be skipped by for-of iteration semantics.
591 V8TRYCATCH_VOID(v8::Local<v8::Value>, nextValue, iterable->Get(i)); 598 V8TRYCATCH_VOID(v8::Local<v8::Value>, nextValue, iterable->Get(i));
592 v8::Local<v8::Object> nextPromise = V8PromiseCustom::toPromise(nextValue , isolate); 599 V8TRYCATCH_VOID(v8::Local<v8::Object>, nextPromise, V8PromiseCustom::toP romise(nextValue, isolate));
593 V8PromiseCustom::then(nextPromise, onFulfilled, onRejected, isolate); 600 V8TRYCATCH_VOID(v8::Local<v8::Value>, unused, V8PromiseCustom::then(next Promise, onFulfilled, onRejected, isolate));
594 } 601 }
595 v8SetReturnValue(info, promise); 602 v8SetReturnValue(info, promise);
596 } 603 }
597 604
598 void V8Promise::allMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 605 void V8Promise::allMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info)
599 { 606 {
600 v8::Isolate* isolate = info.GetIsolate(); 607 v8::Isolate* isolate = info.GetIsolate();
601 v8::Local<v8::Object> promise = V8PromiseCustom::createPromise(info.Holder() , isolate); 608 V8TRYCATCH_VOID(v8::Local<v8::Object>, promise, V8PromiseCustom::createPromi se(info.Holder(), isolate));
602 v8::Local<v8::Array> results = v8::Array::New(info.GetIsolate()); 609 v8::Local<v8::Array> results = v8::Array::New(info.GetIsolate());
603 610
604 if (!info.Length() || !info[0]->IsArray()) { 611 if (!info.Length() || !info[0]->IsArray()) {
605 V8PromiseCustom::resolve(promise, results, isolate); 612 V8PromiseCustom::resolve(promise, results, isolate);
606 v8SetReturnValue(info, promise); 613 v8SetReturnValue(info, promise);
607 return; 614 return;
608 } 615 }
609 616
610 // FIXME: Now we limit the iterable type to the Array type. 617 // FIXME: Now we limit the iterable type to the Array type.
611 v8::Local<v8::Array> iterable = info[0].As<v8::Array>(); 618 v8::Local<v8::Array> iterable = info[0].As<v8::Array>();
612 619
613 if (!iterable->Length()) { 620 if (!iterable->Length()) {
614 V8PromiseCustom::resolve(promise, results, isolate); 621 V8PromiseCustom::resolve(promise, results, isolate);
615 v8SetReturnValue(info, promise); 622 v8SetReturnValue(info, promise);
616 return; 623 return;
617 } 624 }
618 625
619 v8::Local<v8::ObjectTemplate> objectTemplate = primitiveWrapperObjectTemplat e(isolate); 626 v8::Local<v8::ObjectTemplate> objectTemplate = primitiveWrapperObjectTemplat e(isolate);
620 v8::Local<v8::Object> countdownWrapper = objectTemplate->NewInstance(); 627 V8TRYCATCH_VOID(v8::Local<v8::Object>, countdownWrapper, objectTemplate->New Instance());
621 countdownWrapper->SetInternalField(V8PromiseCustom::PrimitiveWrapperPrimitiv eIndex, v8::Integer::New(isolate, iterable->Length())); 628 countdownWrapper->SetInternalField(V8PromiseCustom::PrimitiveWrapperPrimitiv eIndex, v8::Integer::New(isolate, iterable->Length()));
622 629
623 v8::Local<v8::Function> onRejected = createClosure(promiseRejectCallback, pr omise, isolate); 630 V8TRYCATCH_VOID(v8::Local<v8::Function>, onRejected, createClosure(promiseRe jectCallback, promise, isolate));
624 for (unsigned i = 0, length = iterable->Length(); i < length; ++i) { 631 for (unsigned i = 0, length = iterable->Length(); i < length; ++i) {
625 // Array-holes should not be skipped by for-of iteration semantics. 632 // Array-holes should not be skipped by for-of iteration semantics.
626 v8::Local<v8::Object> environment = promiseAllEnvironment(promise, count downWrapper, i, results, isolate); 633 V8TRYCATCH_VOID(v8::Local<v8::Object>, environment, promiseAllEnvironmen t(promise, countdownWrapper, i, results, isolate));
627 v8::Local<v8::Function> onFulfilled = createClosure(promiseAllFulfillCal lback, environment, isolate); 634 V8TRYCATCH_VOID(v8::Local<v8::Function>, onFulfilled, createClosure(prom iseAllFulfillCallback, environment, isolate));
628 V8TRYCATCH_VOID(v8::Local<v8::Value>, nextValue, iterable->Get(i)); 635 V8TRYCATCH_VOID(v8::Local<v8::Value>, nextValue, iterable->Get(i));
629 v8::Local<v8::Object> nextPromise = V8PromiseCustom::toPromise(nextValue , isolate); 636 V8TRYCATCH_VOID(v8::Local<v8::Object>, nextPromise, V8PromiseCustom::toP romise(nextValue, isolate));
630 V8PromiseCustom::then(nextPromise, onFulfilled, onRejected, isolate); 637 V8TRYCATCH_VOID(v8::Local<v8::Value>, unused, V8PromiseCustom::then(next Promise, onFulfilled, onRejected, isolate));
631 } 638 }
632 v8SetReturnValue(info, promise); 639 v8SetReturnValue(info, promise);
633 } 640 }
634 641
635 // 642 //
636 // -- V8PromiseCustom -- 643 // -- V8PromiseCustom --
637 v8::Local<v8::Object> V8PromiseCustom::createPromise(v8::Handle<v8::Object> crea tionContext, v8::Isolate* isolate) 644 v8::Local<v8::Object> V8PromiseCustom::createPromise(v8::Handle<v8::Object> crea tionContext, v8::Isolate* isolate)
638 { 645 {
639 v8::Local<v8::ObjectTemplate> internalTemplate = internalObjectTemplate(isol ate); 646 v8::Local<v8::ObjectTemplate> internalTemplate = internalObjectTemplate(isol ate);
640 v8::Local<v8::Object> internal = internalTemplate->NewInstance(); 647 v8::Local<v8::Object> internal = internalTemplate->NewInstance();
648 if (internal.IsEmpty())
649 return v8::Local<v8::Object>();
641 v8::Local<v8::Object> promise = V8DOMWrapper::createWrapper(creationContext, &V8Promise::wrapperTypeInfo, 0, isolate); 650 v8::Local<v8::Object> promise = V8DOMWrapper::createWrapper(creationContext, &V8Promise::wrapperTypeInfo, 0, isolate);
642 651
643 clearDerived(internal, isolate); 652 clearDerived(internal, isolate);
644 setState(internal, Pending, v8::Undefined(isolate), isolate); 653 setState(internal, Pending, v8::Undefined(isolate), isolate);
645 654
646 promise->SetInternalField(v8DOMWrapperObjectIndex, internal); 655 promise->SetInternalField(v8DOMWrapperObjectIndex, internal);
647 return promise; 656 return promise;
648 } 657 }
649 658
650 v8::Local<v8::Object> V8PromiseCustom::getInternal(v8::Handle<v8::Object> promis e) 659 v8::Local<v8::Object> V8PromiseCustom::getInternal(v8::Handle<v8::Object> promis e)
(...skipping 26 matching lines...) Expand all
677 686
678 v8::Local<v8::Object> V8PromiseCustom::toPromise(v8::Handle<v8::Value> maybeProm ise, v8::Isolate* isolate) 687 v8::Local<v8::Object> V8PromiseCustom::toPromise(v8::Handle<v8::Value> maybeProm ise, v8::Isolate* isolate)
679 { 688 {
680 // FIXME: Currently we don't check [[PromiseConstructor]] since we limit 689 // FIXME: Currently we don't check [[PromiseConstructor]] since we limit
681 // the creation of the promise objects only from the Blink Promise 690 // the creation of the promise objects only from the Blink Promise
682 // constructor. 691 // constructor.
683 if (isPromise(maybePromise, isolate)) 692 if (isPromise(maybePromise, isolate))
684 return maybePromise.As<v8::Object>(); 693 return maybePromise.As<v8::Object>();
685 694
686 v8::Local<v8::Object> promise = createPromise(v8::Handle<v8::Object>(), isol ate); 695 v8::Local<v8::Object> promise = createPromise(v8::Handle<v8::Object>(), isol ate);
696 if (promise.IsEmpty())
697 return v8::Local<v8::Object>();
687 resolve(promise, maybePromise, isolate); 698 resolve(promise, maybePromise, isolate);
688 return promise; 699 return promise;
689 } 700 }
690 701
691 void V8PromiseCustom::resolve(v8::Handle<v8::Object> promise, v8::Handle<v8::Val ue> result, v8::Isolate* isolate) 702 void V8PromiseCustom::resolve(v8::Handle<v8::Object> promise, v8::Handle<v8::Val ue> result, v8::Isolate* isolate)
692 { 703 {
693 ASSERT(!result.IsEmpty()); 704 ASSERT(!result.IsEmpty());
694 v8::Local<v8::Object> internal = getInternal(promise); 705 v8::Local<v8::Object> internal = getInternal(promise);
695 PromiseState state = getState(internal); 706 PromiseState state = getState(internal);
696 if (state != Pending) 707 if (state != Pending)
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
734 { 745 {
735 v8::Handle<v8::Object> internal = getInternal(promise); 746 v8::Handle<v8::Object> internal = getInternal(promise);
736 while (getState(internal) == Following) { 747 while (getState(internal) == Following) {
737 promise = internal->GetInternalField(InternalResultIndex).As<v8::Object> (); 748 promise = internal->GetInternalField(InternalResultIndex).As<v8::Object> ();
738 internal = getInternal(promise); 749 internal = getInternal(promise);
739 } 750 }
740 // FIXME: Currently we don't lookup "constructor" property since we limit 751 // FIXME: Currently we don't lookup "constructor" property since we limit
741 // the creation of the promise objects only from the Blink Promise 752 // the creation of the promise objects only from the Blink Promise
742 // constructor. 753 // constructor.
743 v8::Local<v8::Object> derivedPromise = createPromise(v8::Handle<v8::Object>( ), isolate); 754 v8::Local<v8::Object> derivedPromise = createPromise(v8::Handle<v8::Object>( ), isolate);
755 if (derivedPromise.IsEmpty())
756 return v8::Local<v8::Object>();
744 updateDerivedFromPromise(derivedPromise, onFulfilled, onRejected, promise, i solate); 757 updateDerivedFromPromise(derivedPromise, onFulfilled, onRejected, promise, i solate);
745 return derivedPromise; 758 return derivedPromise;
746 } 759 }
747 760
748 void V8PromiseCustom::setValue(v8::Handle<v8::Object> promise, v8::Handle<v8::Va lue> value, v8::Isolate* isolate) 761 void V8PromiseCustom::setValue(v8::Handle<v8::Object> promise, v8::Handle<v8::Va lue> value, v8::Isolate* isolate)
749 { 762 {
750 PromisePropagator propagator; 763 PromisePropagator propagator;
751 propagator.setValue(promise, value, isolate); 764 propagator.setValue(promise, value, isolate);
752 propagator.performPropagation(isolate); 765 propagator.performPropagation(isolate);
753 } 766 }
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
792 PromisePropagator propagator; 805 PromisePropagator propagator;
793 propagator.updateDerivedFromPromise(derivedPromise, onFulfilled, onRejected, promise, isolate); 806 propagator.updateDerivedFromPromise(derivedPromise, onFulfilled, onRejected, promise, isolate);
794 propagator.performPropagation(isolate); 807 propagator.performPropagation(isolate);
795 } 808 }
796 809
797 v8::Local<v8::Object> V8PromiseCustom::coerceThenable(v8::Handle<v8::Object> the nable, v8::Handle<v8::Function> then, v8::Isolate* isolate) 810 v8::Local<v8::Object> V8PromiseCustom::coerceThenable(v8::Handle<v8::Object> the nable, v8::Handle<v8::Function> then, v8::Isolate* isolate)
798 { 811 {
799 ASSERT(!thenable.IsEmpty()); 812 ASSERT(!thenable.IsEmpty());
800 ASSERT(!then.IsEmpty()); 813 ASSERT(!then.IsEmpty());
801 v8::Local<v8::Object> promise = createPromise(v8::Handle<v8::Object>(), isol ate); 814 v8::Local<v8::Object> promise = createPromise(v8::Handle<v8::Object>(), isol ate);
802 v8::Handle<v8::Value> argv[] = { 815 if (promise.IsEmpty())
803 createClosure(promiseResolveCallback, promise, isolate), 816 return v8::Local<v8::Object>();
804 createClosure(promiseRejectCallback, promise, isolate) 817 v8::Handle<v8::Value> onFulfilled = createClosure(promiseResolveCallback, pr omise, isolate);
805 }; 818 if (onFulfilled.IsEmpty())
819 return v8::Local<v8::Object>();
820 v8::Handle<v8::Value> onRejected = createClosure(promiseRejectCallback, prom ise, isolate);
821 if (onRejected.IsEmpty())
822 return v8::Local<v8::Object>();
823 v8::Handle<v8::Value> argv[] = { onFulfilled, onRejected };
824
806 v8::TryCatch trycatch; 825 v8::TryCatch trycatch;
807 if (V8ScriptRunner::callFunction(then, currentExecutionContext(isolate), the nable, WTF_ARRAY_LENGTH(argv), argv, isolate).IsEmpty()) { 826 if (V8ScriptRunner::callFunction(then, currentExecutionContext(isolate), the nable, WTF_ARRAY_LENGTH(argv), argv, isolate).IsEmpty()) {
808 reject(promise, trycatch.Exception(), isolate); 827 reject(promise, trycatch.Exception(), isolate);
809 } 828 }
810 setHiddenValue(isolate, thenable, "thenableHiddenPromise", promise); 829 setHiddenValue(isolate, thenable, "thenableHiddenPromise", promise);
811 return promise; 830 return promise;
812 } 831 }
813 832
814 void V8PromiseCustom::callHandler(v8::Handle<v8::Object> promise, v8::Handle<v8: :Function> handler, v8::Handle<v8::Value> argument, PromiseState originatorState , v8::Isolate* isolate) 833 void V8PromiseCustom::callHandler(v8::Handle<v8::Object> promise, v8::Handle<v8: :Function> handler, v8::Handle<v8::Value> argument, PromiseState originatorState , v8::Isolate* isolate)
815 { 834 {
816 ASSERT(originatorState == Fulfilled || originatorState == Rejected); 835 ASSERT(originatorState == Fulfilled || originatorState == Rejected);
817 ExecutionContext* executionContext = currentExecutionContext(isolate); 836 ExecutionContext* executionContext = currentExecutionContext(isolate);
818 ASSERT(executionContext && executionContext->isContextThread()); 837 ASSERT(executionContext && executionContext->isContextThread());
819 executionContext->postTask(adoptPtr(new CallHandlerTask(promise, handler, ar gument, originatorState, isolate, executionContext))); 838 executionContext->postTask(adoptPtr(new CallHandlerTask(promise, handler, ar gument, originatorState, isolate, executionContext)));
820 } 839 }
821 840
822 } // namespace WebCore 841 } // namespace WebCore
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698