Changeset 242606 in webkit


Ignore:
Timestamp:
Mar 7, 2019 12:40:14 PM (5 years ago)
Author:
Devin Rousso
Message:

Web Inspector: Protocol: add type checking when commands are called via invoke
https://bugs.webkit.org/show_bug.cgi?id=195310
<rdar://problem/48588679>

Reviewed by Joseph Pecoraro.

Source/WebInspectorUI:

  • UserInterface/Protocol/InspectorBackend.js:

(InspectorBackend.Command.prototype.invoke.deliverFailure): Added.
(InspectorBackend.Command.prototype.invoke):
(InspectorBackend.Command.prototype._invokeWithArguments):

LayoutTests:

  • inspector/protocol/inspector-backend-invocation-return-value.html:
  • inspector/protocol/inspector-backend-invocation-return-value-expected.txt:
Location:
trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r242603 r242606  
     12019-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
    1122019-03-07  John Wilander  <wilander@apple.com>
    213
  • trunk/LayoutTests/inspector/protocol/inspector-backend-invocation-return-value-expected.txt

    r205402 r242606  
    33
    44== Running test suite: Protocol.BackendInvocationReturnValues
    5 -- Running test case: ResolveCommandPromiseOnSuccess
     5-- Running test case: ResolveCommandPromiseOnSuccess.call
    66PASS: A backend command should return a Promise when invoked without a callback.
    77PASS: A successful command invocation's promise should be resolved.
    88
    9 -- Running test case: RejectCommandPromiseWithInvalidArguments
     9-- Running test case: ResolveCommandPromiseOnSuccess.invoke
     10PASS: A backend command should return a Promise when invoked without a callback.
     11PASS: A successful command invocation's promise should be resolved.
     12
     13-- Running test case: RejectCommandPromiseWithInvalidArguments.call
    1014ERROR: Protocol Error: Invalid type of argument 'expression' for command 'Runtime.evaluate' call. It must be 'string' but it is 'number'.
    1115PASS: A backend command should return a Promise when invoked without a callback.
    1216PASS: An invalid command invocation's promise should be rejected.
    1317
    14 -- Running test case: RejectCommandPromiseWithMissingArguments
     18-- Running test case: RejectCommandPromiseWithInvalidArguments.invoke
     19ERROR: Protocol Error: Invalid type of argument 'expression' for command 'Runtime.evaluate' call. It must be 'string' but it is 'number'.
     20PASS: A backend command should return a Promise when invoked without a callback.
     21PASS: An invalid command invocation's promise should be rejected.
     22
     23-- Running test case: RejectCommandPromiseWithMissingArguments.call
    1524ERROR: Protocol Error: Invalid number of arguments for command 'Runtime.evaluate'.
    1625PASS: A backend command should return a Promise when invoked without a callback.
    1726PASS: An invalid command invocation's promise should be rejected.
    1827
    19 -- Running test case: RejectCommandPromiseWithExtraArgumentThatIsNotCallback
     28-- Running test case: RejectCommandPromiseWithMissingArguments.invoke.MissingObject
     29ERROR: Protocol Error: invoke expects an object for command arguments but its type is 'undefined'.
     30PASS: A backend command should return a Promise when invoked without a callback.
     31PASS: An invalid command invocation's promise should be rejected.
     32
     33-- Running test case: RejectCommandPromiseWithMissingArguments.invoke.NonObject
     34ERROR: Protocol Error: invoke expects an object for command arguments but its type is 'string'.
     35PASS: A backend command should return a Promise when invoked without a callback.
     36PASS: An invalid command invocation's promise should be rejected.
     37
     38-- Running test case: RejectCommandPromiseWithMissingArguments.invoke.EmptyObject
     39ERROR: Protocol Error: Missing argument 'expression' for command 'Runtime.evaluate'.
     40PASS: A backend command should return a Promise when invoked without a callback.
     41PASS: An invalid command invocation's promise should be rejected.
     42
     43-- Running test case: RejectCommandPromiseWithExtraArgumentThatIsNotCallback.call
    2044ERROR: Protocol Error: Protocol Error: Optional callback argument for command 'Runtime.enable' call must be a function but its type is 'number'.
    2145PASS: A backend command should return a Promise when invoked without a callback.
    2246PASS: An invalid command invocation's promise should be rejected.
    2347
    24 -- Running test case: ReturnNothingIfCallback
     48-- Running test case: ReturnNothingIfCallback.call
    2549PASS: A backend command should not have a return value when invoked with a callback.
    2650
    27 -- Running test case: InvokeCallbackWithResultOnSuccess
     51-- Running test case: ReturnNothingIfCallback.invoke
     52PASS: A backend command should not have a return value when invoked with a callback.
     53
     54-- Running test case: InvokeCallbackWithResultOnSuccess.call
    2855PASS: A backend command should not return anything when invoked with a callback.
    2956PASS: A backend command should always invoke its callback asynchronously.
     
    3158PASS: A successful command should invoke the callback with one or more result parameters.
    3259
    33 -- Running test case: InvokeCallbackWithErrorForInvalidArguments
     60-- Running test case: InvokeCallbackWithResultOnSuccess.invoke
     61PASS: A backend command should not return anything when invoked with a callback.
     62PASS: A backend command should always invoke its callback asynchronously.
     63PASS: A successful command should invoke the callback with a 'null' first parameter.
     64PASS: A successful command should invoke the callback with one or more result parameters.
     65
     66-- Running test case: InvokeCallbackWithErrorForInvalidArguments.call
    3467ERROR: Protocol Error: Invalid type of argument 'expression' for command 'Runtime.evaluate' call. It must be 'string' but it is 'number'.
    3568PASS: A backend command should not return anything when invoked with a callback.
     
    3871PASS: A failed command should invoke the callback with only an error parameter.
    3972
    40 -- Running test case: InvokeCallbackWithErrorForMissingArguments
     73-- Running test case: InvokeCallbackWithErrorForInvalidArguments.invoke
     74ERROR: Protocol Error: Invalid type of argument 'expression' for command 'Runtime.evaluate' call. It must be 'string' but it is 'number'.
     75PASS: A backend command should not return anything when invoked with a callback.
     76PASS: A backend command should always invoke its callback asynchronously.
     77PASS: A failed command should invoke the callback with a string error message as its first parameter.
     78PASS: A failed command should invoke the callback with only an error parameter.
     79
     80-- Running test case: InvokeCallbackWithErrorForMissingArguments.call
    4181ERROR: Protocol Error: Invalid number of arguments for command 'Runtime.evaluate'.
    4282PASS: A backend command should not return anything when invoked with a callback.
     
    4585PASS: A failed command should invoke the callback with only an error parameter.
    4686
     87-- Running test case: InvokeCallbackWithErrorForMissingArguments.invoke.MissingObject
     88ERROR: Protocol Error: invoke expects an object for command arguments but its type is 'undefined'.
     89PASS: A backend command should not return anything when invoked with a callback.
     90PASS: A backend command should always invoke its callback asynchronously.
     91PASS: A failed command should invoke the callback with a string error message as its first parameter.
     92PASS: A failed command should invoke the callback with only an error parameter.
     93
     94-- Running test case: InvokeCallbackWithErrorForMissingArguments.invoke.NonObject
     95ERROR: Protocol Error: invoke expects an object for command arguments but its type is 'string'.
     96PASS: A backend command should not return anything when invoked with a callback.
     97PASS: A backend command should always invoke its callback asynchronously.
     98PASS: A failed command should invoke the callback with a string error message as its first parameter.
     99PASS: A failed command should invoke the callback with only an error parameter.
     100
     101-- Running test case: InvokeCallbackWithErrorForMissingArguments.invoke.EmptyObject
     102ERROR: Protocol Error: Missing argument 'expression' for command 'Runtime.evaluate'.
     103PASS: A backend command should not return anything when invoked with a callback.
     104PASS: A backend command should always invoke its callback asynchronously.
     105PASS: A failed command should invoke the callback with a string error message as its first parameter.
     106PASS: 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 <!doctype html>
     1<!DOCTYPE html>
    22<html>
    33<head>
     
    1212
    1313    suite.addTestCase({
    14         name: "ResolveCommandPromiseOnSuccess",
     14        name: "ResolveCommandPromiseOnSuccess.call",
    1515        description: "Backend command's returned promise should be resolved if the command is successful.",
    1616        test(resolve, reject) {
     
    3333
    3434    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",
    3657        description: "Backend command's returned promise should be rejected if the command has invalid arguments.",
    3758        test(resolve, reject) {
     
    5475
    5576    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",
    5799        description: "Backend command's returned promise should be rejected if the command lacks required arguments.",
    58100        test(resolve, reject) {
     
    75117
    76118    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",
    78183        description: "Backend command's returned promise should be rejected if the command has an extra argument that is not a callback.",
    79184        test(resolve, reject) {
     
    98203
    99204    suite.addTestCase({
    100         name: "ReturnNothingIfCallback",
     205        name: "ReturnNothingIfCallback.call",
    101206        description: "Backend commands should not return anything if a callback is supplied.",
    102207        test(resolve, reject) {
     
    108213
    109214    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",
    111226        description: "Backend command callback should be invoked with a result if the command is successful.",
    112227        test(resolve, reject) {
     
    125240
    126241    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",
    128260        description: "Backend command callback should be invoked with an error if the command has invalid arguments.",
    129261        test(resolve, reject) {
     
    142274
    143275    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",
    145294        description: "Backend command callback should be invoked with an error if the command lacks required arguments.",
    146295        test(resolve, reject) {
    147296            let initialState = 1;
    148297            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) {
    149352                InspectorTest.expectThat(typeof error === "string", "A failed command should invoke the callback with a string error message as its first parameter.");
    150353                InspectorTest.expectThat(arguments.length === 1, "A failed command should invoke the callback with only an error parameter.");
  • trunk/Source/WebInspectorUI/ChangeLog

    r242604 r242606  
     12019-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
    1142019-03-07  Devin Rousso  <drousso@apple.com>
    215
  • trunk/Source/WebInspectorUI/UserInterface/Protocol/InspectorBackend.js

    r240318 r242606  
    407407        "use strict";
    408408
    409         agent = agent || this._instance._agent;
    410 
    411         if (typeof callback === "function")
    412             agent._connection._sendCommandToBackendWithCallback(this._instance, commandArguments, callback);
    413         else
    414             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     // Private
    425 
    426     _invokeWithArguments(agent, commandArguments)
    427     {
    428         "use strict";
    429 
    430409        let instance = this._instance;
    431         let callback = typeof commandArguments.lastValue === "function" ? commandArguments.pop() : null;
    432410
    433411        function deliverFailure(message) {
     
    439417        }
    440418
     419        if (typeof commandArguments !== "object")
     420            return deliverFailure(`invoke expects an object for command arguments but its type is '${typeof commandArguments}'.`);
     421
    441422        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)
    448471                return deliverFailure(`Invalid number of arguments for command '${instance.qualifiedName}'.`);
    449472
    450473            let value = commandArguments.shift();
    451             if (optionalFlag && value === undefined)
     474            if (optional && value === undefined)
    452475                continue;
    453476
    454             if (typeof value !== typeName)
    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;
    458481        }
    459482
Note: See TracChangeset for help on using the changeset viewer.