Commit b32d7d2e authored by sgjesse@chromium.org's avatar sgjesse@chromium.org

Added context information to scripts.

Added a simple initial version of a context mirror object which just holds the user data from the context, and does not preserve handle identity.

A script object now holds a reference to the custom data from the context it was compiled in. This data is included in the debugger protocol for scripts.

Changed the serialization for the scripts command to use the mirror objects instaed of custom serialization. This included passing options from the debugger request to the serializer for including the full source of scripts in the response.
Review URL: http://codereview.chromium.org/111001

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1877 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent f1e1b39e
......@@ -307,6 +307,25 @@ const AccessorDescriptor Accessors::ScriptLineEnds = {
};
//
// Accessors::ScriptGetContextData
//
Object* Accessors::ScriptGetContextData(Object* object, void*) {
HandleScope scope;
Handle<Script> script(Script::cast(JSValue::cast(object)->value()));
return script->context_data();
}
const AccessorDescriptor Accessors::ScriptContextData = {
ScriptGetContextData,
IllegalSetter,
0
};
//
// Accessors::FunctionPrototype
//
......
......@@ -48,6 +48,7 @@ namespace v8 { namespace internal {
V(ScriptData) \
V(ScriptType) \
V(ScriptLineEnds) \
V(ScriptContextData) \
V(ObjectPrototype)
// Accessors contains all predefined proxy accessors.
......@@ -88,6 +89,7 @@ class Accessors : public AllStatic {
static Object* ScriptGetData(Object* object, void*);
static Object* ScriptGetType(Object* object, void*);
static Object* ScriptGetLineEnds(Object* object, void*);
static Object* ScriptGetContextData(Object* object, void*);
static Object* ObjectGetPrototype(Object* receiver, void*);
static Object* ObjectSetPrototype(JSObject* receiver, Object* value, void*);
......
......@@ -1055,6 +1055,14 @@ bool Genesis::InstallNatives() {
Factory::LookupAsciiSymbol("line_ends"),
proxy_line_ends,
common_attributes);
Handle<Proxy> proxy_context_data =
Factory::NewProxy(&Accessors::ScriptContextData);
script_descriptors =
Factory::CopyAppendProxyDescriptor(
script_descriptors,
Factory::LookupAsciiSymbol("context_data"),
proxy_context_data,
common_attributes);
Handle<Map> script_map = Handle<Map>(script_fun->initial_map());
script_map->set_instance_descriptors(*script_descriptors);
......
......@@ -104,6 +104,8 @@ static Handle<JSFunction> MakeFunction(bool is_global,
StackGuard guard;
PostponeInterruptsScope postpone;
ASSERT(!i::Top::global_context().is_null());
script->set_context_data((*i::Top::global_context())->data());
#ifdef ENABLE_DEBUGGER_SUPPORT
// Notify debugger
Debugger::OnBeforeCompile(script);
......
......@@ -1062,6 +1062,14 @@ function ProtocolMessage(request) {
}
ProtocolMessage.prototype.setOption = function(name, value) {
if (!this.options_) {
this.options_ = {};
}
this.options_[name] = value;
}
ProtocolMessage.prototype.failed = function(message) {
this.success = false;
this.message = message;
......@@ -1090,7 +1098,7 @@ ProtocolMessage.prototype.toJSONProtocol = function() {
if (this.body) {
json += ',"body":';
// Encode the body part.
var serializer = MakeMirrorSerializer(true);
var serializer = MakeMirrorSerializer(true, this.options_);
if (this.body instanceof Mirror) {
json += serializer.serializeValue(this.body);
} else if (this.body instanceof Array) {
......@@ -1680,6 +1688,7 @@ DebugCommandProcessor.prototype.scriptsRequest_ = function(request, response) {
if (!IS_UNDEFINED(request.arguments.includeSource)) {
includeSource = %ToBoolean(request.arguments.includeSource);
response.setOption('includeSource', includeSource);
}
}
......@@ -1690,25 +1699,7 @@ DebugCommandProcessor.prototype.scriptsRequest_ = function(request, response) {
for (var i = 0; i < scripts.length; i++) {
if (types & ScriptTypeFlag(scripts[i].type)) {
var script = {};
if (scripts[i].name) {
script.name = scripts[i].name;
}
script.id = scripts[i].id;
script.lineOffset = scripts[i].line_offset;
script.columnOffset = scripts[i].column_offset;
script.lineCount = scripts[i].lineCount();
if (scripts[i].data) {
script.data = scripts[i].data;
}
if (includeSource) {
script.source = scripts[i].source;
} else {
script.sourceStart = scripts[i].source.substring(0, 80);
}
script.sourceLength = scripts[i].source.length;
script.type = scripts[i].type;
response.body.push(script);
response.body.push(MakeMirror(scripts[i]));
}
}
};
......
......@@ -174,6 +174,7 @@ Handle<Script> Factory::NewScript(Handle<String> source) {
script->set_line_offset(Smi::FromInt(0));
script->set_column_offset(Smi::FromInt(0));
script->set_data(Heap::undefined_value());
script->set_context_data(Heap::undefined_value());
script->set_type(Smi::FromInt(SCRIPT_TYPE_NORMAL));
script->set_wrapper(*Factory::NewProxy(0, TENURED));
script->set_line_ends(Heap::undefined_value());
......
......@@ -155,6 +155,7 @@ const ERROR_TYPE = 'error';
const PROPERTY_TYPE = 'property';
const FRAME_TYPE = 'frame';
const SCRIPT_TYPE = 'script';
const CONTEXT_TYPE = 'context';
// Maximum length when sending strings through the JSON protocol.
const kMaxProtocolStringLength = 80;
......@@ -363,6 +364,15 @@ Mirror.prototype.isScript = function() {
}
/**
* Check whether the mirror reflects a context.
* @returns {boolean} True if the mirror reflects a context
*/
Mirror.prototype.isContext = function() {
return this instanceof ContextMirror;
}
/**
* Allocate a handle id for this object.
*/
......@@ -1561,6 +1571,7 @@ FrameMirror.prototype.toText = function(opt_locals) {
function ScriptMirror(script) {
Mirror.call(this, SCRIPT_TYPE);
this.script_ = script;
this.context_ = new ContextMirror(script.context_data);
this.allocateHandle_();
}
inherits(ScriptMirror, Mirror);
......@@ -1622,6 +1633,11 @@ ScriptMirror.prototype.sourceSlice = function (opt_from_line, opt_to_line) {
}
ScriptMirror.prototype.context = function() {
return this.context_;
};
ScriptMirror.prototype.toText = function() {
var result = '';
result += this.name();
......@@ -1638,14 +1654,36 @@ ScriptMirror.prototype.toText = function() {
}
/**
* Mirror object for context.
* @param {Object} data The context data
* @constructor
* @extends Mirror
*/
function ContextMirror(data) {
Mirror.call(this, CONTEXT_TYPE);
this.data_ = data;
this.allocateHandle_();
}
inherits(ContextMirror, Mirror);
ContextMirror.prototype.data = function() {
return this.data_;
};
/**
* Returns a mirror serializer
*
* @param {boolean} details Set to true to include details
* @param {Object} options Options comtrolling the serialization
* The following options can be set:
* includeSource: include ths full source of scripts
* @returns {MirrorSerializer} mirror serializer
*/
function MakeMirrorSerializer(details) {
return new JSONProtocolSerializer(details);
function MakeMirrorSerializer(details, options) {
return new JSONProtocolSerializer(details, options);
}
......@@ -1655,8 +1693,9 @@ function MakeMirrorSerializer(details) {
* serialized
* @constructor
*/
function JSONProtocolSerializer(details) {
function JSONProtocolSerializer(details, options) {
this.details_ = details;
this.options_ = options;
this.mirrors_ = [ ];
}
......@@ -1708,6 +1747,11 @@ JSONProtocolSerializer.prototype.serializeReferencedObjects = function() {
}
JSONProtocolSerializer.prototype.includeSource_ = function() {
return this.options_ && this.options_.includeSource;
}
JSONProtocolSerializer.prototype.add_ = function(mirror) {
// If this mirror is already in the list just return.
for (var i = 0; i < this.mirrors_.length; i++) {
......@@ -1726,7 +1770,7 @@ JSONProtocolSerializer.prototype.serialize_ = function(mirror, reference,
// If serializing a reference to a mirror just return the reference and add
// the mirror to the referenced mirrors.
if (reference &&
(mirror.isValue() || mirror.isScript())) {
(mirror.isValue() || mirror.isScript() || mirror.isContext())) {
this.add_(mirror);
return '{"ref":' + mirror.handle() + '}';
}
......@@ -1735,7 +1779,7 @@ JSONProtocolSerializer.prototype.serialize_ = function(mirror, reference,
var content = new Array();
// Add the mirror handle.
if (mirror.isValue() || mirror.isScript()) {
if (mirror.isValue() || mirror.isScript() || mirror.isContext()) {
content.push(MakeJSONPair_('handle', NumberToJSON_(mirror.handle())));
}
......@@ -1801,8 +1845,29 @@ JSONProtocolSerializer.prototype.serialize_ = function(mirror, reference,
NumberToJSON_(mirror.columnOffset())));
content.push(MakeJSONPair_('lineCount',
NumberToJSON_(mirror.lineCount())));
if (mirror.data()) {
content.push(MakeJSONPair_('data', JSON.stringify(mirror.data())));
}
if (this.includeSource_()) {
content.push(MakeJSONPair_('source',
StringToJSON_(mirror.source())));
} else {
var sourceStart = mirror.source().substring(0, 80);
content.push(MakeJSONPair_('sourceStart',
StringToJSON_(sourceStart)));
}
content.push(MakeJSONPair_('sourceLength',
NumberToJSON_(mirror.source().length)));
content.push(MakeJSONPair_('scriptType',
NumberToJSON_(mirror.scriptType())));
if (mirror.context()) {
content.push(MakeJSONPair_('context',
this.serializeReference(mirror.context())));
}
break;
case CONTEXT_TYPE:
content.push(MakeJSONPair_('data', JSON.stringify(mirror.data())));
break;
}
......
......@@ -2091,6 +2091,7 @@ ACCESSORS(Script, id, Object, kIdOffset)
ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
ACCESSORS(Script, data, Object, kDataOffset)
ACCESSORS(Script, context_data, Object, kContextOffset)
ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
ACCESSORS(Script, type, Smi, kTypeOffset)
ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
......
......@@ -2642,6 +2642,9 @@ class Script: public Struct {
// [data]: additional data associated with this script.
DECL_ACCESSORS(data, Object)
// [context_data]: context data for the context this script was compiled in.
DECL_ACCESSORS(context_data, Object)
// [wrapper]: the wrapper cache.
DECL_ACCESSORS(wrapper, Proxy)
......@@ -2663,7 +2666,8 @@ class Script: public Struct {
static const int kLineOffsetOffset = kNameOffset + kPointerSize;
static const int kColumnOffsetOffset = kLineOffsetOffset + kPointerSize;
static const int kDataOffset = kColumnOffsetOffset + kPointerSize;
static const int kWrapperOffset = kDataOffset + kPointerSize;
static const int kContextOffset = kDataOffset + kPointerSize;
static const int kWrapperOffset = kContextOffset + kPointerSize;
static const int kTypeOffset = kWrapperOffset + kPointerSize;
static const int kLineEndsOffset = kTypeOffset + kPointerSize;
static const int kIdOffset = kLineEndsOffset + kPointerSize;
......
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