-
Notifications
You must be signed in to change notification settings - Fork 36
/
Copy pathdescriptions.js
229 lines (210 loc) · 9.88 KB
/
descriptions.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
//--------------------------------------------------------------
//
// MIT License
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//--------------------------------------------------------------
"use strict";
Loader.OnLoad(function () {
var registeredDescriptions = new DbgObject.TypeExtension();
DbgObject.TypeDescriptions = registeredDescriptions;
function TypeDescription(name, isPrimary, getter) {
this.name = name;
this.isPrimary = isPrimary;
this.getter = getter;
}
DbgObject._help_AddTypeDescription = {
description: "Provides a function to produce type-specific formatting of DbgObjects.",
notes: "The provided function will be used whenever <code>desc()</code> is called on a DbgObject with a matching type.",
arguments:[
{name: "type", type:"DbgObjectType/function(DbgObjectType) -> bool", description: "The type, or a predicate that matches a type."},
{name: "name", type:"string", description:"The name of the description."},
{name: "isPrimary", type:"bool", description:"A value that indicates if the description should be used by <code>desc()</code>."},
{name: "description", type:"function(DbgObject) -> string", description: "A function that returns an HTML fragment to describe a given DbgObject."}
]
};
DbgObject.AddTypeDescription = function(type, name, isPrimary, description) {
return registeredDescriptions.addExtension(type, name, new TypeDescription(name, isPrimary, description));
}
DbgObject._help_RemoveTypeDescription = {
description: "Removes a previously registered type description.",
arguments: [
{ name: "type", type: "DbgObjectType/function(DbgObjectType) -> bool", description: "The type (or type predicate) to remove the description from." },
{ name: "name", type: "string", description: "The name of the description to remove." }
]
}
DbgObject.RemoveTypeDescription = function(type, name) {
return registeredDescriptions.removeExtension(type, name);
}
DbgObject._help_RenameTypeDescription = {
description: "Renames a previously registered type description.",
arguments: [
{ name: "type", type: "DbgObjectType/function(DbgObjectType) -> bool", description: "The type (or type predicate) to rename the description on." },
{ name: "oldName", type: "string", description: "The name of the description to rename." },
{ name: "newName", type: "string", description: "The new name of the description" },
]
}
DbgObject.RenameTypeDescription = function(type, oldName, newName) {
return registeredDescriptions.renameExtension(type, oldName, newName);
}
DbgObject._help_GetDescriptions = {
description: "Gets the available descriptions for the given type.",
arguments: [
{name: "type", type:"DbgObjectType", description:"The type."}
],
returns: "An array of objects with <code>name</code> and <code>getter</code> fields."
};
DbgObject.GetDescriptions = function (type) {
return registeredDescriptions.getAllExtensions(type).map(function (extension) {
return extension.extension;
})
}
DbgObject.OnDescriptionsChanged = function (type, listener) {
return registeredDescriptions.addListener(type, listener);
}
function getTypeDescriptionFunctionIncludingBaseTypes(type) {
function getTypeDescriptionFunction(type) {
var primaries = registeredDescriptions.getAllExtensions(type).filter(function (e) { return e.extension.isPrimary; }).map(function (e) { return e.extension; });
if (primaries.length == 0) {
return null;
} else {
return primaries[0].getter;
}
}
var natural = getTypeDescriptionFunction(type);
if (natural != null) {
return Promise.resolve(natural);
} else if (type == "void") {
return Promise.resolve(null);
}
return DbgObject.create(type, 0).baseTypes()
.then(function (baseTypes) {
for (var i = 0; i < baseTypes.length; ++i) {
var desc = getTypeDescriptionFunction(baseTypes[i].type);
if (desc != null) {
return desc;
}
}
return null;
});
}
function getDefaultTypeDescription(dbgObject, element) {
if (dbgObject.isNull()) {
return Promise.resolve("nullptr");
}
return getTypeDescriptionFunctionIncludingBaseTypes(dbgObject.type)
.then(function (customDescription) {
var hasCustomDescription = customDescription != null;
if (!hasCustomDescription) {
customDescription = function(x) {
// Default description: first try to get val(), then just provide the pointer with the type.
if (x.type.isScalar()) {
if (x.type.equals("bool") || x.bitcount == 1) {
return x.val()
.then(function (value) {
return value == 1 ? "true" : "false";
});
} else if (x.type.equals("wchar_t")) {
if (x.wasDereferenced) {
return x.string()
.then(null, function() {
return x.val().then(String.fromCharCode);
});
} else {
return x.val().then(String.fromCharCode);
}
} else {
return x.bigval().then(function (bigint) { return bigint.toString(); });
}
} else if (x.type.isPointer()) {
return Promise.resolve(x.deref())
.then(function (dereferenced) {
return dereferenced.ptr();
});
} else {
return x.isEnum()
.then(function (isEnum) {
if (isEnum) {
return x.constant();
} else {
return x.ptr();
}
})
.then(null, function () {
return x.ptr();
})
}
};
}
var description = function(obj) {
return Promise.resolve(obj)
.then(function (obj) {
return customDescription(obj, element);
})
.then(null, function(err) {
if (hasCustomDescription) {
// The custom description provider had an error.
return obj.type.name() + "???";
} else if (obj.isNull()) {
return null;
} else {
return obj.ptr();
}
});
}
if (dbgObject.type.isArray()) {
var length = dbgObject.type.arrayLength();
var elements = [];
for (var i = 0; i < length; ++i) {
elements.push(dbgObject.idx(i));
}
return Promise.map(Promise.all(elements), description)
.then(function(descriptions) {
return "[" + descriptions.map(function(d) { return "<div style=\"display:inline-block;\">" + d + "</div>"; }).join(", ") + "]";
})
} else {
return description(dbgObject);
}
});
}
DbgObject.prototype._help_desc = {
description: "Provides a human-readable description of the object.",
returns: "A promise to an HTML fragment.",
arguments: [
{name: "name (optional)", type:"string", description: "The optional name of the description to use."},
{name: "element (optional)", type:"HTML Element", description: "The element representing the DbgObject, if it exists."}
],
notes: function() {
var html = "<p>Calling with no arguments will use the default description function. Type-specific description generators can be registered with <code>DbgObject.AddTypeDescription</code>.</p>";
var loadedDescriptionTypes = registeredDescriptions.getAllTypes().map(function (type) {
if (DbgObjectType.is(type)) {
return "<li>" + type.toString() + "</li>";
} else {
return "<li>Predicate: (" + type.toString() + ")</li>"
}
});
return html + "Currently registered types with descriptions: <ul>" + loadedDescriptionTypes.join("") + "</ul>";
}
}
DbgObject.prototype.desc = function(name, element) {
if (name === undefined || name === null) {
return getDefaultTypeDescription(this, element);
} else {
var that = this;
return registeredDescriptions.getExtensionIncludingBaseTypes(this, name)
.then(function (result) {
if (result == null) {
throw new Error("There was no description \"" + name + "\" on " + that.type.name());
}
return Promise.resolve(result.extension.getter(result.dbgObject, element));
})
}
}
DbgObject.prototype.hasDefaultDescription = function() {
return getTypeDescriptionFunctionIncludingBaseTypes(this.type)
.then(function (defaultDescription) {
return defaultDescription != null;
})
}
});