[inspector] added type of break location into getPossibleBreakpoints output
This CL provide type with each break location, type could be: call, return or debugger statement. BUG=chromium:432469 R=yangguo@chromium.org,dgozman@chromium.org Review-Url: https://codereview.chromium.org/2728563002 Cr-Commit-Position: refs/heads/master@{#43619}
This commit is contained in:
parent
a3923ce210
commit
562da35614
23
src/api.cc
23
src/api.cc
@ -9212,11 +9212,17 @@ namespace {
|
||||
int GetSmiValue(i::Handle<i::FixedArray> array, int index) {
|
||||
return i::Smi::cast(array->get(index))->value();
|
||||
}
|
||||
|
||||
bool CompareBreakLocation(const i::BreakLocation& loc1,
|
||||
const i::BreakLocation& loc2) {
|
||||
return loc1.position() < loc2.position();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
bool debug::Script::GetPossibleBreakpoints(
|
||||
const debug::Location& start, const debug::Location& end,
|
||||
bool restrict_to_function, std::vector<debug::Location>* locations) const {
|
||||
bool restrict_to_function,
|
||||
std::vector<debug::BreakLocation>* locations) const {
|
||||
CHECK(!start.IsEmpty());
|
||||
i::Handle<i::Script> script = Utils::OpenHandle(this);
|
||||
if (script->type() == i::Script::TYPE_WASM) {
|
||||
@ -9238,15 +9244,17 @@ bool debug::Script::GetPossibleBreakpoints(
|
||||
: GetSourceOffset(end);
|
||||
if (start_offset >= end_offset) return true;
|
||||
|
||||
std::set<int> offsets;
|
||||
std::vector<i::BreakLocation> v8_locations;
|
||||
if (!isolate->debug()->GetPossibleBreakpoints(
|
||||
script, start_offset, end_offset, restrict_to_function, &offsets)) {
|
||||
script, start_offset, end_offset, restrict_to_function,
|
||||
&v8_locations)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::sort(v8_locations.begin(), v8_locations.end(), CompareBreakLocation);
|
||||
int current_line_end_index = 0;
|
||||
for (const auto& it : offsets) {
|
||||
int offset = it;
|
||||
for (const auto& v8_location : v8_locations) {
|
||||
int offset = v8_location.position();
|
||||
while (offset > GetSmiValue(line_ends, current_line_end_index)) {
|
||||
++current_line_end_index;
|
||||
CHECK(current_line_end_index < line_ends->length());
|
||||
@ -9256,10 +9264,11 @@ bool debug::Script::GetPossibleBreakpoints(
|
||||
if (current_line_end_index > 0) {
|
||||
line_offset = GetSmiValue(line_ends, current_line_end_index - 1) + 1;
|
||||
}
|
||||
locations->push_back(debug::Location(
|
||||
locations->emplace_back(
|
||||
current_line_end_index + script->line_offset(),
|
||||
offset - line_offset +
|
||||
(current_line_end_index == 0 ? script->column_offset() : 0)));
|
||||
(current_line_end_index == 0 ? script->column_offset() : 0),
|
||||
v8_location.type());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -136,10 +136,10 @@ class V8_EXPORT_PRIVATE Script {
|
||||
MaybeLocal<String> Source() const;
|
||||
bool IsWasm() const;
|
||||
bool IsModule() const;
|
||||
bool GetPossibleBreakpoints(const debug::Location& start,
|
||||
const debug::Location& end,
|
||||
bool restrict_to_function,
|
||||
std::vector<debug::Location>* locations) const;
|
||||
bool GetPossibleBreakpoints(
|
||||
const debug::Location& start, const debug::Location& end,
|
||||
bool restrict_to_function,
|
||||
std::vector<debug::BreakLocation>* locations) const;
|
||||
int GetSourceOffset(const debug::Location& location) const;
|
||||
v8::debug::Location GetSourceLocation(int offset) const;
|
||||
};
|
||||
|
@ -125,6 +125,20 @@ bool BreakLocation::HasBreakPoint(Handle<DebugInfo> debug_info) const {
|
||||
}
|
||||
}
|
||||
|
||||
debug::BreakLocationType BreakLocation::type() const {
|
||||
switch (type_) {
|
||||
case DEBUGGER_STATEMENT:
|
||||
return debug::kDebuggerStatementBreakLocation;
|
||||
case DEBUG_BREAK_SLOT_AT_CALL:
|
||||
return debug::kCallBreakLocation;
|
||||
case DEBUG_BREAK_SLOT_AT_RETURN:
|
||||
return debug::kReturnBreakLocation;
|
||||
default:
|
||||
return debug::kCommonBreakLocation;
|
||||
}
|
||||
return debug::kCommonBreakLocation;
|
||||
}
|
||||
|
||||
std::unique_ptr<BreakIterator> BreakIterator::GetIterator(
|
||||
Handle<DebugInfo> debug_info, Handle<AbstractCode> abstract_code) {
|
||||
if (abstract_code->IsBytecodeArray()) {
|
||||
@ -1315,36 +1329,32 @@ bool Debug::PrepareFunctionForBreakPoints(Handle<SharedFunctionInfo> shared) {
|
||||
namespace {
|
||||
template <typename Iterator>
|
||||
void GetBreakablePositions(Iterator* it, int start_position, int end_position,
|
||||
BreakPositionAlignment alignment,
|
||||
std::set<int>* positions) {
|
||||
it->SkipToPosition(start_position, alignment);
|
||||
std::vector<BreakLocation>* locations) {
|
||||
it->SkipToPosition(start_position, BREAK_POSITION_ALIGNED);
|
||||
while (!it->Done() && it->position() < end_position &&
|
||||
it->position() >= start_position) {
|
||||
positions->insert(alignment == STATEMENT_ALIGNED ? it->statement_position()
|
||||
: it->position());
|
||||
locations->push_back(it->GetBreakLocation());
|
||||
it->Next();
|
||||
}
|
||||
}
|
||||
|
||||
void FindBreakablePositions(Handle<DebugInfo> debug_info, int start_position,
|
||||
int end_position, BreakPositionAlignment alignment,
|
||||
std::set<int>* positions) {
|
||||
int end_position,
|
||||
std::vector<BreakLocation>* locations) {
|
||||
if (debug_info->HasDebugCode()) {
|
||||
CodeBreakIterator it(debug_info);
|
||||
GetBreakablePositions(&it, start_position, end_position, alignment,
|
||||
positions);
|
||||
GetBreakablePositions(&it, start_position, end_position, locations);
|
||||
} else {
|
||||
DCHECK(debug_info->HasDebugBytecodeArray());
|
||||
BytecodeArrayBreakIterator it(debug_info);
|
||||
GetBreakablePositions(&it, start_position, end_position, alignment,
|
||||
positions);
|
||||
GetBreakablePositions(&it, start_position, end_position, locations);
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
bool Debug::GetPossibleBreakpoints(Handle<Script> script, int start_position,
|
||||
int end_position, bool restrict_to_function,
|
||||
std::set<int>* positions) {
|
||||
std::vector<BreakLocation>* locations) {
|
||||
if (restrict_to_function) {
|
||||
Handle<Object> result =
|
||||
FindSharedFunctionInfoInScript(script, start_position);
|
||||
@ -1356,8 +1366,7 @@ bool Debug::GetPossibleBreakpoints(Handle<Script> script, int start_position,
|
||||
if (!EnsureDebugInfo(shared)) return false;
|
||||
|
||||
Handle<DebugInfo> debug_info(shared->GetDebugInfo());
|
||||
FindBreakablePositions(debug_info, start_position, end_position,
|
||||
BREAK_POSITION_ALIGNED, positions);
|
||||
FindBreakablePositions(debug_info, start_position, end_position, locations);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1395,7 +1404,7 @@ bool Debug::GetPossibleBreakpoints(Handle<Script> script, int start_position,
|
||||
CHECK(candidates[i]->HasDebugInfo());
|
||||
Handle<DebugInfo> debug_info(candidates[i]->GetDebugInfo());
|
||||
FindBreakablePositions(debug_info, start_position, end_position,
|
||||
BREAK_POSITION_ALIGNED, positions);
|
||||
locations);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -88,6 +88,8 @@ class BreakLocation {
|
||||
|
||||
inline int position() const { return position_; }
|
||||
|
||||
debug::BreakLocationType type() const;
|
||||
|
||||
private:
|
||||
BreakLocation(Handle<AbstractCode> abstract_code, DebugBreakType type,
|
||||
int code_offset, int position)
|
||||
@ -313,7 +315,7 @@ class Debug {
|
||||
bool PrepareFunctionForBreakPoints(Handle<SharedFunctionInfo> shared);
|
||||
bool GetPossibleBreakpoints(Handle<Script> script, int start_position,
|
||||
int end_position, bool restrict_to_function,
|
||||
std::set<int>* positions);
|
||||
std::vector<BreakLocation>* locations);
|
||||
|
||||
void RecordGenerator(Handle<JSGeneratorObject> generator_object);
|
||||
|
||||
|
@ -50,6 +50,7 @@ struct WasmDisassemblyOffsetTableEntry {
|
||||
int line;
|
||||
int column;
|
||||
};
|
||||
|
||||
struct WasmDisassembly {
|
||||
using OffsetTable = std::vector<WasmDisassemblyOffsetTableEntry>;
|
||||
WasmDisassembly() {}
|
||||
@ -71,6 +72,24 @@ enum PromiseDebugActionType {
|
||||
kDebugDidHandle,
|
||||
};
|
||||
|
||||
enum BreakLocationType {
|
||||
kCallBreakLocation,
|
||||
kReturnBreakLocation,
|
||||
kDebuggerStatementBreakLocation,
|
||||
kCommonBreakLocation
|
||||
};
|
||||
|
||||
class V8_EXPORT_PRIVATE BreakLocation : public Location {
|
||||
public:
|
||||
BreakLocation(int line_number, int column_number, BreakLocationType type)
|
||||
: Location(line_number, column_number), type_(type) {}
|
||||
|
||||
BreakLocationType type() const { return type_; }
|
||||
|
||||
private:
|
||||
BreakLocationType type_;
|
||||
};
|
||||
|
||||
} // namespace debug
|
||||
} // namespace v8
|
||||
|
||||
|
@ -471,6 +471,17 @@
|
||||
{ "name": "lineContent", "type": "string", "description": "Line with match content." }
|
||||
],
|
||||
"experimental": true
|
||||
},
|
||||
{
|
||||
"id": "BreakLocation",
|
||||
"type": "object",
|
||||
"properties": [
|
||||
{ "name": "scriptId", "$ref": "Runtime.ScriptId", "description": "Script identifier as reported in the <code>Debugger.scriptParsed</code>." },
|
||||
{ "name": "lineNumber", "type": "integer", "description": "Line number in the script (0-based)." },
|
||||
{ "name": "columnNumber", "type": "integer", "optional": true, "description": "Column number in the script (0-based)." },
|
||||
{ "name": "type", "type": "string", "enum": [ "debuggerStatement", "call", "return" ], "optional": true }
|
||||
],
|
||||
"experimental": true
|
||||
}
|
||||
],
|
||||
"commands": [
|
||||
@ -538,7 +549,7 @@
|
||||
{ "name": "restrictToFunction", "type": "boolean", "optional": true, "description": "Only consider locations which are in the same (non-nested) function as start." }
|
||||
],
|
||||
"returns": [
|
||||
{ "name": "locations", "type": "array", "items": { "$ref": "Location" }, "description": "List of the possible breakpoint locations." }
|
||||
{ "name": "locations", "type": "array", "items": { "$ref": "BreakLocation" }, "description": "List of the possible breakpoint locations." }
|
||||
],
|
||||
"description": "Returns possible locations for breakpoint. scriptId in start and end range locations should be the same.",
|
||||
"experimental": true
|
||||
|
@ -171,6 +171,21 @@ void adjustBreakpointLocation(const V8DebuggerScript& script,
|
||||
breakpoint->line_number = hintPosition.GetLineNumber();
|
||||
breakpoint->column_number = hintPosition.GetColumnNumber();
|
||||
}
|
||||
|
||||
String16 breakLocationType(v8::debug::BreakLocationType type) {
|
||||
switch (type) {
|
||||
case v8::debug::kCallBreakLocation:
|
||||
return protocol::Debugger::BreakLocation::TypeEnum::Call;
|
||||
case v8::debug::kReturnBreakLocation:
|
||||
return protocol::Debugger::BreakLocation::TypeEnum::Return;
|
||||
case v8::debug::kDebuggerStatementBreakLocation:
|
||||
return protocol::Debugger::BreakLocation::TypeEnum::DebuggerStatement;
|
||||
case v8::debug::kCommonBreakLocation:
|
||||
return String16();
|
||||
}
|
||||
return String16();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
V8DebuggerAgentImpl::V8DebuggerAgentImpl(
|
||||
@ -420,7 +435,8 @@ void V8DebuggerAgentImpl::removeBreakpointImpl(const String16& breakpointId) {
|
||||
Response V8DebuggerAgentImpl::getPossibleBreakpoints(
|
||||
std::unique_ptr<protocol::Debugger::Location> start,
|
||||
Maybe<protocol::Debugger::Location> end, Maybe<bool> restrictToFunction,
|
||||
std::unique_ptr<protocol::Array<protocol::Debugger::Location>>* locations) {
|
||||
std::unique_ptr<protocol::Array<protocol::Debugger::BreakLocation>>*
|
||||
locations) {
|
||||
String16 scriptId = start->getScriptId();
|
||||
|
||||
if (start->getLineNumber() < 0 || start->getColumnNumber(0) < 0)
|
||||
@ -443,19 +459,24 @@ Response V8DebuggerAgentImpl::getPossibleBreakpoints(
|
||||
auto it = m_scripts.find(scriptId);
|
||||
if (it == m_scripts.end()) return Response::Error("Script not found");
|
||||
|
||||
std::vector<v8::debug::Location> v8Locations;
|
||||
std::vector<v8::debug::BreakLocation> v8Locations;
|
||||
if (!it->second->getPossibleBreakpoints(
|
||||
v8Start, v8End, restrictToFunction.fromMaybe(false), &v8Locations))
|
||||
v8Start, v8End, restrictToFunction.fromMaybe(false), &v8Locations)) {
|
||||
return Response::InternalError();
|
||||
}
|
||||
|
||||
*locations = protocol::Array<protocol::Debugger::Location>::create();
|
||||
*locations = protocol::Array<protocol::Debugger::BreakLocation>::create();
|
||||
for (size_t i = 0; i < v8Locations.size(); ++i) {
|
||||
(*locations)
|
||||
->addItem(protocol::Debugger::Location::create()
|
||||
.setScriptId(scriptId)
|
||||
.setLineNumber(v8Locations[i].GetLineNumber())
|
||||
.setColumnNumber(v8Locations[i].GetColumnNumber())
|
||||
.build());
|
||||
std::unique_ptr<protocol::Debugger::BreakLocation> breakLocation =
|
||||
protocol::Debugger::BreakLocation::create()
|
||||
.setScriptId(scriptId)
|
||||
.setLineNumber(v8Locations[i].GetLineNumber())
|
||||
.setColumnNumber(v8Locations[i].GetColumnNumber())
|
||||
.build();
|
||||
if (v8Locations[i].type() != v8::debug::kCommonBreakLocation) {
|
||||
breakLocation->setType(breakLocationType(v8Locations[i].type()));
|
||||
}
|
||||
(*locations)->addItem(std::move(breakLocation));
|
||||
}
|
||||
return Response::OK();
|
||||
}
|
||||
|
@ -67,8 +67,8 @@ class V8DebuggerAgentImpl : public protocol::Debugger::Backend {
|
||||
Response getPossibleBreakpoints(
|
||||
std::unique_ptr<protocol::Debugger::Location> start,
|
||||
Maybe<protocol::Debugger::Location> end, Maybe<bool> restrictToFunction,
|
||||
std::unique_ptr<protocol::Array<protocol::Debugger::Location>>* locations)
|
||||
override;
|
||||
std::unique_ptr<protocol::Array<protocol::Debugger::BreakLocation>>*
|
||||
locations) override;
|
||||
Response setScriptSource(
|
||||
const String16& inScriptId, const String16& inScriptSource,
|
||||
Maybe<bool> dryRun,
|
||||
|
@ -155,11 +155,40 @@ class ActualScript : public V8DebuggerScript {
|
||||
bool getPossibleBreakpoints(
|
||||
const v8::debug::Location& start, const v8::debug::Location& end,
|
||||
bool restrictToFunction,
|
||||
std::vector<v8::debug::Location>* locations) override {
|
||||
std::vector<v8::debug::BreakLocation>* locations) override {
|
||||
v8::HandleScope scope(m_isolate);
|
||||
v8::Local<v8::debug::Script> script = m_script.Get(m_isolate);
|
||||
return script->GetPossibleBreakpoints(start, end, restrictToFunction,
|
||||
locations);
|
||||
std::vector<v8::debug::BreakLocation> allLocations;
|
||||
if (!script->GetPossibleBreakpoints(start, end, restrictToFunction,
|
||||
&allLocations)) {
|
||||
return false;
|
||||
}
|
||||
if (!allLocations.size()) return true;
|
||||
v8::debug::BreakLocation current = allLocations[0];
|
||||
for (size_t i = 1; i < allLocations.size(); ++i) {
|
||||
if (allLocations[i].GetLineNumber() == current.GetLineNumber() &&
|
||||
allLocations[i].GetColumnNumber() == current.GetColumnNumber()) {
|
||||
if (allLocations[i].type() != v8::debug::kCommonBreakLocation) {
|
||||
DCHECK(allLocations[i].type() == v8::debug::kCallBreakLocation ||
|
||||
allLocations[i].type() == v8::debug::kReturnBreakLocation);
|
||||
// debugger can returns more then one break location at the same
|
||||
// source location, e.g. foo() - in this case there are two break
|
||||
// locations before foo: for statement and for function call, we can
|
||||
// merge them for inspector and report only one with call type.
|
||||
current = allLocations[i];
|
||||
}
|
||||
} else {
|
||||
// we assume that returned break locations are sorted.
|
||||
DCHECK(
|
||||
allLocations[i].GetLineNumber() > current.GetLineNumber() ||
|
||||
(allLocations[i].GetColumnNumber() >= current.GetColumnNumber() &&
|
||||
allLocations[i].GetLineNumber() == current.GetLineNumber()));
|
||||
locations->push_back(current);
|
||||
current = allLocations[i];
|
||||
}
|
||||
}
|
||||
locations->push_back(current);
|
||||
return true;
|
||||
}
|
||||
|
||||
void resetBlackboxedStateCache() override {
|
||||
@ -223,7 +252,7 @@ class WasmVirtualScript : public V8DebuggerScript {
|
||||
bool getPossibleBreakpoints(
|
||||
const v8::debug::Location& start, const v8::debug::Location& end,
|
||||
bool restrictToFunction,
|
||||
std::vector<v8::debug::Location>* locations) override {
|
||||
std::vector<v8::debug::BreakLocation>* locations) override {
|
||||
v8::HandleScope scope(m_isolate);
|
||||
v8::Local<v8::debug::Script> script = m_script.Get(m_isolate);
|
||||
String16 v8ScriptId = String16::fromInteger(script->Id());
|
||||
@ -244,7 +273,7 @@ class WasmVirtualScript : public V8DebuggerScript {
|
||||
|
||||
bool success = script->GetPossibleBreakpoints(
|
||||
translatedStart, translatedEnd, restrictToFunction, locations);
|
||||
for (v8::debug::Location& loc : *locations) {
|
||||
for (v8::debug::BreakLocation& loc : *locations) {
|
||||
TranslateV8LocationToProtocolLocation(m_wasmTranslation, &loc, v8ScriptId,
|
||||
scriptId());
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ class V8DebuggerScript {
|
||||
virtual bool getPossibleBreakpoints(
|
||||
const v8::debug::Location& start, const v8::debug::Location& end,
|
||||
bool ignoreNestedFunctions,
|
||||
std::vector<v8::debug::Location>* locations) = 0;
|
||||
std::vector<v8::debug::BreakLocation>* locations) = 0;
|
||||
virtual void resetBlackboxedStateCache() = 0;
|
||||
|
||||
static const int kNoOffset = -1;
|
||||
|
@ -1041,7 +1041,7 @@ v8::debug::WasmDisassembly WasmCompiledModule::DisassembleFunction(
|
||||
|
||||
bool WasmCompiledModule::GetPossibleBreakpoints(
|
||||
const v8::debug::Location& start, const v8::debug::Location& end,
|
||||
std::vector<v8::debug::Location>* locations) {
|
||||
std::vector<v8::debug::BreakLocation>* locations) {
|
||||
DisallowHeapAllocation no_gc;
|
||||
|
||||
std::vector<WasmFunction>& functions = module()->functions;
|
||||
@ -1104,7 +1104,7 @@ bool WasmCompiledModule::GetPossibleBreakpoints(
|
||||
break;
|
||||
}
|
||||
if (total_offset < start_offset) continue;
|
||||
locations->push_back(v8::debug::Location(func_idx, offset));
|
||||
locations->emplace_back(func_idx, offset, debug::kCommonBreakLocation);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -385,7 +385,7 @@ class WasmCompiledModule : public FixedArray {
|
||||
// Get a list of all possible breakpoints within a given range of this module.
|
||||
bool GetPossibleBreakpoints(const debug::Location& start,
|
||||
const debug::Location& end,
|
||||
std::vector<debug::Location>* locations);
|
||||
std::vector<debug::BreakLocation>* locations);
|
||||
|
||||
// Set a breakpoint on the given byte position inside the given module.
|
||||
// This will affect all live and future instances of the module.
|
||||
|
@ -25,7 +25,7 @@ void CheckLocations(
|
||||
WasmCompiledModule *compiled_module, debug::Location start,
|
||||
debug::Location end,
|
||||
std::initializer_list<debug::Location> expected_locations_init) {
|
||||
std::vector<debug::Location> locations;
|
||||
std::vector<debug::BreakLocation> locations;
|
||||
bool success =
|
||||
compiled_module->GetPossibleBreakpoints(start, end, &locations);
|
||||
CHECK(success);
|
||||
@ -48,7 +48,7 @@ void CheckLocations(
|
||||
}
|
||||
void CheckLocationsFail(WasmCompiledModule *compiled_module,
|
||||
debug::Location start, debug::Location end) {
|
||||
std::vector<debug::Location> locations;
|
||||
std::vector<debug::BreakLocation> locations;
|
||||
bool success =
|
||||
compiled_module->GetPossibleBreakpoints(start, end, &locations);
|
||||
CHECK(!success);
|
||||
|
@ -16,11 +16,13 @@
|
||||
columnNumber : 7
|
||||
lineNumber : 0
|
||||
scriptId : <scriptId>
|
||||
type : return
|
||||
}
|
||||
[3] : {
|
||||
columnNumber : 8
|
||||
lineNumber : 0
|
||||
scriptId : <scriptId>
|
||||
type : return
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -4,267 +4,267 @@ Checks Debugger.getPossibleBreakpoints
|
||||
// found in the LICENSE file.
|
||||
|
||||
function testEval() {
|
||||
#eval('// comment only');
|
||||
#eval('// comment only\n');
|
||||
#}
|
||||
|C|eval('// comment only');
|
||||
|C|eval('// comment only\n');
|
||||
|R|}
|
||||
|
||||
// function without return
|
||||
function procedure() {
|
||||
var a = #1;
|
||||
var b = #2;
|
||||
#}
|
||||
var a = |_|1;
|
||||
var b = |_|2;
|
||||
|R|}
|
||||
|
||||
function testProcedure() {
|
||||
#procedure();
|
||||
#}
|
||||
|C|procedure();
|
||||
|R|}
|
||||
|
||||
function returnTrue() {
|
||||
#return true;
|
||||
#}
|
||||
|_|return true;
|
||||
|R|}
|
||||
|
||||
function testIf() {
|
||||
var a;
|
||||
#if (true) #a = true;
|
||||
#if (!a) {
|
||||
#a = true;
|
||||
|_|if (true) |_|a = true;
|
||||
|_|if (!a) {
|
||||
|_|a = true;
|
||||
} else {
|
||||
#a = false;
|
||||
|_|a = false;
|
||||
}
|
||||
#if (#returnTrue()) {
|
||||
#a = false;
|
||||
|_|if (|C|returnTrue()) {
|
||||
|_|a = false;
|
||||
} else {
|
||||
#a = true;
|
||||
|_|a = true;
|
||||
}
|
||||
#}
|
||||
|R|}
|
||||
|
||||
function emptyFunction() {#}
|
||||
function emptyFunction() {|R|}
|
||||
|
||||
function testEmptyFunction() {
|
||||
#emptyFunction();
|
||||
#}
|
||||
|C|emptyFunction();
|
||||
|R|}
|
||||
|
||||
function twoArguments(a1, a2) {
|
||||
#}
|
||||
|R|}
|
||||
|
||||
function testCallArguments() {
|
||||
#twoArguments(#emptyFunction(), #emptyFunction());
|
||||
#}
|
||||
|C|twoArguments(|C|emptyFunction(), |C|emptyFunction());
|
||||
|R|}
|
||||
|
||||
function testNested() {
|
||||
function nested1() {
|
||||
function nested2() {
|
||||
function nested3() {
|
||||
#}
|
||||
#nested3();
|
||||
#return;
|
||||
#}
|
||||
#return #nested2();
|
||||
#}
|
||||
#nested1();
|
||||
#}
|
||||
|R|}
|
||||
|C|nested3();
|
||||
|_|return;
|
||||
|R|}
|
||||
|_|return |C|nested2();
|
||||
|R|}
|
||||
|C|nested1();
|
||||
|R|}
|
||||
|
||||
function return42() {
|
||||
#return 42;
|
||||
#}
|
||||
|_|return 42;
|
||||
|R|}
|
||||
|
||||
function returnCall() {
|
||||
#return #return42();
|
||||
#}
|
||||
|_|return |C|return42();
|
||||
|R|}
|
||||
|
||||
function testCallAtReturn() {
|
||||
#return #returnCall();
|
||||
#}
|
||||
|_|return |C|returnCall();
|
||||
|R|}
|
||||
|
||||
function returnObject() {
|
||||
#return ({ foo: () => #42# });
|
||||
#}
|
||||
|_|return ({ foo: () => |_|42|R| });
|
||||
|R|}
|
||||
|
||||
function testWith() {
|
||||
#with (#returnObject()) {
|
||||
#foo();
|
||||
|_|with (|C|returnObject()) {
|
||||
|C|foo();
|
||||
}
|
||||
#with({}) {
|
||||
#return;
|
||||
|_|with({}) {
|
||||
|_|return;
|
||||
}
|
||||
#}
|
||||
|R|}
|
||||
|
||||
function testForLoop() {
|
||||
for (var i = #0; i #< 1; ++#i) {}
|
||||
for (var i = #0; i #< 1; ++#i) #i;
|
||||
for (var i = #0; i #< 0; ++#i) {}
|
||||
#}
|
||||
for (var i = |_|0; i |_|< 1; ++|_|i) {}
|
||||
for (var i = |_|0; i |_|< 1; ++|_|i) |_|i;
|
||||
for (var i = |_|0; i |_|< 0; ++|_|i) {}
|
||||
|R|}
|
||||
|
||||
function testForOfLoop() {
|
||||
for (var k #of []) {}
|
||||
for (var k #of #[1]) #k;
|
||||
var a = #[];
|
||||
for (var k #of #a) {}
|
||||
#}
|
||||
for (var k |C|of []) {}
|
||||
for (var k |C|of |_|[1]) |_|k;
|
||||
var a = |_|[];
|
||||
for (var k |C|of |_|a) {}
|
||||
|R|}
|
||||
|
||||
function testForInLoop() {
|
||||
var o = #{};
|
||||
for (var #k in #o) {}
|
||||
for (var #k in #o) #k;
|
||||
for (var #k in #{ a:1 }) {}
|
||||
for (var #k in #{ a:1 }) #k;
|
||||
#}
|
||||
var o = |_|{};
|
||||
for (var |_|k in |_|o) {}
|
||||
for (var |_|k in |_|o) |_|k;
|
||||
for (var |_|k in |_|{ a:1 }) {}
|
||||
for (var |_|k in |_|{ a:1 }) |_|k;
|
||||
|R|}
|
||||
|
||||
function testSimpleExpressions() {
|
||||
#1 + 2 + 3;
|
||||
var a = #1;
|
||||
#++a;
|
||||
#a--;
|
||||
#}
|
||||
|_|1 + 2 + 3;
|
||||
var a = |_|1;
|
||||
|_|++a;
|
||||
|_|a--;
|
||||
|R|}
|
||||
|
||||
Object.defineProperty(this, 'getterFoo', {
|
||||
get: () => #return42#
|
||||
get: () => |_|return42|R|
|
||||
});
|
||||
|
||||
function testGetter() {
|
||||
#getterFoo();
|
||||
#}
|
||||
|C|getterFoo();
|
||||
|R|}
|
||||
|
||||
var obj = {
|
||||
foo: () => (#{
|
||||
boo: () => #return42#
|
||||
})#
|
||||
foo: () => (|_|{
|
||||
boo: () => |_|return42|R|
|
||||
})|R|
|
||||
};
|
||||
|
||||
function testChainedCalls() {
|
||||
#obj.#foo().#boo()#();
|
||||
#}
|
||||
|_|obj.|C|foo().|C|boo()|C|();
|
||||
|R|}
|
||||
|
||||
function testChainedWithNative() {
|
||||
#Array.#from([1]).#concat([2]).#map(v => v #* 2#);
|
||||
#}
|
||||
|_|Array.|C|from([1]).|C|concat([2]).|C|map(v => v |_|* 2|R|);
|
||||
|R|}
|
||||
|
||||
function testPromiseThen() {
|
||||
#return Promise.#resolve().#then(v => v #* 2#).#then(v => v #* 2#);
|
||||
#}
|
||||
|_|return Promise.|C|resolve().|C|then(v => v |_|* 2|R|).|C|then(v => v |_|* 2|R|);
|
||||
|R|}
|
||||
|
||||
function testSwitch() {
|
||||
for (var i = #0; i #< 3; ++#i) {
|
||||
#switch(i) {
|
||||
case 0: #continue;
|
||||
case 1: #return42(); #break;
|
||||
default: #return;
|
||||
for (var i = |_|0; i |_|< 3; ++|_|i) {
|
||||
|_|switch(i) {
|
||||
case 0: |_|continue;
|
||||
case 1: |C|return42(); |_|break;
|
||||
default: |_|return;
|
||||
}
|
||||
}
|
||||
#}
|
||||
|R|}
|
||||
|
||||
function* idMaker() {
|
||||
#yield 1;
|
||||
#yield 2;
|
||||
#yield 3;
|
||||
#}
|
||||
|_|yield 1;
|
||||
|_|yield 2;
|
||||
|_|yield 3;
|
||||
|R|}
|
||||
|
||||
function testGenerator() {
|
||||
var gen = #idMaker();
|
||||
#return42();
|
||||
#gen.#next().value;
|
||||
#debugger;
|
||||
#gen.#next().value;
|
||||
#return42();
|
||||
#gen.#next().value;
|
||||
#return42();
|
||||
#gen.#next().value;
|
||||
#}
|
||||
var gen = |C|idMaker();
|
||||
|C|return42();
|
||||
|_|gen.|C|next().value;
|
||||
|D|debugger;
|
||||
|_|gen.|C|next().value;
|
||||
|C|return42();
|
||||
|_|gen.|C|next().value;
|
||||
|C|return42();
|
||||
|_|gen.|C|next().value;
|
||||
|R|}
|
||||
|
||||
function throwException() {
|
||||
#throw #new Error();
|
||||
#}
|
||||
|_|throw |C|new Error();
|
||||
|R|}
|
||||
|
||||
function testCaughtException() {
|
||||
try {
|
||||
#throwException()
|
||||
|C|throwException()
|
||||
} catch (e) {
|
||||
#return;
|
||||
|_|return;
|
||||
}
|
||||
#}
|
||||
|R|}
|
||||
|
||||
function testClasses() {
|
||||
#class Cat {
|
||||
|_|class Cat {
|
||||
constructor(name) {
|
||||
#this.name = name;
|
||||
#}
|
||||
|_|this.name = name;
|
||||
|R|}
|
||||
|
||||
speak() {
|
||||
#}
|
||||
|R|}
|
||||
}
|
||||
#class Lion extends Cat {
|
||||
|_|class Lion extends Cat {
|
||||
constructor(name) {
|
||||
#super(name);
|
||||
#}
|
||||
|C|super(name);
|
||||
|R|}
|
||||
|
||||
speak() {
|
||||
#super.#speak();
|
||||
#}
|
||||
|_|super.|C|speak();
|
||||
|R|}
|
||||
}
|
||||
#new Lion().#speak();
|
||||
#}
|
||||
|C|new Lion().|C|speak();
|
||||
|R|}
|
||||
|
||||
async function asyncFoo() {
|
||||
#await Promise.resolve().then(v => v #* 2#);
|
||||
#return42();
|
||||
#await #asyncBoo();
|
||||
#}
|
||||
|_|await Promise.resolve().then(v => v |_|* 2|R|);
|
||||
|C|return42();
|
||||
|_|await |C|asyncBoo();
|
||||
|R|}
|
||||
|
||||
async function asyncBoo() {
|
||||
#await Promise.resolve();
|
||||
#}
|
||||
|_|await Promise.resolve();
|
||||
|R|}
|
||||
|
||||
async function testAsyncAwait() {
|
||||
#await asyncFoo();
|
||||
#await #awaitBoo();
|
||||
#}
|
||||
|_|await asyncFoo();
|
||||
|_|await |C|awaitBoo();
|
||||
|R|}
|
||||
|
||||
// TODO(kozyatinskiy): fix this.
|
||||
async function testPromiseAsyncWithCode() {
|
||||
var nextTest;
|
||||
var testPromise = #new Promise(resolve => nextTest #= resolve#);
|
||||
var testPromise = |C|new Promise(resolve => nextTest |_|= resolve|R|);
|
||||
async function main() {
|
||||
async function foo() {
|
||||
var resolveNested;
|
||||
var p = #new Promise(resolve => resolveNested #= resolve#);
|
||||
#setTimeout(resolveNested, 0);
|
||||
#await #p;
|
||||
#}
|
||||
#setTimeout(returnCall, 0);
|
||||
#await #foo();
|
||||
#await #foo();
|
||||
#nextTest();
|
||||
#}
|
||||
#main();
|
||||
#return testPromise;
|
||||
#}
|
||||
var p = |C|new Promise(resolve => resolveNested |_|= resolve|R|);
|
||||
|C|setTimeout(resolveNested, 0);
|
||||
|_|await |_|p;
|
||||
|R|}
|
||||
|C|setTimeout(returnCall, 0);
|
||||
|_|await |C|foo();
|
||||
|_|await |C|foo();
|
||||
|C|nextTest();
|
||||
|R|}
|
||||
|C|main();
|
||||
|_|return testPromise;
|
||||
|R|}
|
||||
|
||||
function returnFunction() {
|
||||
#return returnObject;
|
||||
#}
|
||||
|_|return returnObject;
|
||||
|R|}
|
||||
|
||||
async function testPromiseComplex() {
|
||||
var nextTest;
|
||||
var testPromise = #new Promise(resolve => nextTest #= resolve#);
|
||||
var testPromise = |C|new Promise(resolve => nextTest |_|= resolve|R|);
|
||||
async function main() {
|
||||
async function foo() {
|
||||
#await Promise.resolve();
|
||||
#return 42;
|
||||
#}
|
||||
var x = #1;
|
||||
var y = #2;
|
||||
#returnFunction(#emptyFunction(), x++, --y, x => 2 #* x#, #returnCall())#().a = #await #foo((a => 2 #*a#)#(5));
|
||||
#nextTest();
|
||||
#}
|
||||
#main();
|
||||
#return testPromise;
|
||||
#}
|
||||
|_|await Promise.resolve();
|
||||
|_|return 42;
|
||||
|R|}
|
||||
var x = |_|1;
|
||||
var y = |_|2;
|
||||
|C|returnFunction(|C|emptyFunction(), x++, --y, x => 2 |_|* x|R|, |C|returnCall())|C|().a = |_|await |C|foo((a => 2 |_|*a|R|)|C|(5));
|
||||
|C|nextTest();
|
||||
|R|}
|
||||
|C|main();
|
||||
|_|return testPromise;
|
||||
|R|}
|
||||
|
||||
function twiceDefined() {
|
||||
return a + b;
|
||||
}
|
||||
|
||||
function twiceDefined() {
|
||||
#return a + b;
|
||||
#}
|
||||
|_|return a + b;
|
||||
|R|}
|
||||
|
||||
|
||||
|
@ -25,10 +25,17 @@ function dumpAllLocations(message) {
|
||||
});
|
||||
for (var location of locations) {
|
||||
var line = lines[location.lineNumber];
|
||||
line = line.slice(0, location.columnNumber) + '#' + line.slice(location.columnNumber);
|
||||
line = line.slice(0, location.columnNumber) + locationMark(location.type) + line.slice(location.columnNumber);
|
||||
lines[location.lineNumber] = line;
|
||||
}
|
||||
lines = lines.filter(line => line.indexOf('//# sourceURL=') === -1);
|
||||
InspectorTest.log(lines.join('\n'));
|
||||
return message;
|
||||
}
|
||||
|
||||
function locationMark(type) {
|
||||
if (type === 'return') return '|R|';
|
||||
if (type === 'call') return '|C|';
|
||||
if (type === 'debuggerStatement') return '|D|';
|
||||
return '|_|';
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user