Index: test/cctest/test-code-stub-assembler.cc |
diff --git a/test/cctest/test-code-stub-assembler.cc b/test/cctest/test-code-stub-assembler.cc |
index 8b5a8b965d9631acb80fd7d65e2324fc1dc3b9f0..d0bae923aefda7f6d8f7be7609d243b28242afc3 100644 |
--- a/test/cctest/test-code-stub-assembler.cc |
+++ b/test/cctest/test-code-stub-assembler.cc |
@@ -2070,5 +2070,154 @@ TEST(AllocateFunctionWithMapAndContext) { |
CHECK_EQ(isolate->heap()->undefined_value(), fun->next_function_link()); |
} |
+TEST(CreatePromiseGetCapabilitiesExecutorContext) { |
+ Isolate* isolate(CcTest::InitIsolateOnce()); |
+ |
+ const int kNumParams = 1; |
+ CodeAssemblerTester data(isolate, kNumParams); |
+ PromiseBuiltinsAssembler m(data.state()); |
+ |
+ Node* const context = m.Parameter(kNumParams + 2); |
+ Node* const native_context = m.LoadNativeContext(context); |
+ |
+ Node* const map = m.LoadRoot(Heap::kJSPromiseCapabilityMapRootIndex); |
+ Node* const capability = m.AllocateJSObjectFromMap(map); |
+ m.StoreObjectFieldNoWriteBarrier( |
+ capability, JSPromiseCapability::kPromiseOffset, m.UndefinedConstant()); |
+ m.StoreObjectFieldNoWriteBarrier( |
+ capability, JSPromiseCapability::kResolveOffset, m.UndefinedConstant()); |
+ m.StoreObjectFieldNoWriteBarrier( |
+ capability, JSPromiseCapability::kRejectOffset, m.UndefinedConstant()); |
+ Node* const executor_context = |
+ m.CreatePromiseGetCapabilitiesExecutorContext(capability, native_context); |
+ m.Return(executor_context); |
+ |
+ Handle<Code> code = data.GenerateCode(); |
+ CHECK(!code.is_null()); |
+ |
+ FunctionTester ft(code, kNumParams); |
+ Handle<Object> result_obj = |
+ ft.Call(isolate->factory()->undefined_value()).ToHandleChecked(); |
+ CHECK(result_obj->IsContext()); |
+ Handle<Context> context_js = Handle<Context>::cast(result_obj); |
+ CHECK_EQ(GetPromiseCapabilityExecutor::kContextLength, context_js->length()); |
+ CHECK_EQ(isolate->native_context()->closure(), context_js->closure()); |
+ CHECK_EQ(isolate->heap()->the_hole_value(), context_js->extension()); |
+ CHECK_EQ(*isolate->native_context(), context_js->native_context()); |
+ CHECK(context_js->get(GetPromiseCapabilityExecutor::kCapabilitySlot) |
+ ->IsJSPromiseCapability()); |
+} |
+ |
+TEST(NewPromiseCapability) { |
+ Isolate* isolate(CcTest::InitIsolateOnce()); |
+ |
+ { // Builtin Promise |
+ const int kNumParams = 1; |
+ CodeAssemblerTester data(isolate, kNumParams); |
+ PromiseBuiltinsAssembler m(data.state()); |
+ |
+ Node* const context = m.Parameter(kNumParams + 2); |
+ Node* const native_context = m.LoadNativeContext(context); |
+ Node* const promise_constructor = |
+ m.LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX); |
+ |
+ Node* const capability = |
+ m.NewPromiseCapability(context, promise_constructor); |
+ m.Return(capability); |
+ |
+ Handle<Code> code = data.GenerateCode(); |
+ FunctionTester ft(code, kNumParams); |
+ |
+ Handle<Object> result_obj = |
+ ft.Call(isolate->factory()->undefined_value()).ToHandleChecked(); |
+ CHECK(result_obj->IsJSPromiseCapability()); |
+ Handle<JSPromiseCapability> result = |
+ Handle<JSPromiseCapability>::cast(result_obj); |
+ |
+ CHECK(result->promise()->IsJSPromise()); |
+ CHECK(result->resolve()->IsJSFunction()); |
+ CHECK(result->reject()->IsJSFunction()); |
+ CHECK_EQ(isolate->native_context()->promise_resolve_shared_fun(), |
+ JSFunction::cast(result->resolve())->shared()); |
+ CHECK_EQ(isolate->native_context()->promise_reject_shared_fun(), |
+ JSFunction::cast(result->reject())->shared()); |
+ |
+ Handle<JSFunction> callbacks[] = { |
+ handle(JSFunction::cast(result->resolve())), |
+ handle(JSFunction::cast(result->reject()))}; |
+ |
+ for (auto&& callback : callbacks) { |
+ Handle<Context> context(Context::cast(callback->context())); |
+ CHECK_EQ(isolate->native_context()->closure(), context->closure()); |
+ CHECK_EQ(isolate->heap()->the_hole_value(), context->extension()); |
+ CHECK_EQ(*isolate->native_context(), context->native_context()); |
+ CHECK_EQ(PromiseUtils::kPromiseContextLength, context->length()); |
+ CHECK_EQ(context->get(PromiseUtils::kPromiseSlot), result->promise()); |
+ } |
+ } |
+ |
+ { // Custom Promise |
+ const int kNumParams = 2; |
+ CodeAssemblerTester data(isolate, kNumParams); |
+ PromiseBuiltinsAssembler m(data.state()); |
+ |
+ Node* const context = m.Parameter(kNumParams + 2); |
+ |
+ Node* const constructor = m.Parameter(1); |
+ Node* const capability = m.NewPromiseCapability(context, constructor); |
+ m.Return(capability); |
+ |
+ Handle<Code> code = data.GenerateCode(); |
+ FunctionTester ft(code, kNumParams); |
+ |
+ Handle<JSFunction> constructor_fn = |
+ Handle<JSFunction>::cast(v8::Utils::OpenHandle(*CompileRun( |
+ "(function FakePromise(executor) {" |
+ " var self = this;" |
+ " function resolve(value) { self.resolvedValue = value; }" |
+ " function reject(reason) { self.rejectedReason = reason; }" |
+ " executor(resolve, reject);" |
+ "})"))); |
+ |
+ Handle<Object> result_obj = |
+ ft.Call(isolate->factory()->undefined_value(), constructor_fn) |
+ .ToHandleChecked(); |
+ CHECK(result_obj->IsJSPromiseCapability()); |
+ Handle<JSPromiseCapability> result = |
+ Handle<JSPromiseCapability>::cast(result_obj); |
+ |
+ CHECK(result->promise()->IsJSObject()); |
+ Handle<JSObject> promise(JSObject::cast(result->promise())); |
+ CHECK_EQ(constructor_fn->prototype_or_initial_map(), promise->map()); |
+ CHECK(result->resolve()->IsJSFunction()); |
+ CHECK(result->reject()->IsJSFunction()); |
+ |
+ Handle<String> resolved_str = |
+ isolate->factory()->NewStringFromAsciiChecked("resolvedStr"); |
+ Handle<String> rejected_str = |
+ isolate->factory()->NewStringFromAsciiChecked("rejectedStr"); |
+ |
+ Handle<Object> argv1[] = {resolved_str}; |
+ Handle<Object> ret = |
+ Execution::Call(isolate, handle(result->resolve(), isolate), |
+ isolate->factory()->undefined_value(), 1, argv1) |
+ .ToHandleChecked(); |
+ |
+ Handle<Object> prop1 = |
+ JSReceiver::GetProperty(isolate, promise, "resolvedValue") |
+ .ToHandleChecked(); |
+ CHECK_EQ(*resolved_str, *prop1); |
+ |
+ Handle<Object> argv2[] = {rejected_str}; |
+ ret = Execution::Call(isolate, handle(result->reject(), isolate), |
+ isolate->factory()->undefined_value(), 1, argv2) |
+ .ToHandleChecked(); |
+ Handle<Object> prop2 = |
+ JSReceiver::GetProperty(isolate, promise, "rejectedReason") |
+ .ToHandleChecked(); |
+ CHECK_EQ(*rejected_str, *prop2); |
+ } |
+} |
+ |
} // namespace internal |
} // namespace v8 |