OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 InspectorTest = {}; | 5 InspectorTest = {}; |
6 InspectorTest._dumpInspectorProtocolMessages = false; | 6 InspectorTest._dumpInspectorProtocolMessages = false; |
7 InspectorTest._commandsForLogging = new Set(); | 7 InspectorTest._commandsForLogging = new Set(); |
| 8 InspectorTest._sessions = new Set(); |
8 | 9 |
9 InspectorTest.createContextGroup = function() { | 10 InspectorTest.log = utils.print.bind(utils); |
10 var contextGroup = {}; | 11 InspectorTest.quitImmediately = utils.quit.bind(utils); |
11 contextGroup.id = utils.createContextGroup(); | 12 |
12 contextGroup.schedulePauseOnNextStatement = (reason, details) => utils.schedul
ePauseOnNextStatement(contextGroup.id, reason, details); | 13 InspectorTest.logProtocolCommandCalls = function(command) { |
13 contextGroup.cancelPauseOnNextStatement = () => utils.cancelPauseOnNextStateme
nt(contextGroup.id); | 14 InspectorTest._commandsForLogging.add(command); |
14 contextGroup.addScript = (string, lineOffset, columnOffset, url) => utils.comp
ileAndRunWithOrigin(contextGroup.id, string, url || '', lineOffset || 0, columnO
ffset || 0, false); | |
15 contextGroup.addModule = (string, url, lineOffset, columnOffset) => utils.comp
ileAndRunWithOrigin(contextGroup.id, string, url, lineOffset || 0, columnOffset
|| 0, true); | |
16 return contextGroup; | |
17 } | 15 } |
18 | 16 |
19 InspectorTest._sessions = new Map(); | 17 InspectorTest.completeTest = function() { |
20 InspectorTest.createSession = function(contextGroup) { | 18 var promises = []; |
21 var session = { | 19 for (var session of InspectorTest._sessions) |
22 contextGroup: contextGroup, | 20 promises.push(session.Protocol.Debugger.disable()); |
23 _dispatchTable: new Map(), | 21 Promise.all(promises).then(() => utils.quit()); |
24 _eventHandler: {}, | |
25 _requestId: 0, | |
26 }; | |
27 session.Protocol = new Proxy({}, { | |
28 get: function(target, agentName, receiver) { | |
29 return new Proxy({}, { | |
30 get: function(target, methodName, receiver) { | |
31 const eventPattern = /^on(ce)?([A-Z][A-Za-z0-9]+)/; | |
32 var match = eventPattern.exec(methodName); | |
33 if (!match) { | |
34 return args => session._sendCommandPromise(`${agentName}.${methodNam
e}`, args || {}); | |
35 } else { | |
36 var eventName = match[2]; | |
37 eventName = eventName.charAt(0).toLowerCase() + eventName.slice(1); | |
38 if (match[1]) | |
39 return () => InspectorTest._waitForEventPromise(session, `${agentN
ame}.${eventName}`); | |
40 else | |
41 return (listener) => { session._eventHandler[`${agentName}.${event
Name}`] = listener }; | |
42 } | |
43 } | |
44 }); | |
45 } | |
46 }); | |
47 session._dispatchMessage = messageString => { | |
48 let messageObject = JSON.parse(messageString); | |
49 if (InspectorTest._dumpInspectorProtocolMessages) | |
50 utils.print("backend: " + JSON.stringify(messageObject)); | |
51 try { | |
52 var messageId = messageObject["id"]; | |
53 if (typeof messageId === "number") { | |
54 var handler = session._dispatchTable.get(messageId); | |
55 if (handler) { | |
56 handler(messageObject); | |
57 session._dispatchTable.delete(messageId); | |
58 } | |
59 } else { | |
60 var eventName = messageObject["method"]; | |
61 var eventHandler = session._eventHandler[eventName]; | |
62 if (session._scriptMap && eventName === "Debugger.scriptParsed") | |
63 session._scriptMap.set(messageObject.params.scriptId, JSON.parse(JSON.
stringify(messageObject.params))); | |
64 if (eventName === "Debugger.scriptParsed" && messageObject.params.url ==
= "wait-pending-tasks.js") | |
65 return; | |
66 if (eventHandler) | |
67 eventHandler(messageObject); | |
68 } | |
69 } catch (e) { | |
70 InspectorTest.log("Exception when dispatching message: " + e + "\n" + e.st
ack + "\n message = " + JSON.stringify(messageObject, null, 2)); | |
71 InspectorTest.completeTest(); | |
72 } | |
73 }; | |
74 session.id = utils.connectSession(contextGroup.id, '', session._dispatchMessag
e.bind(session)); | |
75 InspectorTest._sessions.set(session.id, session); | |
76 session.disconnect = () => utils.disconnectSession(session.id); | |
77 session.reconnect = () => { | |
78 InspectorTest._sessions.delete(session.id); | |
79 var state = utils.disconnectSession(session.id); | |
80 session.id = utils.connectSession(contextGroup.id, state, session._dispatchM
essage.bind(session)); | |
81 InspectorTest._sessions.set(session.id, session); | |
82 }; | |
83 session.sendRawCommand = (requestId, command, handler) => { | |
84 if (InspectorTest._dumpInspectorProtocolMessages) | |
85 utils.print("frontend: " + command); | |
86 session._dispatchTable.set(requestId, handler); | |
87 utils.sendMessageToBackend(session.id, command); | |
88 } | |
89 session._sendCommandPromise = (method, params) => { | |
90 var requestId = ++session._requestId; | |
91 var messageObject = { "id": requestId, "method": method, "params": params }; | |
92 var fulfillCallback; | |
93 var promise = new Promise(fulfill => fulfillCallback = fulfill); | |
94 if (InspectorTest._commandsForLogging.has(method)) { | |
95 utils.print(method + ' called'); | |
96 } | |
97 session.sendRawCommand(requestId, JSON.stringify(messageObject), fulfillCall
back); | |
98 return promise; | |
99 } | |
100 return session; | |
101 } | 22 } |
102 | 23 |
103 InspectorTest.logProtocolCommandCalls = (command) => InspectorTest._commandsForL
ogging.add(command); | 24 InspectorTest.waitForPendingTasks = function() { |
| 25 var promises = []; |
| 26 for (var session of InspectorTest._sessions) |
| 27 promises.push(session.Protocol.Runtime.evaluate({ expression: "new Promise(r
=> setTimeout(r, 0))//# sourceURL=wait-for-pending-tasks.js", awaitPromise: tru
e })); |
| 28 return Promise.all(promises); |
| 29 } |
104 | 30 |
105 InspectorTest.log = utils.print.bind(null); | 31 InspectorTest.startDumpingProtocolMessages = function() { |
| 32 InspectorTest._dumpInspectorProtocolMessages = true; |
| 33 } |
106 | 34 |
107 InspectorTest.logMessage = function(originalMessage) | 35 InspectorTest.logMessage = function(originalMessage) { |
108 { | |
109 var message = JSON.parse(JSON.stringify(originalMessage)); | 36 var message = JSON.parse(JSON.stringify(originalMessage)); |
110 if (message.id) | 37 if (message.id) |
111 message.id = "<messageId>"; | 38 message.id = "<messageId>"; |
112 | 39 |
113 const nonStableFields = new Set(["objectId", "scriptId", "exceptionId", "times
tamp", | 40 const nonStableFields = new Set(["objectId", "scriptId", "exceptionId", "times
tamp", |
114 "executionContextId", "callFrameId", "breakpointId", "bindRemoteObjectFuncti
onId", "formatterObjectId" ]); | 41 "executionContextId", "callFrameId", "breakpointId", "bindRemoteObjectFuncti
onId", "formatterObjectId" ]); |
115 var objects = [ message ]; | 42 var objects = [ message ]; |
116 while (objects.length) { | 43 while (objects.length) { |
117 var object = objects.shift(); | 44 var object = objects.shift(); |
118 for (var key in object) { | 45 for (var key in object) { |
119 if (nonStableFields.has(key)) | 46 if (nonStableFields.has(key)) |
120 object[key] = `<${key}>`; | 47 object[key] = `<${key}>`; |
121 else if (typeof object[key] === "string" && object[key].match(/\d+:\d+:\d+
:debug/)) | 48 else if (typeof object[key] === "string" && object[key].match(/\d+:\d+:\d+
:debug/)) |
122 object[key] = object[key].replace(/\d+/, '<scriptId>'); | 49 object[key] = object[key].replace(/\d+/, '<scriptId>'); |
123 else if (typeof object[key] === "object") | 50 else if (typeof object[key] === "object") |
124 objects.push(object[key]); | 51 objects.push(object[key]); |
125 } | 52 } |
126 } | 53 } |
127 | 54 |
128 InspectorTest.logObject(message); | 55 InspectorTest.logObject(message); |
129 return originalMessage; | 56 return originalMessage; |
130 } | 57 } |
131 | 58 |
132 InspectorTest.logObject = function(object, title) | 59 InspectorTest.logObject = function(object, title) { |
133 { | |
134 var lines = []; | 60 var lines = []; |
135 | 61 |
136 function dumpValue(value, prefix, prefixWithName) | 62 function dumpValue(value, prefix, prefixWithName) { |
137 { | |
138 if (typeof value === "object" && value !== null) { | 63 if (typeof value === "object" && value !== null) { |
139 if (value instanceof Array) | 64 if (value instanceof Array) |
140 dumpItems(value, prefix, prefixWithName); | 65 dumpItems(value, prefix, prefixWithName); |
141 else | 66 else |
142 dumpProperties(value, prefix, prefixWithName); | 67 dumpProperties(value, prefix, prefixWithName); |
143 } else { | 68 } else { |
144 lines.push(prefixWithName + String(value).replace(/\n/g, " ")); | 69 lines.push(prefixWithName + String(value).replace(/\n/g, " ")); |
145 } | 70 } |
146 } | 71 } |
147 | 72 |
148 function dumpProperties(object, prefix, firstLinePrefix) | 73 function dumpProperties(object, prefix, firstLinePrefix) { |
149 { | |
150 prefix = prefix || ""; | 74 prefix = prefix || ""; |
151 firstLinePrefix = firstLinePrefix || prefix; | 75 firstLinePrefix = firstLinePrefix || prefix; |
152 lines.push(firstLinePrefix + "{"); | 76 lines.push(firstLinePrefix + "{"); |
153 | 77 |
154 var propertyNames = Object.keys(object); | 78 var propertyNames = Object.keys(object); |
155 propertyNames.sort(); | 79 propertyNames.sort(); |
156 for (var i = 0; i < propertyNames.length; ++i) { | 80 for (var i = 0; i < propertyNames.length; ++i) { |
157 var name = propertyNames[i]; | 81 var name = propertyNames[i]; |
158 if (!object.hasOwnProperty(name)) | 82 if (!object.hasOwnProperty(name)) |
159 continue; | 83 continue; |
160 var prefixWithName = " " + prefix + name + " : "; | 84 var prefixWithName = " " + prefix + name + " : "; |
161 dumpValue(object[name], " " + prefix, prefixWithName); | 85 dumpValue(object[name], " " + prefix, prefixWithName); |
162 } | 86 } |
163 lines.push(prefix + "}"); | 87 lines.push(prefix + "}"); |
164 } | 88 } |
165 | 89 |
166 function dumpItems(object, prefix, firstLinePrefix) | 90 function dumpItems(object, prefix, firstLinePrefix) { |
167 { | |
168 prefix = prefix || ""; | 91 prefix = prefix || ""; |
169 firstLinePrefix = firstLinePrefix || prefix; | 92 firstLinePrefix = firstLinePrefix || prefix; |
170 lines.push(firstLinePrefix + "["); | 93 lines.push(firstLinePrefix + "["); |
171 for (var i = 0; i < object.length; ++i) | 94 for (var i = 0; i < object.length; ++i) |
172 dumpValue(object[i], " " + prefix, " " + prefix + "[" + i + "] : "); | 95 dumpValue(object[i], " " + prefix, " " + prefix + "[" + i + "] : "); |
173 lines.push(prefix + "]"); | 96 lines.push(prefix + "]"); |
174 } | 97 } |
175 | 98 |
176 dumpValue(object, "", title || ""); | 99 dumpValue(object, "", title || ""); |
177 InspectorTest.log(lines.join("\n")); | 100 InspectorTest.log(lines.join("\n")); |
178 } | 101 } |
179 | 102 |
180 InspectorTest.logCallFrames = function(callFrames, session) | 103 InspectorTest.ContextGroup = class { |
181 { | 104 constructor() { |
182 session = session || InspectorTest.session; | 105 this.id = utils.createContextGroup(); |
183 for (var frame of callFrames) { | 106 } |
184 var functionName = frame.functionName || '(anonymous)'; | 107 |
185 var url = frame.url ? frame.url : session._scriptMap.get(frame.location.scri
ptId).url; | 108 schedulePauseOnNextStatement(reason, details) { |
186 var lineNumber = frame.location ? frame.location.lineNumber : frame.lineNumb
er; | 109 utils.schedulePauseOnNextStatement(this.id, reason, details); |
187 var columnNumber = frame.location ? frame.location.columnNumber : frame.colu
mnNumber; | 110 } |
188 InspectorTest.log(`${functionName} (${url}:${lineNumber}:${columnNumber})`); | 111 |
189 } | 112 cancelPauseOnNextStatement() { |
190 } | 113 utils.cancelPauseOnNextStatement(this.id); |
191 | 114 } |
192 InspectorTest.logSourceLocation = function(location, session) | 115 |
193 { | 116 addScript(string, lineOffset, columnOffset, url) { |
194 session = session || InspectorTest.session; | 117 utils.compileAndRunWithOrigin(this.id, string, url || '', lineOffset || 0, c
olumnOffset || 0, false); |
195 var scriptId = location.scriptId; | 118 } |
196 if (!session._scriptMap || !session._scriptMap.has(scriptId)) { | 119 |
197 InspectorTest.log("InspectorTest.setupScriptMap should be called before Prot
ocol.Debugger.enable."); | 120 addModule(string, url, lineOffset, columnOffset) { |
198 InspectorTest.completeTest(); | 121 utils.compileAndRunWithOrigin(this.id, string, url, lineOffset || 0, columnO
ffset || 0, true); |
199 } | 122 } |
200 var script = session._scriptMap.get(scriptId); | 123 |
201 if (!script.scriptSource) { | 124 loadScript(fileName) { |
202 return session.Protocol.Debugger.getScriptSource({ scriptId }) | 125 this.addScript(utils.read(fileName)); |
203 .then(message => script.scriptSource = message.result.scriptSource) | 126 } |
204 .then(dumpSourceWithLocation); | 127 |
205 } | 128 connect() { |
206 return Promise.resolve().then(dumpSourceWithLocation); | 129 return new InspectorTest.Session(this); |
207 | 130 } |
208 function dumpSourceWithLocation() { | 131 |
209 var lines = script.scriptSource.split('\n'); | 132 setupInjectedScriptEnvironment(debug) { |
210 var line = lines[location.lineNumber]; | 133 let scriptSource = ''; |
211 line = line.slice(0, location.columnNumber) + '#' + (line.slice(location.col
umnNumber) || ''); | 134 // First define all getters on Object.prototype. |
212 lines[location.lineNumber] = line; | 135 let injectedScriptSource = utils.read('src/inspector/injected-script-source.
js'); |
213 lines = lines.filter(line => line.indexOf('//# sourceURL=') === -1); | 136 let getterRegex = /\.[a-zA-Z0-9]+/g; |
214 InspectorTest.log(lines.slice(Math.max(location.lineNumber - 1, 0), location
.lineNumber + 2).join('\n')); | 137 let match; |
215 InspectorTest.log(''); | 138 let getters = new Set(); |
216 } | 139 while (match = getterRegex.exec(injectedScriptSource)) { |
217 } | 140 getters.add(match[0].substr(1)); |
218 | 141 } |
219 InspectorTest.logSourceLocations = function(locations, session) { | 142 scriptSource += `(function installSettersAndGetters() { |
220 if (locations.length == 0) return Promise.resolve(); | 143 let defineProperty = Object.defineProperty; |
221 return InspectorTest.logSourceLocation(locations[0], session) | 144 let ObjectPrototype = Object.prototype;\n`; |
222 .then(() => InspectorTest.logSourceLocations(locations.splice(1), session)
); | 145 scriptSource += Array.from(getters).map(getter => ` |
223 } | 146 defineProperty(ObjectPrototype, '${getter}', { |
224 | 147 set() { debugger; throw 42; }, get() { debugger; throw 42; }, |
225 InspectorTest.logAsyncStackTrace = function(asyncStackTrace, session) | 148 __proto__: null |
226 { | 149 }); |
227 session = InspectorTest.session || session; | 150 `).join('\n') + '})();'; |
228 while (asyncStackTrace) { | 151 this.addScript(scriptSource); |
229 if (asyncStackTrace.promiseCreationFrame) { | 152 |
230 var frame = asyncStackTrace.promiseCreationFrame; | 153 if (debug) { |
231 InspectorTest.log(`-- ${asyncStackTrace.description} (${frame.url | 154 InspectorTest.log('WARNING: setupInjectedScriptEnvironment with debug flag
for debugging only and should not be landed.'); |
232 }:${frame.lineNumber}:${frame.columnNumber})--`); | 155 InspectorTest.log('WARNING: run test with --expose-inspector-scripts flag
to get more details.'); |
233 } else { | 156 InspectorTest.log('WARNING: you can additionally comment rjsmin in xxd.py
to get unminified injected-script-source.js.'); |
234 InspectorTest.log(`-- ${asyncStackTrace.description} --`); | 157 var session = InspectorTest._sessions.next().vale; |
235 } | 158 session.setupScriptMap(); |
236 InspectorTest.logCallFrames(asyncStackTrace.callFrames, session); | 159 sesison.Protocol.Debugger.enable(); |
237 asyncStackTrace = asyncStackTrace.parent; | 160 session.Protocol.Debugger.onPaused(message => { |
238 } | 161 let callFrames = message.params.callFrames; |
239 } | 162 session.logSourceLocations(callFrames.map(frame => frame.location)); |
240 | 163 }) |
241 InspectorTest.completeTest = () => Protocol.Debugger.disable().then(() => utils.
quit()); | 164 } |
242 | 165 } |
243 InspectorTest.completeTestAfterPendingTimeouts = function() | 166 }; |
244 { | 167 |
245 InspectorTest.waitPendingTasks().then(InspectorTest.completeTest); | 168 InspectorTest.Session = class { |
246 } | 169 constructor(contextGroup) { |
247 | 170 this.contextGroup = contextGroup; |
248 InspectorTest.waitPendingTasks = function() | 171 this._dispatchTable = new Map(); |
249 { | 172 this._eventHandlers = new Map(); |
250 var promises = []; | 173 this._requestId = 0; |
251 for (var session of InspectorTest._sessions.values()) | 174 this.Protocol = this._setupProtocol(); |
252 promises.push(session.Protocol.Runtime.evaluate({ expression: "new Promise(r
=> setTimeout(r, 0))//# sourceURL=wait-pending-tasks.js", awaitPromise: true })
); | 175 InspectorTest._sessions.add(this); |
253 return Promise.all(promises); | 176 this.id = utils.connectSession(contextGroup.id, '', this._dispatchMessage.bi
nd(this)); |
254 } | 177 } |
255 | 178 |
256 InspectorTest.startDumpingProtocolMessages = function() | 179 disconnect() { |
257 { | 180 InspectorTest._sessions.delete(this); |
258 InspectorTest._dumpInspectorProtocolMessages = true; | 181 utils.disconnectSession(this.id); |
259 } | 182 } |
260 | 183 |
261 InspectorTest.checkExpectation = function(fail, name, messageObject) | 184 reconnect() { |
262 { | 185 var state = utils.disconnectSession(this.id); |
263 if (fail === !!messageObject.error) { | 186 this.id = utils.connectSession(this.contextGroup.id, state, this._dispatchMe
ssage.bind(this)); |
264 InspectorTest.log("PASS: " + name); | 187 } |
265 return true; | 188 |
266 } | 189 sendRawCommand(requestId, command, handler) { |
267 | 190 if (InspectorTest._dumpInspectorProtocolMessages) |
268 InspectorTest.log("FAIL: " + name + ": " + JSON.stringify(messageObject)); | 191 utils.print("frontend: " + command); |
269 InspectorTest.completeTest(); | 192 this._dispatchTable.set(requestId, handler); |
270 return false; | 193 utils.sendMessageToBackend(this.id, command); |
271 } | 194 } |
272 InspectorTest.expectedSuccess = InspectorTest.checkExpectation.bind(null, false)
; | 195 |
273 InspectorTest.expectedError = InspectorTest.checkExpectation.bind(null, true); | 196 setupScriptMap() { |
274 | 197 if (this._scriptMap) |
275 InspectorTest.setupScriptMap = function(session) { | 198 return; |
276 session = session || InspectorTest.session; | 199 this._scriptMap = new Map(); |
277 if (session._scriptMap) | 200 } |
278 return; | 201 |
279 session._scriptMap = new Map(); | 202 logCallFrames(callFrames) { |
280 } | 203 for (var frame of callFrames) { |
281 | 204 var functionName = frame.functionName || '(anonymous)'; |
282 InspectorTest.runTestSuite = function(testSuite) | 205 var url = frame.url ? frame.url : this._scriptMap.get(frame.location.scrip
tId).url; |
283 { | 206 var lineNumber = frame.location ? frame.location.lineNumber : frame.lineNu
mber; |
284 function nextTest() | 207 var columnNumber = frame.location ? frame.location.columnNumber : frame.co
lumnNumber; |
285 { | 208 InspectorTest.log(`${functionName} (${url}:${lineNumber}:${columnNumber})`
); |
| 209 } |
| 210 } |
| 211 |
| 212 logSourceLocation(location) { |
| 213 var scriptId = location.scriptId; |
| 214 if (!this._scriptMap || !this._scriptMap.has(scriptId)) { |
| 215 InspectorTest.log("setupScriptMap should be called before Protocol.Debugge
r.enable."); |
| 216 InspectorTest.completeTest(); |
| 217 } |
| 218 var script = this._scriptMap.get(scriptId); |
| 219 if (!script.scriptSource) { |
| 220 return this.Protocol.Debugger.getScriptSource({ scriptId }) |
| 221 .then(message => script.scriptSource = message.result.scriptSource) |
| 222 .then(dumpSourceWithLocation); |
| 223 } |
| 224 return Promise.resolve().then(dumpSourceWithLocation); |
| 225 |
| 226 function dumpSourceWithLocation() { |
| 227 var lines = script.scriptSource.split('\n'); |
| 228 var line = lines[location.lineNumber]; |
| 229 line = line.slice(0, location.columnNumber) + '#' + (line.slice(location.c
olumnNumber) || ''); |
| 230 lines[location.lineNumber] = line; |
| 231 lines = lines.filter(line => line.indexOf('//# sourceURL=') === -1); |
| 232 InspectorTest.log(lines.slice(Math.max(location.lineNumber - 1, 0), locati
on.lineNumber + 2).join('\n')); |
| 233 InspectorTest.log(''); |
| 234 } |
| 235 } |
| 236 |
| 237 logSourceLocations(locations) { |
| 238 if (locations.length == 0) return Promise.resolve(); |
| 239 return this.logSourceLocation(locations[0]).then(() => this.logSourceLocatio
ns(locations.splice(1))); |
| 240 } |
| 241 |
| 242 logAsyncStackTrace(asyncStackTrace) { |
| 243 while (asyncStackTrace) { |
| 244 if (asyncStackTrace.promiseCreationFrame) { |
| 245 var frame = asyncStackTrace.promiseCreationFrame; |
| 246 InspectorTest.log(`-- ${asyncStackTrace.description} (${frame.url}:${fra
me.lineNumber}:${frame.columnNumber})--`); |
| 247 } else { |
| 248 InspectorTest.log(`-- ${asyncStackTrace.description} --`); |
| 249 } |
| 250 this.logCallFrames(asyncStackTrace.callFrames); |
| 251 asyncStackTrace = asyncStackTrace.parent; |
| 252 } |
| 253 } |
| 254 |
| 255 _sendCommandPromise(method, params) { |
| 256 if (InspectorTest._commandsForLogging.has(method)) |
| 257 utils.print(method + ' called'); |
| 258 var requestId = ++this._requestId; |
| 259 var messageObject = { "id": requestId, "method": method, "params": params }; |
| 260 return new Promise(fulfill => this.sendRawCommand(requestId, JSON.stringify(
messageObject), fulfill)); |
| 261 } |
| 262 |
| 263 _setupProtocol() { |
| 264 return new Proxy({}, { get: (target, agentName, receiver) => new Proxy({}, { |
| 265 get: (target, methodName, receiver) => { |
| 266 const eventPattern = /^on(ce)?([A-Z][A-Za-z0-9]+)/; |
| 267 var match = eventPattern.exec(methodName); |
| 268 if (!match) |
| 269 return args => this._sendCommandPromise(`${agentName}.${methodName}`,
args || {}); |
| 270 var eventName = match[2]; |
| 271 eventName = eventName.charAt(0).toLowerCase() + eventName.slice(1); |
| 272 if (match[1]) |
| 273 return () => this._waitForEventPromise(`${agentName}.${eventName}`); |
| 274 return listener => this._eventHandlers.set(`${agentName}.${eventName}`,
listener); |
| 275 } |
| 276 })}); |
| 277 } |
| 278 |
| 279 _dispatchMessage(messageString) { |
| 280 var messageObject = JSON.parse(messageString); |
| 281 if (InspectorTest._dumpInspectorProtocolMessages) |
| 282 utils.print("backend: " + JSON.stringify(messageObject)); |
| 283 try { |
| 284 var messageId = messageObject["id"]; |
| 285 if (typeof messageId === "number") { |
| 286 var handler = this._dispatchTable.get(messageId); |
| 287 if (handler) { |
| 288 handler(messageObject); |
| 289 this._dispatchTable.delete(messageId); |
| 290 } |
| 291 } else { |
| 292 var eventName = messageObject["method"]; |
| 293 var eventHandler = this._eventHandlers.get(eventName); |
| 294 if (this._scriptMap && eventName === "Debugger.scriptParsed") |
| 295 this._scriptMap.set(messageObject.params.scriptId, JSON.parse(JSON.str
ingify(messageObject.params))); |
| 296 if (eventName === "Debugger.scriptParsed" && messageObject.params.url ==
= "wait-for-pending-tasks.js") |
| 297 return; |
| 298 if (eventHandler) |
| 299 eventHandler(messageObject); |
| 300 } |
| 301 } catch (e) { |
| 302 InspectorTest.log("Exception when dispatching message: " + e + "\n" + e.st
ack + "\n message = " + JSON.stringify(messageObject, null, 2)); |
| 303 InspectorTest.completeTest(); |
| 304 } |
| 305 }; |
| 306 |
| 307 _waitForEventPromise(eventName) { |
| 308 return new Promise(fulfill => { |
| 309 this._eventHandlers.set(eventName, result => { |
| 310 delete this._eventHandlers.delete(eventName); |
| 311 fulfill(result); |
| 312 }); |
| 313 }); |
| 314 } |
| 315 }; |
| 316 |
| 317 InspectorTest.runTestSuite = function(testSuite) { |
| 318 function nextTest() { |
286 if (!testSuite.length) { | 319 if (!testSuite.length) { |
287 InspectorTest.completeTest(); | 320 InspectorTest.completeTest(); |
288 return; | 321 return; |
289 } | 322 } |
290 var fun = testSuite.shift(); | 323 var fun = testSuite.shift(); |
291 InspectorTest.log("\nRunning test: " + fun.name); | 324 InspectorTest.log("\nRunning test: " + fun.name); |
292 fun(nextTest); | 325 fun(nextTest); |
293 } | 326 } |
294 nextTest(); | 327 nextTest(); |
295 } | 328 } |
296 | 329 |
297 InspectorTest.runAsyncTestSuite = async function(testSuite) { | 330 InspectorTest.runAsyncTestSuite = async function(testSuite) { |
298 for (var test of testSuite) { | 331 for (var test of testSuite) { |
299 InspectorTest.log("\nRunning test: " + test.name); | 332 InspectorTest.log("\nRunning test: " + test.name); |
300 try { | 333 try { |
301 await test(); | 334 await test(); |
302 } catch (e) { | 335 } catch (e) { |
303 utils.print(e.stack); | 336 utils.print(e.stack); |
304 } | 337 } |
305 } | 338 } |
306 InspectorTest.completeTest(); | 339 InspectorTest.completeTest(); |
307 } | 340 } |
308 | 341 |
309 InspectorTest._waitForEventPromise = function(session, eventName) | 342 InspectorTest.start = function(description) { |
310 { | 343 try { |
311 return new Promise(fulfill => session._eventHandler[eventName] = fullfillAndCl
earListener.bind(null, fulfill)); | 344 InspectorTest.log(description); |
312 | 345 var contextGroup = new InspectorTest.ContextGroup(); |
313 function fullfillAndClearListener(fulfill, result) | 346 var session = contextGroup.connect(); |
314 { | 347 return { session: session, contextGroup: contextGroup, Protocol: session.Pro
tocol }; |
315 delete session._eventHandler[eventName]; | 348 } catch (e) { |
316 fulfill(result); | 349 utils.print(e.stack); |
317 } | 350 } |
318 } | 351 } |
319 | |
320 InspectorTest.setupInjectedScriptEnvironment = function(debug, session) { | |
321 session = session || InspectorTest.session; | |
322 let scriptSource = ''; | |
323 // First define all getters on Object.prototype. | |
324 let injectedScriptSource = utils.read('src/inspector/injected-script-source.js
'); | |
325 let getterRegex = /\.[a-zA-Z0-9]+/g; | |
326 let match; | |
327 let getters = new Set(); | |
328 while (match = getterRegex.exec(injectedScriptSource)) { | |
329 getters.add(match[0].substr(1)); | |
330 } | |
331 scriptSource += `(function installSettersAndGetters() { | |
332 let defineProperty = Object.defineProperty; | |
333 let ObjectPrototype = Object.prototype;\n`; | |
334 scriptSource += Array.from(getters).map(getter => ` | |
335 defineProperty(ObjectPrototype, '${getter}', { | |
336 set() { debugger; throw 42; }, get() { debugger; throw 42; }, | |
337 __proto__: null | |
338 }); | |
339 `).join('\n') + '})();'; | |
340 session.contextGroup.addScript(scriptSource); | |
341 | |
342 if (debug) { | |
343 InspectorTest.log('WARNING: InspectorTest.setupInjectedScriptEnvironment wit
h debug flag for debugging only and should not be landed.'); | |
344 InspectorTest.log('WARNING: run test with --expose-inspector-scripts flag to
get more details.'); | |
345 InspectorTest.log('WARNING: you can additionally comment rjsmin in xxd.py to
get unminified injected-script-source.js.'); | |
346 InspectorTest.setupScriptMap(session); | |
347 sesison.Protocol.Debugger.enable(); | |
348 session.Protocol.Debugger.onPaused(message => { | |
349 let callFrames = message.params.callFrames; | |
350 InspectorTest.logSourceLocations(callFrames.map(frame => frame.location),
session); | |
351 }) | |
352 } | |
353 } | |
354 | |
355 try { | |
356 InspectorTest.contextGroup = InspectorTest.createContextGroup(); | |
357 InspectorTest.session = InspectorTest.createSession(InspectorTest.contextGroup
); | |
358 this.Protocol = InspectorTest.session.Protocol; | |
359 InspectorTest.addScript = InspectorTest.contextGroup.addScript.bind(InspectorT
est.contextGroup); | |
360 InspectorTest.addModule = InspectorTest.contextGroup.addModule.bind(InspectorT
est.contextGroup); | |
361 InspectorTest.loadScript = fileName => InspectorTest.addScript(utils.read(file
Name)); | |
362 } catch (e) { | |
363 utils.print(e.stack); | |
364 } | |
OLD | NEW |