Upload Kmake

This commit is contained in:
Gorochu
2026-05-26 23:36:42 -07:00
parent ba051b2f74
commit 555ec72358
41615 changed files with 13344630 additions and 1 deletions

View File

@ -0,0 +1,488 @@
// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --noanalyze-environment-liveness --turbofan
// The functions used for testing backtraces. They are at the top to make the
// testing of source line/column easier.
"use strict";
var Debug = debug.Debug;
var test_name;
var listener_delegate;
var listener_called;
var exception;
var begin_test_count = 0;
var end_test_count = 0;
var break_count = 0;
var global_marker = 7;
// Debug event listener which delegates.
function listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Break) {
break_count++;
listener_called = true;
listener_delegate(exec_state);
}
} catch (e) {
print(e, e.stack);
exception = e;
}
}
// Add the debug event listener.
Debug.setListener(listener);
// Initialize for a new test.
function BeginTest(name) {
test_name = name;
listener_delegate = null;
listener_called = false;
exception = null;
begin_test_count++;
}
// Check result of a test.
function EndTest() {
assertTrue(listener_called, "listener not called for " + test_name);
assertNull(exception, test_name, exception);
end_test_count++;
}
var global_object = this;
// Check that the scope chain contains the expected types of scopes.
function CheckScopeChain(scopes, exec_state) {
assertEquals(scopes.length, exec_state.frame().scopeCount());
for (var i = 0; i < scopes.length; i++) {
var scope = exec_state.frame().scope(i);
assertEquals(scopes[i], scope.scopeType());
// Check the global object when hitting the global scope.
if (scopes[i] == debug.ScopeType.Global) {
// Objects don't have same class (one is "global", other is "Object",
// so just check the properties directly.
assertEquals(global_object.global_marker,
scope.scopeObject().value().global_marker);
}
}
}
// Check that the content of the scope is as expected. For functions just check
// that there is a function.
function CheckScopeContent(content, number, exec_state) {
var scope = exec_state.frame().scope(number);
var count = 0;
for (var p in content) {
var property_mirror = scope.scopeObject().property(p);
if (property_mirror.isUndefined()) {
print('property ' + p + ' not found in scope');
}
assertFalse(property_mirror.isUndefined(),
'property ' + p + ' not found in scope');
assertEquals(content[p], property_mirror.value().value(),
'property ' + p + ' has unexpected value');
count++;
}
// 'arguments' and might be exposed in the local and closure scope. Just
// ignore this.
var scope_size = scope.scopeObject().properties().length;
if (!scope.scopeObject().property('arguments').isUndefined()) {
scope_size--;
}
// Temporary variables introduced by the parser have not been materialized.
assertTrue(scope.scopeObject().property('').isUndefined());
if (count != scope_size) {
print('Names found in scope:');
var names = scope.scopeObject().propertyNames();
for (var i = 0; i < names.length; i++) {
print(names[i]);
}
}
assertEquals(count, scope_size);
}
function assertEqualsUnlessOptimized(expected, value, f) {
try {
assertEquals(expected, value);
} catch (e) {
assertOptimized(f);
}
}
// Simple empty block scope in local scope.
BeginTest("Local block 1");
function local_block_1() {
{
debugger;
}
}
listener_delegate = function(exec_state) {
CheckScopeChain([debug.ScopeType.Local,
debug.ScopeType.Script,
debug.ScopeType.Global], exec_state);
CheckScopeContent({}, 0, exec_state);
};
local_block_1();
EndTest();
// Simple empty block scope in local scope with a parameter.
BeginTest("Local 2");
function local_2(a) {
{
debugger;
}
}
listener_delegate = function(exec_state) {
CheckScopeChain([debug.ScopeType.Local,
debug.ScopeType.Script,
debug.ScopeType.Global], exec_state);
CheckScopeContent({a:1}, 0, exec_state);
};
local_2(1);
EndTest();
// Local scope with a parameter and a local variable.
BeginTest("Local 3");
function local_3(a) {
let x = 3;
debugger;
}
listener_delegate = function(exec_state) {
CheckScopeChain([debug.ScopeType.Local,
debug.ScopeType.Script,
debug.ScopeType.Global], exec_state);
CheckScopeContent({a:1,x:3}, 0, exec_state);
};
local_3(1);
EndTest();
// Local scope with parameters and local variables.
BeginTest("Local 4");
function local_4(a, b) {
let x = 3;
let y = 4;
debugger;
}
listener_delegate = function(exec_state) {
CheckScopeChain([debug.ScopeType.Local,
debug.ScopeType.Script,
debug.ScopeType.Global], exec_state);
CheckScopeContent({a:1,b:2,x:3,y:4}, 0, exec_state);
};
local_4(1, 2);
EndTest();
// Single variable in a block scope.
BeginTest("Local 5");
function local_5(a) {
{
let x = 5;
debugger;
}
}
listener_delegate = function(exec_state) {
CheckScopeChain([debug.ScopeType.Block,
debug.ScopeType.Local,
debug.ScopeType.Script,
debug.ScopeType.Global], exec_state);
CheckScopeContent({x:5}, 0, exec_state);
CheckScopeContent({a:1}, 1, exec_state);
};
local_5(1);
EndTest();
// Two variables in a block scope.
BeginTest("Local 6");
function local_6(a) {
{
let x = 6;
let y = 7;
debugger;
}
}
listener_delegate = function(exec_state) {
CheckScopeChain([debug.ScopeType.Block,
debug.ScopeType.Local,
debug.ScopeType.Script,
debug.ScopeType.Global], exec_state);
CheckScopeContent({x:6,y:7}, 0, exec_state);
CheckScopeContent({a:1}, 1, exec_state);
};
local_6(1);
EndTest();
// Two variables in a block scope.
BeginTest("Local 7");
function local_7(a) {
{
{
let x = 8;
debugger;
}
}
}
listener_delegate = function(exec_state) {
CheckScopeChain([debug.ScopeType.Block,
debug.ScopeType.Local,
debug.ScopeType.Script,
debug.ScopeType.Global], exec_state);
CheckScopeContent({x:8}, 0, exec_state);
CheckScopeContent({a:1}, 1, exec_state);
};
local_7(1);
EndTest();
// Simple closure formed by returning an inner function referering to an outer
// block local variable and an outer function's parameter.
BeginTest("Closure 1");
function closure_1(a) {
var x = 2;
let y = 3;
if (true) {
let z = 4;
function f() {
debugger;
return a + x + y + z;
};
return f;
}
}
listener_delegate = function(exec_state) {
CheckScopeChain([debug.ScopeType.Local,
debug.ScopeType.Block,
debug.ScopeType.Closure,
debug.ScopeType.Script,
debug.ScopeType.Global], exec_state);
CheckScopeContent({}, 0, exec_state);
CheckScopeContent({a:1,x:2,y:3}, 2, exec_state);
};
closure_1(1)();
EndTest();
// Simple for-in loop over the keys of an object.
BeginTest("For loop 1");
function for_loop_1() {
for (let x in {y:undefined}) {
debugger;
}
}
listener_delegate = function(exec_state) {
CheckScopeChain([debug.ScopeType.Block,
debug.ScopeType.Local,
debug.ScopeType.Script,
debug.ScopeType.Global], exec_state);
CheckScopeContent({x:'y'}, 0, exec_state);
// The function scope contains a temporary iteration variable, but it is
// hidden to the debugger.
};
for_loop_1();
EndTest();
// For-in loop over the keys of an object with a block scoped let variable
// shadowing the iteration variable.
BeginTest("For loop 2");
function for_loop_2() {
for (let x in {y:undefined}) {
let x = 3;
debugger;
}
}
listener_delegate = function(exec_state) {
CheckScopeChain([debug.ScopeType.Block,
debug.ScopeType.Block,
debug.ScopeType.Local,
debug.ScopeType.Script,
debug.ScopeType.Global], exec_state);
CheckScopeContent({x:3}, 0, exec_state);
CheckScopeContent({x:'y'}, 1, exec_state);
// The function scope contains a temporary iteration variable, hidden to the
// debugger.
};
for_loop_2();
EndTest();
// Simple for loop.
BeginTest("For loop 3");
function for_loop_3() {
for (let x = 3; x < 4; ++x) {
debugger;
}
}
listener_delegate = function(exec_state) {
CheckScopeChain([debug.ScopeType.Block,
debug.ScopeType.Local,
debug.ScopeType.Script,
debug.ScopeType.Global], exec_state);
CheckScopeContent({x:3}, 0, exec_state);
CheckScopeContent({}, 1, exec_state);
};
for_loop_3();
EndTest();
// For loop with a block scoped let variable shadowing the iteration variable.
BeginTest("For loop 4");
function for_loop_4() {
for (let x = 3; x < 4; ++x) {
let x = 5;
debugger;
}
}
listener_delegate = function(exec_state) {
CheckScopeChain([debug.ScopeType.Block,
debug.ScopeType.Block,
debug.ScopeType.Local,
debug.ScopeType.Script,
debug.ScopeType.Global], exec_state);
CheckScopeContent({x:5}, 0, exec_state);
CheckScopeContent({x:3}, 1, exec_state);
CheckScopeContent({}, 2, exec_state);
};
for_loop_4();
EndTest();
// For loop with two variable declarations.
BeginTest("For loop 5");
function for_loop_5() {
for (let x = 3, y = 5; x < 4; ++x) {
debugger;
}
}
listener_delegate = function(exec_state) {
CheckScopeChain([debug.ScopeType.Block,
debug.ScopeType.Local,
debug.ScopeType.Script,
debug.ScopeType.Global], exec_state);
CheckScopeContent({x:3,y:5}, 0, exec_state);
CheckScopeContent({}, 1, exec_state);
};
for_loop_5();
EndTest();
// Uninitialized variables
BeginTest("Uninitialized 1");
function uninitialized_1() {
{
debugger;
let x = 1;
}
}
listener_delegate = function(exec_state) {
CheckScopeChain([debug.ScopeType.Block,
debug.ScopeType.Local,
debug.ScopeType.Script,
debug.ScopeType.Global], exec_state);
const prop = exec_state.frame().scope(0).scopeObject().property('x');
assertTrue(prop.isUnavailable());
};
uninitialized_1();
EndTest();
// Block scopes shadowing
BeginTest("Block scopes shadowing 1");
function shadowing_1() {
let i = 0;
{
let i = 5;
debugger;
}
assertEquals(0, i);
}
listener_delegate = function (exec_state) {
assertEqualsUnlessOptimized(5, exec_state.frame(0).evaluate("i").value());
}
shadowing_1();
EndTest();
// Block scopes shadowing
BeginTest("Block scopes shadowing 2");
function shadowing_2() {
let i = 0;
{
let j = 5;
debugger;
}
}
listener_delegate = function (exec_state) {
assertEqualsUnlessOptimized(0, exec_state.frame(0).evaluate("i").value());
assertEqualsUnlessOptimized(5, exec_state.frame(0).evaluate("j").value());
}
shadowing_2();
EndTest();

View File

@ -0,0 +1,41 @@
// Copyright 2015 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.
"use strict";
var Debug = debug.Debug;
var exception = null;
var super_called = false;
var step_count = 0;
function listener(event, execState, eventData, data) {
if (event != Debug.DebugEvent.Break) return;
try {
execState.prepareStep(Debug.StepAction.StepInto);
var s = execState.frame().sourceLineText();
step_count++;
assertTrue(s.indexOf('// ' + step_count + '.') >= 0);
} catch (e) {
exception = e;
}
}
class Base {
constructor() {
var x = 1; // 2.
} // 3.
}
class Derived extends Base {} // 1. // 4.
Debug.setListener(listener);
var bp = Debug.setBreakPoint(Derived, 0);
new Derived();
Debug.setListener(null); // 5.
assertNull(exception);
assertEquals(5, step_count);

View File

@ -0,0 +1,115 @@
// Copyright 2015 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.
// Test that debug-evaluate can find the correct this value for an arrow
// function, if "this" is referenced within the arrow function scope.
Debug = debug.Debug
var break_count = 0;
var exception = null;
function listener(event, exec_state, event_data, data) {
if (event != Debug.DebugEvent.Break) return;
try {
for (var i = 0; i < exec_state.frameCount() - 1; i++) {
var frame = exec_state.frame(i);
var this_value = frame.evaluate("'' + this").value();
var expected = frame.sourceLineText().match(/\/\/ (.*$)/)[1];
print(expected, this_value, frame.sourceLineText());
assertEquals(String(expected), String(this_value));
}
break_count++;
} catch (e) {
exception = e;
print(e + e.stack);
}
}
// Context-allocated receiver.
function f() {
debugger; // foo
return () => {
debugger; // foo
with ({}) {
return () => {
debugger; // foo
try {
throw new Error();
} catch (e) {
return () => {
(() => this); // bind this.
debugger; // foo
return () => {
debugger; // undefined
return g.call("goo"); // undefined
}
};
}
};
}
};
}
// Stack-allocated receiver.
function g() {
debugger; // goo
return () => {
debugger; // undefined
with ({}) {
return () => {
debugger; // undefined
try {
throw new Error();
} catch (e) {
return () => {
debugger; // undefined
return f.call("foo"); // undefined
};
}
};
}
};
}
Debug.setListener(listener);
var h = f.call("foo");
for (var i = 0; i < 20; i++) h = h();
var h = g.call("goo");
for (var i = 0; i < 20; i++) h = h();
function x() {
(() => this); // bind this.
function y() {
(() => {
(() => this); // bind this.
debugger; // Y
})(); // Y
}
y.call("Y"); // X
}
x.call("X");
function u() {
(() => this);
function v() {
(() => {
debugger; // undefined
})(); // V
}
v.call("V"); // U
}
u.call("U");
(() => {
(() => this);
debugger; // [object global]
})();
Debug.setListener(null);
assertEquals(55, break_count);
assertNull(exception);

View File

@ -0,0 +1,113 @@
// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Test debug evaluation for functions without local context, but with
// nested catch contexts.
// Flags: --no-always-turbofan
"use strict";
var x;
var result;
function f() {
{ // Line 1.
let i = 1; // Line 2.
try { // Line 3.
throw 'stuff'; // Line 4.
} catch (e) { // Line 5.
x = 2; // Line 6.
}
}
};
var Debug = debug.Debug
function listener(event, exec_state, event_data, data) {
if (event == Debug.DebugEvent.Break) {
result = exec_state.frame().evaluate("i").value();
}
};
// Add the debug event listener.
Debug.setListener(listener);
//Set breakpoint on line 6.
var bp = Debug.setBreakPoint(f, 6);
result = -1;
f();
assertEquals(1, result);
// Clear breakpoint.
Debug.clearBreakPoint(bp);
// Get rid of the debug event listener.
Debug.setListener(null);
function f1() {
{
let i = 1;
debugger;
assertEquals(2, i);
}
}
function f2() {
{
let i = 1;
debugger;
assertEquals(2, i);
return function() { return i++; }
}
}
var exception;
Debug.setListener(function (event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Break) {
var frame = exec_state.frame();
assertEquals(1, frame.evaluate("i").value());
var allScopes = frame.allScopes();
assertEquals(1, allScopes[0].scopeObject().value().i);
allScopes[0].setVariableValue("i", 2);
}
} catch (e) {
exception = e;
}
});
exception = null;
f1();
assertEquals(null, exception, exception);
exception = null;
f2();
assertEquals(null, exception, exception);
Debug.setListener(null);

View File

@ -0,0 +1,37 @@
// Copyright 2016 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.
// Test that debug-evaluate doesn't crash when this is used before super() call
// in constructor.
Debug = debug.Debug
var result;
function listener(event, exec_state, event_data, data)
{
try {
if (event == Debug.DebugEvent.Break) {
result = exec_state.frame(0).evaluate("this.a").value();
}
} catch (e) {
result = e.message;
}
}
Debug.setListener(listener);
class A { constructor () { this.a = 239; } }
class B extends A {
constructor () {
debugger;
assertTrue(result.indexOf("Cannot access 'this' from debugger") >= 0);
super();
debugger;
assertEquals(239, result);
}
}
new B();
Debug.setListener(null);

View File

@ -0,0 +1,48 @@
// Copyright 2016 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.
Debug = debug.Debug
var exception = null;
var log = [];
function listener(event, exec_state, event_data, data) {
if (event != Debug.DebugEvent.Exception) return;
try {
var line = exec_state.frame(0).sourceLineText();
var match = /Exception (\w)/.exec(line);
assertNotNull(match);
assertEquals(match[1], event_data.exception());
log.push(match[1]);
} catch (e) {
exception = e;
}
}
function* g() {
try {
throw "a"; // Ordinary throw. Exception a
} catch (e) {}
try {
yield 1; // Caught internally. Exception b
} catch (e) {}
yield 2;
yield 3; // Caught externally. Exception c
yield 4;
}
Debug.setListener(listener);
Debug.setBreakOnException();
var g_obj = g();
assertEquals(1, g_obj.next().value);
assertEquals(2, g_obj.throw("b").value);
assertEquals(3, g_obj.next().value);
assertThrows(() => g_obj.throw("c"));
assertThrows(() => g_obj.throw("d")); // Closed generator. Exception d
Debug.setListener(null);
Debug.clearBreakOnException();
assertEquals(["a", "b", "c", "d"], log);
assertNull(exception);

View File

@ -0,0 +1,136 @@
// Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"use strict";
let top_level_let = 255;
var Debug = debug.Debug;
const ScopeType = debug.ScopeType;
let exception = null;
let listenerDelegate = null;
const expected_break_count = 5;
let break_count = 0;
Debug.setListener(function(event, exec_state, event_data, data) {
if (event != Debug.DebugEvent.Break) return;
try {
break_count++;
listenerDelegate(exec_state);
} catch (e) {
exception = e;
print(e, e.stack);
}
});
function CheckScope(scope_frame, scope_expectations, expected_scope_type) {
assertEquals(expected_scope_type, scope_frame.scopeType());
var scope_object = scope_frame.scopeObject().value();
for (let name in scope_expectations) {
let actual = scope_object[name];
let expected = scope_expectations[name];
assertEquals(expected, actual);
}
}
// ---
listenerDelegate = function(exec_state) {
const frame = exec_state.frame(0);
assertEquals(6, frame.scopeCount());
CheckScope(frame.scope(0), {}, ScopeType.Local);
CheckScope(frame.scope(1), { a: 4, b: 5 }, ScopeType.Closure);
CheckScope(frame.scope(2), { z: 22, w: 5, v: "Capybara" }, ScopeType.Closure);
CheckScope(frame.scope(3), { x: 5 }, ScopeType.Closure);
CheckScope(frame.scope(4), { top_level_let: 255 }, ScopeType.Script);
CheckScope(frame.scope(5), {}, ScopeType.Global);
};
(function F1(x) {
function F2(y) {
var z = x + y;
{
var w = 5;
var v = "Capybara";
var F3 = function(a, b) {
function F4(p) {
debugger;
return p + a + b + z + w + v.length;
}
return F4;
}
return F3(4, 5);
}
}
return F2(17);
})(5)();
// ---
listenerDelegate = function(exec_state) {
const frame = exec_state.frame(0);
assertEquals(6, frame.scopeCount());
CheckScope(frame.scope(0), {}, ScopeType.Local);
CheckScope(frame.scope(1), { l3: 9 }, ScopeType.Block);
CheckScope(frame.scope(2), { l2: 7 }, ScopeType.Block);
CheckScope(frame.scope(3), { v1:3, l0: 0, v3: 5, v6: 11 }, ScopeType.Closure);
CheckScope(frame.scope(4), { top_level_let: 255 }, ScopeType.Script);
CheckScope(frame.scope(5), {}, ScopeType.Global);
};
(function() {
var v1 = 3;
var v2 = 4;
let l0 = 0;
{
var v3 = 5;
let l1 = 6;
let l2 = 7;
{
var v4 = 8;
let l3 = 9;
{
var v5 = "Cat";
let l4 = 11;
var v6 = l4;
return function() {
debugger;
return l0 + v1 + v3 + l2 + l3 + v6;
};
}
}
}
})()();

View File

@ -0,0 +1,87 @@
// Copyright 2015 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.
// Test that live-editing a frame that uses new.target fails.
// Flags: --allow-natives-syntax
Debug = debug.Debug
var calls = 0;
var exceptions = 0;
var results = [];
var replace_again;
eval(`
function LogNewTarget() {
calls++;
ReplaceOnce();
results.push(true);
results.push(new.target);
}
`);
function Dummy() {}
function ExecuteInDebugContext(f) {
var result;
var exception = null;
Debug.setListener(function(event) {
if (event == Debug.DebugEvent.Break) {
try {
result = f();
} catch (e) {
// Rethrow this exception later.
exception = e;
}
}
});
debugger;
Debug.setListener(null);
if (exception !== null) throw exception;
return result;
}
function Replace(fun, original, patch) {
ExecuteInDebugContext(function() {
try {
%LiveEditPatchScript(fun, Debug.scriptSource(fun).replace(original, patch));
} catch (e) {
assertEquals(e, 'LiveEdit failed: BLOCKED_BY_ACTIVE_FUNCTION');
exceptions++;
}
});
}
function ReplaceOnce() {
if (replace_again) {
replace_again = false;
Replace(LogNewTarget, "true", "false");
}
}
function Revert() {
Replace(LogNewTarget, "false", "true");
}
replace_again = true;
ReplaceOnce();
new LogNewTarget();
Revert();
assertEquals(1, calls);
assertEquals(0, exceptions);
assertEquals([false, LogNewTarget], results);
replace_again = true;
LogNewTarget();
replace_again = true;
new LogNewTarget();
replace_again = true;
Reflect.construct(LogNewTarget, [], Dummy);
assertEquals(
[false, LogNewTarget, true, undefined, true, LogNewTarget, true, Dummy],
results);
assertEquals(4, calls); // No restarts
assertEquals(3, exceptions); // Replace failed.

View File

@ -0,0 +1,75 @@
// Copyright 2015 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
// Test that live-editing a frame to introduce new.target fails.
Debug = debug.Debug
var calls = 0;
var exceptions = 0;
var results = [];
var replace_again;
eval(`
function LogNewTarget() {
calls++;
ReplaceOnce();
results.push(true);
}
`);
function ExecuteInDebugContext(f) {
var result;
var exception = null;
Debug.setListener(function(event) {
if (event == Debug.DebugEvent.Break) {
try {
result = f();
} catch (e) {
// Rethrow this exception later.
exception = e;
}
}
});
debugger;
Debug.setListener(null);
if (exception !== null) throw exception;
return result;
}
function Replace(fun, original, patch) {
ExecuteInDebugContext(function() {
try {
%LiveEditPatchScript(fun, Debug.scriptSource(fun).replace(original, patch));
} catch (e) {
assertEquals(e, 'LiveEdit failed: BLOCKED_BY_ACTIVE_FUNCTION');
exceptions++;
}
});
}
function ReplaceOnce(x) {
if (replace_again) {
replace_again = false;
Replace(LogNewTarget, "true", "new.target");
}
}
function Revert() {
Replace(LogNewTarget, "new.target", "true");
}
replace_again = true;
ReplaceOnce();
new LogNewTarget();
Revert();
assertEquals(1, calls);
assertEquals(0, exceptions);
assertEquals([LogNewTarget], results);
replace_again = true;
new LogNewTarget();
assertEquals(2, calls); // No restarts
assertEquals(1, exceptions); // Replace failed.
assertEquals([LogNewTarget, true], results);

View File

@ -0,0 +1,88 @@
// Copyright 2015 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.
// Test that live-editing a frame above one that uses new.target succeeds.
// Flags: --allow-natives-syntax
Debug = debug.Debug;
var wrapper_calls = 0;
var construct_calls = 0;
var exceptions = 0;
var results = [];
var replace_again;
eval(`
function LogNewTarget(arg) {
construct_calls++;
results.push(new.target);
}
function Wrapper() {
wrapper_calls++;
ReplaceOnce();
new LogNewTarget(true);
}
`);
function ExecuteInDebugContext(f) {
var result;
var exception = null;
Debug.setListener(function(event) {
if (event == Debug.DebugEvent.Break) {
try {
result = f();
} catch (e) {
// Rethrow this exception later.
exception = e;
}
}
});
debugger;
Debug.setListener(null);
if (exception !== null) throw exception;
return result;
}
function Replace(fun, original, patch) {
ExecuteInDebugContext(function() {
var change_log = [];
try {
%LiveEditPatchScript(fun, Debug.scriptSource(fun).replace(original, patch));
} catch (e) {
exceptions++;
}
});
}
function ReplaceOnce(x) {
if (replace_again) {
replace_again = false;
Replace(Wrapper, "true", "false");
}
}
function Revert() {
Replace(Wrapper, "false", "true");
}
replace_again = true;
ReplaceOnce();
Wrapper();
Revert();
assertEquals(1, construct_calls);
assertEquals(1, wrapper_calls);
assertEquals(0, exceptions); // Replace succeeds
assertEquals([LogNewTarget], results);
Wrapper();
assertEquals(2, construct_calls);
assertEquals(2, wrapper_calls);
assertEquals(0, exceptions); // Replace succeeds
assertEquals([LogNewTarget, LogNewTarget], results);
replace_again = true;
Wrapper();
assertEquals(3, construct_calls);
assertEquals(3, wrapper_calls);
assertEquals(1, exceptions); // Replace failed
assertEquals([LogNewTarget, LogNewTarget, LogNewTarget], results);

View File

@ -0,0 +1,65 @@
// 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.
var Debug = debug.Debug;
var listenerComplete = false;
var exception = null;
var count = 0;
var log = [];
var done = false;
function LogX(x) {
var stored_count = count;
return function() {
log.push(`[${stored_count}] ${x}`);
};
}
function DebuggerStatement() {
log.push(`[${count}] debugger`);
if (count++ < 3) {
debugger;
}
}
function listener(event, exec_state, event_data, data) {
if (event != Debug.DebugEvent.Break) return;
try {
var p = Promise.resolve();
var q = p.then(LogX("then 1"));
p.then(LogX("then 2"));
q.then(LogX("then 3"));
q.then(DebuggerStatement);
var r = q.then(() => { throw 1; });
r.catch(LogX("catch"));
listenerComplete = true;
} catch (e) {
exception = e;
print(e, e.stack);
quit(1);
};
};
// Add the debug event listener.
Debug.setListener(listener);
DebuggerStatement();
LogX("start")();
// Make sure that the debug event listener was invoked.
assertTrue(listenerComplete);
%PerformMicrotaskCheckpoint();
var expectation =
[ "[0] debugger", "[1] start", "[1] then 1",
"[1] then 2", "[1] then 3", "[1] debugger",
"[2] then 1", "[2] then 2", "[1] catch",
"[2] then 3", "[2] debugger", "[3] then 1",
"[3] then 2", "[2] catch", "[3] then 3",
"[3] debugger", "[3] catch",
];
assertEquals(expectation, log);

View File

@ -0,0 +1,39 @@
// Copyright 2015 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.
// Test debug events when we only listen to uncaught exceptions and a
// Promise p3 created by Promise.all has a catch handler, and is rejected
// because one of the Promises p2 passed to Promise.all is rejected. We
// expect no Exception debug event to be triggered, since p3 and by
// extension p2 have a catch handler.
var Debug = debug.Debug;
var expected_events = 2;
var p1 = Promise.resolve();
p1.name = "p1";
var p2 = p1.then(function() {
throw new Error("caught");
});
p2.name = "p2";
var p3 = Promise.all([p2]);
p3.name = "p3";
p3.catch(function(e) {});
function listener(event, exec_state, event_data, data) {
try {
assertTrue(event != Debug.DebugEvent.Exception)
} catch (e) {
%AbortJS(e + "\n" + e.stack);
}
}
Debug.setBreakOnUncaughtException();
Debug.setListener(listener);

View File

@ -0,0 +1,68 @@
// Copyright 2015 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: --ignore-unhandled-promises
// Test debug events when we only listen to uncaught exceptions and a
// Promise p3 created by Promise.all has no catch handler, and is rejected
// because one of the Promises p2 passed to Promise.all is rejected.
// We expect one event for p2; the system recognizes the rejection of p3
// to be redundant and based on the rejection of p2 and does not trigger
// an additional rejection.
var Debug = debug.Debug;
var expected_events = 1;
var log = [];
function listener(event, exec_state, event_data, data) {
if (event != Debug.DebugEvent.Exception) return;
try {
expected_events--;
assertTrue(expected_events >= 0);
assertEquals("uncaught", event_data.exception().message);
// Assert that the debug event is triggered at the throw site.
assertTrue(exec_state.frame(0).sourceLineText().indexOf("// event") > 0);
assertTrue(event_data.uncaught());
} catch (e) {
%AbortJS(e + "\n" + e.stack);
}
}
Debug.setBreakOnUncaughtException();
Debug.setListener(listener);
var p1 = Promise.resolve();
p1.name = "p1";
var p2 = p1.then(function() {
log.push("throw");
throw new Error("uncaught"); // event
});
p2.name = "p2";
var p3 = Promise.all([p2]);
p3.name = "p3";
log.push("end main");
function testDone(iteration) {
function checkResult() {
try {
assertTrue(iteration < 10);
if (expected_events === 0) {
assertEquals(["end main", "throw"], log);
} else {
testDone(iteration + 1);
}
} catch (e) {
%AbortJS(e + "\n" + e.stack);
}
}
%EnqueueMicrotask(checkResult);
}
testDone(0);

View File

@ -0,0 +1,37 @@
// Copyright 2020 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.
// Test debug events when we only listen to uncaught exceptions and a
// Promise p3 created by Promise.any has a catch handler, and is rejected
// because the Promise p2 passed to Promise.any is rejected. We
// expect no Exception debug event to be triggered, since p3 and by
// extension p2 have a catch handler.
let Debug = debug.Debug;
let expected_events = 2;
let p1 = Promise.resolve();
p1.name = "p1";
let p2 = p1.then(function() {
throw new Error("caught");
});
p2.name = "p2";
let p3 = Promise.any([p2]);
p3.name = "p3";
p3.catch(function(e) {});
function listener(event, exec_state, event_data, data) {
try {
assertTrue(event != Debug.DebugEvent.Exception)
} catch (e) {
%AbortJS(e + "\n" + e.stack);
}
}
Debug.setBreakOnUncaughtException();
Debug.setListener(listener);

View File

@ -0,0 +1,67 @@
// Copyright 2015 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: --ignore-unhandled-promises
// Test debug events when we only listen to uncaught exceptions and a
// Promise p3 created by Promise.any has no catch handler, and is rejected
// because the Promise p2 passed to Promise.any is rejected.
// We expect one event for p2; the system recognizes the rejection of p3
// to be redundant and based on the rejection of p2 and does not trigger
// an additional rejection.
let Debug = debug.Debug;
let expected_events = 1;
let log = [];
function listener(event, exec_state, event_data, data) {
if (event != Debug.DebugEvent.Exception) return;
try {
expected_events--;
assertTrue(expected_events >= 0);
assertEquals("uncaught", event_data.exception().message);
// Assert that the debug event is triggered at the throw site.
assertTrue(exec_state.frame(0).sourceLineText().indexOf("// event") > 0);
assertTrue(event_data.uncaught());
} catch (e) {
%AbortJS(e + "\n" + e.stack);
}
}
Debug.setBreakOnUncaughtException();
Debug.setListener(listener);
let p1 = Promise.resolve();
p1.name = "p1";
let p2 = p1.then(function() {
log.push("throw");
throw new Error("uncaught"); // event
});
p2.name = "p2";
let p3 = Promise.any([p2]);
p3.name = "p3";
log.push("end main");
function testDone(iteration) {
function checkResult() {
try {
assertTrue(iteration < 10);
if (expected_events === 0) {
assertEquals(["end main", "throw"], log);
} else {
testDone(iteration + 1);
}
} catch (e) {
%AbortJS(e + "\n" + e.stack);
}
}
%EnqueueMicrotask(checkResult);
}
testDone(0);

View File

@ -0,0 +1,39 @@
// Copyright 2015 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.
// Test debug events when we only listen to uncaught exceptions and a
// Promise p3 created by Promise.race has a catch handler, and is rejected
// because one of the Promises p2 passed to Promise.all is rejected. We
// expect no Exception debug event to be triggered, since p3 and by
// extension p2 have a catch handler.
var Debug = debug.Debug;
var expected_events = 2;
var p1 = Promise.resolve();
p1.name = "p1";
var p2 = p1.then(function() {
throw new Error("caught");
});
p2.name = "p2";
var p3 = Promise.all([p2]);
p3.name = "p3";
p3.catch(function(e) {});
function listener(event, exec_state, event_data, data) {
try {
assertTrue(event != Debug.DebugEvent.Exception)
} catch (e) {
%AbortJS(e + "\n" + e.stack);
}
}
Debug.setBreakOnUncaughtException();
Debug.setListener(listener);

View File

@ -0,0 +1,68 @@
// Copyright 2015 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: --ignore-unhandled-promises
// Test debug events when we only listen to uncaught exceptions and a
// Promise p3 created by Promise.race has no catch handler, and is rejected
// because one of the Promises p2 passed to Promise.race is rejected.
// We expect one event for p2; the system recognizes the rejection of p3
// to be redundant and based on the rejection of p2 and does not trigger
// an additional rejection.
var Debug = debug.Debug;
var expected_events = 1;
var log = [];
function listener(event, exec_state, event_data, data) {
if (event != Debug.DebugEvent.Exception) return;
try {
expected_events--;
assertTrue(expected_events >= 0);
assertEquals("uncaught", event_data.exception().message);
// Assert that the debug event is triggered at the throw site.
assertTrue(exec_state.frame(0).sourceLineText().indexOf("// event") > 0);
assertTrue(event_data.uncaught());
} catch (e) {
%AbortJS(e + "\n" + e.stack);
}
}
Debug.setBreakOnUncaughtException();
Debug.setListener(listener);
var p1 = Promise.resolve();
p1.name = "p1";
var p2 = p1.then(function() {
log.push("throw");
throw new Error("uncaught"); // event
});
p2.name = "p2";
var p3 = Promise.race([p2]);
p3.name = "p3";
log.push("end main");
function testDone(iteration) {
function checkResult() {
try {
assertTrue(iteration < 10);
if (expected_events === 0) {
assertEquals(["end main", "throw"], log);
} else {
testDone(iteration + 1);
}
} catch (e) {
%AbortJS(e + "\n" + e.stack);
}
}
%EnqueueMicrotask(checkResult);
}
testDone(0);

View File

@ -0,0 +1,43 @@
// Copyright 2018 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: --ignore-unhandled-promises
// 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 expected_events = 1;
var log = [];
class P extends Promise {
constructor(...args) {
super(...args);
return new Proxy(this, {
get(target, property, receiver) {
if (property in target) {
return Reflect.get(target, property, receiver);
} else {
return (...args) =>
new Promise((resolve, reject) =>
target.then(v => resolve(v[property](...args)))
.catch(reject)
);
}
}
});
}
}
P.resolve({doStuff(){log.push(1)}}).doStuff()
function listener(event, exec_state, event_data, data) {}
Debug.setBreakOnUncaughtException();
Debug.setListener(listener);
%PerformMicrotaskCheckpoint();

View File

@ -0,0 +1,16 @@
// 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.
// Test reentry of special try catch for Promises.
Debug = debug.Debug;
Debug.setBreakOnUncaughtException();
Debug.setListener(function(event, exec_state, event_data, data) { });
var p = new Promise(function(resolve, reject) { resolve(); });
var q = p.then(function() {
new Promise(function(resolve, reject) { resolve(); });
});

View File

@ -0,0 +1,36 @@
// 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.
// Test debug events when we listen to uncaught exceptions and
// the Promise is rejected in a chained closure after it has been resolved.
// We expect no Exception debug event to be triggered.
Debug = debug.Debug;
var log = [];
var p = new Promise(function(resolve, reject) {
log.push("resolve");
resolve(reject);
});
var q = p.then(
function(value) {
assertEquals(["resolve", "end main"], log);
value(new Error("reject"));
});
function listener(event, exec_state, event_data, data) {
try {
assertTrue(event != Debug.DebugEvent.Exception);
} catch (e) {
%AbortJS(e + "\n" + e.stack);
}
}
Debug.setBreakOnException();
Debug.setListener(listener);
log.push("end main");

View File

@ -0,0 +1,67 @@
// 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.
// Test debug events when we listen to all exceptions and
// there is a catch handler for the to-be-rejected Promise.
// We expect a normal Exception debug event to be triggered.
Debug = debug.Debug;
var log = [];
var expected_events = 1;
var p = new Promise(function(resolve, reject) {
log.push("resolve");
resolve();
});
var q = p.then(
function(value) {
log.push("reject");
return Promise.reject(new Error("reject"));
});
q.catch(
function(e) {
assertEquals("reject", e.message);
});
function listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Exception) {
expected_events--;
assertTrue(expected_events >= 0);
assertEquals("reject", event_data.exception().message);
assertFalse(event_data.uncaught());
}
} catch (e) {
%AbortJS(e + "\n" + e.stack);
}
}
Debug.setBreakOnException();
Debug.setListener(listener);
log.push("end main");
function testDone(iteration) {
function checkResult() {
try {
assertTrue(iteration < 10);
if (expected_events === 0) {
assertEquals(["resolve", "end main", "reject"], log);
} else {
testDone(iteration + 1);
}
} catch (e) {
%AbortJS(e + "\n" + e.stack);
}
}
%EnqueueMicrotask(checkResult);
}
testDone(0);

View File

@ -0,0 +1,75 @@
// 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: --ignore-unhandled-promises
// Test debug events when we only listen to uncaught exceptions and
// there is only a default reject handler for the to-be-rejected Promise.
// We expect only one debug event: when the first Promise is rejected
// and only has default reject handlers. No event is triggered when
// simply forwarding the rejection with .then's default handler.
Debug = debug.Debug;
var expected_events = 1;
var log = [];
var resolve, reject;
var p0 = new Promise(function(res, rej) { resolve = res; reject = rej; });
var p1 = p0.then(function() {
log.push("p0.then");
return Promise.reject(new Error("123"));
});
var p2 = p1.then(function() {
log.push("p1.then");
});
var q = new Promise(function(res, rej) {
log.push("resolve q");
res();
});
q.then(function() {
log.push("resolve p");
resolve();
})
function listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Exception) {
expected_events--;
assertTrue(expected_events >= 0);
assertTrue(event_data.uncaught());
// p1 is rejected, uncaught, with the error from the Promise.reject line
assertNotNull(event_data.sourceLineText().match("Promise.reject"));
}
} catch (e) {
%AbortJS(e + "\n" + e.stack);
}
}
Debug.setBreakOnUncaughtException();
Debug.setListener(listener);
log.push("end main");
function testDone(iteration) {
function checkResult() {
try {
assertTrue(iteration < 10);
if (expected_events === 0) {
assertEquals(["resolve q", "end main", "resolve p", "p0.then"], log);
} else {
testDone(iteration + 1);
}
} catch (e) {
%AbortJS(e + "\n" + e.stack);
}
}
%EnqueueMicrotask(checkResult);
}
testDone(0);

View File

@ -0,0 +1,33 @@
// 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.
// Test debug events when we only listen to uncaught exceptions, the Promise
// is rejected, and a catch handler is installed right before the rejection.
// We expect no debug event to be triggered.
Debug = debug.Debug;
var p = new Promise(function(resolve, reject) {
resolve();
});
var q = p.then(
function() {
q.catch(function(e) {
assertEquals("caught", e.message);
});
return Promise.reject(Error("caught"));
});
function listener(event, exec_state, event_data, data) {
try {
assertTrue(event != Debug.DebugEvent.Exception);
} catch (e) {
%AbortJS(e + "\n" + e.stack);
}
}
Debug.setBreakOnUncaughtException();
Debug.setListener(listener);

View File

@ -0,0 +1,35 @@
// 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.
// Test debug events when we only listen to uncaught exceptions and
// there is a catch handler for the to-be-rejected Promise.
// We expect no debug event to be triggered.
Debug = debug.Debug;
var p = new Promise(function(resolve, reject) {
resolve();
});
var q = p.then(
function() {
return Promise.reject(Error("caught reject"));
});
q.catch(
function(e) {
assertEquals("caught reject", e.message);
});
function listener(event, exec_state, event_data, data) {
try {
assertTrue(event != Debug.DebugEvent.Exception);
} catch (e) {
%AbortJS(e + "\n" + e.stack);
}
}
Debug.setBreakOnUncaughtException();
Debug.setListener(listener);

View File

@ -0,0 +1,65 @@
// Copyright 2018 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: --ignore-unhandled-promises
// Test exercises code paths for catching exceptions in the promise constructor
// in conjunction with deoptimization.
Debug = debug.Debug;
var expected_events = 4;
function listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Exception) {
expected_events--;
assertTrue(expected_events >= 0);
assertEquals("uncaught", event_data.exception().message);
assertTrue(event_data.uncaught());
// The frame comes from the Promise.reject call
assertNotNull(/\/\/ EXCEPTION/.exec(event_data.sourceLineText()));
assertTrue(event_data.uncaught());
}
} catch (e) {
%AbortJS(e + "\n" + e.stack);
}
}
Debug.setBreakOnException();
Debug.setListener(listener);
function foo(a,b) {
let P = new Promise((resolve, reject) => { bar(a,b); resolve()})
return P;
}
function bar(a,b) {
%DeoptimizeFunction(foo);
throw new Error("uncaught"); // EXCEPTION
}
%PrepareFunctionForOptimization(foo);
foo();
%PerformMicrotaskCheckpoint();
foo();
%PerformMicrotaskCheckpoint();
%OptimizeFunctionOnNextCall(foo);
// bar likely gets inlined into foo.
foo();
%PerformMicrotaskCheckpoint();
%NeverOptimizeFunction(bar);
%PrepareFunctionForOptimization(foo);
%OptimizeFunctionOnNextCall(foo);
// bar does not get inlined into foo.
foo();
%PerformMicrotaskCheckpoint();
assertEquals(0, expected_events);

View File

@ -0,0 +1,38 @@
// 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: --ignore-unhandled-promises
// Test debug events when we only listen to uncaught exceptions and
// the Promise is rejected in the Promise constructor.
// We expect an Exception debug event with a promise to be triggered.
Debug = debug.Debug;
var steps = 0;
var exception = null;
function listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Exception) {
steps++;
assertEquals("uncaught", event_data.exception().message);
assertTrue(event_data.uncaught());
// Assert that the debug event is triggered at the throw site.
assertTrue(exec_state.frame(0).sourceLineText().indexOf("// event") > 0);
}
} catch (e) {
exception = e;
}
}
Debug.setBreakOnUncaughtException();
Debug.setListener(listener);
var p = new Promise(function(resolve, reject) {
reject(new Error("uncaught")); // event
});
assertEquals(1, steps);
assertNull(exception);

View File

@ -0,0 +1,64 @@
// 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: --ignore-unhandled-promises
// Test debug events when we listen to all exceptions and
// there is a catch handler for the to-be-rejected Promise.
// We expect an Exception debug event with a promise to be triggered.
Debug = debug.Debug;
var expected_events = 1;
var log = [];
var p = new Promise(function(resolve, reject) {
log.push("resolve");
resolve();
});
var q = p.then(
function() {
log.push("reject");
return Promise.reject(new Error("uncaught reject"));
});
function listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Exception) {
expected_events--;
assertTrue(expected_events >= 0);
assertEquals("uncaught reject", event_data.exception().message);
assertTrue(event_data.uncaught());
// The frame comes from the Promise.reject call
assertNotNull(/Promise\.reject/.exec(event_data.sourceLineText()));
}
} catch (e) {
%AbortJS(e + "\n" + e.stack);
}
}
Debug.setBreakOnException();
Debug.setListener(listener);
log.push("end main");
function testDone(iteration) {
function checkResult() {
try {
assertTrue(iteration < 10);
if (expected_events === 0) {
assertEquals(["resolve", "end main", "reject"], log);
} else {
testDone(iteration + 1);
}
} catch (e) {
%AbortJS(e + "\n" + e.stack);
}
}
%EnqueueMicrotask(checkResult);
}
testDone(0);

View File

@ -0,0 +1,71 @@
// 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: --ignore-unhandled-promises
// Test debug events when we only listen to uncaught exceptions and
// there is a catch handler for the to-be-rejected Promise.
// We expect an Exception debug event with a promise to be triggered.
Debug = debug.Debug;
var expected_events = 1;
var log = [];
var reject_closure;
var p = new Promise(function(resolve, reject) {
log.push("postpone p");
reject_closure = reject;
});
var q = new Promise(function(resolve, reject) {
log.push("resolve q");
resolve();
});
q.then(function() {
log.push("reject p");
reject_closure(new Error("uncaught reject p")); // event
})
function listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Exception) {
expected_events--;
assertTrue(expected_events >= 0);
assertEquals("uncaught reject p", event_data.exception().message);
assertTrue(event_data.uncaught());
// Assert that the debug event is triggered at the throw site.
assertTrue(exec_state.frame(0).sourceLineText().indexOf("// event") > 0);
}
} catch (e) {
%AbortJS(e + "\n" + e.stack);
}
}
Debug.setBreakOnUncaughtException();
Debug.setListener(listener);
log.push("end main");
function testDone(iteration) {
function checkResult() {
try {
assertTrue(iteration < 10);
if (expected_events === 0) {
assertEquals(["postpone p", "resolve q", "end main", "reject p"], log);
} else {
testDone(iteration + 1);
}
} catch (e) {
%AbortJS(e + "\n" + e.stack);
}
}
%EnqueueMicrotask(checkResult);
}
testDone(0);

View File

@ -0,0 +1,64 @@
// 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: --ignore-unhandled-promises
// Test debug events when we only listen to uncaught exceptions and
// there is no catch handler for the to-be-rejected Promise.
// We expect an Exception debug event with a promise to be triggered.
Debug = debug.Debug;
var expected_events = 1;
var log = [];
var p = new Promise(function(resolve, reject) {
log.push("resolve");
resolve();
});
var q = p.then(
function() {
log.push("reject");
return Promise.reject(Error("uncaught reject")); // event
});
function listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Exception) {
expected_events--;
assertTrue(expected_events >= 0);
assertEquals("uncaught reject", event_data.exception().message);
assertTrue(event_data.uncaught());
// The JavaScript frame is from the Promise rejection
assertTrue(/Promise\.reject/.test(event_data.sourceLineText()));
}
} catch (e) {
%AbortJS(e + "\n" + e.stack);
}
}
Debug.setBreakOnUncaughtException();
Debug.setListener(listener);
log.push("end main");
function testDone(iteration) {
function checkResult() {
try {
assertTrue(iteration < 10);
if (expected_events === 0) {
assertEquals(["resolve", "end main", "reject"], log);
} else {
testDone(iteration + 1);
}
} catch (e) {
%AbortJS(e + "\n" + e.stack);
}
}
%EnqueueMicrotask(checkResult);
}
testDone(0);

View File

@ -0,0 +1,73 @@
// 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.
// Test debug events when a Promise is rejected, which is caught by a custom
// promise, which has a number for reject closure. We expect an Exception debug
// events trying to call the invalid reject closure.
Debug = debug.Debug;
var expected_events = 1;
var log = [];
var p = new Promise(function(resolve, reject) {
log.push("resolve");
resolve();
});
function MyPromise(resolver) {
var reject = 1;
var resolve = function() { };
log.push("construct");
resolver(resolve, reject);
};
MyPromise.prototype = new Promise(function() {});
p.constructor = MyPromise;
var q = p.then(
function() {
log.push("reject caught");
return Promise.reject(new Error("caught"));
});
function listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Exception) {
expected_events--;
assertTrue(expected_events >= 0);
assertEquals("number is not a function", event_data.exception().message);
// All of the frames on the stack are from native Javascript.
assertEquals(0, exec_state.frameCount());
}
} catch (e) {
%AbortJS(e + "\n" + e.stack);
}
}
Debug.setBreakOnUncaughtException();
Debug.setListener(listener);
function testDone(iteration) {
function checkResult() {
try {
assertTrue(iteration < 10);
if (expected_events === 0) {
assertEquals(["resolve", "construct", "end main", "reject caught"],
log);
} else {
testDone(iteration + 1);
}
} catch (e) {
%AbortJS(e + "\n" + e.stack);
}
}
%EnqueueMicrotask(checkResult);
}
testDone(0);
log.push("end main");

View File

@ -0,0 +1,83 @@
// 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.
// Test debug events when a Promise is rejected, which is caught by a
// custom promise, which throws a new exception in its reject handler.
// We expect two Exception debug events:
// 1) when promise q is rejected.
// 2) when the custom reject closure in MyPromise throws an exception.
Debug = debug.Debug;
var expected_events = 1;
var log = [];
var p = new Promise(function(resolve, reject) {
log.push("resolve");
resolve();
});
function MyPromise(resolver) {
var reject = function() {
log.push("throw in reject");
throw new Error("reject"); // event
};
var resolve = function() { };
log.push("construct");
resolver(resolve, reject);
};
MyPromise.prototype = new Promise(function() {});
p.constructor = MyPromise;
var q = p.then(
function() {
log.push("reject caught");
return Promise.reject(new Error("caught"));
});
function listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Exception) {
expected_events--;
assertTrue(expected_events >= 0);
assertEquals("reject", event_data.exception().message);
// Assert that the debug event is triggered at the throw site.
assertTrue(
exec_state.frame(0).sourceLineText().indexOf("// event") > 0);
}
} catch (e) {
// Signal a failure with exit code 1. This is necessary since the
// debugger swallows exceptions and we expect the chained function
// and this listener to be executed after the main script is finished.
print("Unexpected exception: " + e + "\n" + e.stack);
quit(1);
}
}
Debug.setBreakOnUncaughtException();
Debug.setListener(listener);
log.push("end main");
function testDone(iteration) {
function checkResult() {
try {
assertTrue(iteration < 10);
if (expected_events === 0) {
assertEquals(["resolve", "construct", "end main",
"reject caught", "throw in reject"], log);
} else {
testDone(iteration + 1);
}
} catch (e) {
%AbortJS(e + "\n" + e.stack);
}
}
%EnqueueMicrotask(checkResult);
}
testDone(0);

View File

@ -0,0 +1,73 @@
// 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.
// Test debug events when a Promise is rejected, which is caught by a custom
// promise, which has undefined for reject closure. We expect an Exception
// debug even calling the (undefined) custom rejected closure.
Debug = debug.Debug;
var expected_events = 1;
var log = [];
var p = new Promise(function(resolve, reject) {
log.push("resolve");
resolve();
});
function MyPromise(resolver) {
var reject = undefined;
var resolve = function() { };
log.push("construct");
resolver(resolve, reject);
};
MyPromise.prototype = new Promise(function() {});
p.constructor = MyPromise;
var q = p.then(
function() {
log.push("reject caught");
return Promise.reject(new Error("caught"));
});
function listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Exception) {
expected_events--;
assertTrue(expected_events >= 0);
assertEquals("caught", event_data.exception().message);
// All of the frames on the stack are from native Javascript.
assertEquals(0, exec_state.frameCount());
}
} catch (e) {
%AbortJS(e + "\n" + e.stack);
}
}
Debug.setBreakOnUncaughtException();
Debug.setListener(listener);
function testDone(iteration) {
function checkResult() {
try {
assertTrue(iteration < 10);
if (expected_events === 0) {
assertEquals(["resolve", "construct", "end main", "reject caught"],
log);
} else {
testDone(iteration + 1);
}
} catch (e) {
%AbortJS(e + "\n" + e.stack);
}
}
%EnqueueMicrotask(checkResult);
}
testDone(0);
log.push("end main");

View File

@ -0,0 +1,46 @@
// Copyright 2015 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.
var Debug = debug.Debug;
var exception = null;
var breaks = [];
function listener(event, exec_state, event_data, data) {
if (event != Debug.DebugEvent.Break) return;
try {
breaks.push(exec_state.frame(0).sourceLineText().trimLeft());
exec_state.prepareStep(Debug.StepAction.StepInto);
} catch (e) {
exception = e;
}
}
Debug.setListener(listener);
function resolver(resolve, reject) {
print(1);
print(2);
print(3);
resolve();
}
debugger;
var p = new Promise(resolver);
Debug.setListener(null);
var expected_breaks = [
"debugger;",
"var p = new Promise(resolver);",
"print(1);",
"print(2);",
"print(3);",
"resolve();",
"}",
"Debug.setListener(null);"
];
assertEquals(expected_breaks, breaks);
assertNull(exception);

View File

@ -0,0 +1,60 @@
// Copyright 2015 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: --noalways-turbofan
// Tests stepping into through Promises.
Debug = debug.Debug
var exception = null;
var break_count = 0;
const expected_breaks = 9;
function listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Break) {
assertTrue(exec_state.frameCount() != 0, "FAIL: Empty stack trace");
var source = exec_state.frame(0).sourceLineText();
print("paused at: " + source);
assertTrue(source.indexOf("// Break " + break_count + ".") > 0,
"Unexpected pause at: " + source + "\n" +
"Expected: // Break " + break_count + ".");
++break_count;
if (break_count !== expected_breaks) {
exec_state.prepareStep(Debug.StepAction.StepInto);
}
}
} catch(e) {
exception = e;
print(e, e.stack);
}
};
Debug.setListener(listener);
Promise.resolve(42)
.then(
function f0() {
debugger; // Break 0.
} // Break 1.
)
.then(callback)
.then(callback.bind(null))
.then(Object)
.then(callback.bind(null).bind(null))
.then(finalize)
.catch(function(err) {
%AbortJS("FAIL: " + err);
});
function callback(x) {
return x // Break 2. // Break 4. // Break 6.
; // Break 3. // Break 5. // Break 7.
}
function finalize() {
assertNull(exception); // Break 8.
assertEquals(expected_breaks, break_count);
Debug.setListener(null);
}

View File

@ -0,0 +1,66 @@
// 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.
// 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 expected_events = 1;
var log = [];
var p = new Promise(function(resolve, reject) {
log.push("resolve");
resolve();
});
var q = p.then(
function() {
log.push("throw");
throw new Error("caught");
});
q.catch(
function(e) {
assertEquals("caught", e.message);
});
function listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Exception) {
expected_events--;
assertTrue(expected_events >= 0);
assertEquals("caught", event_data.exception().message);
assertFalse(event_data.uncaught());
}
} catch (e) {
%AbortJS(e + "\n" + e.stack);
}
}
Debug.setBreakOnException();
Debug.setListener(listener);
log.push("end main");
function testDone(iteration) {
function checkResult() {
try {
assertTrue(iteration < 10);
if (expected_events === 0) {
assertEquals(["resolve", "end main", "throw"], log);
} else {
testDone(iteration + 1);
}
} catch (e) {
%AbortJS(e + "\n" + e.stack);
}
}
%EnqueueMicrotask(checkResult);
}
testDone(0);

View File

@ -0,0 +1,76 @@
// 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: --ignore-unhandled-promises
// Test debug events when we only listen to uncaught exceptions and
// there is only a default reject handler for the to-be-rejected Promise.
// We expect only one debug event: when the first Promise is rejected
// and only has default reject handlers. No event is triggered when
// simply forwarding the rejection with .then's default handler.
Debug = debug.Debug;
var expected_events = 1;
var log = [];
var resolve, reject;
var p0 = new Promise(function(res, rej) { resolve = res; reject = rej; });
var p1 = p0.then(function() {
log.push("p0.then");
throw new Error("123"); // event
});
var p2 = p1.then(function() {
log.push("p1.then");
});
var q = new Promise(function(res, rej) {
log.push("resolve q");
res();
});
q.then(function() {
log.push("resolve p");
resolve();
})
function listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Exception) {
expected_events--;
assertTrue(expected_events >= 0);
assertTrue(event_data.uncaught());
// p1 is rejected, uncaught except for its default reject handler.
assertTrue(
exec_state.frame(0).sourceLineText().indexOf("// event") > 0);
}
} catch (e) {
%AbortJS(e + "\n" + e.stack);
}
}
Debug.setBreakOnUncaughtException();
Debug.setListener(listener);
log.push("end main");
function testDone(iteration) {
function checkResult() {
try {
assertTrue(iteration < 10);
if (expected_events === 0) {
assertEquals(["resolve q", "end main", "resolve p", "p0.then"], log);
} else {
testDone(iteration + 1);
}
} catch (e) {
%AbortJS(e + "\n" + e.stack);
}
}
%EnqueueMicrotask(checkResult);
}
testDone(0);

View File

@ -0,0 +1,33 @@
// 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.
// Test debug events when we only listen to uncaught exceptions, the Promise
// throws, and a catch handler is installed right before throwing.
// We expect no debug event to be triggered.
Debug = debug.Debug;
var p = new Promise(function(resolve, reject) {
resolve();
});
var q = p.then(
function() {
q.catch(function(e) {
assertEquals("caught", e.message);
});
throw new Error("caught");
});
function listener(event, exec_state, event_data, data) {
try {
assertTrue(event != Debug.DebugEvent.Exception);
} catch (e) {
%AbortJS(e + "\n" + e.stack);
}
}
Debug.setBreakOnUncaughtException();
Debug.setListener(listener);

View File

@ -0,0 +1,35 @@
// 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.
// Test debug events when we only listen to uncaught exceptions and
// there is a catch handler for the exception thrown in a Promise.
// We expect no debug event to be triggered.
Debug = debug.Debug;
var p = new Promise(function(resolve, reject) {
resolve();
});
var q = p.then(
function() {
throw new Error("caught throw");
});
q.catch(
function(e) {
assertEquals("caught throw", e.message);
});
function listener(event, exec_state, event_data, data) {
try {
assertTrue(event != Debug.DebugEvent.Exception);
} catch (e) {
%AbortJS(e + "\n" + e.stack);
}
}
Debug.setBreakOnUncaughtException();
Debug.setListener(listener);

View File

@ -0,0 +1,41 @@
// 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.
// Test debug events when we only listen to uncaught exceptions and
// there is a catch handler for the to-be-rejected Promise.
// We expect no Exception debug events, since the default reject handler passes
// the rejection on to a user-defined reject handler.
Debug = debug.Debug;
var resolve, reject;
var p0 = new Promise(function(res, rej) { resolve = res; reject = rej; });
var p1 = p0.then(function() {
throw new Error();
});
var p2 = p1.then(function() { });
var p3 = p2.catch(function() { });
var q = new Promise(function(res, rej) {
res();
});
q.then(function() {
resolve();
})
function listener(event, exec_state, event_data, data) {
try {
assertTrue(event != Debug.DebugEvent.Exception);
} catch (e) {
%AbortJS(e + "\n" + e.stack);
}
}
Debug.setBreakOnUncaughtException();
Debug.setListener(listener);

View File

@ -0,0 +1,70 @@
// Copyright 2016 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.
// Test debug events when we listen to all exceptions and
// there is a catch handler for the exception thrown in a Promise, first
// caught by a try-finally, and immediately rethrown.
// We expect a normal Exception debug event to be triggered.
Debug = debug.Debug;
var expected_events = 1;
var log = [];
var p = new Promise(function(resolve, reject) {
log.push("resolve");
resolve();
});
var q = p.then(
function() {
log.push("throw");
try {
throw new Error("caught");
} finally {
}
});
q.catch(
function(e) {
assertEquals("caught", e.message);
});
function listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Exception) {
expected_events--;
assertTrue(expected_events >= 0);
assertEquals("caught", event_data.exception().message);
assertFalse(event_data.uncaught());
}
} catch (e) {
%AbortJS(e + "\n" + e.stack);
}
}
Debug.setBreakOnException();
Debug.setListener(listener);
log.push("end main");
function testDone(iteration) {
function checkResult() {
try {
assertTrue(iteration < 10);
if (expected_events === 0) {
assertEquals(["resolve", "end main", "throw"], log);
} else {
testDone(iteration + 1);
}
} catch (e) {
%AbortJS(e + "\n" + e.stack);
}
}
%EnqueueMicrotask(checkResult);
}
testDone(0);

View File

@ -0,0 +1,39 @@
// 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: --ignore-unhandled-promises
// Test debug events when we only listen to uncaught exceptions and
// an exception is thrown in the Promise constructor.
// We expect an Exception debug event with a promise to be triggered.
Debug = debug.Debug;
var step = 0;
var exception = null;
function listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Exception) {
assertEquals(0, step);
assertEquals("uncaught", event_data.exception().message);
assertTrue(event_data.uncaught());
// Assert that the debug event is triggered at the throw site.
assertTrue(exec_state.frame(0).sourceLineText().indexOf("// event") > 0);
step++;
}
} catch (e) {
exception = e;
}
}
Debug.setBreakOnUncaughtException();
Debug.setListener(listener);
var p = new Promise(function(resolve, reject) {
throw new Error("uncaught"); // event
});
assertEquals(1, step);
assertNull(exception);

View File

@ -0,0 +1,65 @@
// 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: --ignore-unhandled-promises
// Test debug events when we listen to all exceptions and
// there is no catch handler for the exception thrown in a Promise.
// We expect an Exception debug event with a promise to be triggered.
Debug = debug.Debug;
var expected_events = 1;
var log = [];
var p = new Promise(function(resolve, reject) {
log.push("resolve");
resolve();
});
var q = p.then(
function() {
log.push("throw");
throw new Error("uncaught"); // event
});
function listener(event, exec_state, event_data, data) {
try {
// Ignore exceptions during startup in stress runs.
if (event == Debug.DebugEvent.Exception) {
expected_events--;
assertTrue(expected_events >= 0);
assertEquals("uncaught", event_data.exception().message);
assertTrue(event_data.uncaught());
// Assert that the debug event is triggered at the throw site.
assertTrue(exec_state.frame(0).sourceLineText().indexOf("// event") > 0);
}
} catch (e) {
%AbortJS(e + "\n" + e.stack);
}
}
Debug.setBreakOnException();
Debug.setListener(listener);
log.push("end main");
function testDone(iteration) {
function checkResult() {
try {
assertTrue(iteration < 10);
if (expected_events === 0) {
assertEquals(["resolve", "end main", "throw"], log);
} else {
testDone(iteration + 1);
}
} catch (e) {
%AbortJS(e + "\n" + e.stack);
}
}
%EnqueueMicrotask(checkResult);
}
testDone(0);

View File

@ -0,0 +1,64 @@
// 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: --ignore-unhandled-promises
// Test debug events when we only listen to uncaught exceptions and
// there is a catch handler for the exception thrown in a Promise.
// We expect an Exception debug event with a promise to be triggered.
Debug = debug.Debug;
var expected_events = 1;
var log = [];
var p = new Promise(function(resolve, reject) {
log.push("resolve");
resolve();
});
var q = p.then(
function() {
log.push("throw");
throw new Error("uncaught"); // event
});
function listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Exception) {
expected_events--;
assertTrue(expected_events >= 0);
assertEquals("uncaught", event_data.exception().message);
assertTrue(event_data.uncaught());
// Assert that the debug event is triggered at the throw site.
assertTrue(exec_state.frame(0).sourceLineText().indexOf("// event") > 0);
}
} catch (e) {
%AbortJS(e + "\n" + e.stack);
}
}
Debug.setBreakOnUncaughtException();
Debug.setListener(listener);
log.push("end main");
function testDone(iteration) {
function checkResult() {
try {
assertTrue(iteration < 10);
if (expected_events === 0) {
assertEquals(["resolve", "end main", "throw"], log);
} else {
testDone(iteration + 1);
}
} catch (e) {
%AbortJS(e + "\n" + e.stack);
}
}
%EnqueueMicrotask(checkResult);
}
testDone(0);

View File

@ -0,0 +1,76 @@
// 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.
// Test debug events when an exception is thrown inside a Promise,
// which is caught by a custom promise, which throws a new exception
// in its reject handler. We expect no Exception debug events.
Debug = debug.Debug;
var expected_events = 2;
var log = [];
var p = new Promise(function(resolve, reject) {
log.push("resolve");
resolve();
});
function MyPromise(resolver) {
var reject = function() {
throw new Error("reject"); // event
};
var resolve = function() { };
resolver(resolve, reject);
};
MyPromise.prototype = new Promise(function() {});
MyPromise.__proto__ = Promise;
p.constructor = MyPromise;
var q = p.then(
function() {
log.push("throw caught");
throw new Error("caught"); // event
});
function listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Exception) {
if (expected_events === 0) {
assertUnreachable();
} else {
expected_events--;
log.push("uncaught exception");
}
}
} catch (e) {
%AbortJS(e + "\n" + e.stack);
}
}
Debug.setBreakOnUncaughtException();
Debug.setListener(listener);
log.push("end main");
function testDone(iteration) {
function checkResult() {
try {
assertTrue(iteration < 10);
if (expected_events === 0) {
assertEquals(["resolve", "end main",
"throw caught", "uncaught exception", "uncaught exception"], log);
} else {
testDone(iteration + 1);
}
} catch (e) {
%AbortJS(e + "\n" + e.stack);
}
}
%EnqueueMicrotask(checkResult);
}
testDone(0);

View File

@ -0,0 +1,41 @@
// 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: --ignore-unhandled-promises
// Test debug events when we only listen to uncaught exceptions and
// the Promise is rejected within a try-catch in the Promise constructor.
// We expect an Exception debug event with a promise to be triggered.
Debug = debug.Debug;
var step = 0;
var exception = null;
function listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Exception) {
assertEquals(0, step);
assertEquals("uncaught", event_data.exception().message);
assertTrue(event_data.uncaught());
// Assert that the debug event is triggered at the throw site.
assertTrue(exec_state.frame(0).sourceLineText().indexOf("// event") > 0);
step++;
}
} catch (e) {
exception = e;
}
}
Debug.setBreakOnUncaughtException();
Debug.setListener(listener);
var p = new Promise(function(resolve, reject) {
try { // This try-catch must not prevent this uncaught reject event.
reject(new Error("uncaught")); // event
} catch (e) { }
});
assertEquals(1, step);
assertNull(exception);

View File

@ -0,0 +1,43 @@
// 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: --ignore-unhandled-promises
// Test debug events when we only listen to uncaught exceptions and
// an exception is thrown in the Promise constructor, but caught in an
// inner try-catch. The Promise is rejected afterwards.
// We expect an Exception debug event with a promise to be triggered.
Debug = debug.Debug;
var step = 0;
var exception = null;
function listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Exception) {
assertEquals(0, step);
assertEquals("uncaught", event_data.exception().message);
assertTrue(event_data.uncaught());
// Assert that the debug event is triggered at the throw site.
assertTrue(exec_state.frame(0).sourceLineText().indexOf("// event") > 0);
step++;
}
} catch (e) {
exception = e;
}
}
Debug.setBreakOnUncaughtException();
Debug.setListener(listener);
var p = new Promise(function(resolve, reject) {
try { // This try-catch must not prevent this uncaught reject event.
throw new Error("caught");
} catch (e) { }
reject(new Error("uncaught")); // event
});
assertEquals(1, step);
assertNull(exception);

View File

@ -0,0 +1,60 @@
// Copyright 2016 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.
// Test that the parameter initialization block scope set up for
// sloppy eval is visible to the debugger.
var Debug = debug.Debug;
var exception = null;
var break_count = 0;
function call_for_break() {
return 5;
}
function test(x = eval("var y = 7; debugger; y") + call_for_break()) {
return x;
}
function listener(event, exec_state, event_data, data) {
if (event != Debug.DebugEvent.Break) return;
try {
var frame = exec_state.frame(0);
var block_scope;
if (break_count++ == 0) {
// Inside eval.
assertEquals([ debug.ScopeType.Eval,
debug.ScopeType.Block,
debug.ScopeType.Closure,
debug.ScopeType.Script,
debug.ScopeType.Global ],
frame.allScopes().map(s => s.scopeType()));
exec_state.prepareStep(Debug.StepAction.StepOut);
block_scope = frame.scope(1);
} else {
// Outside of eval.
assertEquals([ debug.ScopeType.Block,
debug.ScopeType.Local,
debug.ScopeType.Script,
debug.ScopeType.Global ],
frame.allScopes().map(s => s.scopeType()));
block_scope = frame.scope(0);
}
assertTrue(block_scope.scopeObject().propertyNames().includes('y'));
assertEquals(7, block_scope.scopeObject().property('y').value().value());
} catch (e) {
print(e);
exception = e;
}
}
Debug.setListener(listener);
assertEquals(12, test());
Debug.setListener(null);
assertNull(exception);
assertEquals(2, break_count);

View File

@ -0,0 +1,41 @@
// 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.
'use strict';
var Debug = debug.Debug
var done = false;
var stepCount = 0;
function listener(event, execState, eventData, data) {
if (event == Debug.DebugEvent.Break) {
if (!done) {
execState.prepareStep(Debug.StepAction.StepInto);
var s = execState.frame().sourceLineText();
assertTrue(s.indexOf('// ' + stepCount + '.') !== -1);
stepCount++;
}
}
};
Debug.setListener(listener);
function GetBase() {
var x = 1; // 1.
var y = 2; // 2.
done = true; // 3.
return null;
}
function f() {
class Derived extends GetBase() {} // 0.
}
var bp = Debug.setBreakPoint(f, 1, 20);
f();
assertEquals(4, stepCount);
Debug.setListener(null);

View File

@ -0,0 +1,117 @@
// 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.
'use strict';
var Debug = debug.Debug
var done, stepCount;
var exception = null;
function listener(event, execState, eventData, data) {
if (event != Debug.DebugEvent.Break) return;
try {
if (!done) {
execState.prepareStep(Debug.StepAction.StepInto);
var s = execState.frame().sourceLineText();
assertTrue(s.indexOf('// ' + stepCount + '.') !== -1);
stepCount++;
}
} catch (e) {
exception = e;
}
};
Debug.setListener(listener);
class Base {
constructor() {
var x = 1; // 1.
var y = 2; // 2.
done = true; // 3.
}
}
class Derived extends Base {} // 0.
(function TestBreakPointInConstructor() {
done = false;
stepCount = 1;
var bp = Debug.setBreakPoint(Base, 0);
new Base();
assertEquals(4, stepCount);
Debug.clearBreakPoint(bp);
})();
(function TestDefaultConstructor() {
done = false;
stepCount = 1;
var bp = Debug.setBreakPoint(Base, 0);
new Derived();
assertEquals(4, stepCount);
Debug.clearBreakPoint(bp);
})();
(function TestStepInto() {
done = false;
stepCount = -1;
function f() {
new Derived(); // -1.
}
var bp = Debug.setBreakPoint(f, 0);
f();
assertEquals(4, stepCount);
Debug.clearBreakPoint(bp);
})();
(function TestExtraIndirection() {
done = false;
stepCount = -2;
class Derived2 extends Derived {} // -1.
function f() {
new Derived2(); // -2.
}
var bp = Debug.setBreakPoint(f, 0);
f();
assertEquals(4, stepCount);
Debug.clearBreakPoint(bp);
})();
(function TestBoundClass() {
done = false;
stepCount = -1;
var bound = Derived.bind(null);
function f() {
new bound(); // -1.
}
var bp = Debug.setBreakPoint(f, 0);
f();
assertEquals(4, stepCount);
Debug.clearBreakPoint(bp);
})();
Debug.setListener(null);
assertNull(exception);

View File

@ -0,0 +1,36 @@
// Copyright 2015 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.
Debug = debug.Debug
var exception = null;
var break_count = 0;
function listener(event, exec_state, event_data, data) {
if (event != Debug.DebugEvent.Break) return;
try {
print(event_data.sourceLineText());
assertTrue(
event_data.sourceLineText().indexOf(`Break ${break_count++}.`) > 0);
exec_state.prepareStep(Debug.StepAction.StepInto);
} catch (e) {
exception = e;
}
};
function customSplit() {
return "x" // Break 2.
; // Break 3.
}
var o = {};
o[Symbol.split] = customSplit;
Debug.setListener(listener);
debugger; // Break 0.
var result = "".split(o); // Break 1.
Debug.setListener(null); // Break 4.
assertEquals("x", result);
assertNull(exception);

View File

@ -0,0 +1,99 @@
// 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.
//
Debug = debug.Debug
var exception = null;
function listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Break) {
exec_state.prepareStep(Debug.StepAction.StepInto);
print(event_data.sourceLineText());
assertTrue(
event_data.sourceLineText().indexOf(`B${breaks++}`) > 0);
}
} catch (e) {
print(e);
quit();
exception = e;
}
}
function cb_set(num) {
print("element " + num); // B2 B5 B8
return true; // B3 B6 B9
} // B4 B7 B10
function cb_map(key, val) {
print("key " + key + ", value " + val); // B2 B5 B8
return true; // B3 B6 B9
} // B4 B7 B10
var s = new Set();
s.add(1);
s.add(2);
s.add(3);
var m = new Map();
m.set('foo', 1);
m.set('bar', 2);
m.set('baz', 3);
var breaks = 0;
Debug.setListener(listener);
debugger; // B0
s.forEach(cb_set); // B1
Debug.setListener(null); // B11
assertNull(exception);
assertEquals(12, breaks);
breaks = 0;
Debug.setListener(listener);
debugger; // B0
m.forEach(cb_map); // B1
Debug.setListener(null); // B11
assertNull(exception);
assertEquals(12, breaks);
// Test two levels of builtin callbacks:
// Array.forEach calls a callback function, which by itself uses
// Array.forEach with another callback function.
function cb_set_2(num) {
print("element " + num); // B3 B6 B9 B15 B18 B21 B27 B30 B33
return true; // B4 B7 B10 B16 B19 B22 B28 B31 B34
} // B5 B8 B11 B17 B20 B23 B29 B32 B35
function cb_map_2(k, v) {
print(`key ${k}, value ${v}`); // B3 B6 B9 B15 B18 B21 B27 B30 B33
return true; // B4 B7 B10 B16 B19 B22 B28 B31 B34
} // B5 B8 B11 B17 B20 B23 B29 B32 B35
function cb_set_foreach(num) {
s.forEach(cb_set_2); // B2 B14 B26
print("back."); // B12 B24 B36
} // B13 B25 B37
function cb_map_foreach(key, val) {
m.forEach(cb_map_2); // B2 B14 B26
print("back."); // B12 B24 B36
} // B13 B25 B37
breaks = 0;
Debug.setListener(listener);
debugger; // B0
s.forEach(cb_set_foreach); // B1
Debug.setListener(null); // B38
assertNull(exception);
assertEquals(39, breaks);
breaks = 0;
Debug.setListener(listener);
debugger; // B0
m.forEach(cb_map_foreach); // B1
Debug.setListener(null); // B38
assertNull(exception);
assertEquals(39, breaks);

View File

@ -0,0 +1,45 @@
// Copyright 2015 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.
Debug = debug.Debug
var exception = null;
var log = [];
function listener(event, exec_state, event_data, data) {
if (event != Debug.DebugEvent.Break) return;
try {
print(event_data.sourceLineText());
var entry = "";
for (var i = 0; i < exec_state.frameCount(); i++) {
entry += exec_state.frame(i).sourceLineText().substr(-1);
entry += exec_state.frame(i).sourceColumn();
}
log.push(entry);
exec_state.prepareStep(Debug.StepAction.StepInto);
} catch (e) {
exception = e;
}
};
function default_arg(x) {
return "default"; // d
} // e
function f(arg0 = default_arg()) { // f
return arg0; // g
} // h
Debug.setListener(listener);
debugger; // a
var result = f(); // b
Debug.setListener(null); // c
assertNull(exception);
assertEquals("default", result);
assertEquals(["a0","b13","f18b13","d2f18b13","d19f18b13","g14b13","c0"],
log);

View File

@ -0,0 +1,48 @@
// 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.
Debug = debug.Debug
var exception = null;
var yields = 0;
function listener(event, exec_state, event_data, data) {
if (event != Debug.DebugEvent.Break) return;
try {
var source = exec_state.frame(0).sourceLineText();
print(source);
if (/stop stepping/.test(source)) return;
if (/yield/.test(source)) yields++;
if (yields == 4) {
exec_state.prepareStep(Debug.StepAction.StepOut);
} else {
exec_state.prepareStep(Debug.StepAction.StepInto);
}
} catch (e) {
print(e, e.stack);
exception = e;
}
};
Debug.setListener(listener);
function* g() {
for (var i = 0; i < 3; ++i) {
yield i;
}
}
var i = g();
debugger;
for (var num of g()) {}
i.next();
print(); // stop stepping
// Not stepped into.
i.next();
i.next();
assertNull(exception);
assertEquals(4, yields);

View File

@ -0,0 +1,79 @@
// 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.
Debug = debug.Debug
var exception = null;
var break_count = 0;
const expected_breaks = 10;
function listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Break) {
assertTrue(exec_state.frameCount() != 0, "FAIL: Empty stack trace");
var source = exec_state.frame(0).sourceLineText();
print("paused at: " + source);
assertTrue(source.indexOf("// Break " + break_count + ".") > 0,
"Unexpected pause at: " + source + "\n" +
"Expected: // Break " + break_count + ".");
if (source.indexOf("StepOver.") !== -1) {
exec_state.prepareStep(Debug.StepAction.StepOver);
} else if (source.indexOf("StepOut.") !== -1) {
exec_state.prepareStep(Debug.StepAction.StepOut);
} else {
exec_state.prepareStep(Debug.StepAction.StepInto);
}
++break_count;
}
} catch (e) {
exception = e;
print(e, e.stack);
}
};
Debug.setListener(listener);
Promise.resolve(42)
.then(promise1)
.then(Object) // Should skip stepping into native.
.then(Boolean) // Should skip stepping into native.
.then(promise2)
.catch(promise3)
.then(promise4)
.catch(function(e) {
%AbortJS("FAIL: uncaught exception " + e);
});
function promise1() {
debugger; // Break 0.
return exception || 1 // Break 1.
; // Break 2. StepOver.
}
function promise2() {
throw new Error; // Break 3.
}
function promise3() {
return break_count // Break 4.
; // Break 5.
}
function promise4() {
finalize(); // Break 6. StepOver.
return 0 // Break 7.
; // Break 8. StepOut.
}
function finalize() {
Promise.resolve().then(function() {
if (expected_breaks !== break_count) { // Break 9. StepOut.
%AbortJS("FAIL: expected <" + expected_breaks + "> breaks instead of <" +
break_count + ">");
}
if (exception !== null) {
%AbortJS("FAIL: exception: " + exception);
}
});
}

View File

@ -0,0 +1,60 @@
// Copyright 2015 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.
Debug = debug.Debug
var exception = null;
var log = [];
function listener(event, exec_state, event_data, data) {
if (event != Debug.DebugEvent.Break) return;
try {
print(event_data.sourceLineText());
var entry = "";
for (var i = 0; i < exec_state.frameCount(); i++) {
entry += exec_state.frame(i).sourceLineText().substr(-1);
entry += exec_state.frame(i).sourceColumn();
}
log.push(entry);
exec_state.prepareStep(Debug.StepAction.StepInto);
} catch (e) {
exception = e;
}
};
var target = {};
var handler = {
has: function(target, name) {
return true; // h
}, // i
get: function(target, name) {
return 42; // j
}, // k
set: function(target, name, value) {
return false; // l
}, // m
}
var proxy = new Proxy(target, handler);
Debug.setListener(listener);
debugger; // a
var has = "step" in proxy; // b
var get = proxy.step; // c
proxy.step = 43; // d
Debug.setListener(null); // g
assertNull(exception);
assertTrue(has);
assertEquals(42, get);
assertEquals([
"a0",
"b10", "h4b17", "h16b17", // [[Has]]
"c10", "j4c16", "j14c16", // [[Get]]
"d0", "l4d11", "l17d11", // [[Set]]
"g0"
], log);

View File

@ -0,0 +1,59 @@
// Copyright 2015 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.
Debug = debug.Debug
var exception = null;
var log = [];
function listener(event, exec_state, event_data, data) {
if (event != Debug.DebugEvent.Break) return;
try {
print(event_data.sourceLineText());
var entry = "";
for (var i = 0; i < exec_state.frameCount(); i++) {
entry += exec_state.frame(i).sourceLineText().substr(-1);
entry += exec_state.frame(i).sourceColumn();
}
log.push(entry);
exec_state.prepareStep(Debug.StepAction.StepInto);
} catch (e) {
exception = e;
}
};
function u(x) {
return x.toUpperCase(); // d
} // e
var n = 3;
var o = {
toString: function() {
return "D"; // f
} // g
}
Debug.setListener(listener);
debugger; // a
var s = `1 ${u("a")} 2 ${u("b")} 3 ${n} 4 ${o}`; // b
Debug.setListener(null); // c
assertNull(exception);
assertEquals([
"a0",
"b8",
"d11b13",
"d25b13",
"b25",
"d11b25",
"d25b25",
"f4b44",
"f15b44",
"c0"
], log);

View File

@ -0,0 +1,209 @@
// 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: --harmony
Debug = debug.Debug;
var break_count = 0
var exception = null;
var log = []
var s = 0;
var a = [1, 2, 3];
var b = [1, 2, 3, 4];
var null_value = null;
var i = 0;
function f() {
"use strict";
debugger; // Break a
var j; // Break b
for (var i in null_value) { // Break c
s += a[i];
}
for (j in null_value) { // Break d
s += a[j];
}
for (var i in a) { // Break e
s += a[i]; // Break E
}
for (j in a) { // Break f
s += a[j]; // Break F
}
for (let i in a) { // Break g
s += a[i]; // Break G
}
for (var i of a) { // Break h
s += i; // Break H
}
for (j of a) { // Break i
s += j; // Break I
}
for (let i of a) { // Break j
s += i; // Break J
}
for (var i = 0; i < 3; i++) { // Break k
s += a[i]; // Break K
}
for (j = 0; j < 3; j++) { // Break l
s += a[j]; // Break L
}
for (let i = 0; i < 3; i++) { // Break m
s += a[i]; // Break M
}
for (let i of a) {} // Break n
[1, ...a] // Break o
} // Break y
function listener(event, exec_state, event_data, data) {
if (event != Debug.DebugEvent.Break) return;
try {
var line = exec_state.frame(0).sourceLineText();
var col = exec_state.frame(0).sourceColumn();
print(line);
var match = line.match(/\/\/ Break (\w)$/);
assertEquals(2, match.length);
log.push(match[1] + col);
exec_state.prepareStep(Debug.StepAction.StepOver);
break_count++;
} catch (e) {
exception = e;
}
}
Debug.setListener(listener);
f();
Debug.setListener(null); // Break z
print("log:\n"+ JSON.stringify(log));
// The let declaration differs from var in that the loop variable
// is declared in every iteration.
// TODO(verwaest): For-of has hacky position numbers for Symbol.iterator and
// .next. Restore to proper positions once the CallPrinter can disambiguate
// based on other values.
var expected = [
// Entry
'a2',
// Empty for-in-var: get enumerable
'c16',
// Empty for-in: get enumerable
'd12',
// For-in-var: get enumerable, assign, body, assign, body, ...
'e16',
'e11',
'E4',
'e11',
'E4',
'e11',
'E4',
'e11',
// For-in: get enumerable, assign, body, assign, body, ...
'f12',
'f7',
'F4',
'f7',
'F4',
'f7',
'F4',
'f7',
// For-in-let: get enumerable, next, body, next, ...
'g16',
'g11',
'G4',
'g11',
'G4',
'g11',
'G4',
'g11',
// For-of-var: [Symbol.iterator](), next(), body, next(), body, ...
'h16',
'h11',
'H4',
'h11',
'H4',
'h11',
'H4',
'h11',
// For-of: [Symbol.iterator](), next(), body, next(), body, ...
'i12',
'i7',
'I4',
'i7',
'I4',
'i7',
'I4',
'i7',
// For-of-let: [Symbol.iterator](), next(), body, next(), ...
'j18',
'j11',
'J4',
'j11',
'J4',
'j11',
'J4',
'j11',
// For-var: init, condition, body, next, condition, body, ...
'k15',
'k20',
'K4',
'k26',
'k20',
'K4',
'k26',
'k20',
'K4',
'k26',
'k20',
// For: init, condition, body, next, condition, body, ...
'l7',
'l16',
'L4',
'l22',
'l16',
'L4',
'l22',
'l16',
'L4',
'l22',
'l16',
// For-let: init, condition, body, next, condition, body, ...
'm15',
'm20',
'M4',
'm26',
'm20',
'M4',
'm26',
'm20',
'M4',
'm26',
'm20',
// For-of, empty: [Symbol.iterator](), next() once
'n16',
'n11',
// Spread: expression statement
'o2',
// Exit.
'y0',
'z0',
]
print("expected:\n"+ JSON.stringify(expected));
assertArrayEquals(expected, log);
assertEquals(54, s);
assertNull(exception);

View File

@ -0,0 +1,48 @@
// Copyright 2016 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.
Debug = debug.Debug
var exception = null;
var breaks = 0;
function listener(event, exec_state, event_data, data) {
if (event != Debug.DebugEvent.Break) return;
try {
var source = exec_state.frame(0).sourceLineText();
assertTrue(RegExp(`B${breaks++}`).test(source));
if (/stop/.test(source)) return;
if (/step out/.test(source)) {
exec_state.prepareStep(Debug.StepAction.StepOut);
} else if (/step in/.test(source)) {
exec_state.prepareStep(Debug.StepAction.StepInto);
} else {
exec_state.prepareStep(Debug.StepAction.StepOver);
}
} catch (e) {
print(e, e.stack);
exception = e;
}
}
Debug.setListener(listener);
function * g() {
debugger; // B0
yield 1; // B1
yield 2; // B2 step out
yield 3; // B5
yield 4; // B6 step out
return 2 * (yield 5);
}
var i = g();
assertEquals(1, i.next().value);
assertEquals(2, i.next().value); // B3
assertEquals(3, i.next().value); // B4 step in
assertEquals(4, i.next().value); // B7
assertEquals(5, i.next().value); // B8
assertEquals(6, i.next(3).value); // B9 stop
assertNull(exception);
assertEquals(10, breaks);

View File

@ -0,0 +1,54 @@
// Copyright 2015 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: --noanalyze-environment-liveness
Debug = debug.Debug
listenerComplete = false;
breakPointCount = 0;
exception = null;
function listener(event, exec_state, event_data, data) {
if (event != Debug.DebugEvent.Break) return;
try {
breakPointCount++;
if (breakPointCount == 1) {
// Break point in initializer for parameter `a`, invoked by
// initializer for parameter `b`
assertEquals('default', exec_state.frame(0).evaluate('mode').value());
assertThrows(() => exec_state.frame(1).evaluate('b'));
assertThrows(() => exec_state.frame(1).evaluate('c'));
} else if (breakPointCount == 2) {
// Break point in IIFE initializer for parameter `c`
assertEquals('modeFn', exec_state.frame(1).evaluate('a.name').value());
assertEquals('default', exec_state.frame(1).evaluate('b').value());
assertThrows(() => exec_state.frame(1).evaluate('c'));
} else if (breakPointCount == 3) {
// Break point in function body --- `c` parameter is shadowed
assertEquals('modeFn', exec_state.frame(0).evaluate('a.name').value());
assertEquals('default', exec_state.frame(0).evaluate('b').value());
assertEquals('local', exec_state.frame(0).evaluate('d').value());
}
} catch (e) {
exception = e;
}
};
// Add the debug event listener.
Debug.setListener(listener);
function f(a = function modeFn(mode) { debugger; return mode; },
b = a("default"),
c = (function() { debugger; })()) {
var d = 'local';
debugger;
};
f();
// Make sure that the debug event listener vas invoked.
assertEquals(3, breakPointCount);
assertNull(exception);

View File

@ -0,0 +1,283 @@
// 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: --noanalyze-environment-liveness
var Debug = debug.Debug;
var global_marker = 7;
function RunTest(name, formals_and_body, args, handler, continuation) {
var handler_called = false;
var exception = null;
function listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Break) {
handler_called = true;
handler(exec_state);
}
} catch (e) {
exception = e;
}
}
function run(thunk) {
handler_called = false;
exception = null;
var res = thunk();
if (continuation)
continuation(res);
assertTrue(handler_called, "listener not called for " + name);
assertNull(exception, name + " / " + exception);
}
var fun = Function.apply(null, formals_and_body);
var gen = (function*(){}).constructor.apply(null, formals_and_body);
Debug.setListener(listener);
run(function () { return fun.apply(null, args) });
run(function () { return gen.apply(null, args).next().value });
Debug.setListener(null);
}
// Check that two scope are the same.
function assertScopeMirrorEquals(scope1, scope2) {
assertEquals(scope1.scopeType(), scope2.scopeType());
assertEquals(scope1.frameIndex(), scope2.frameIndex());
assertEquals(scope1.scopeIndex(), scope2.scopeIndex());
assertPropertiesEqual(scope1.scopeObject().value(), scope2.scopeObject().value());
}
function CheckFastAllScopes(scopes, exec_state) {
var fast_all_scopes = exec_state.frame().allScopes(true);
var length = fast_all_scopes.length;
assertTrue(scopes.length >= length);
for (var i = 0; i < scopes.length && i < length; i++) {
var scope = fast_all_scopes[length - i - 1];
assertEquals(scopes[scopes.length - i - 1], scope.scopeType());
}
}
// Check that the scope chain contains the expected types of scopes.
function CheckScopeChain(scopes, exec_state) {
var all_scopes = exec_state.frame().allScopes();
assertEquals(scopes.length, exec_state.frame().scopeCount());
assertEquals(scopes.length, all_scopes.length, "FrameMirror.allScopes length");
for (var i = 0; i < scopes.length; i++) {
var scope = exec_state.frame().scope(i);
assertEquals(scopes[i], scope.scopeType());
assertScopeMirrorEquals(all_scopes[i], scope);
// Check the global object when hitting the global scope.
if (scopes[i] == debug.ScopeType.Global) {
assertEquals(global_marker, scope.scopeObject().value().global_marker);
}
}
CheckFastAllScopes(scopes, exec_state);
}
// Check that the content of the scope is as expected. For functions just check
// that there is a function.
function CheckScopeContent(content, number, exec_state) {
var scope = exec_state.frame().scope(number);
var count = 0;
for (var p in content) {
var property_mirror = scope.scopeObject().property(p);
assertFalse(property_mirror.isUndefined(),
'property ' + p + ' not found in scope');
assertEquals(content[p], property_mirror.value().value(),
'property ' + p + ' has unexpected value');
count++;
}
// 'arguments' and might be exposed in the local and closure scope. Just
// ignore this.
var scope_size = scope.scopeObject().properties().length;
if (!scope.scopeObject().property('arguments').isUndefined()) {
scope_size--;
}
// Skip property with empty name.
if (!scope.scopeObject().property('').isUndefined()) {
scope_size--;
}
if (scope_size < count) {
print('Names found in scope:');
var names = scope.scopeObject().propertyNames();
for (var i = 0; i < names.length; i++) {
print(names[i]);
}
}
assertTrue(scope_size >= count);
}
// Simple empty local scope.
RunTest("Local 1",
['debugger;'],
[],
function (exec_state) {
CheckScopeChain([debug.ScopeType.Local,
debug.ScopeType.Script,
debug.ScopeType.Global], exec_state);
CheckScopeContent({}, 0, exec_state);
});
// Local scope with a parameter.
RunTest("Local 2",
['a', 'debugger;'],
[1],
function (exec_state) {
CheckScopeChain([debug.ScopeType.Local,
debug.ScopeType.Script,
debug.ScopeType.Global], exec_state);
CheckScopeContent({a:1}, 0, exec_state);
});
// Local scope with a parameter and a local variable.
RunTest("Local 3",
['a', 'var x = 3; debugger;'],
[1],
function (exec_state) {
CheckScopeChain([debug.ScopeType.Local,
debug.ScopeType.Script,
debug.ScopeType.Global], exec_state);
CheckScopeContent({a:1,x:3}, 0, exec_state);
});
// Local scope with parameters and local variables.
RunTest("Local 4",
['a', 'b', 'var x = 3; var y = 4; debugger;'],
[1, 2],
function (exec_state) {
CheckScopeChain([debug.ScopeType.Local,
debug.ScopeType.Script,
debug.ScopeType.Global], exec_state);
CheckScopeContent({a:1,b:2,x:3,y:4}, 0, exec_state);
});
// Empty local scope with use of eval.
RunTest("Local 5",
['eval(""); debugger;'],
[],
function (exec_state) {
CheckScopeChain([debug.ScopeType.Local,
debug.ScopeType.Script,
debug.ScopeType.Global], exec_state);
CheckScopeContent({}, 0, exec_state);
});
// Local introducing local variable using eval.
RunTest("Local 6",
['eval("var i = 5"); debugger;'],
[],
function (exec_state) {
CheckScopeChain([debug.ScopeType.Local,
debug.ScopeType.Script,
debug.ScopeType.Global], exec_state);
CheckScopeContent({i:5}, 0, exec_state);
});
// Local scope with parameters, local variables and local variable introduced
// using eval.
RunTest("Local 7",
['a', 'b',
"var x = 3; var y = 4;\n"
+ "eval('var i = 5'); eval ('var j = 6');\n"
+ "debugger;"],
[1, 2],
function (exec_state) {
CheckScopeChain([debug.ScopeType.Local,
debug.ScopeType.Script,
debug.ScopeType.Global], exec_state);
CheckScopeContent({a:1,b:2,x:3,y:4,i:5,j:6}, 0, exec_state);
});
// Nested empty with blocks.
RunTest("With",
["with ({a:1}) { with ({b:2}) { debugger; } }"],
[],
function (exec_state) {
CheckScopeChain([debug.ScopeType.With,
debug.ScopeType.With,
debug.ScopeType.Local,
debug.ScopeType.Script,
debug.ScopeType.Global], exec_state);
CheckScopeContent({b:2}, 0, exec_state);
CheckScopeContent({a:1}, 1, exec_state);
});
// Simple closure formed by returning an inner function referering the outer
// functions arguments.
RunTest("Closure 1",
['a', 'return function() { debugger; return a; }'],
[1],
function (exec_state) {
CheckScopeChain([debug.ScopeType.Local,
debug.ScopeType.Closure,
debug.ScopeType.Script,
debug.ScopeType.Global], exec_state);
CheckScopeContent({a:1}, 1, exec_state);
},
function (result) { result() });
RunTest("The full monty",
['a', 'b',
"var x = 3;\n" +
"var y = 4;\n" +
"eval('var i = 5');\n" +
"eval('var j = 6');\n" +
"function f(a, b) {\n" +
" var x = 9;\n" +
" var y = 10;\n" +
" eval('var i = 11');\n" +
" eval('var j = 12');\n" +
" with ({j:13}){\n" +
" return function() {\n" +
" var x = 14;\n" +
" with ({a:15}) {\n" +
" with ({b:16}) {\n" +
" debugger;\n" +
" some_global = a;\n" +
" return f;\n" +
" }\n" +
" }\n" +
" };\n" +
" }\n" +
"}\n" +
"return f(a, b);"],
[1, 2],
function (exec_state) {
CheckScopeChain([debug.ScopeType.With,
debug.ScopeType.With,
debug.ScopeType.Local,
debug.ScopeType.With,
debug.ScopeType.Closure,
debug.ScopeType.Closure,
debug.ScopeType.Script,
debug.ScopeType.Global], exec_state);
CheckScopeContent({b:16}, 0, exec_state);
CheckScopeContent({a:15}, 1, exec_state);
CheckScopeContent({x:14}, 2, exec_state);
CheckScopeContent({j:13}, 3, exec_state);
CheckScopeContent({a:1,b:2,x:9,y:10,i:11,j:12}, 4, exec_state);
CheckScopeContent({a:1,b:2,x:3,y:4,i:5,j:6,f:undefined}, 5,
exec_state);
},
function (result) { result() });
RunTest("Catch block 1",
["try { throw 'Exception'; } catch (e) { debugger; }"],
[],
function (exec_state) {
CheckScopeChain([debug.ScopeType.Catch,
debug.ScopeType.Local,
debug.ScopeType.Script,
debug.ScopeType.Global], exec_state);
CheckScopeContent({e:'Exception'}, 0, exec_state);
});

View File

@ -0,0 +1,63 @@
// 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-gc
var Debug = debug.Debug;
function assertIteratorResult(value, done, result) {
assertEquals({value: value, done: done}, result);
}
function RunTest(formals_and_body, args, value1, value2) {
// A null listener. It isn't important what the listener does.
function listener(event, exec_state, event_data, data) {
}
// Create the generator function outside a debugging context. It will probably
// be lazily compiled.
var gen = (function*(){}).constructor.apply(null, formals_and_body);
// Instantiate the generator object.
var obj = gen.apply(null, args);
// Advance to the first yield.
assertIteratorResult(value1, false, obj.next());
// Enable the debugger, which should force recompilation of the generator
// function and relocation of the suspended generator activation.
Debug.setListener(listener);
gc();
// Add a breakpoint on line 3 (the second yield).
var bp = Debug.setBreakPoint(gen, 3);
// Check that the generator resumes and suspends properly.
assertIteratorResult(value2, false, obj.next());
// Disable debugger -- should not force recompilation.
Debug.clearBreakPoint(bp);
Debug.setListener(null);
// Run to completion.
assertIteratorResult(undefined, true, obj.next());
}
function prog(a, b, c) {
return a + ';\n' + 'yield ' + b + ';\n' + 'yield ' + c;
}
// Simple empty local scope.
RunTest([prog('', '1', '2')], [], 1, 2);
RunTest([prog('for (;;) break', '1', '2')], [], 1, 2);
RunTest([prog('while (0) foo()', '1', '2')], [], 1, 2);
RunTest(['a', prog('var x = 3', 'a', 'x')], [1], 1, 3);
RunTest(['a', prog('', '1', '2')], [42], 1, 2);
RunTest(['a', prog('for (;;) break', '1', '2')], [42], 1, 2);

View File

@ -0,0 +1,24 @@
// 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.
var Debug = debug.Debug;
var listener_called;
function listener(event, exec_state, event_data, data) {
if (event == Debug.DebugEvent.Break) {
listener_called = true;
exec_state.frame().allScopes();
}
}
Debug.setListener(listener);
function *generator_local_2(a) {
debugger;
}
generator_local_2(1).next();
assertTrue(listener_called, "listener not called");

View File

@ -0,0 +1,69 @@
// Copyright 2015 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.
Debug = debug.Debug
var exception = null;
var break_count = 0;
const expected_breaks = 9;
var expected_values =
[ReferenceError, ReferenceError, 0, 0, 0, 0, 1,
ReferenceError, ReferenceError];
function listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Break) {
assertTrue(exec_state.frameCount() != 0, "FAIL: Empty stack trace");
var frameMirror = exec_state.frame(0);
var v = null;;
try {
v = frameMirror.evaluate('i').value();
} catch(e) {
v = e;
}
frameMirror.allScopes();
var source = frameMirror.sourceLineText();
print("paused at: " + source);
assertTrue(source.indexOf("// Break " + break_count + ".") > 0,
"Unexpected pause at: " + source + "\n" +
"Expected: // Break " + break_count + ".");
if (expected_values[break_count] === ReferenceError) {
assertTrue(v instanceof ReferenceError);
} else {
assertSame(expected_values[break_count], v);
}
++break_count;
if (break_count !== expected_breaks) {
exec_state.prepareStep(Debug.StepAction.StepInto);
print("Next step prepared");
}
}
} catch(e) {
exception = e;
print(e, e.stack);
}
};
Debug.setListener(listener);
var sum = 0;
(function (){
'use strict';
debugger; // Break 0.
for (let i=0; // Break 1.
i < 1; // Break 2. // Break 6.
i++) { // Break 5.
let key = i; // Break 3.
sum += key; // Break 4.
}
}()); // Break 7.
assertNull(exception); // Break 8.
assertEquals(expected_breaks, break_count);
Debug.setListener(null);