Commit cda1a60a authored by jgruber's avatar jgruber Committed by Commit bot

[debug-wrapper] Migrate suspended generator scope test

Unfortunately, there's currently no satisfying way of accessing scopes
of suspended generator objects through inspector. This CL implements
access to such scopes through runtime functions instead.

BUG=v8:5530

Review-Url: https://codereview.chromium.org/2513343004
Cr-Commit-Position: refs/heads/master@{#41179}
parent 30d2fb6b
...@@ -2,11 +2,10 @@ ...@@ -2,11 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// Flags: --expose-debug-as debug --allow-natives-syntax --ignition // Flags: --ignition
// The functions used for testing backtraces. They are at the top to make the // The functions used for testing backtraces. They are at the top to make the
// testing of source line/column easier. // testing of source line/column easier.
// Get the Debug object exposed from the debug context global object.
var Debug = debug.Debug; var Debug = debug.Debug;
var test_name; var test_name;
...@@ -30,24 +29,21 @@ function EndTest() { ...@@ -30,24 +29,21 @@ function EndTest() {
// Check that two scope are the same. // Check that two scope are the same.
function assertScopeMirrorEquals(scope1, scope2) { function assertScopeMirrorEquals(scope1, scope2) {
assertEquals(scope1.scopeType(), scope2.scopeType()); assertEquals(scope1.scopeType(), scope2.scopeType());
assertEquals(scope1.frameIndex(), scope2.frameIndex());
assertEquals(scope1.scopeIndex(), scope2.scopeIndex()); assertEquals(scope1.scopeIndex(), scope2.scopeIndex());
assertPropertiesEqual(scope1.scopeObject().value(), assertPropertiesEqual(scope1.scopeObject().value(),
scope2.scopeObject().value()); scope2.scopeObject().value());
} }
// Check that the scope chain contains the expected types of scopes. // Check that the scope chain contains the expected types of scopes.
function CheckScopeChain(scopes, gen_mirror) { function CheckScopeChain(scopes, gen) {
var all_scopes = gen_mirror.allScopes(); var all_scopes = Debug.generatorScopes(gen);
assertEquals(scopes.length, gen_mirror.scopeCount()); assertEquals(scopes.length, Debug.generatorScopeCount(gen));
assertEquals(scopes.length, all_scopes.length, assertEquals(scopes.length, all_scopes.length,
"FrameMirror.allScopes length"); "FrameMirror.allScopes length");
for (var i = 0; i < scopes.length; i++) { for (var i = 0; i < scopes.length; i++) {
var scope = gen_mirror.scope(i); var scope = all_scopes[i];
assertTrue(scope.isScope());
assertEquals(scopes[i], scope.scopeType(), assertEquals(scopes[i], scope.scopeType(),
`Scope ${i} has unexpected type`); `Scope ${i} has unexpected type`);
assertScopeMirrorEquals(all_scopes[i], scope);
// Check the global object when hitting the global scope. // Check the global object when hitting the global scope.
if (scopes[i] == debug.ScopeType.Global) { if (scopes[i] == debug.ScopeType.Global) {
...@@ -60,17 +56,21 @@ function CheckScopeChain(scopes, gen_mirror) { ...@@ -60,17 +56,21 @@ function CheckScopeChain(scopes, gen_mirror) {
// Check that the content of the scope is as expected. For functions just check // Check that the content of the scope is as expected. For functions just check
// that there is a function. // that there is a function.
function CheckScopeContent(content, number, gen_mirror) { function CheckScopeContent(content, number, gen) {
var scope = gen_mirror.scope(number); var scope = Debug.generatorScope(gen, number);
var count = 0; var count = 0;
for (var p in content) { for (var p in content) {
var property_mirror = scope.scopeObject().property(p); var property_mirror = scope.scopeObject().property(p);
assertFalse(property_mirror.isUndefined(), if (content[p] === undefined) {
'property ' + p + ' not found in scope'); assertTrue(property_mirror === undefined);
} else {
assertFalse(property_mirror === undefined,
'property ' + p + ' not found in scope');
}
if (typeof(content[p]) === 'function') { if (typeof(content[p]) === 'function') {
assertTrue(property_mirror.value().isFunction()); assertTrue(typeof property_mirror == "function");
} else { } else {
assertEquals(content[p], property_mirror.value().value(), assertEquals(content[p], property_mirror,
'property ' + p + ' has unexpected value'); 'property ' + p + ' has unexpected value');
} }
count++; count++;
...@@ -79,15 +79,15 @@ function CheckScopeContent(content, number, gen_mirror) { ...@@ -79,15 +79,15 @@ function CheckScopeContent(content, number, gen_mirror) {
// 'arguments' and might be exposed in the local and closure scope. Just // 'arguments' and might be exposed in the local and closure scope. Just
// ignore this. // ignore this.
var scope_size = scope.scopeObject().properties().length; var scope_size = scope.scopeObject().properties().length;
if (!scope.scopeObject().property('arguments').isUndefined()) { if (scope.scopeObject().property('arguments') !== undefined) {
scope_size--; scope_size--;
} }
// Ditto for 'this'. // Ditto for 'this'.
if (!scope.scopeObject().property('this').isUndefined()) { if (scope.scopeObject().property('this') !== undefined) {
scope_size--; scope_size--;
} }
// Temporary variables introduced by the parser have not been materialized. // Temporary variables introduced by the parser have not been materialized.
assertTrue(scope.scopeObject().property('').isUndefined()); assertTrue(scope.scopeObject().property('') === undefined);
if (count != scope_size) { if (count != scope_size) {
print('Names found in scope:'); print('Names found in scope:');
...@@ -107,11 +107,10 @@ function *gen1() { ...@@ -107,11 +107,10 @@ function *gen1() {
} }
var g = gen1(); var g = gen1();
var gm = debug.MakeMirror(g);
CheckScopeChain([debug.ScopeType.Closure, CheckScopeChain([debug.ScopeType.Closure,
debug.ScopeType.Script, debug.ScopeType.Script,
debug.ScopeType.Global], gm); debug.ScopeType.Global], g);
CheckScopeContent({}, 0, gm); CheckScopeContent({}, 0, g);
// Closure scope with a parameter. // Closure scope with a parameter.
...@@ -121,11 +120,10 @@ function *gen2(a) { ...@@ -121,11 +120,10 @@ function *gen2(a) {
} }
g = gen2(42); g = gen2(42);
gm = debug.MakeMirror(g);
CheckScopeChain([debug.ScopeType.Closure, CheckScopeChain([debug.ScopeType.Closure,
debug.ScopeType.Script, debug.ScopeType.Script,
debug.ScopeType.Global], gm); debug.ScopeType.Global], g);
CheckScopeContent({a: 42}, 0, gm); CheckScopeContent({a: 42}, 0, g);
// Closure scope with a parameter. // Closure scope with a parameter.
...@@ -136,14 +134,13 @@ function *gen3(a) { ...@@ -136,14 +134,13 @@ function *gen3(a) {
} }
g = gen3(0); g = gen3(0);
gm = debug.MakeMirror(g);
CheckScopeChain([debug.ScopeType.Closure, CheckScopeChain([debug.ScopeType.Closure,
debug.ScopeType.Script, debug.ScopeType.Script,
debug.ScopeType.Global], gm); debug.ScopeType.Global], g);
CheckScopeContent({a: 0, b: undefined}, 0, gm); CheckScopeContent({a: 0, b: undefined}, 0, g);
g.next(); // Create b. g.next(); // Create b.
CheckScopeContent({a: 0, b: 1}, 0, gm); CheckScopeContent({a: 0, b: 1}, 0, g);
// Closure scope with a parameter. // Closure scope with a parameter.
...@@ -155,17 +152,16 @@ function *gen4(a, b) { ...@@ -155,17 +152,16 @@ function *gen4(a, b) {
} }
g = gen4(0, 1); g = gen4(0, 1);
gm = debug.MakeMirror(g);
CheckScopeChain([debug.ScopeType.Closure, CheckScopeChain([debug.ScopeType.Closure,
debug.ScopeType.Script, debug.ScopeType.Script,
debug.ScopeType.Global], gm); debug.ScopeType.Global], g);
CheckScopeContent({a: 0, b: 1, x: undefined, y: undefined}, 0, gm); CheckScopeContent({a: 0, b: 1, x: undefined, y: undefined}, 0, g);
g.next(); // Create x. g.next(); // Create x.
CheckScopeContent({a: 0, b: 1, x: 2, y: undefined}, 0, gm); CheckScopeContent({a: 0, b: 1, x: 2, y: undefined}, 0, g);
g.next(); // Create y. g.next(); // Create y.
CheckScopeContent({a: 0, b: 1, x: 2, y: 3}, 0, gm); CheckScopeContent({a: 0, b: 1, x: 2, y: 3}, 0, g);
// Closure introducing local variable using eval. // Closure introducing local variable using eval.
...@@ -176,11 +172,10 @@ function *gen5(a) { ...@@ -176,11 +172,10 @@ function *gen5(a) {
g = gen5(1); g = gen5(1);
g.next(); g.next();
gm = debug.MakeMirror(g);
CheckScopeChain([debug.ScopeType.Closure, CheckScopeChain([debug.ScopeType.Closure,
debug.ScopeType.Script, debug.ScopeType.Script,
debug.ScopeType.Global], gm); debug.ScopeType.Global], g);
CheckScopeContent({a: 1, b: 2}, 0, gm); CheckScopeContent({a: 1, b: 2}, 0, g);
// Single empty with block. // Single empty with block.
...@@ -194,17 +189,16 @@ function *gen6() { ...@@ -194,17 +189,16 @@ function *gen6() {
g = gen6(); g = gen6();
g.next(); g.next();
gm = debug.MakeMirror(g);
CheckScopeChain([debug.ScopeType.With, CheckScopeChain([debug.ScopeType.With,
debug.ScopeType.Closure, debug.ScopeType.Closure,
debug.ScopeType.Script, debug.ScopeType.Script,
debug.ScopeType.Global], gm); debug.ScopeType.Global], g);
CheckScopeContent({}, 0, gm); CheckScopeContent({}, 0, g);
g.next(); g.next();
CheckScopeChain([debug.ScopeType.Closure, CheckScopeChain([debug.ScopeType.Closure,
debug.ScopeType.Script, debug.ScopeType.Script,
debug.ScopeType.Global], gm); debug.ScopeType.Global], g);
// Nested empty with blocks. // Nested empty with blocks.
...@@ -220,13 +214,12 @@ function *gen7() { ...@@ -220,13 +214,12 @@ function *gen7() {
g = gen7(); g = gen7();
g.next(); g.next();
gm = debug.MakeMirror(g);
CheckScopeChain([debug.ScopeType.With, CheckScopeChain([debug.ScopeType.With,
debug.ScopeType.With, debug.ScopeType.With,
debug.ScopeType.Closure, debug.ScopeType.Closure,
debug.ScopeType.Script, debug.ScopeType.Script,
debug.ScopeType.Global], gm); debug.ScopeType.Global], g);
CheckScopeContent({}, 0, gm); CheckScopeContent({}, 0, g);
// Nested with blocks using in-place object literals. // Nested with blocks using in-place object literals.
...@@ -242,16 +235,15 @@ function *gen8() { ...@@ -242,16 +235,15 @@ function *gen8() {
g = gen8(); g = gen8();
g.next(); g.next();
gm = debug.MakeMirror(g);
CheckScopeChain([debug.ScopeType.With, CheckScopeChain([debug.ScopeType.With,
debug.ScopeType.With, debug.ScopeType.With,
debug.ScopeType.Closure, debug.ScopeType.Closure,
debug.ScopeType.Script, debug.ScopeType.Script,
debug.ScopeType.Global], gm); debug.ScopeType.Global], g);
CheckScopeContent({a: 2, b: 1}, 0, gm); CheckScopeContent({a: 2, b: 1}, 0, g);
g.next(); g.next();
CheckScopeContent({a: 1, b: 2}, 0, gm); CheckScopeContent({a: 1, b: 2}, 0, g);
// Catch block. // Catch block.
...@@ -266,12 +258,11 @@ function *gen9() { ...@@ -266,12 +258,11 @@ function *gen9() {
g = gen9(); g = gen9();
g.next(); g.next();
gm = debug.MakeMirror(g);
CheckScopeChain([debug.ScopeType.Catch, CheckScopeChain([debug.ScopeType.Catch,
debug.ScopeType.Closure, debug.ScopeType.Closure,
debug.ScopeType.Script, debug.ScopeType.Script,
debug.ScopeType.Global], gm); debug.ScopeType.Global], g);
CheckScopeContent({e: 42}, 0, gm); CheckScopeContent({e: 42}, 0, g);
// For statement with block scope. // For statement with block scope.
...@@ -282,17 +273,16 @@ function *gen10() { ...@@ -282,17 +273,16 @@ function *gen10() {
g = gen10(); g = gen10();
g.next(); g.next();
gm = debug.MakeMirror(g);
CheckScopeChain([debug.ScopeType.Block, CheckScopeChain([debug.ScopeType.Block,
debug.ScopeType.Block, debug.ScopeType.Block,
debug.ScopeType.Closure, debug.ScopeType.Closure,
debug.ScopeType.Script, debug.ScopeType.Script,
debug.ScopeType.Global], gm); debug.ScopeType.Global], g);
CheckScopeContent({i: 0}, 0, gm); CheckScopeContent({i: 0}, 0, g);
g.next(); g.next();
CheckScopeContent({i: 1}, 0, gm); CheckScopeContent({i: 1}, 0, g);
CheckScopeContent({i: 0}, 1, gm); // Additional block scope with i = 0; CheckScopeContent({i: 0}, 1, g); // Additional block scope with i = 0;
// Nested generators. // Nested generators.
...@@ -308,16 +298,15 @@ function *gen11() { ...@@ -308,16 +298,15 @@ function *gen11() {
yield* gen12; yield* gen12;
} }
g = gen11(); gen11().next();
g.next(); g = gen12;
gm = debug.MakeMirror(gen12);
CheckScopeChain([debug.ScopeType.Closure, CheckScopeChain([debug.ScopeType.Closure,
debug.ScopeType.Closure, debug.ScopeType.Closure,
debug.ScopeType.Script, debug.ScopeType.Script,
debug.ScopeType.Global], gm); debug.ScopeType.Global], g);
CheckScopeContent({a: 1}, 0, gm); CheckScopeContent({a: 1}, 0, g);
CheckScopeContent({a: 0}, 1, gm); CheckScopeContent({a: 0}, 1, g);
// Set a variable in an empty scope. // Set a variable in an empty scope.
...@@ -327,9 +316,8 @@ function *gen13() { ...@@ -327,9 +316,8 @@ function *gen13() {
} }
var g = gen13(); var g = gen13();
var gm = debug.MakeMirror(g); assertThrows(() => Debug.generatorScope(g, 0).setVariableValue("a", 42));
assertThrows(() => gm.scope(0).setVariableValue("a", 42)); CheckScopeContent({}, 0, g);
CheckScopeContent({}, 0, gm);
// Set a variable in a simple scope. // Set a variable in a simple scope.
...@@ -343,11 +331,10 @@ function *gen14() { ...@@ -343,11 +331,10 @@ function *gen14() {
var g = gen14(); var g = gen14();
assertEquals(1, g.next().value); assertEquals(1, g.next().value);
var gm = debug.MakeMirror(g); CheckScopeContent({a: 0}, 0, g);
CheckScopeContent({a: 0}, 0, gm);
gm.scope(0).setVariableValue("a", 1); Debug.generatorScope(g, 0).setVariableValue("a", 1);
CheckScopeContent({a: 1}, 0, gm); CheckScopeContent({a: 1}, 0, g);
assertEquals(1, g.next().value); assertEquals(1, g.next().value);
...@@ -367,36 +354,35 @@ function *gen15() { ...@@ -367,36 +354,35 @@ function *gen15() {
var g = gen15(); var g = gen15();
assertEquals(1, g.next().value); assertEquals(1, g.next().value);
var gm = debug.MakeMirror(g);
CheckScopeChain([debug.ScopeType.With, CheckScopeChain([debug.ScopeType.With,
debug.ScopeType.Closure, debug.ScopeType.Closure,
debug.ScopeType.Script, debug.ScopeType.Script,
debug.ScopeType.Global], gm); debug.ScopeType.Global], g);
CheckScopeContent({a: 1, b: 2}, 0, gm); CheckScopeContent({a: 1, b: 2}, 0, g);
CheckScopeContent({c: 3, d: 4, e: undefined}, 1, gm); CheckScopeContent({c: 3, d: 4, e: undefined}, 1, g);
// Variables don't exist in given scope. // Variables don't exist in given scope.
assertThrows(() => gm.scope(0).setVariableValue("c", 42)); assertThrows(() => Debug.generatorScope(g, 0).setVariableValue("c", 42));
assertThrows(() => gm.scope(1).setVariableValue("a", 42)); assertThrows(() => Debug.generatorScope(g, 1).setVariableValue("a", 42));
// Variables in with scope are immutable. // Variables in with scope are immutable.
assertThrows(() => gm.scope(0).setVariableValue("a", 3)); assertThrows(() => Debug.generatorScope(g, 0).setVariableValue("a", 3));
assertThrows(() => gm.scope(0).setVariableValue("b", 3)); assertThrows(() => Debug.generatorScope(g, 0).setVariableValue("b", 3));
gm.scope(1).setVariableValue("c", 1); Debug.generatorScope(g, 1).setVariableValue("c", 1);
gm.scope(1).setVariableValue("e", 42); Debug.generatorScope(g, 1).setVariableValue("e", 42);
CheckScopeContent({a: 1, b: 2}, 0, gm); CheckScopeContent({a: 1, b: 2}, 0, g);
CheckScopeContent({c: 1, d: 4, e: 42}, 1, gm); CheckScopeContent({c: 1, d: 4, e: 42}, 1, g);
assertEquals(5, g.next().value); // Initialized after set. assertEquals(5, g.next().value); // Initialized after set.
CheckScopeChain([debug.ScopeType.Closure, CheckScopeChain([debug.ScopeType.Closure,
debug.ScopeType.Script, debug.ScopeType.Script,
debug.ScopeType.Global], gm); debug.ScopeType.Global], g);
gm.scope(0).setVariableValue("e", 42); Debug.generatorScope(g, 0).setVariableValue("e", 42);
CheckScopeContent({c: 1, d: 4, e: 42}, 0, gm); CheckScopeContent({c: 1, d: 4, e: 42}, 0, g);
assertEquals(42, g.next().value); assertEquals(42, g.next().value);
// Set a variable in nested with blocks using in-place object literals plus a // Set a variable in nested with blocks using in-place object literals plus a
...@@ -416,18 +402,17 @@ function *gen16() { ...@@ -416,18 +402,17 @@ function *gen16() {
var g = gen16(); var g = gen16();
g.next(); g.next();
var gm = debug.MakeMirror(g);
CheckScopeChain([debug.ScopeType.Block, CheckScopeChain([debug.ScopeType.Block,
debug.ScopeType.With, debug.ScopeType.With,
debug.ScopeType.Closure, debug.ScopeType.Closure,
debug.ScopeType.Script, debug.ScopeType.Script,
debug.ScopeType.Global], gm); debug.ScopeType.Global], g);
CheckScopeContent({d: 4}, 0, gm); CheckScopeContent({d: 4}, 0, g);
CheckScopeContent({a: 1, b: 2}, 1, gm); CheckScopeContent({a: 1, b: 2}, 1, g);
CheckScopeContent({c: 3}, 2, gm); CheckScopeContent({c: 3}, 2, g);
gm.scope(0).setVariableValue("d", 1); Debug.generatorScope(g, 0).setVariableValue("d", 1);
CheckScopeContent({d: 1}, 0, gm); CheckScopeContent({d: 1}, 0, g);
assertEquals(1, g.next().value); assertEquals(1, g.next().value);
...@@ -448,23 +433,26 @@ function *gen17() { ...@@ -448,23 +433,26 @@ function *gen17() {
g = gen17(); g = gen17();
g.next(); g.next();
gm = debug.MakeMirror(g);
CheckScopeChain([debug.ScopeType.Catch, CheckScopeChain([debug.ScopeType.Catch,
debug.ScopeType.Closure, debug.ScopeType.Closure,
debug.ScopeType.Script, debug.ScopeType.Script,
debug.ScopeType.Global], gm); debug.ScopeType.Global], g);
CheckScopeContent({e: 42}, 0, gm); CheckScopeContent({e: 42}, 0, g);
CheckScopeContent({xxxyyxxyx: 42284}, 2, gm); CheckScopeContent({xxxyyxxyx: 42284,
printProtocolMessages : printProtocolMessages,
activeWrapper : activeWrapper,
DebugWrapper : DebugWrapper
}, 2, g);
gm.scope(0).setVariableValue("e", 1); Debug.generatorScope(g, 0).setVariableValue("e", 1);
CheckScopeContent({e: 1}, 0, gm); CheckScopeContent({e: 1}, 0, g);
assertEquals(1, g.next().value); assertEquals(1, g.next().value);
// Script scope. // Script scope.
gm.scope(2).setVariableValue("xxxyyxxyx", 42); Debug.generatorScope(g, 2).setVariableValue("xxxyyxxyx", 42);
assertEquals(42, xxxyyxxyx); assertEquals(42, xxxyyxxyx);
// Global scope. // Global scope.
assertThrows(() => gm.scope(3).setVariableValue("yyzyzzyz", 42)); assertThrows(() => Debug.generatorScope(g, 3).setVariableValue("yyzyzzyz", 42));
assertEquals(4829, yyzyzzyz); assertEquals(4829, yyzyzzyz);
...@@ -292,6 +292,50 @@ class DebugWrapper { ...@@ -292,6 +292,50 @@ class DebugWrapper {
this.takeReplyChecked(msgid); this.takeReplyChecked(msgid);
} }
generatorScopeCount(gen) {
return %GetGeneratorScopeCount(gen);
}
generatorScope(gen, index) {
// These indexes correspond definitions in debug-scopes.h.
const kScopeDetailsTypeIndex = 0;
const kScopeDetailsObjectIndex = 1;
const details = %GetGeneratorScopeDetails(gen, index);
function scopeObjectProperties() {
const obj = details[kScopeDetailsObjectIndex];
return Object.keys(obj).map((k, v) => v);
}
function setScopeVariableValue(name, value) {
const res = %SetScopeVariableValue(gen, null, null, index, name, value);
if (!res) throw new Error("Failed to set variable value");
}
const scopeObject =
{ value : () => details[kScopeDetailsObjectIndex],
property : (prop) => details[kScopeDetailsObjectIndex][prop],
properties : scopeObjectProperties,
propertyNames : () => Object.keys(details[kScopeDetailsObjectIndex])
.map((key, _) => key),
};
return { scopeType : () => details[kScopeDetailsTypeIndex],
scopeIndex : () => index,
scopeObject : () => scopeObject,
setVariableValue : setScopeVariableValue,
}
}
generatorScopes(gen) {
const count = %GetGeneratorScopeCount(gen);
const scopes = [];
for (let i = 0; i < count; i++) {
scopes.push(this.generatorScope(gen, i));
}
return scopes;
}
get LiveEdit() { get LiveEdit() {
const debugContext = %GetDebugContext(); const debugContext = %GetDebugContext();
return debugContext.Debug.LiveEdit; return debugContext.Debug.LiveEdit;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment