Introduce debug events for promises.
R=aandrey@chromium.org, rossberg@chromium.org BUG=v8:3093 LOG=Y Review URL: https://codereview.chromium.org/357603005 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@22086 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
7aa8cb462f
commit
f6c4178aa7
@ -20,7 +20,8 @@ enum DebugEvent {
|
||||
BeforeCompile = 4,
|
||||
AfterCompile = 5,
|
||||
CompileError = 6,
|
||||
BreakForCommand = 7
|
||||
PromiseEvent = 7,
|
||||
BreakForCommand = 8
|
||||
};
|
||||
|
||||
|
||||
|
@ -19,7 +19,8 @@ Debug.DebugEvent = { Break: 1,
|
||||
NewFunction: 3,
|
||||
BeforeCompile: 4,
|
||||
AfterCompile: 5,
|
||||
CompileError: 6 };
|
||||
CompileError: 6,
|
||||
PromiseEvent: 7 };
|
||||
|
||||
// Types of exceptions that can be broken upon.
|
||||
Debug.ExceptionBreak = { Caught : 0,
|
||||
@ -1199,6 +1200,32 @@ function MakeScriptObject_(script, include_source) {
|
||||
}
|
||||
|
||||
|
||||
function MakePromiseEvent(event_data) {
|
||||
if (event_data.type = "new Promise") {
|
||||
return new NewPromiseEvent(event_data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function PromiseGetter() {
|
||||
return MakeMirror(this.promise_);
|
||||
}
|
||||
|
||||
|
||||
function NewPromiseEvent(event_data) {
|
||||
this.resolver_ = event_data.resolver;
|
||||
this.promise_ = event_data.promise;
|
||||
}
|
||||
|
||||
|
||||
NewPromiseEvent.prototype.promise = PromiseGetter;
|
||||
|
||||
|
||||
NewPromiseEvent.prototype.resolver = function() {
|
||||
return MakeMirror(this.resolver_);
|
||||
}
|
||||
|
||||
|
||||
function DebugCommandProcessor(exec_state, opt_is_running) {
|
||||
this.exec_state_ = exec_state;
|
||||
this.running_ = opt_is_running || false;
|
||||
|
26
src/debug.cc
26
src/debug.cc
@ -2544,6 +2544,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 MakeJSObject("MakePromiseEvent", ARRAY_SIZE(argv), argv);
|
||||
}
|
||||
|
||||
|
||||
void Debug::OnException(Handle<Object> exception, bool uncaught) {
|
||||
if (in_debug_scope() || ignore_events()) return;
|
||||
|
||||
@ -2689,6 +2696,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::ProcessDebugEvent(v8::DebugEvent event,
|
||||
Handle<JSObject> event_data,
|
||||
bool auto_continue) {
|
||||
|
@ -365,6 +365,7 @@ class Debug {
|
||||
void OnCompileError(Handle<Script> script);
|
||||
void OnBeforeCompile(Handle<Script> script);
|
||||
void OnAfterCompile(Handle<Script> script);
|
||||
void OnPromiseEvent(Handle<JSObject> data);
|
||||
|
||||
// API facing.
|
||||
void SetEventListener(Handle<Object> callback, Handle<Object> data);
|
||||
@ -535,6 +536,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);
|
||||
|
||||
// Mirror cache handling.
|
||||
void ClearMirrorCache();
|
||||
|
@ -38,6 +38,11 @@ var promiseRaw = GLOBAL_PRIVATE("Promise#raw");
|
||||
if (!IS_SPEC_FUNCTION(resolver))
|
||||
throw MakeTypeError('resolver_not_a_function', [resolver]);
|
||||
var promise = PromiseInit(this);
|
||||
if (DEBUG_IS_ACTIVE) {
|
||||
%DebugPromiseEvent({ type : "new Promise",
|
||||
promise: this,
|
||||
resolver: resolver });
|
||||
}
|
||||
try {
|
||||
%DebugPromiseHandlePrologue(function() { return promise });
|
||||
resolver(function(x) { PromiseResolve(promise, x) },
|
||||
|
@ -5530,6 +5530,15 @@ RUNTIME_FUNCTION(Runtime_DebugPromiseHandleEpilogue) {
|
||||
}
|
||||
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_DebugPromiseEvent) {
|
||||
ASSERT(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_DeleteProperty) {
|
||||
HandleScope scope(isolate);
|
||||
ASSERT(args.length() == 3);
|
||||
|
@ -77,6 +77,7 @@ namespace internal {
|
||||
F(DebugPrepareStepInIfStepping, 1, 1) \
|
||||
F(DebugPromiseHandlePrologue, 1, 1) \
|
||||
F(DebugPromiseHandleEpilogue, 0, 1) \
|
||||
F(DebugPromiseEvent, 1, 1) \
|
||||
F(FlattenString, 1, 1) \
|
||||
F(LoadMutableDouble, 2, 1) \
|
||||
F(TryMigrateInstance, 1, 1) \
|
||||
|
40
test/mjsunit/es6/debug-promises-new-event.js
Normal file
40
test/mjsunit/es6/debug-promises-new-event.js
Normal file
@ -0,0 +1,40 @@
|
||||
// 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
|
||||
|
||||
Debug = debug.Debug;
|
||||
|
||||
var exception = null;
|
||||
var new_promise;
|
||||
|
||||
function listener(event, exec_state, event_data, data) {
|
||||
if (event != Debug.DebugEvent.PromiseEvent) return;
|
||||
try {
|
||||
assertTrue(event_data.resolver().isFunction());
|
||||
assertEquals(resolver, event_data.resolver().value());
|
||||
assertTrue(event_data.resolver().resolved());
|
||||
assertEquals("resolver", event_data.resolver().name());
|
||||
assertTrue(event_data.resolver().source().indexOf("Token") > 0);
|
||||
|
||||
assertTrue(event_data.promise().isPromise());
|
||||
new_promise = event_data.promise().value();
|
||||
assertEquals("pending", event_data.promise().status());
|
||||
} catch (e) {
|
||||
print(e + e.stack)
|
||||
exception = e;
|
||||
}
|
||||
}
|
||||
|
||||
Debug.setListener(listener);
|
||||
|
||||
function resolver(resolve, reject) {
|
||||
resolve(); // Token
|
||||
}
|
||||
|
||||
var p = new Promise(resolver);
|
||||
assertEquals(new_promise, p);
|
||||
|
||||
assertNull(exception);
|
||||
Debug.setListener(null);
|
5
test/mjsunit/runtime-gen/debugpromiseevent.js
Normal file
5
test/mjsunit/runtime-gen/debugpromiseevent.js
Normal file
@ -0,0 +1,5 @@
|
||||
// Copyright 2014 the V8 project authors. All rights reserved.
|
||||
// AUTO-GENERATED BY tools/generate-runtime-tests.py, DO NOT MODIFY
|
||||
// Flags: --allow-natives-syntax --harmony
|
||||
var _data = new Object();
|
||||
%DebugPromiseEvent(_data);
|
@ -47,11 +47,11 @@ EXPAND_MACROS = [
|
||||
# that the parser doesn't bit-rot. Change the values as needed when you add,
|
||||
# remove or change runtime functions, but make sure we don't lose our ability
|
||||
# to parse them!
|
||||
EXPECTED_FUNCTION_COUNT = 415
|
||||
EXPECTED_FUZZABLE_COUNT = 330
|
||||
EXPECTED_FUNCTION_COUNT = 416
|
||||
EXPECTED_FUZZABLE_COUNT = 331
|
||||
EXPECTED_CCTEST_COUNT = 6
|
||||
EXPECTED_UNKNOWN_COUNT = 4
|
||||
EXPECTED_BUILTINS_COUNT = 806
|
||||
EXPECTED_BUILTINS_COUNT = 809
|
||||
|
||||
|
||||
# Don't call these at all.
|
||||
|
Loading…
Reference in New Issue
Block a user