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 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
47 #include "core/frame/UseCounter.h" | 47 #include "core/frame/UseCounter.h" |
48 #include "core/inspector/InspectorPromiseInstrumentation.h" | 48 #include "core/inspector/InspectorPromiseInstrumentation.h" |
49 #include "core/workers/WorkerGlobalScope.h" | 49 #include "core/workers/WorkerGlobalScope.h" |
50 #include "platform/Task.h" | 50 #include "platform/Task.h" |
51 #include "wtf/Deque.h" | 51 #include "wtf/Deque.h" |
52 #include "wtf/Functional.h" | 52 #include "wtf/Functional.h" |
53 #include "wtf/Noncopyable.h" | 53 #include "wtf/Noncopyable.h" |
54 #include "wtf/PassOwnPtr.h" | 54 #include "wtf/PassOwnPtr.h" |
55 #include <v8.h> | 55 #include <v8.h> |
56 | 56 |
57 #define V8TRYCATCH_VOID_EMPTY(type, var, value) \ | 57 #define TONATIVE_VOID_EMPTY(type, var, value) \ |
58 type var; \ | 58 type var; \ |
59 { \ | 59 { \ |
60 v8::TryCatch block; \ | 60 v8::TryCatch block; \ |
61 var = (value); \ | 61 var = (value); \ |
62 if (UNLIKELY(block.HasCaught())) { \ | 62 if (UNLIKELY(block.HasCaught())) { \ |
63 return; \ | 63 return; \ |
64 } \ | 64 } \ |
65 } | 65 } |
66 | 66 |
67 namespace WebCore { | 67 namespace WebCore { |
(...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
516 { | 516 { |
517 v8SetReturnValue(info, v8::Local<v8::Value>()); | 517 v8SetReturnValue(info, v8::Local<v8::Value>()); |
518 v8::Isolate* isolate = info.GetIsolate(); | 518 v8::Isolate* isolate = info.GetIsolate(); |
519 ExecutionContext* executionContext = callingExecutionContext(isolate); | 519 ExecutionContext* executionContext = callingExecutionContext(isolate); |
520 UseCounter::count(executionContext, UseCounter::PromiseConstructor); | 520 UseCounter::count(executionContext, UseCounter::PromiseConstructor); |
521 if (!info.Length() || !info[0]->IsFunction()) { | 521 if (!info.Length() || !info[0]->IsFunction()) { |
522 throwTypeError("Promise constructor takes a function argument", isolate)
; | 522 throwTypeError("Promise constructor takes a function argument", isolate)
; |
523 return; | 523 return; |
524 } | 524 } |
525 v8::Local<v8::Function> init = info[0].As<v8::Function>(); | 525 v8::Local<v8::Function> init = info[0].As<v8::Function>(); |
526 V8TRYCATCH_VOID_EMPTY(v8::Local<v8::Object>, promise, V8PromiseCustom::creat
ePromise(info.Holder(), isolate)); | 526 TONATIVE_VOID_EMPTY(v8::Local<v8::Object>, promise, V8PromiseCustom::createP
romise(info.Holder(), isolate)); |
527 V8TRYCATCH_VOID_EMPTY(v8::Handle<v8::Value>, resolve, createClosure(promiseR
esolveCallback, promise, isolate)); | 527 TONATIVE_VOID_EMPTY(v8::Handle<v8::Value>, resolve, createClosure(promiseRes
olveCallback, promise, isolate)); |
528 V8TRYCATCH_VOID_EMPTY(v8::Handle<v8::Value>, reject, createClosure(promiseRe
jectCallback, promise, isolate)); | 528 TONATIVE_VOID_EMPTY(v8::Handle<v8::Value>, reject, createClosure(promiseReje
ctCallback, promise, isolate)); |
529 v8::Handle<v8::Value> argv[] = { resolve, reject }; | 529 v8::Handle<v8::Value> argv[] = { resolve, reject }; |
530 v8::TryCatch trycatch; | 530 v8::TryCatch trycatch; |
531 if (V8ScriptRunner::callFunction(init, currentExecutionContext(isolate), v8:
:Undefined(isolate), WTF_ARRAY_LENGTH(argv), argv, isolate).IsEmpty()) { | 531 if (V8ScriptRunner::callFunction(init, currentExecutionContext(isolate), v8:
:Undefined(isolate), WTF_ARRAY_LENGTH(argv), argv, isolate).IsEmpty()) { |
532 // An exception is thrown. Reject the promise if its resolved flag is un
set. | 532 // An exception is thrown. Reject the promise if its resolved flag is un
set. |
533 V8PromiseCustom::reject(promise, trycatch.Exception(), isolate); | 533 V8PromiseCustom::reject(promise, trycatch.Exception(), isolate); |
534 } | 534 } |
535 v8SetReturnValue(info, promise); | 535 v8SetReturnValue(info, promise); |
536 return; | 536 return; |
537 } | 537 } |
538 | 538 |
539 void V8Promise::thenMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info
) | 539 void V8Promise::thenMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info
) |
540 { | 540 { |
541 v8::Isolate* isolate = info.GetIsolate(); | 541 v8::Isolate* isolate = info.GetIsolate(); |
542 v8::Local<v8::Function> onFulfilled, onRejected; | 542 v8::Local<v8::Function> onFulfilled, onRejected; |
543 if (info.Length() > 0 && info[0]->IsFunction()) | 543 if (info.Length() > 0 && info[0]->IsFunction()) |
544 onFulfilled = info[0].As<v8::Function>(); | 544 onFulfilled = info[0].As<v8::Function>(); |
545 if (info.Length() > 1 && info[1]->IsFunction()) | 545 if (info.Length() > 1 && info[1]->IsFunction()) |
546 onRejected = info[1].As<v8::Function>(); | 546 onRejected = info[1].As<v8::Function>(); |
547 V8TRYCATCH_VOID_EMPTY(v8::Local<v8::Value>, newPromise, V8PromiseCustom::the
n(info.Holder(), onFulfilled, onRejected, isolate)); | 547 TONATIVE_VOID_EMPTY(v8::Local<v8::Value>, newPromise, V8PromiseCustom::then(
info.Holder(), onFulfilled, onRejected, isolate)); |
548 v8SetReturnValue(info, newPromise); | 548 v8SetReturnValue(info, newPromise); |
549 } | 549 } |
550 | 550 |
551 void V8Promise::castMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info
) | 551 void V8Promise::castMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info
) |
552 { | 552 { |
553 v8::Isolate* isolate = info.GetIsolate(); | 553 v8::Isolate* isolate = info.GetIsolate(); |
554 ExecutionContext* executionContext = callingExecutionContext(isolate); | 554 ExecutionContext* executionContext = callingExecutionContext(isolate); |
555 UseCounter::count(executionContext, UseCounter::PromiseCast); | 555 UseCounter::count(executionContext, UseCounter::PromiseCast); |
556 v8::Local<v8::Value> result = v8::Undefined(isolate); | 556 v8::Local<v8::Value> result = v8::Undefined(isolate); |
557 if (info.Length() > 0) | 557 if (info.Length() > 0) |
558 result = info[0]; | 558 result = info[0]; |
559 | 559 |
560 V8TRYCATCH_VOID_EMPTY(v8::Local<v8::Value>, cast, V8PromiseCustom::toPromise
(result, isolate)); | 560 TONATIVE_VOID_EMPTY(v8::Local<v8::Value>, cast, V8PromiseCustom::toPromise(r
esult, isolate)); |
561 v8SetReturnValue(info, cast); | 561 v8SetReturnValue(info, cast); |
562 } | 562 } |
563 | 563 |
564 void V8Promise::catchMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& inf
o) | 564 void V8Promise::catchMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& inf
o) |
565 { | 565 { |
566 v8::Isolate* isolate = info.GetIsolate(); | 566 v8::Isolate* isolate = info.GetIsolate(); |
567 v8::Local<v8::Function> onFulfilled, onRejected; | 567 v8::Local<v8::Function> onFulfilled, onRejected; |
568 | 568 |
569 if (info.Length() > 0 && !info[0]->IsUndefined()) { | 569 if (info.Length() > 0 && !info[0]->IsUndefined()) { |
570 if (!info[0]->IsFunction()) { | 570 if (!info[0]->IsFunction()) { |
571 v8SetReturnValue(info, throwTypeError("onRejected must be a function
or undefined", isolate)); | 571 v8SetReturnValue(info, throwTypeError("onRejected must be a function
or undefined", isolate)); |
572 return; | 572 return; |
573 } | 573 } |
574 onRejected = info[0].As<v8::Function>(); | 574 onRejected = info[0].As<v8::Function>(); |
575 } | 575 } |
576 V8TRYCATCH_VOID_EMPTY(v8::Local<v8::Value>, newPromise, V8PromiseCustom::the
n(info.Holder(), onFulfilled, onRejected, isolate)); | 576 TONATIVE_VOID_EMPTY(v8::Local<v8::Value>, newPromise, V8PromiseCustom::then(
info.Holder(), onFulfilled, onRejected, isolate)); |
577 v8SetReturnValue(info, newPromise); | 577 v8SetReturnValue(info, newPromise); |
578 } | 578 } |
579 | 579 |
580 void V8Promise::resolveMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& i
nfo) | 580 void V8Promise::resolveMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& i
nfo) |
581 { | 581 { |
582 v8::Isolate* isolate = info.GetIsolate(); | 582 v8::Isolate* isolate = info.GetIsolate(); |
583 ExecutionContext* executionContext = callingExecutionContext(isolate); | 583 ExecutionContext* executionContext = callingExecutionContext(isolate); |
584 UseCounter::count(executionContext, UseCounter::PromiseResolve); | 584 UseCounter::count(executionContext, UseCounter::PromiseResolve); |
585 v8::Local<v8::Value> result = v8::Undefined(isolate); | 585 v8::Local<v8::Value> result = v8::Undefined(isolate); |
586 if (info.Length() > 0) | 586 if (info.Length() > 0) |
587 result = info[0]; | 587 result = info[0]; |
588 | 588 |
589 V8TRYCATCH_VOID_EMPTY(v8::Local<v8::Object>, promise, V8PromiseCustom::creat
ePromise(info.Holder(), isolate)); | 589 TONATIVE_VOID_EMPTY(v8::Local<v8::Object>, promise, V8PromiseCustom::createP
romise(info.Holder(), isolate)); |
590 V8PromiseCustom::resolve(promise, result, isolate); | 590 V8PromiseCustom::resolve(promise, result, isolate); |
591 v8SetReturnValue(info, promise); | 591 v8SetReturnValue(info, promise); |
592 } | 592 } |
593 | 593 |
594 void V8Promise::rejectMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& in
fo) | 594 void V8Promise::rejectMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& in
fo) |
595 { | 595 { |
596 v8::Isolate* isolate = info.GetIsolate(); | 596 v8::Isolate* isolate = info.GetIsolate(); |
597 ExecutionContext* executionContext = callingExecutionContext(isolate); | 597 ExecutionContext* executionContext = callingExecutionContext(isolate); |
598 UseCounter::count(executionContext, UseCounter::PromiseReject); | 598 UseCounter::count(executionContext, UseCounter::PromiseReject); |
599 v8::Local<v8::Value> result = v8::Undefined(isolate); | 599 v8::Local<v8::Value> result = v8::Undefined(isolate); |
600 if (info.Length() > 0) | 600 if (info.Length() > 0) |
601 result = info[0]; | 601 result = info[0]; |
602 | 602 |
603 V8TRYCATCH_VOID_EMPTY(v8::Local<v8::Object>, promise, V8PromiseCustom::creat
ePromise(info.Holder(), isolate)); | 603 TONATIVE_VOID_EMPTY(v8::Local<v8::Object>, promise, V8PromiseCustom::createP
romise(info.Holder(), isolate)); |
604 V8PromiseCustom::reject(promise, result, isolate); | 604 V8PromiseCustom::reject(promise, result, isolate); |
605 v8SetReturnValue(info, promise); | 605 v8SetReturnValue(info, promise); |
606 } | 606 } |
607 | 607 |
608 void V8Promise::raceMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info
) | 608 void V8Promise::raceMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info
) |
609 { | 609 { |
610 v8::Isolate* isolate = info.GetIsolate(); | 610 v8::Isolate* isolate = info.GetIsolate(); |
611 V8TRYCATCH_VOID_EMPTY(v8::Local<v8::Object>, promise, V8PromiseCustom::creat
ePromise(info.Holder(), isolate)); | 611 TONATIVE_VOID_EMPTY(v8::Local<v8::Object>, promise, V8PromiseCustom::createP
romise(info.Holder(), isolate)); |
612 | 612 |
613 if (!info.Length() || !info[0]->IsArray()) { | 613 if (!info.Length() || !info[0]->IsArray()) { |
614 v8SetReturnValue(info, promise); | 614 v8SetReturnValue(info, promise); |
615 return; | 615 return; |
616 } | 616 } |
617 | 617 |
618 // FIXME: Now we limit the iterable type to the Array type. | 618 // FIXME: Now we limit the iterable type to the Array type. |
619 v8::Local<v8::Array> iterable = info[0].As<v8::Array>(); | 619 v8::Local<v8::Array> iterable = info[0].As<v8::Array>(); |
620 V8TRYCATCH_VOID_EMPTY(v8::Local<v8::Function>, onFulfilled, createClosure(pr
omiseResolveCallback, promise, isolate)); | 620 TONATIVE_VOID_EMPTY(v8::Local<v8::Function>, onFulfilled, createClosure(prom
iseResolveCallback, promise, isolate)); |
621 V8TRYCATCH_VOID_EMPTY(v8::Local<v8::Function>, onRejected, createClosure(pro
miseRejectCallback, promise, isolate)); | 621 TONATIVE_VOID_EMPTY(v8::Local<v8::Function>, onRejected, createClosure(promi
seRejectCallback, promise, isolate)); |
622 | 622 |
623 for (unsigned i = 0, length = iterable->Length(); i < length; ++i) { | 623 for (unsigned i = 0, length = iterable->Length(); i < length; ++i) { |
624 // Array-holes should not be skipped by for-of iteration semantics. | 624 // Array-holes should not be skipped by for-of iteration semantics. |
625 V8TRYCATCH_VOID_EMPTY(v8::Local<v8::Value>, nextValue, iterable->Get(i))
; | 625 TONATIVE_VOID_EMPTY(v8::Local<v8::Value>, nextValue, iterable->Get(i)); |
626 V8TRYCATCH_VOID_EMPTY(v8::Local<v8::Object>, nextPromise, V8PromiseCusto
m::toPromise(nextValue, isolate)); | 626 TONATIVE_VOID_EMPTY(v8::Local<v8::Object>, nextPromise, V8PromiseCustom:
:toPromise(nextValue, isolate)); |
627 V8TRYCATCH_VOID_EMPTY(v8::Local<v8::Value>, unused, V8PromiseCustom::the
n(nextPromise, onFulfilled, onRejected, isolate)); | 627 TONATIVE_VOID_EMPTY(v8::Local<v8::Value>, unused, V8PromiseCustom::then(
nextPromise, onFulfilled, onRejected, isolate)); |
628 } | 628 } |
629 v8SetReturnValue(info, promise); | 629 v8SetReturnValue(info, promise); |
630 } | 630 } |
631 | 631 |
632 void V8Promise::allMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) | 632 void V8Promise::allMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) |
633 { | 633 { |
634 v8::Isolate* isolate = info.GetIsolate(); | 634 v8::Isolate* isolate = info.GetIsolate(); |
635 V8TRYCATCH_VOID_EMPTY(v8::Local<v8::Object>, promise, V8PromiseCustom::creat
ePromise(info.Holder(), isolate)); | 635 TONATIVE_VOID_EMPTY(v8::Local<v8::Object>, promise, V8PromiseCustom::createP
romise(info.Holder(), isolate)); |
636 v8::Local<v8::Array> results = v8::Array::New(info.GetIsolate()); | 636 v8::Local<v8::Array> results = v8::Array::New(info.GetIsolate()); |
637 | 637 |
638 if (!info.Length() || !info[0]->IsArray()) { | 638 if (!info.Length() || !info[0]->IsArray()) { |
639 V8PromiseCustom::resolve(promise, results, isolate); | 639 V8PromiseCustom::resolve(promise, results, isolate); |
640 v8SetReturnValue(info, promise); | 640 v8SetReturnValue(info, promise); |
641 return; | 641 return; |
642 } | 642 } |
643 | 643 |
644 // FIXME: Now we limit the iterable type to the Array type. | 644 // FIXME: Now we limit the iterable type to the Array type. |
645 v8::Local<v8::Array> iterable = info[0].As<v8::Array>(); | 645 v8::Local<v8::Array> iterable = info[0].As<v8::Array>(); |
646 | 646 |
647 if (!iterable->Length()) { | 647 if (!iterable->Length()) { |
648 V8PromiseCustom::resolve(promise, results, isolate); | 648 V8PromiseCustom::resolve(promise, results, isolate); |
649 v8SetReturnValue(info, promise); | 649 v8SetReturnValue(info, promise); |
650 return; | 650 return; |
651 } | 651 } |
652 | 652 |
653 v8::Local<v8::ObjectTemplate> objectTemplate = primitiveWrapperObjectTemplat
e(isolate); | 653 v8::Local<v8::ObjectTemplate> objectTemplate = primitiveWrapperObjectTemplat
e(isolate); |
654 V8TRYCATCH_VOID_EMPTY(v8::Local<v8::Object>, countdownWrapper, objectTemplat
e->NewInstance()); | 654 TONATIVE_VOID_EMPTY(v8::Local<v8::Object>, countdownWrapper, objectTemplate-
>NewInstance()); |
655 countdownWrapper->SetInternalField(V8PromiseCustom::PrimitiveWrapperPrimitiv
eIndex, v8::Integer::New(isolate, iterable->Length())); | 655 countdownWrapper->SetInternalField(V8PromiseCustom::PrimitiveWrapperPrimitiv
eIndex, v8::Integer::New(isolate, iterable->Length())); |
656 | 656 |
657 V8TRYCATCH_VOID_EMPTY(v8::Local<v8::Function>, onRejected, createClosure(pro
miseRejectCallback, promise, isolate)); | 657 TONATIVE_VOID_EMPTY(v8::Local<v8::Function>, onRejected, createClosure(promi
seRejectCallback, promise, isolate)); |
658 for (unsigned i = 0, length = iterable->Length(); i < length; ++i) { | 658 for (unsigned i = 0, length = iterable->Length(); i < length; ++i) { |
659 // Array-holes should not be skipped by for-of iteration semantics. | 659 // Array-holes should not be skipped by for-of iteration semantics. |
660 V8TRYCATCH_VOID_EMPTY(v8::Local<v8::Object>, environment, promiseAllEnvi
ronment(promise, countdownWrapper, i, results, isolate)); | 660 TONATIVE_VOID_EMPTY(v8::Local<v8::Object>, environment, promiseAllEnviro
nment(promise, countdownWrapper, i, results, isolate)); |
661 V8TRYCATCH_VOID_EMPTY(v8::Local<v8::Function>, onFulfilled, createClosur
e(promiseAllFulfillCallback, environment, isolate)); | 661 TONATIVE_VOID_EMPTY(v8::Local<v8::Function>, onFulfilled, createClosure(
promiseAllFulfillCallback, environment, isolate)); |
662 V8TRYCATCH_VOID_EMPTY(v8::Local<v8::Value>, nextValue, iterable->Get(i))
; | 662 TONATIVE_VOID_EMPTY(v8::Local<v8::Value>, nextValue, iterable->Get(i)); |
663 V8TRYCATCH_VOID_EMPTY(v8::Local<v8::Object>, nextPromise, V8PromiseCusto
m::toPromise(nextValue, isolate)); | 663 TONATIVE_VOID_EMPTY(v8::Local<v8::Object>, nextPromise, V8PromiseCustom:
:toPromise(nextValue, isolate)); |
664 V8TRYCATCH_VOID_EMPTY(v8::Local<v8::Value>, unused, V8PromiseCustom::the
n(nextPromise, onFulfilled, onRejected, isolate)); | 664 TONATIVE_VOID_EMPTY(v8::Local<v8::Value>, unused, V8PromiseCustom::then(
nextPromise, onFulfilled, onRejected, isolate)); |
665 } | 665 } |
666 v8SetReturnValue(info, promise); | 666 v8SetReturnValue(info, promise); |
667 } | 667 } |
668 | 668 |
669 // | 669 // |
670 // -- V8PromiseCustom -- | 670 // -- V8PromiseCustom -- |
671 v8::Local<v8::Object> V8PromiseCustom::createPromise(v8::Handle<v8::Object> crea
tionContext, v8::Isolate* isolate) | 671 v8::Local<v8::Object> V8PromiseCustom::createPromise(v8::Handle<v8::Object> crea
tionContext, v8::Isolate* isolate) |
672 { | 672 { |
673 v8::Local<v8::ObjectTemplate> internalTemplate = internalObjectTemplate(isol
ate); | 673 v8::Local<v8::ObjectTemplate> internalTemplate = internalObjectTemplate(isol
ate); |
674 v8::Local<v8::Object> internal = internalTemplate->NewInstance(); | 674 v8::Local<v8::Object> internal = internalTemplate->NewInstance(); |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
854 | 854 |
855 void V8PromiseCustom::callHandler(v8::Handle<v8::Object> promise, v8::Handle<v8:
:Function> handler, v8::Handle<v8::Value> argument, PromiseState originatorState
, v8::Isolate* isolate) | 855 void V8PromiseCustom::callHandler(v8::Handle<v8::Object> promise, v8::Handle<v8:
:Function> handler, v8::Handle<v8::Value> argument, PromiseState originatorState
, v8::Isolate* isolate) |
856 { | 856 { |
857 ASSERT(originatorState == Fulfilled || originatorState == Rejected); | 857 ASSERT(originatorState == Fulfilled || originatorState == Rejected); |
858 ExecutionContext* executionContext = currentExecutionContext(isolate); | 858 ExecutionContext* executionContext = currentExecutionContext(isolate); |
859 ASSERT(executionContext && executionContext->isContextThread()); | 859 ASSERT(executionContext && executionContext->isContextThread()); |
860 executionContext->postTask(adoptPtr(new CallHandlerTask(promise, handler, ar
gument, originatorState, isolate, executionContext))); | 860 executionContext->postTask(adoptPtr(new CallHandlerTask(promise, handler, ar
gument, originatorState, isolate, executionContext))); |
861 } | 861 } |
862 | 862 |
863 } // namespace WebCore | 863 } // namespace WebCore |
OLD | NEW |