| 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 |