Skip to content

Commit

Permalink
Fixed method call not considering callee optional (#2985)
Browse files Browse the repository at this point in the history
* fix: optional method call fixed

* fix: method call with optional owner

* refactor: code refactored

* add: new test cases added

* refactor: changed the name of the call method

* fix: tests updated

* fix: method call and tests refactored

* fix: test fixed

* add: new testcase added
  • Loading branch information
Bayheck authored Dec 18, 2023
1 parent df9c497 commit ce25a67
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 8 deletions.
4 changes: 2 additions & 2 deletions src/client/sandbox/code-instrumentation/methods.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,9 @@ export default class MethodCallInstrumentation extends SandboxBase {
// NOTE: In Google Chrome, iframes whose src contains html code raise the 'load' event twice.
// So, we need to define code instrumentation functions as 'configurable' so that they can be redefined.
nativeMethods.objectDefineProperty(window, INSTRUCTION.callMethod, {
value: (owner: any, methName: any, args: any[], optional = false) => {
value: (owner: any, methName: any, args: any[], optional = false, calleeOptional = false) => {
if (isNullOrUndefined(owner)) {
if (optional)
if (optional || calleeOptional)
return void 0;

MethodCallInstrumentation._error(`Cannot call method '${methName}' of ${inaccessibleTypeToStr(owner)}`);
Expand Down
7 changes: 5 additions & 2 deletions src/processing/script/node-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,14 +163,17 @@ export function createPropertySetWrapper (propertyName: string, obj: Expression,
return createSimpleCallExpression(setPropertyIdentifier, [obj, createSimpleLiteral(propertyName), value]);
}

export function createMethodCallWrapper (owner: Expression, method: Literal, methodArgs: (Expression | SpreadElement)[], optional = false): CallExpression {
export function createMethodCallWrapper (owner: Expression, method: Literal, methodArgs: (Expression | SpreadElement)[], optional = false, calleeOptional = false): CallExpression {
const callMethodIdentifier = createIdentifier(INSTRUCTION.callMethod);
const methodArgsArray = createArrayExpression(methodArgs);
const args = [owner, method, methodArgsArray];

if (optional)
if (optional || calleeOptional)
args.push(createSimpleLiteral(optional));

if (calleeOptional)
args.push(createSimpleLiteral(calleeOptional));

return createSimpleCallExpression(callMethodIdentifier, args);
}

Expand Down
9 changes: 5 additions & 4 deletions src/processing/script/transformers/method-call.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,14 @@ const transformer: Transformer<CallExpression> = {
},

run: node => {
const callee = node.callee as MemberExpression;
const method = callee.computed
const callee = node.callee as MemberExpression;
const method = callee.computed
? callee.property as Literal
: createSimpleLiteral((callee.property as Identifier).name); // eslint-disable-line no-extra-parens
const optional = (node as SimpleCallExpression).optional;
const optional = (node as SimpleCallExpression).optional;
const calleeOptional = callee.optional;

return createMethodCallWrapper(callee.object as Expression, method, node.arguments, optional);
return createMethodCallWrapper(callee.object as Expression, method, node.arguments, optional, calleeOptional);
},
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,7 @@ test('optional chaining', function () {
];

var additionalCases = [];
var errorCases = [];

// NOTE: Safari until iOS 13.4 don't have full support optional chaining
if (!browserUtils.isIOS || browserUtils.compareVersions([browserUtils.webkitVersion, '608.2.11']) === 1) {
Expand All @@ -296,6 +297,25 @@ test('optional chaining', function () {
src: 'var obj = { href: "123" }; var name = "name"; window.optionChainingResult = obj?.link?.[name]?.();',
expected: void 0,
},
{
src: 'var obj = { link: null }; var name = "name"; window.optionChainingResult = obj.link?.[name]();',
expected: void 0,
},
{
src: 'var obj = {}; var name = "name"; window.optionChainingResult = obj[name]?.();',
expected: void 0,
},
];

errorCases = [
{
src: 'var obj = { name: "123" }; var name = "name"; window.optionChainingResult = obj?.[name]();',
expected: '\'name\' is not a function',
},
{
src: 'var obj = { link: {name: "123"} }; var name = "name"; window.optionChainingResult = obj.link?.[name]();',
expected: '\'name\' is not a function',
},
];

for (let i = 0; i < additionalCases.length; i++)
Expand All @@ -313,4 +333,22 @@ test('optional chaining', function () {
delete window.optionChainingResult;
delete window.obj;
}

for (var i = 0; i < errorCases.length; i++) {
var testCase = errorCases[i];
var script = processScript(testCase.src);
var errorMessage = '';

try {
eval(script);
}
catch (e) {
errorMessage = e.message;
}

strictEqual(errorMessage, testCase.expected);

delete window.optionChainingResult;
delete window.obj;
}
});

0 comments on commit ce25a67

Please sign in to comment.