如何检查一个函数是否是纯函数?

7

我正在开发react-metaform,其中一个挑战是我需要允许最终用户将元数据定义为函数。例如:

socialSecurityNumber.required: (m) => m.type == 'person'

问题很明显:我不能相信用户。因此,这些是我计划采取的预防措施:
  • 用户定义的函数应该是纯函数。也就是说,这些函数只能访问它们的参数,而不能访问其他任何东西。
  • 用户定义的函数将在一个对异常、执行时间过长和无限循环具有弹性的环境中运行。(目前我不担心这个问题。)
问题是:如何确保用户定义的函数只访问它的参数而不访问其他内容?

3
我认为最好的方法是定义自己的表达式语言,并在实际对象上进行解析和评估,而不是使用new Function - Bergi
2
https://dev59.com/i27Xa4cB1Zd3GeqPqX-K - epascarello
2
我认为从要求用户编写JS并执行它的那一刻起,你就已经做得差不多了。你无法防止长时间的执行(运行到完成,是的!),也无法确保函数是纯的(也许可以通过参数的大量遮蔽来实现,但那会很奇怪)。 - Kyll
我明白了。感谢大家的帮助。也许我应该定义自己的表达式语法,但那并不容易... =/ - Andre Pena
现在,您可以使用ES2015(V8已经支持许多必要的功能)将函数的环境锁定到相当大的程度,通过将其放置在严格模式下的自己的模块中,并使用this设置为undefined来调用它,从而防止其访问或创建全局变量。但是,您仍然会遇到无限循环问题,这只能通过子进程来解决。 - T.J. Crowder
显示剩余4条评论
2个回答

2
我会使用esprima来解析存储在文件或数据库中的用户JavaScript函数。我将允许仅运行通过解析测试的代码(仅限白名单功能-使用本地变量、参数等)。
您可以从一个非常简单的检查代码开始,只允许非常有限的脚本,并逐步改进它。然而,我猜您将会花费很多时间来完善解决方案,因为您的用户总是希望更多。
注意:Angular.js 使用这种“技巧”来进行依赖注入:https://jsfiddle.net/987Lwezy/
function test() {
   console.log("This is my secret!");
}


function parser(f) {
    document.body.innerHTML = test.toString();
}

parser(test);

1
哦,这怎么能防止像 function() { [].__proto__.slice = function() { return "I've screwed you app!"; }; } 这样的东西呢(它不使用自由变量)? - Bergi
OP说他想要只允许访问用户参数。对[].__proto__.slice的赋值不是对用户参数的赋值。 - MartyIX
基本上,你必须要么想出一组允许的 JavaScript 子集,要么选择另一个解决方案。使用“白名单解决方案”而不是“黑名单解决方案”绝对至关重要。我的意思是,你不能只是禁用 eval 并希望一切都好。你可以仅启用函数参数的基本算术运算……据我所知,在某些情况下这可能已经足够了。 - MartyIX
3
啊,我明白了,你只允许无副作用的表达式,因此属性访问和赋值(尤其是组合使用)将受到严格限制。有道理。 - Bergi
这种方法对我来说非常有意义 :) 你在2022年仍然会使用Esprisma吗?还是现在有更好的替代品? - pir

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接