From c805bba0c73e80b9d1083ed0b4a05eaabf264d88 Mon Sep 17 00:00:00 2001 From: Rainke Date: Wed, 12 Jul 2023 16:22:08 +0800 Subject: [PATCH 1/2] fix: keep `this` in parse expression function 1. Wrong work when function has `__self` 2. All `this` will replaced anyway --- packages/renderer-core/src/utils/common.ts | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/packages/renderer-core/src/utils/common.ts b/packages/renderer-core/src/utils/common.ts index 29381b547..262231eef 100644 --- a/packages/renderer-core/src/utils/common.ts +++ b/packages/renderer-core/src/utils/common.ts @@ -251,23 +251,21 @@ function parseExpression(a: any, b?: any, c = false) { thisRequired = c; } try { - const contextArr = ['"use strict";', 'var __self = arguments[0];']; - contextArr.push('return '); let tarStr: string; tarStr = (str.value || '').trim(); - // NOTE: use __self replace 'this' in the original function str - // may be wrong in extreme case which contains '__self' already - tarStr = tarStr.replace(/this(\W|$)/g, (_a: any, b: any) => `__self${b}`); - tarStr = contextArr.join('\n') + tarStr; + let code = `"use strict"; function __wrapper(){ return ${tarStr}} return __wrapper.call(arguments[0])`; // 默认调用顶层窗口的parseObj, 保障new Function的window对象是顶层的window对象 if (inSameDomain() && (window.parent as any).__newFunc) { - return (window.parent as any).__newFunc(tarStr)(self); + return (window.parent as any).__newFunc(code)(self); } - const code = `with(${thisRequired ? '{}' : '$scope || {}'}) { ${tarStr} }`; - return new Function('$scope', code)(self); + if (!thisRequired) { + code = `with($scope){${code}}`; + } + const result = new Function('$scope', code)(self); + return typeof result === "function" ? result.bind(self): result; } catch (err) { logger.error(`${logScope || ''} parseExpression.error`, err, str, self?.__self ?? self); return undefined; From fc947d2feb0411223430ab154398cfcd83c11dcb Mon Sep 17 00:00:00 2001 From: Rainke Date: Tue, 18 Jul 2023 10:37:46 +0800 Subject: [PATCH 2/2] fix: remove function bind If the returned function is bound to a context, there is no way to call it with `call` and `apply`. --- packages/renderer-core/src/utils/common.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/renderer-core/src/utils/common.ts b/packages/renderer-core/src/utils/common.ts index 262231eef..3439bf297 100644 --- a/packages/renderer-core/src/utils/common.ts +++ b/packages/renderer-core/src/utils/common.ts @@ -264,8 +264,7 @@ function parseExpression(a: any, b?: any, c = false) { if (!thisRequired) { code = `with($scope){${code}}`; } - const result = new Function('$scope', code)(self); - return typeof result === "function" ? result.bind(self): result; + return new Function('$scope', code)(self); } catch (err) { logger.error(`${logScope || ''} parseExpression.error`, err, str, self?.__self ?? self); return undefined;