Changeset 242606 in webkit
- Timestamp:
- Mar 7, 2019 12:40:14 PM (5 years ago)
- Location:
- trunk
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r242603 r242606 1 2019-03-07 Devin Rousso <drousso@apple.com> 2 3 Web Inspector: Protocol: add type checking when commands are called via invoke 4 https://bugs.webkit.org/show_bug.cgi?id=195310 5 <rdar://problem/48588679> 6 7 Reviewed by Joseph Pecoraro. 8 9 * inspector/protocol/inspector-backend-invocation-return-value.html: 10 * inspector/protocol/inspector-backend-invocation-return-value-expected.txt: 11 1 12 2019-03-07 John Wilander <wilander@apple.com> 2 13 -
trunk/LayoutTests/inspector/protocol/inspector-backend-invocation-return-value-expected.txt
r205402 r242606 3 3 4 4 == Running test suite: Protocol.BackendInvocationReturnValues 5 -- Running test case: ResolveCommandPromiseOnSuccess 5 -- Running test case: ResolveCommandPromiseOnSuccess.call 6 6 PASS: A backend command should return a Promise when invoked without a callback. 7 7 PASS: A successful command invocation's promise should be resolved. 8 8 9 -- Running test case: RejectCommandPromiseWithInvalidArguments 9 -- Running test case: ResolveCommandPromiseOnSuccess.invoke 10 PASS: A backend command should return a Promise when invoked without a callback. 11 PASS: A successful command invocation's promise should be resolved. 12 13 -- Running test case: RejectCommandPromiseWithInvalidArguments.call 10 14 ERROR: Protocol Error: Invalid type of argument 'expression' for command 'Runtime.evaluate' call. It must be 'string' but it is 'number'. 11 15 PASS: A backend command should return a Promise when invoked without a callback. 12 16 PASS: An invalid command invocation's promise should be rejected. 13 17 14 -- Running test case: RejectCommandPromiseWithMissingArguments 18 -- Running test case: RejectCommandPromiseWithInvalidArguments.invoke 19 ERROR: Protocol Error: Invalid type of argument 'expression' for command 'Runtime.evaluate' call. It must be 'string' but it is 'number'. 20 PASS: A backend command should return a Promise when invoked without a callback. 21 PASS: An invalid command invocation's promise should be rejected. 22 23 -- Running test case: RejectCommandPromiseWithMissingArguments.call 15 24 ERROR: Protocol Error: Invalid number of arguments for command 'Runtime.evaluate'. 16 25 PASS: A backend command should return a Promise when invoked without a callback. 17 26 PASS: An invalid command invocation's promise should be rejected. 18 27 19 -- Running test case: RejectCommandPromiseWithExtraArgumentThatIsNotCallback 28 -- Running test case: RejectCommandPromiseWithMissingArguments.invoke.MissingObject 29 ERROR: Protocol Error: invoke expects an object for command arguments but its type is 'undefined'. 30 PASS: A backend command should return a Promise when invoked without a callback. 31 PASS: An invalid command invocation's promise should be rejected. 32 33 -- Running test case: RejectCommandPromiseWithMissingArguments.invoke.NonObject 34 ERROR: Protocol Error: invoke expects an object for command arguments but its type is 'string'. 35 PASS: A backend command should return a Promise when invoked without a callback. 36 PASS: An invalid command invocation's promise should be rejected. 37 38 -- Running test case: RejectCommandPromiseWithMissingArguments.invoke.EmptyObject 39 ERROR: Protocol Error: Missing argument 'expression' for command 'Runtime.evaluate'. 40 PASS: A backend command should return a Promise when invoked without a callback. 41 PASS: An invalid command invocation's promise should be rejected. 42 43 -- Running test case: RejectCommandPromiseWithExtraArgumentThatIsNotCallback.call 20 44 ERROR: Protocol Error: Protocol Error: Optional callback argument for command 'Runtime.enable' call must be a function but its type is 'number'. 21 45 PASS: A backend command should return a Promise when invoked without a callback. 22 46 PASS: An invalid command invocation's promise should be rejected. 23 47 24 -- Running test case: ReturnNothingIfCallback 48 -- Running test case: ReturnNothingIfCallback.call 25 49 PASS: A backend command should not have a return value when invoked with a callback. 26 50 27 -- Running test case: InvokeCallbackWithResultOnSuccess 51 -- Running test case: ReturnNothingIfCallback.invoke 52 PASS: A backend command should not have a return value when invoked with a callback. 53 54 -- Running test case: InvokeCallbackWithResultOnSuccess.call 28 55 PASS: A backend command should not return anything when invoked with a callback. 29 56 PASS: A backend command should always invoke its callback asynchronously. … … 31 58 PASS: A successful command should invoke the callback with one or more result parameters. 32 59 33 -- Running test case: InvokeCallbackWithErrorForInvalidArguments 60 -- Running test case: InvokeCallbackWithResultOnSuccess.invoke 61 PASS: A backend command should not return anything when invoked with a callback. 62 PASS: A backend command should always invoke its callback asynchronously. 63 PASS: A successful command should invoke the callback with a 'null' first parameter. 64 PASS: A successful command should invoke the callback with one or more result parameters. 65 66 -- Running test case: InvokeCallbackWithErrorForInvalidArguments.call 34 67 ERROR: Protocol Error: Invalid type of argument 'expression' for command 'Runtime.evaluate' call. It must be 'string' but it is 'number'. 35 68 PASS: A backend command should not return anything when invoked with a callback. … … 38 71 PASS: A failed command should invoke the callback with only an error parameter. 39 72 40 -- Running test case: InvokeCallbackWithErrorForMissingArguments 73 -- Running test case: InvokeCallbackWithErrorForInvalidArguments.invoke 74 ERROR: Protocol Error: Invalid type of argument 'expression' for command 'Runtime.evaluate' call. It must be 'string' but it is 'number'. 75 PASS: A backend command should not return anything when invoked with a callback. 76 PASS: A backend command should always invoke its callback asynchronously. 77 PASS: A failed command should invoke the callback with a string error message as its first parameter. 78 PASS: A failed command should invoke the callback with only an error parameter. 79 80 -- Running test case: InvokeCallbackWithErrorForMissingArguments.call 41 81 ERROR: Protocol Error: Invalid number of arguments for command 'Runtime.evaluate'. 42 82 PASS: A backend command should not return anything when invoked with a callback. … … 45 85 PASS: A failed command should invoke the callback with only an error parameter. 46 86 87 -- Running test case: InvokeCallbackWithErrorForMissingArguments.invoke.MissingObject 88 ERROR: Protocol Error: invoke expects an object for command arguments but its type is 'undefined'. 89 PASS: A backend command should not return anything when invoked with a callback. 90 PASS: A backend command should always invoke its callback asynchronously. 91 PASS: A failed command should invoke the callback with a string error message as its first parameter. 92 PASS: A failed command should invoke the callback with only an error parameter. 93 94 -- Running test case: InvokeCallbackWithErrorForMissingArguments.invoke.NonObject 95 ERROR: Protocol Error: invoke expects an object for command arguments but its type is 'string'. 96 PASS: A backend command should not return anything when invoked with a callback. 97 PASS: A backend command should always invoke its callback asynchronously. 98 PASS: A failed command should invoke the callback with a string error message as its first parameter. 99 PASS: A failed command should invoke the callback with only an error parameter. 100 101 -- Running test case: InvokeCallbackWithErrorForMissingArguments.invoke.EmptyObject 102 ERROR: Protocol Error: Missing argument 'expression' for command 'Runtime.evaluate'. 103 PASS: A backend command should not return anything when invoked with a callback. 104 PASS: A backend command should always invoke its callback asynchronously. 105 PASS: A failed command should invoke the callback with a string error message as its first parameter. 106 PASS: A failed command should invoke the callback with only an error parameter. 107 -
trunk/LayoutTests/inspector/protocol/inspector-backend-invocation-return-value.html
r210062 r242606 1 <! doctypehtml>1 <!DOCTYPE html> 2 2 <html> 3 3 <head> … … 12 12 13 13 suite.addTestCase({ 14 name: "ResolveCommandPromiseOnSuccess ",14 name: "ResolveCommandPromiseOnSuccess.call", 15 15 description: "Backend command's returned promise should be resolved if the command is successful.", 16 16 test(resolve, reject) { … … 33 33 34 34 suite.addTestCase({ 35 name: "RejectCommandPromiseWithInvalidArguments", 35 name: "ResolveCommandPromiseOnSuccess.invoke", 36 description: "Backend command's returned promise should be resolved if the command is successful.", 37 test(resolve, reject) { 38 let returnValue = RuntimeAgent.evaluate.invoke({expression: "42"}); 39 40 InspectorTest.expectThat(returnValue instanceof Promise, "A backend command should return a Promise when invoked without a callback."); 41 // If a promise wasn't returned, we can't test the rest so just die. 42 if (!(returnValue instanceof Promise)) 43 reject(); 44 45 returnValue.then(function resolved(result) { 46 InspectorTest.log("PASS: A successful command invocation's promise should be resolved."); 47 resolve(); 48 }, function rejected(result) { 49 InspectorTest.log("FAIL: A successful command invocation's promise should be resolved."); 50 reject(); 51 }); 52 } 53 }); 54 55 suite.addTestCase({ 56 name: "RejectCommandPromiseWithInvalidArguments.call", 36 57 description: "Backend command's returned promise should be rejected if the command has invalid arguments.", 37 58 test(resolve, reject) { … … 54 75 55 76 suite.addTestCase({ 56 name: "RejectCommandPromiseWithMissingArguments", 77 name: "RejectCommandPromiseWithInvalidArguments.invoke", 78 description: "Backend command's returned promise should be rejected if the command has invalid arguments.", 79 test(resolve, reject) { 80 let result = RuntimeAgent.evaluate.invoke({expression: 42}); 81 82 InspectorTest.expectThat(result instanceof Promise, "A backend command should return a Promise when invoked without a callback."); 83 // If a promise wasn't returned, we can't test the rest so just die. 84 if (!(result instanceof Promise)) 85 reject(); 86 87 result.then(function resolved(result) { 88 InspectorTest.log("FAIL: An invalid command invocation's promise should be rejected."); 89 reject(); 90 }, function rejected(result) { 91 InspectorTest.log("PASS: An invalid command invocation's promise should be rejected."); 92 resolve(); 93 }); 94 } 95 }); 96 97 suite.addTestCase({ 98 name: "RejectCommandPromiseWithMissingArguments.call", 57 99 description: "Backend command's returned promise should be rejected if the command lacks required arguments.", 58 100 test(resolve, reject) { … … 75 117 76 118 suite.addTestCase({ 77 name: "RejectCommandPromiseWithExtraArgumentThatIsNotCallback", 119 name: "RejectCommandPromiseWithMissingArguments.invoke.MissingObject", 120 description: "Backend command's returned promise should be rejected if the command lacks required arguments.", 121 test(resolve, reject) { 122 let result = RuntimeAgent.evaluate.invoke(); 123 124 InspectorTest.expectThat(result instanceof Promise, "A backend command should return a Promise when invoked without a callback."); 125 // If a promise wasn't returned, we can't test the rest so just die. 126 if (!(result instanceof Promise)) 127 reject(); 128 129 result.then(function resolved(result) { 130 InspectorTest.log("FAIL: An invalid command invocation's promise should be rejected."); 131 reject(); 132 }, function rejected(result) { 133 InspectorTest.log("PASS: An invalid command invocation's promise should be rejected."); 134 resolve(); 135 }); 136 } 137 }); 138 139 suite.addTestCase({ 140 name: "RejectCommandPromiseWithMissingArguments.invoke.NonObject", 141 description: "Backend command's returned promise should be rejected if the command lacks required arguments.", 142 test(resolve, reject) { 143 let result = RuntimeAgent.evaluate.invoke("test"); 144 145 InspectorTest.expectThat(result instanceof Promise, "A backend command should return a Promise when invoked without a callback."); 146 // If a promise wasn't returned, we can't test the rest so just die. 147 if (!(result instanceof Promise)) 148 reject(); 149 150 result.then(function resolved(result) { 151 InspectorTest.log("FAIL: An invalid command invocation's promise should be rejected."); 152 reject(); 153 }, function rejected(result) { 154 InspectorTest.log("PASS: An invalid command invocation's promise should be rejected."); 155 resolve(); 156 }); 157 } 158 }); 159 160 suite.addTestCase({ 161 name: "RejectCommandPromiseWithMissingArguments.invoke.EmptyObject", 162 description: "Backend command's returned promise should be rejected if the command lacks required arguments.", 163 test(resolve, reject) { 164 let result = RuntimeAgent.evaluate.invoke({}); 165 166 InspectorTest.expectThat(result instanceof Promise, "A backend command should return a Promise when invoked without a callback."); 167 // If a promise wasn't returned, we can't test the rest so just die. 168 if (!(result instanceof Promise)) 169 reject(); 170 171 result.then(function resolved(result) { 172 InspectorTest.log("FAIL: An invalid command invocation's promise should be rejected."); 173 reject(); 174 }, function rejected(result) { 175 InspectorTest.log("PASS: An invalid command invocation's promise should be rejected."); 176 resolve(); 177 }); 178 } 179 }); 180 181 suite.addTestCase({ 182 name: "RejectCommandPromiseWithExtraArgumentThatIsNotCallback.call", 78 183 description: "Backend command's returned promise should be rejected if the command has an extra argument that is not a callback.", 79 184 test(resolve, reject) { … … 98 203 99 204 suite.addTestCase({ 100 name: "ReturnNothingIfCallback ",205 name: "ReturnNothingIfCallback.call", 101 206 description: "Backend commands should not return anything if a callback is supplied.", 102 207 test(resolve, reject) { … … 108 213 109 214 suite.addTestCase({ 110 name: "InvokeCallbackWithResultOnSuccess", 215 name: "ReturnNothingIfCallback.invoke", 216 description: "Backend commands should not return anything if a callback is supplied.", 217 test(resolve, reject) { 218 let returnValue = RuntimeAgent.evaluate.invoke({expression: "41"}, dummyCallback); 219 InspectorTest.expectThat(returnValue === undefined, "A backend command should not have a return value when invoked with a callback."); 220 resolve(); 221 } 222 }); 223 224 suite.addTestCase({ 225 name: "InvokeCallbackWithResultOnSuccess.call", 111 226 description: "Backend command callback should be invoked with a result if the command is successful.", 112 227 test(resolve, reject) { … … 125 240 126 241 suite.addTestCase({ 127 name: "InvokeCallbackWithErrorForInvalidArguments", 242 name: "InvokeCallbackWithResultOnSuccess.invoke", 243 description: "Backend command callback should be invoked with a result if the command is successful.", 244 test(resolve, reject) { 245 let initialState = 1; 246 let returnValue = RuntimeAgent.evaluate.invoke({expression: "42"}, function(error, result) { 247 InspectorTest.expectThat(error === null, "A successful command should invoke the callback with a 'null' first parameter."); 248 InspectorTest.expectThat(arguments.length > 1, "A successful command should invoke the callback with one or more result parameters."); 249 initialState++; 250 resolve(); 251 }); 252 253 InspectorTest.expectThat(returnValue === undefined, "A backend command should not return anything when invoked with a callback."); 254 InspectorTest.expectThat(initialState === 1, "A backend command should always invoke its callback asynchronously."); 255 } 256 }); 257 258 suite.addTestCase({ 259 name: "InvokeCallbackWithErrorForInvalidArguments.call", 128 260 description: "Backend command callback should be invoked with an error if the command has invalid arguments.", 129 261 test(resolve, reject) { … … 142 274 143 275 suite.addTestCase({ 144 name: "InvokeCallbackWithErrorForMissingArguments", 276 name: "InvokeCallbackWithErrorForInvalidArguments.invoke", 277 description: "Backend command callback should be invoked with an error if the command has invalid arguments.", 278 test(resolve, reject) { 279 let initialState = 1; 280 let returnValue = RuntimeAgent.evaluate.invoke({expression: 42}, function callback(error) { 281 InspectorTest.expectThat(typeof error === "string", "A failed command should invoke the callback with a string error message as its first parameter."); 282 InspectorTest.expectThat(arguments.length === 1, "A failed command should invoke the callback with only an error parameter."); 283 initialState++; 284 resolve(); 285 }); 286 287 InspectorTest.expectThat(returnValue === undefined, "A backend command should not return anything when invoked with a callback."); 288 InspectorTest.expectThat(initialState === 1, "A backend command should always invoke its callback asynchronously."); 289 } 290 }); 291 292 suite.addTestCase({ 293 name: "InvokeCallbackWithErrorForMissingArguments.call", 145 294 description: "Backend command callback should be invoked with an error if the command lacks required arguments.", 146 295 test(resolve, reject) { 147 296 let initialState = 1; 148 297 let returnValue = RuntimeAgent.evaluate(function callback(error) { 298 InspectorTest.expectThat(typeof error === "string", "A failed command should invoke the callback with a string error message as its first parameter."); 299 InspectorTest.expectThat(arguments.length === 1, "A failed command should invoke the callback with only an error parameter."); 300 301 initialState++; 302 resolve(); 303 }); 304 305 InspectorTest.expectThat(returnValue === undefined, "A backend command should not return anything when invoked with a callback."); 306 InspectorTest.expectThat(initialState === 1, "A backend command should always invoke its callback asynchronously."); 307 } 308 }); 309 310 suite.addTestCase({ 311 name: "InvokeCallbackWithErrorForMissingArguments.invoke.MissingObject", 312 description: "Backend command callback should be invoked with an error if the command lacks required arguments.", 313 test(resolve, reject) { 314 let initialState = 1; 315 let returnValue = RuntimeAgent.evaluate.invoke(undefined, function callback(error) { 316 InspectorTest.expectThat(typeof error === "string", "A failed command should invoke the callback with a string error message as its first parameter."); 317 InspectorTest.expectThat(arguments.length === 1, "A failed command should invoke the callback with only an error parameter."); 318 319 initialState++; 320 resolve(); 321 }); 322 323 InspectorTest.expectThat(returnValue === undefined, "A backend command should not return anything when invoked with a callback."); 324 InspectorTest.expectThat(initialState === 1, "A backend command should always invoke its callback asynchronously."); 325 } 326 }); 327 328 suite.addTestCase({ 329 name: "InvokeCallbackWithErrorForMissingArguments.invoke.NonObject", 330 description: "Backend command callback should be invoked with an error if the command lacks required arguments.", 331 test(resolve, reject) { 332 let initialState = 1; 333 let returnValue = RuntimeAgent.evaluate.invoke("test", function callback(error) { 334 InspectorTest.expectThat(typeof error === "string", "A failed command should invoke the callback with a string error message as its first parameter."); 335 InspectorTest.expectThat(arguments.length === 1, "A failed command should invoke the callback with only an error parameter."); 336 337 initialState++; 338 resolve(); 339 }); 340 341 InspectorTest.expectThat(returnValue === undefined, "A backend command should not return anything when invoked with a callback."); 342 InspectorTest.expectThat(initialState === 1, "A backend command should always invoke its callback asynchronously."); 343 } 344 }); 345 346 suite.addTestCase({ 347 name: "InvokeCallbackWithErrorForMissingArguments.invoke.EmptyObject", 348 description: "Backend command callback should be invoked with an error if the command lacks required arguments.", 349 test(resolve, reject) { 350 let initialState = 1; 351 let returnValue = RuntimeAgent.evaluate.invoke({}, function callback(error) { 149 352 InspectorTest.expectThat(typeof error === "string", "A failed command should invoke the callback with a string error message as its first parameter."); 150 353 InspectorTest.expectThat(arguments.length === 1, "A failed command should invoke the callback with only an error parameter."); -
trunk/Source/WebInspectorUI/ChangeLog
r242604 r242606 1 2019-03-07 Devin Rousso <drousso@apple.com> 2 3 Web Inspector: Protocol: add type checking when commands are called via invoke 4 https://bugs.webkit.org/show_bug.cgi?id=195310 5 <rdar://problem/48588679> 6 7 Reviewed by Joseph Pecoraro. 8 9 * UserInterface/Protocol/InspectorBackend.js: 10 (InspectorBackend.Command.prototype.invoke.deliverFailure): Added. 11 (InspectorBackend.Command.prototype.invoke): 12 (InspectorBackend.Command.prototype._invokeWithArguments): 13 1 14 2019-03-07 Devin Rousso <drousso@apple.com> 2 15 -
trunk/Source/WebInspectorUI/UserInterface/Protocol/InspectorBackend.js
r240318 r242606 407 407 "use strict"; 408 408 409 agent = agent || this._instance._agent;410 411 if (typeof callback === "function")412 agent._connection._sendCommandToBackendWithCallback(this._instance, commandArguments, callback);413 else414 return agent._connection._sendCommandToBackendExpectingPromise(this._instance, commandArguments);415 },416 417 supports(parameterName)418 {419 "use strict";420 421 return this._instance.callSignature.some((parameter) => parameter["name"] === parameterName);422 },423 424 // Private425 426 _invokeWithArguments(agent, commandArguments)427 {428 "use strict";429 430 409 let instance = this._instance; 431 let callback = typeof commandArguments.lastValue === "function" ? commandArguments.pop() : null;432 410 433 411 function deliverFailure(message) { … … 439 417 } 440 418 419 if (typeof commandArguments !== "object") 420 return deliverFailure(`invoke expects an object for command arguments but its type is '${typeof commandArguments}'.`); 421 441 422 let parameters = {}; 442 for (let parameter of instance.callSignature) { 443 let parameterName = parameter["name"]; 444 let typeName = parameter["type"]; 445 let optionalFlag = parameter["optional"]; 446 447 if (!commandArguments.length && !optionalFlag) 423 for (let {name, type, optional} of instance.callSignature) { 424 if (!(name in commandArguments) && !optional) 425 return deliverFailure(`Missing argument '${name}' for command '${instance.qualifiedName}'.`); 426 427 let value = commandArguments[name]; 428 if (optional && value === undefined) 429 continue; 430 431 if (typeof value !== type) 432 return deliverFailure(`Invalid type of argument '${name}' for command '${instance.qualifiedName}' call. It must be '${type}' but it is '${typeof value}'.`); 433 434 parameters[name] = value; 435 } 436 437 agent = agent || instance._agent; 438 if (typeof callback === "function") 439 agent._connection._sendCommandToBackendWithCallback(instance, parameters, callback); 440 else 441 return agent._connection._sendCommandToBackendExpectingPromise(instance, parameters); 442 }, 443 444 supports(parameterName) 445 { 446 "use strict"; 447 448 return this._instance.callSignature.some((parameter) => parameter["name"] === parameterName); 449 }, 450 451 // Private 452 453 _invokeWithArguments(agent, commandArguments) 454 { 455 "use strict"; 456 457 let instance = this._instance; 458 let callback = typeof commandArguments.lastValue === "function" ? commandArguments.pop() : null; 459 460 function deliverFailure(message) { 461 console.error(`Protocol Error: ${message}`); 462 if (callback) 463 setTimeout(callback.bind(null, message), 0); 464 else 465 return Promise.reject(new Error(message)); 466 } 467 468 let parameters = {}; 469 for (let {name, type, optional} of instance.callSignature) { 470 if (!commandArguments.length && !optional) 448 471 return deliverFailure(`Invalid number of arguments for command '${instance.qualifiedName}'.`); 449 472 450 473 let value = commandArguments.shift(); 451 if (optional Flag&& value === undefined)474 if (optional && value === undefined) 452 475 continue; 453 476 454 if (typeof value !== type Name)455 return deliverFailure(`Invalid type of argument '${ parameterName}' for command '${instance.qualifiedName}' call. It must be '${typeName}' but it is '${typeof value}'.`);456 457 parameters[ parameterName] = value;477 if (typeof value !== type) 478 return deliverFailure(`Invalid type of argument '${name}' for command '${instance.qualifiedName}' call. It must be '${type}' but it is '${typeof value}'.`); 479 480 parameters[name] = value; 458 481 } 459 482
Note: See TracChangeset
for help on using the changeset viewer.