Commit 9d17b0d4 authored by sgjesse@chromium.org's avatar sgjesse@chromium.org

Whenever a script object is created it is assigned a unique id. Currently this...

Whenever a script object is created it is assigned a unique id. Currently this id is assigned from an 32 bit integer counter.

Changed the script break points to be able to handle both break points based on script names and script ids. When break points are set through a script id the position is relative to the script itself. This is different from the script break points set through script names where the line/coulmn offset is taken into account.

This has the side effect that function break points are not converted into script break points for named scripts.

Show the script id in the D8 shell debugger when listing all scripts using the 'scripts' command.
Review URL: http://codereview.chromium.org/40317

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1468 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent bab4b3b2
......@@ -524,6 +524,11 @@ class EXPORT Script {
* Runs the script returning the resulting value.
*/
Local<Value> Run();
/**
* Returns the script id value.
*/
Local<Value> Id();
};
......
......@@ -197,6 +197,24 @@ const AccessorDescriptor Accessors::ScriptName = {
};
//
// Accessors::ScriptId
//
Object* Accessors::ScriptGetId(Object* object, void*) {
Object* script = JSValue::cast(object)->value();
return Script::cast(script)->id();
}
const AccessorDescriptor Accessors::ScriptId = {
ScriptGetId,
IllegalSetter,
0
};
//
// Accessors::ScriptLineOffset
//
......
......@@ -42,6 +42,7 @@ namespace v8 { namespace internal {
V(StringLength) \
V(ScriptSource) \
V(ScriptName) \
V(ScriptId) \
V(ScriptLineOffset) \
V(ScriptColumnOffset) \
V(ScriptType) \
......@@ -79,6 +80,7 @@ class Accessors : public AllStatic {
static Object* ArrayGetLength(Object* object, void*);
static Object* StringGetLength(Object* object, void*);
static Object* ScriptGetName(Object* object, void*);
static Object* ScriptGetId(Object* object, void*);
static Object* ScriptGetSource(Object* object, void*);
static Object* ScriptGetLineOffset(Object* object, void*);
static Object* ScriptGetColumnOffset(Object* object, void*);
......
......@@ -1054,6 +1054,22 @@ Local<Value> Script::Run() {
}
Local<Value> Script::Id() {
ON_BAILOUT("v8::Script::Id()", return Local<Value>());
LOG_API("Script::Id");
i::Object* raw_id = NULL;
{
HandleScope scope;
i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
i::Handle<i::Script> script(i::Script::cast(fun->shared()->script()));
i::Handle<i::Object> id(script->id());
raw_id = *id;
}
i::Handle<i::Object> id(raw_id);
return Utils::ToLocal(id);
}
// --- E x c e p t i o n s ---
......
......@@ -985,12 +985,19 @@ bool Genesis::InstallNatives() {
Factory::LookupAsciiSymbol("source"),
proxy_source,
common_attributes);
Handle<Proxy> proxy_data = Factory::NewProxy(&Accessors::ScriptName);
Handle<Proxy> proxy_name = Factory::NewProxy(&Accessors::ScriptName);
script_descriptors =
Factory::CopyAppendProxyDescriptor(
script_descriptors,
Factory::LookupAsciiSymbol("name"),
proxy_data,
proxy_name,
common_attributes);
Handle<Proxy> proxy_id = Factory::NewProxy(&Accessors::ScriptId);
script_descriptors =
Factory::CopyAppendProxyDescriptor(
script_descriptors,
Factory::LookupAsciiSymbol("id"),
proxy_id,
common_attributes);
Handle<Proxy> proxy_line_offset =
Factory::NewProxy(&Accessors::ScriptLineOffset);
......
......@@ -888,18 +888,19 @@ function DebugResponseDetails(response) {
var result = '';
for (i = 0; i < body.length; i++) {
if (i != 0) result += '\n';
if (body[i].id) {
result += body[i].id;
} else {
result += '[no id]';
}
result += ', ';
if (body[i].name) {
result += body[i].name;
} else {
result += '[unnamed] ';
var sourceStart = body[i].sourceStart;
if (sourceStart.length > 40) {
sourceStart = sourceStart.substring(0, 37) + '...';
}
result += sourceStart;
}
result += ' (lines: ';
result += body[i].sourceLines;
result += body[i].lineCount;
result += ', length: ';
result += body[i].sourceLength;
if (body[i].type == Debug.ScriptType.Native) {
......@@ -907,7 +908,13 @@ function DebugResponseDetails(response) {
} else if (body[i].type == Debug.ScriptType.Extension) {
result += ', extension';
}
result += ')';
result += '), [';
var sourceStart = body[i].sourceStart;
if (sourceStart.length > 40) {
sourceStart = sourceStart.substring(0, 37) + '...';
}
result += sourceStart;
result += ']';
}
details.text = result;
break;
......
This diff is collapsed.
......@@ -153,9 +153,12 @@ Handle<AccessorInfo> Factory::NewAccessorInfo() {
Handle<Script> Factory::NewScript(Handle<String> source) {
static uint32_t next_id = 1;
Handle<Script> script = Handle<Script>::cast(NewStruct(SCRIPT_TYPE));
script->set_source(*source);
script->set_name(Heap::undefined_value());
script->set_id(*Factory::NewNumberFromUint(next_id++));
script->set_line_offset(Smi::FromInt(0));
script->set_column_offset(Smi::FromInt(0));
script->set_type(Smi::FromInt(SCRIPT_TYPE_NORMAL));
......@@ -277,6 +280,11 @@ Handle<Object> Factory::NewNumberFromInt(int value) {
}
Handle<Object> Factory::NewNumberFromUint(uint32_t value) {
CALL_HEAP_FUNCTION(Heap::NumberFromUint32(value), Object);
}
Handle<JSObject> Factory::NewNeanderObject() {
CALL_HEAP_FUNCTION(Heap::AllocateJSObjectFromMap(Heap::neander_map()),
JSObject);
......
......@@ -170,6 +170,7 @@ class Factory : public AllStatic {
PretenureFlag pretenure = NOT_TENURED);
static Handle<Object> NewNumberFromInt(int value);
static Handle<Object> NewNumberFromUint(uint32_t value);
// These objects are used by the api to create env-independent data
// structures in the heap.
......
......@@ -1359,7 +1359,8 @@ FrameMirror.prototype.sourcePosition = function() {
FrameMirror.prototype.sourceLocation = function() {
if (this.func().resolved() && this.func().script()) {
return this.func().script().locationFromPosition(this.sourcePosition());
return this.func().script().locationFromPosition(this.sourcePosition(),
true);
}
};
......@@ -1561,6 +1562,11 @@ ScriptMirror.prototype.name = function() {
};
ScriptMirror.prototype.id = function() {
return this.script_.id;
};
ScriptMirror.prototype.source = function() {
return this.script_.source;
};
......
......@@ -2041,6 +2041,7 @@ ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
ACCESSORS(Script, source, Object, kSourceOffset)
ACCESSORS(Script, name, Object, kNameOffset)
ACCESSORS(Script, id, Object, kIdOffset)
ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
......
......@@ -2550,6 +2550,9 @@ class Script: public Struct {
// [name]: the script name.
DECL_ACCESSORS(name, Object)
// [id]: the script id.
DECL_ACCESSORS(id, Object)
// [line_offset]: script line offset in resource from where it was extracted.
DECL_ACCESSORS(line_offset, Smi)
......@@ -2583,7 +2586,8 @@ class Script: public Struct {
static const int kWrapperOffset = kColumnOffsetOffset + kPointerSize;
static const int kTypeOffset = kWrapperOffset + kPointerSize;
static const int kLineEndsOffset = kTypeOffset + kPointerSize;
static const int kSize = kLineEndsOffset + kPointerSize;
static const int kIdOffset = kLineEndsOffset + kPointerSize;
static const int kSize = kIdOffset + kPointerSize;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(Script);
......
This diff is collapsed.
......@@ -29,8 +29,8 @@
// Get the Debug object exposed from the debug context global object.
Debug = debug.Debug
// Set and remove a script break point.
var sbp = Debug.setScriptBreakPoint("1", 2, 3);
// Set and remove a script break point for a named script.
var sbp = Debug.setScriptBreakPointByName("1", 2, 3);
assertEquals(1, Debug.scriptBreakPoints().length);
assertEquals("1", Debug.scriptBreakPoints()[0].script_name());
assertEquals(2, Debug.scriptBreakPoints()[0].line());
......@@ -38,10 +38,10 @@ assertEquals(3, Debug.scriptBreakPoints()[0].column());
Debug.clearBreakPoint(sbp);
assertEquals(0, Debug.scriptBreakPoints().length);
// Set three script break points.
var sbp1 = Debug.setScriptBreakPoint("1", 2, 3);
var sbp2 = Debug.setScriptBreakPoint("2", 3, 4);
var sbp3 = Debug.setScriptBreakPoint("3", 4, 5);
// Set three script break points for named scripts.
var sbp1 = Debug.setScriptBreakPointByName("1", 2, 3);
var sbp2 = Debug.setScriptBreakPointByName("2", 3, 4);
var sbp3 = Debug.setScriptBreakPointByName("3", 4, 5);
// Check the content of the script break points.
assertEquals(3, Debug.scriptBreakPoints().length);
......@@ -57,7 +57,48 @@ for (var i = 0; i < Debug.scriptBreakPoints().length; i++) {
assertEquals(4, x.line());
assertEquals(5, x.column());
} else {
assertUnreachable("unecpected script_data " + x.script_data());
assertUnreachable("unecpected script_name " + x.script_name());
}
}
// Remove script break points (in another order than they where added).
assertEquals(3, Debug.scriptBreakPoints().length);
Debug.clearBreakPoint(sbp1);
assertEquals(2, Debug.scriptBreakPoints().length);
Debug.clearBreakPoint(sbp3);
assertEquals(1, Debug.scriptBreakPoints().length);
Debug.clearBreakPoint(sbp2);
assertEquals(0, Debug.scriptBreakPoints().length);
// Set and remove a script break point for a script id.
var sbp = Debug.setScriptBreakPointById(1, 2, 3);
assertEquals(1, Debug.scriptBreakPoints().length);
assertEquals(1, Debug.scriptBreakPoints()[0].script_id());
assertEquals(2, Debug.scriptBreakPoints()[0].line());
assertEquals(3, Debug.scriptBreakPoints()[0].column());
Debug.clearBreakPoint(sbp);
assertEquals(0, Debug.scriptBreakPoints().length);
// Set three script break points for script ids.
var sbp1 = Debug.setScriptBreakPointById(1, 2, 3);
var sbp2 = Debug.setScriptBreakPointById(2, 3, 4);
var sbp3 = Debug.setScriptBreakPointById(3, 4, 5);
// Check the content of the script break points.
assertEquals(3, Debug.scriptBreakPoints().length);
for (var i = 0; i < Debug.scriptBreakPoints().length; i++) {
var x = Debug.scriptBreakPoints()[i];
if (1 == x.script_id()) {
assertEquals(2, x.line());
assertEquals(3, x.column());
} else if (2 == x.script_id()) {
assertEquals(3, x.line());
assertEquals(4, x.column());
} else if (3 == x.script_id()) {
assertEquals(4, x.line());
assertEquals(5, x.column());
} else {
assertUnreachable("unecpected script_id " + x.script_id());
}
}
......
......@@ -30,8 +30,13 @@
Debug = debug.Debug
// Simple function which stores the last debug event.
listenerComplete = false;
exception = false;
var listenerComplete = false;
var exception = false;
var f_script_id = 0;
var g_script_id = 0;
var h_script_id = 0;
var f_line = 0;
var g_line = 0;
var base_request = '"seq":0,"type":"request","command":"setbreakpoint"'
......@@ -44,13 +49,18 @@ function safeEval(code) {
}
}
function testArguments(dcp, arguments, success, type) {
function testArguments(dcp, arguments, success, is_script) {
var request = '{' + base_request + ',"arguments":' + arguments + '}'
var json_response = dcp.processDebugJSONRequest(request);
var response = safeEval(json_response);
if (success) {
assertTrue(response.success, json_response);
assertEquals(type ? type : 'script', response.body.type, json_response);
if (is_script) {
assertEquals('scriptName', response.body.type, json_response);
} else {
assertEquals('scriptId', response.body.type, json_response);
print(response.body.script_id);
}
} else {
assertFalse(response.success, json_response);
}
......@@ -79,18 +89,23 @@ function listener(event, exec_state, event_data, data) {
testArguments(dcp, '{"type":"function","target":"f","ignoreCount":-1}', false);
// Test some legal setbreakpoint requests.
testArguments(dcp, '{"type":"function","target":"f"}', true);
testArguments(dcp, '{"type":"function","target":"h"}', true, 'function');
testArguments(dcp, '{"type":"function","target":"f","line":1}', true);
testArguments(dcp, '{"type":"function","target":"f","position":1}', true);
testArguments(dcp, '{"type":"function","target":"f","condition":"i == 1"}', true);
testArguments(dcp, '{"type":"function","target":"f","enabled":true}', true);
testArguments(dcp, '{"type":"function","target":"f","enabled":false}', true);
testArguments(dcp, '{"type":"function","target":"f","ignoreCount":7}', true);
testArguments(dcp, '{"type":"script","target":"test"}', true);
testArguments(dcp, '{"type":"script","target":"test"}', true);
testArguments(dcp, '{"type":"script","target":"test","line":1}', true);
testArguments(dcp, '{"type":"script","target":"test","column":1}', true);
testArguments(dcp, '{"type":"function","target":"f"}', true, false);
testArguments(dcp, '{"type":"function","target":"h"}', true, false);
testArguments(dcp, '{"type":"function","target":"f","line":1}', true, false);
testArguments(dcp, '{"type":"function","target":"f","position":1}', true, false);
testArguments(dcp, '{"type":"function","target":"f","condition":"i == 1"}', true, false);
testArguments(dcp, '{"type":"function","target":"f","enabled":true}', true, false);
testArguments(dcp, '{"type":"function","target":"f","enabled":false}', true, false);
testArguments(dcp, '{"type":"function","target":"f","ignoreCount":7}', true, false);
testArguments(dcp, '{"type":"script","target":"test"}', true, true);
testArguments(dcp, '{"type":"script","target":"test"}', true, true);
testArguments(dcp, '{"type":"script","target":"test","line":1}', true, true);
testArguments(dcp, '{"type":"script","target":"test","column":1}', true, true);
testArguments(dcp, '{"type":"scriptId","target":' + f_script_id + ',"line":' + f_line + '}', true, false);
testArguments(dcp, '{"type":"scriptId","target":' + g_script_id + ',"line":' + g_line + '}', true, false);
testArguments(dcp, '{"type":"scriptId","target":' + h_script_id + ',"line":' + h_line + '}', true, false);
// Indicate that all was processed.
listenerComplete = true;
......@@ -113,10 +128,27 @@ function g() {
eval('function h(){}');
// Check the script ids for the test functions.
f_script_id = Debug.findScript(f).id;
g_script_id = Debug.findScript(g).id;
h_script_id = Debug.findScript(h).id;
assertTrue(f_script_id > 0, "invalid script id for f");
assertTrue(g_script_id > 0, "invalid script id for g");
assertTrue(h_script_id > 0, "invalid script id for h");
assertEquals(f_script_id, g_script_id);
// Get the source line for the test functions.
f_line = Debug.findFunctionSourceLocation(f).line;
g_line = Debug.findFunctionSourceLocation(g).line;
h_line = Debug.findFunctionSourceLocation(h).line;
assertTrue(f_line > 0, "invalid line for f");
assertTrue(g_line > 0, "invalid line for g");
assertTrue(f_line < g_line);
assertEquals(h_line, 0, "invalid line for h");
// Set a break point and call to invoke the debug event listener.
Debug.setBreakPoint(g, 0, 0);
g();
// Make sure that the debug event listener vas invoked.
assertTrue(listenerComplete, "listener did not run to completion");
assertFalse(exception, "exception in listener")
assertTrue(listenerComplete, "listener did not run to completion: " + exception);
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