diff options
Diffstat (limited to 'deps')
-rw-r--r-- | deps/v8/include/v8-debug.h | 6 | ||||
-rw-r--r-- | deps/v8/src/debug/debug.cc | 27 | ||||
-rw-r--r-- | deps/v8/src/debug/debug.h | 3 | ||||
-rw-r--r-- | deps/v8/src/debug/debug.js | 37 | ||||
-rw-r--r-- | deps/v8/src/js/promise.js | 6 | ||||
-rw-r--r-- | deps/v8/src/runtime/runtime-debug.cc | 9 | ||||
-rw-r--r-- | deps/v8/src/runtime/runtime.h | 1 | ||||
-rw-r--r-- | deps/v8/test/mjsunit/es6/debug-promises/events.js | 122 | ||||
-rw-r--r-- | deps/v8/test/mjsunit/es6/debug-promises/resolve-after-aborted-try-finally.js | 32 | ||||
-rw-r--r-- | deps/v8/test/mjsunit/es6/debug-promises/resolve-after-try-catch.js | 29 | ||||
-rw-r--r-- | deps/v8/test/mjsunit/es6/debug-promises/rethrow-in-try-finally.js | 30 |
11 files changed, 299 insertions, 3 deletions
diff --git a/deps/v8/include/v8-debug.h b/deps/v8/include/v8-debug.h index e41df29ad0..50314501e3 100644 --- a/deps/v8/include/v8-debug.h +++ b/deps/v8/include/v8-debug.h @@ -18,11 +18,13 @@ enum DebugEvent { Exception = 2, NewFunction = 3, BeforeCompile = 4, - AfterCompile = 5, + AfterCompile = 5, CompileError = 6, - AsyncTaskEvent = 7, + PromiseEvent = 7, + AsyncTaskEvent = 8, }; + class V8_EXPORT Debug { public: /** diff --git a/deps/v8/src/debug/debug.cc b/deps/v8/src/debug/debug.cc index 6e94012579..7c76742bb9 100644 --- a/deps/v8/src/debug/debug.cc +++ b/deps/v8/src/debug/debug.cc @@ -1708,6 +1708,13 @@ MaybeHandle<Object> Debug::MakeCompileEvent(Handle<Script> script, } +MaybeHandle<Object> Debug::MakePromiseEvent(Handle<JSObject> event_data) { + // Create the promise event object. + Handle<Object> argv[] = { event_data }; + return CallFunction("MakePromiseEvent", arraysize(argv), argv); +} + + MaybeHandle<Object> Debug::MakeAsyncTaskEvent(Handle<JSObject> task_event) { // Create the async task event object. Handle<Object> argv[] = { task_event }; @@ -1838,6 +1845,25 @@ void Debug::OnAfterCompile(Handle<Script> script) { } +void Debug::OnPromiseEvent(Handle<JSObject> data) { + if (in_debug_scope() || ignore_events()) return; + + HandleScope scope(isolate_); + DebugScope debug_scope(this); + if (debug_scope.failed()) return; + + // Create the script collected state object. + Handle<Object> event_data; + // Bail out and don't call debugger if exception. + if (!MakePromiseEvent(data).ToHandle(&event_data)) return; + + // Process debug event. + ProcessDebugEvent(v8::PromiseEvent, + Handle<JSObject>::cast(event_data), + true); +} + + void Debug::OnAsyncTaskEvent(Handle<JSObject> data) { if (in_debug_scope() || ignore_events()) return; @@ -1987,6 +2013,7 @@ void Debug::NotifyMessageHandler(v8::DebugEvent event, case v8::NewFunction: case v8::BeforeCompile: case v8::CompileError: + case v8::PromiseEvent: case v8::AsyncTaskEvent: break; case v8::Exception: diff --git a/deps/v8/src/debug/debug.h b/deps/v8/src/debug/debug.h index 501de63181..35aa8db049 100644 --- a/deps/v8/src/debug/debug.h +++ b/deps/v8/src/debug/debug.h @@ -417,6 +417,7 @@ class Debug { void OnCompileError(Handle<Script> script); void OnBeforeCompile(Handle<Script> script); void OnAfterCompile(Handle<Script> script); + void OnPromiseEvent(Handle<JSObject> data); void OnAsyncTaskEvent(Handle<JSObject> data); // API facing. @@ -579,6 +580,8 @@ class Debug { Handle<Object> promise); MUST_USE_RESULT MaybeHandle<Object> MakeCompileEvent( Handle<Script> script, v8::DebugEvent type); + MUST_USE_RESULT MaybeHandle<Object> MakePromiseEvent( + Handle<JSObject> promise_event); MUST_USE_RESULT MaybeHandle<Object> MakeAsyncTaskEvent( Handle<JSObject> task_event); diff --git a/deps/v8/src/debug/debug.js b/deps/v8/src/debug/debug.js index 7f06ca1be1..6849bf5345 100644 --- a/deps/v8/src/debug/debug.js +++ b/deps/v8/src/debug/debug.js @@ -51,7 +51,8 @@ Debug.DebugEvent = { Break: 1, BeforeCompile: 4, AfterCompile: 5, CompileError: 6, - AsyncTaskEvent: 7 }; + PromiseEvent: 7, + AsyncTaskEvent: 8 }; // Types of exceptions that can be broken upon. Debug.ExceptionBreak = { Caught : 0, @@ -1140,6 +1141,39 @@ function MakeScriptObject_(script, include_source) { } +function MakePromiseEvent(event_data) { + return new PromiseEvent(event_data); +} + + +function PromiseEvent(event_data) { + this.promise_ = event_data.promise; + this.parentPromise_ = event_data.parentPromise; + this.status_ = event_data.status; + this.value_ = event_data.value; +} + + +PromiseEvent.prototype.promise = function() { + return MakeMirror(this.promise_); +} + + +PromiseEvent.prototype.parentPromise = function() { + return MakeMirror(this.parentPromise_); +} + + +PromiseEvent.prototype.status = function() { + return this.status_; +} + + +PromiseEvent.prototype.value = function() { + return MakeMirror(this.value_); +} + + function MakeAsyncTaskEvent(event_data) { return new AsyncTaskEvent(event_data); } @@ -2483,6 +2517,7 @@ utils.InstallFunctions(utils, DONT_ENUM, [ "MakeExceptionEvent", MakeExceptionEvent, "MakeBreakEvent", MakeBreakEvent, "MakeCompileEvent", MakeCompileEvent, + "MakePromiseEvent", MakePromiseEvent, "MakeAsyncTaskEvent", MakeAsyncTaskEvent, "IsBreakPointTriggered", IsBreakPointTriggered, "UpdateScriptBreakPoints", UpdateScriptBreakPoints, diff --git a/deps/v8/src/js/promise.js b/deps/v8/src/js/promise.js index bcf826a101..201a06ca08 100644 --- a/deps/v8/src/js/promise.js +++ b/deps/v8/src/js/promise.js @@ -89,6 +89,9 @@ function PromiseSet(promise, status, value, onResolve, onReject) { SET_PRIVATE(promise, promiseValueSymbol, value); SET_PRIVATE(promise, promiseOnResolveSymbol, onResolve); SET_PRIVATE(promise, promiseOnRejectSymbol, onReject); + if (DEBUG_IS_ACTIVE) { + %DebugPromiseEvent({ promise: promise, status: status, value: value }); + } return promise; } @@ -303,6 +306,9 @@ function PromiseThen(onResolve, onReject) { } // Mark this promise as having handler. SET_PRIVATE(this, promiseHasHandlerSymbol, true); + if (DEBUG_IS_ACTIVE) { + %DebugPromiseEvent({ promise: deferred.promise, parentPromise: this }); + } return deferred.promise; } diff --git a/deps/v8/src/runtime/runtime-debug.cc b/deps/v8/src/runtime/runtime-debug.cc index ad8375a8d4..3263a89809 100644 --- a/deps/v8/src/runtime/runtime-debug.cc +++ b/deps/v8/src/runtime/runtime-debug.cc @@ -1635,6 +1635,15 @@ RUNTIME_FUNCTION(Runtime_DebugPopPromise) { } +RUNTIME_FUNCTION(Runtime_DebugPromiseEvent) { + DCHECK(args.length() == 1); + HandleScope scope(isolate); + CONVERT_ARG_HANDLE_CHECKED(JSObject, data, 0); + isolate->debug()->OnPromiseEvent(data); + return isolate->heap()->undefined_value(); +} + + RUNTIME_FUNCTION(Runtime_DebugAsyncTaskEvent) { DCHECK(args.length() == 1); HandleScope scope(isolate); diff --git a/deps/v8/src/runtime/runtime.h b/deps/v8/src/runtime/runtime.h index dc1678bb73..704145462b 100644 --- a/deps/v8/src/runtime/runtime.h +++ b/deps/v8/src/runtime/runtime.h @@ -190,6 +190,7 @@ namespace internal { F(DebugPrepareStepInIfStepping, 1, 1) \ F(DebugPushPromise, 2, 1) \ F(DebugPopPromise, 0, 1) \ + F(DebugPromiseEvent, 1, 1) \ F(DebugAsyncTaskEvent, 1, 1) \ F(DebugIsActive, 0, 1) \ F(DebugBreakInOptimizedCode, 0, 1) diff --git a/deps/v8/test/mjsunit/es6/debug-promises/events.js b/deps/v8/test/mjsunit/es6/debug-promises/events.js new file mode 100644 index 0000000000..3fcb22ff27 --- /dev/null +++ b/deps/v8/test/mjsunit/es6/debug-promises/events.js @@ -0,0 +1,122 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax --expose-debug-as debug + +Debug = debug.Debug; + +var eventsExpected = 16; +var exception = null; +var result = []; + +function updatePromise(promise, parentPromise, status, value) { + var i; + for (i = 0; i < result.length; ++i) { + if (result[i].promise === promise) { + result[i].parentPromise = parentPromise || result[i].parentPromise; + result[i].status = status || result[i].status; + result[i].value = value || result[i].value; + break; + } + } + assertTrue(i < result.length); +} + +function listener(event, exec_state, event_data, data) { + if (event != Debug.DebugEvent.PromiseEvent) return; + try { + eventsExpected--; + assertTrue(event_data.promise().isPromise()); + if (event_data.status() === 0) { + // New promise. + assertEquals("pending", event_data.promise().status()); + result.push({ promise: event_data.promise().value(), status: 0 }); + assertTrue(exec_state.frame(0).sourceLineText().indexOf("// event") > 0); + } else if (event_data.status() !== undefined) { + // Resolve/reject promise. + updatePromise(event_data.promise().value(), + undefined, + event_data.status(), + event_data.value().value()); + } else { + // Chain promises. + assertTrue(event_data.parentPromise().isPromise()); + updatePromise(event_data.promise().value(), + event_data.parentPromise().value()); + assertTrue(exec_state.frame(0).sourceLineText().indexOf("// event") > 0); + } + } catch (e) { + print(e + e.stack) + exception = e; + } +} + +Debug.setListener(listener); + +function resolver(resolve, reject) { resolve(); } + +var p1 = new Promise(resolver); // event +var p2 = p1.then().then(); // event +var p3 = new Promise(function(resolve, reject) { // event + reject("rejected"); +}); +var p4 = p3.then(); // event +var p5 = p1.then(); // event + +function assertAsync(b, s) { + if (b) { + print(s, "succeeded"); + } else { + %AbortJS(s + " FAILED!"); + } +} + +function testDone(iteration) { + function checkResult() { + if (eventsExpected === 0) { + assertAsync(result.length === 6, "result.length"); + + assertAsync(result[0].promise === p1, "result[0].promise"); + assertAsync(result[0].parentPromise === undefined, + "result[0].parentPromise"); + assertAsync(result[0].status === 1, "result[0].status"); + assertAsync(result[0].value === undefined, "result[0].value"); + + assertAsync(result[1].parentPromise === p1, + "result[1].parentPromise"); + assertAsync(result[1].status === 1, "result[1].status"); + + assertAsync(result[2].promise === p2, "result[2].promise"); + + assertAsync(result[3].promise === p3, "result[3].promise"); + assertAsync(result[3].parentPromise === undefined, + "result[3].parentPromise"); + assertAsync(result[3].status === -1, "result[3].status"); + assertAsync(result[3].value === "rejected", "result[3].value"); + + assertAsync(result[4].promise === p4, "result[4].promise"); + assertAsync(result[4].parentPromise === p3, + "result[4].parentPromise"); + assertAsync(result[4].status === -1, "result[4].status"); + assertAsync(result[4].value === "rejected", "result[4].value"); + + assertAsync(result[5].promise === p5, "result[5].promise"); + assertAsync(result[5].parentPromise === p1, + "result[5].parentPromise"); + assertAsync(result[5].status === 1, "result[5].status"); + + assertAsync(exception === null, "exception === null"); + Debug.setListener(null); + } else if (iteration > 10) { + %AbortJS("Not all events were received!"); + } else { + testDone(iteration + 1); + } + } + + var iteration = iteration || 0; + %EnqueueMicrotask(checkResult); +} + +testDone(); diff --git a/deps/v8/test/mjsunit/es6/debug-promises/resolve-after-aborted-try-finally.js b/deps/v8/test/mjsunit/es6/debug-promises/resolve-after-aborted-try-finally.js new file mode 100644 index 0000000000..918ae2a2e8 --- /dev/null +++ b/deps/v8/test/mjsunit/es6/debug-promises/resolve-after-aborted-try-finally.js @@ -0,0 +1,32 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --expose-debug-as debug --allow-natives-syntax + +// Test debug events when we listen to all exceptions and +// there is a catch handler for the exception thrown in a Promise. +// We expect a normal Exception debug event to be triggered. + +Debug = debug.Debug; + +var events = []; + +function listener(event, exec_state, event_data, data) { + if (event == Debug.DebugEvent.PromiseEvent) events.push(event_data.status()); +} + +Debug.setListener(listener); + +var p = new Promise(function(resolve, reject) { + do { + try { + throw new Error("reject"); + } finally { + break; // No rethrow. + } + } while (false); + resolve(); +}); + +assertEquals([0 /* create */, 1 /* resolve */], events); diff --git a/deps/v8/test/mjsunit/es6/debug-promises/resolve-after-try-catch.js b/deps/v8/test/mjsunit/es6/debug-promises/resolve-after-try-catch.js new file mode 100644 index 0000000000..298201f103 --- /dev/null +++ b/deps/v8/test/mjsunit/es6/debug-promises/resolve-after-try-catch.js @@ -0,0 +1,29 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --expose-debug-as debug --allow-natives-syntax + +// Test debug events when we listen to all exceptions and +// there is a catch handler for the exception thrown in a Promise. +// We expect a normal Exception debug event to be triggered. + +Debug = debug.Debug; + +var events = []; + +function listener(event, exec_state, event_data, data) { + if (event == Debug.DebugEvent.PromiseEvent) events.push(event_data.status()); +} + +Debug.setListener(listener); + +var p = new Promise(function (resolve, reject) { + try { + throw new Error("reject"); + } catch (e) { + } + resolve(); +}); + +assertEquals([0 /* create */, 1 /* resolve */], events); diff --git a/deps/v8/test/mjsunit/es6/debug-promises/rethrow-in-try-finally.js b/deps/v8/test/mjsunit/es6/debug-promises/rethrow-in-try-finally.js new file mode 100644 index 0000000000..b1e2ff98e1 --- /dev/null +++ b/deps/v8/test/mjsunit/es6/debug-promises/rethrow-in-try-finally.js @@ -0,0 +1,30 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --expose-debug-as debug --allow-natives-syntax + +// Test debug events when we listen to all exceptions and +// there is a catch handler for the exception thrown in a Promise. +// We expect a normal Exception debug event to be triggered. + +Debug = debug.Debug; + +var events = []; + +function listener(event, exec_state, event_data, data) { + if (event == Debug.DebugEvent.PromiseEvent) events.push(event_data.status()); +} + +Debug.setListener(listener); + +var p = new Promise(function(resolve, reject) { + try { + throw new Error("reject"); + } finally { + // Implicit rethrow. + } + resolve(); +}); + +assertEquals([0 /* create */, -1 /* rethrown */], events); |