怎样平安的运转第三方javascript代码(上) | 申博官网
登录
  • 欢迎进入申博官网!
  • 如果您觉得申博官网对你有帮助,那么赶紧使用Ctrl+D 收藏申博官网并分享出去吧
  • 这里是申博官方网!
  • 申博官网是菲律宾sunbet官网品牌平台!
  • 申博开户专业品牌平台!

怎样平安的运转第三方javascript代码(上)

申博_新闻事件 申博 37次浏览 未收录 0个评论

近来,我们团队完成了Figma的插件API的开辟事变,如许第三方开辟职员便可以直接在基于浏览器的设想东西中运转代码了。这给第三方开辟职员带来方便的同时,也给我们带来了很多严重的应战,比方,怎样确保插件中运转的代码不会带来平安题目?

更头痛的是,我们的软件是建立在异常规的客栈之上的,因而面对很多东西所没有的束缚。我们的设想编辑器是建立在WebGL和WebAssembly的基本之上的,个中一些用户界面是运用Typescript&React来完成的。而且,我们的软件支撑多人同时编辑文件。在这个历程当中,浏览器手艺为我们供应了很大的支撑,同时,也带来了很多的限定。

这篇文章将带您相识我们对圆满插件解决方案的探究历程。终究,我们的题目可以归结为一点:怎样平安、稳固和高效地运转插件?以下是我们面对的主要束缚的扼要概述:

平安性:插件只需在显式启动时才接见文件。插件应当被限定在当前文件中。插件不能像figma.com那样举行挪用。插件不能接见对方的数据,除非是自愿供应的。插件不能改动Figma UI及其行为来误导用户(比方收集垂纶)。

稳固性:插件不能下降Figma的速率,使其没法运用。插件不能损坏我们产物中的症结不变量,比方让每一个人在检察同一个文件时老是看到雷同内容的属性。为了检察文件,不须要治理跨装备/用户的插件装置。对Figma产物或内部api的修正不会损坏现有的插件。

易于开辟:插件应当易于开辟,以支撑充满活力的生态体系。我们的大多数用户都是设想师,能够对JavaScript履历不多。开辟职员应当可以运用现有的调试东西。

机能:插件应当运转得足够快,以支撑大多数罕见的场景,比方搜刮文档、天生图表等等。

尝试#1:<inline-iframe>沙箱要领

在我们最初几周的研讨事变中,我们尝试了多种第三方代码沙箱,个中一些运用了诸如代码到代码之间的转换之类的手艺。然则,大多数沙箱都没有在临盆运用程序中经太长时候的历练,因而,运用这些沙箱肯定存在肯定的风险。

末了,作为我们的第一次尝试,我们运用了最接近范例沙箱解决方案的一种要领:<inline-iframe>标签。该要领适用于须要运转第三方代码的运用程序,如CodePen。

须要注重的是,这里的<inline-iframe>并非我们寻常运用的HTML标签。要明白<inline-iframe>要领为何可以供应平安性,就必需先来相识一下它供应了哪些特征。一般来讲,<inline-iframe>一般用于将一个网站嵌入到另一个网站中。比方,鄙人图中,您可以看到yelp.com网站中嵌入了google.com/maps,如许便可认为用户供应地图功用了。

怎样平安的运转第三方javascript代码(上)

在这里,我们固然不愿望因Yelp嵌入谷歌地图功用就可以读取Google网站内的内容,因为那边能够存有用户的私家信息。一样,您也不愿望谷歌因而而获得了接见Yelp网站内的内容的权限。

这意味着<inline-iframe>之间的通讯应当遭到浏览器的严厉限定。当<inline-iframe>的源不同于其容器的源(如yelp.com与google.com)时,它们应当是完整断绝的。同时,与<inline-iframe>举行通讯的唯一要领是经由过程音讯通报。现实上,这些音讯就是一些纯字符串。收到音讯后,每一个网站都即可以对这些音讯采纳响应的行为,也可以对它们置之度外。

事实上,它们是云云自力,以至于HTML范例许可浏览器将<inline-iframe>完成为零丁的历程,只需他们喜好的话。

既然相识了<inline-iframe>的事变道理,我们便可以经由过程在每次插件运转时建立一个新的<inline-iframe>,并将插件的代码粘贴在<inline-iframe>中来完成插件,如许,插件可以在<inline-iframe>中做任何想做的事变了。然则,除非音讯经由过程了显式的白名单检测,不然,它没法与Figma文档举行交互。<inline-iframe>也是一种特别的null源,这意味着向figma.com发送请求的尝试都会被浏览器的跨源资源同享战略所谢绝。

怎样平安的运转第三方javascript代码(上)

现实上,<inline-iframe>在这里充当了插件的沙箱的角色,而浏览器供应商则为我们供应了沙箱的平安保证,毕竟他们多年来一直在忙着搜刮和修复沙箱中的种种破绽。

运用这个沙箱模子的现实插件将运用我们添加到沙箱中的一个运用程序接口,详细以下所示:

const scene = await figma.loadScene() // gets data from the main thread
scene.selection[0].width *= 2
scene.createNode({
  type: 'RECTANGLE',
  x: 10, y: 20,
  ...
})
await figma.updateScene() // flush changes back, to the main thread

这里的重点在于,插件是经由过程挪用loadScene(它向Figma发送音讯以猎取文档的副本)来举行初始化,并经由过程挪用updateScene(将插件而至修正发送回Figma)作为其完毕的。请注重:

我们是经由过程猎取文档的副本,而不是运用音讯通报来完成属性的读取和写入操纵的。通报音讯时,每次往复需耗时0.1ms,如许的话,每秒只能通报1000条摆布的音讯。

我们不会让插件直接运用postMessage,因为如许做很贫苦。

自剑桥剖析丑闻以来,Facebook遭受的又一严峻数据走漏事宜

今年是Facebook成立15周年,现在它的月度用户量已经达到23.2亿,什么概念呢?相当于全球46.7%的互联网用户每月都在使用Facebook的应用程序,或者占全球总人口23%的人在使用它,足以显示它在全球的受欢迎程度。 这意味着Facebook拥有海量数据,而且增长很快,单机数据库完全无法满足这种需求。因此, Facebook的数据库服务器有成千上万台。目前可知,这些数据被用于各种分析,而这势必会带来安全隐患。 根据今天国外媒体的爆料,一个存储了数以亿条与Facebook帐户关联的电话号码数据库

决议采纳这类要领后,我们约莫用了一个月的时候构建好了响应的API。当时来看,立时就功德圆满了,我们以至邀请了一些alpha测试职员。然则,我们很快就发明,这类要领存在两大缺点。

题目1:async/await症结字对用户来讲不够友爱

我们获得的第一反应是,人们憎恶运用async/await症结字——然则在这类要领中,这是不可避免的。音讯通报本质上就是异步操纵,而在JavaScript中是没有办法对异步操纵举行同步壅塞式的挪用的。关于这类要领来讲,我们不仅须要运用await症结字,同时还须要将一切挪用函数标签为async。综上所述,异步/守候仍然是一个比较新鲜的JavaScript功用,要想玩转它,须要对并发性观点有相称深切的明白——很明显,这关于我们的插件开辟职员来讲,请求过于高了。

不过,假如只须要在插件开首和结尾处各运用一次await和await症结字的话,状况就没有那末糟糕了。我们只须要示知开辟职员始终将await、loadScene和updateScene搭配运用即可,纵然他们不太相识它们的作用的话也影响不大。

题目是某些API挪用须要运转很多庞杂的逻辑。比方,偶然变动某图层上的单个属性后,必需同时更新其他多个图层。比方,调解frame的大小后,须要递归地将束缚运用于其子frame。

这些行为一般触及很多行为庞杂且差异纤细的算法。假如因插件而从新完成这些算法的话,肯定不是一个好主意。另外,这些逻辑还会被编译到WebAssembly二进制文件中,因而,重用起来并不轻易。假如我们不在插件沙箱中运转这些逻辑的话,插件将会读取过期的数据。

所以,只管这类要领具有肯定的可行性,然则照样比较贫苦。比方:

await figma.loadScene()
... do stuff ...
await figma.updateScene()

纵然是履历丰富的工程师,事变也很快变得异常辣手:

await figma.loadScene()
... do stuff ...
await figma.updateScene()
await figma.loadScene()
... do stuff ...
await figma.updateScene()
await figma.loadScene()
... do stuff ...
await figma.updateScene()

题目2:复制操纵的开支过大

<inline-iframe>要领的第二个题目是,在将文档的大部分内容发送到插件之前,须要先对其举行序列化。

事实证明,人们偶然会在Figma软件中建立异常异常大的文档,以至抵达内存的上限。比方,关于微软的设想体系文件(客岁我们花了一个月时候对其举行优化)来讲,将文档序列化并将其发送给插件就须要消费14秒时候——这些照样发生在插件运转之前。鉴于大多数插件都触及疾速的操纵,比方“交流选中的两个对象”,这将使插件的可用性取消。

以增量体式格局加载数据或延后加载数据也不是一个好的挑选,因为:

1.要想重构中心产物,最少须要花上几个月的时候。

2.一切须要守候还没有抵达的数据的API,都是异步的。

总之,因为Figma文档能够包括大批相互依赖的数据,所以<inline-iframe>对我们来讲是不可取的。

主线程要领

因为排除了<inline-iframe>要领,我们不得不另觅他途。今后的两个星期中,我们又尝试了多种要领,然则或多或少存在某些不可接收的缺点:

API难以运用(比方,须要运用REST API或相似GraphQL的要领接见文档)

须要借助于浏览器供应商已摒弃或正盘算摒弃的浏览器功用(比方,同步xhr请求+Service Worker、同享缓冲区)

须要大批的研讨事变或从新构建我们的运用程序,这能够须要消费几个月的时候来考证其可行与否(比方,经由过程CRDT,运用iframe+sync体式格局加载Figma的副本等)

终究,我们终究得出结论:必需找到一种要领来建立一个模子,个中插件可以直接操纵文档。如许,编写插件在肯定程度上就是完成手动操纵的自动化,为此,我们必需许可插件在主线程上运转。

(未完待续)

本文翻译自:https://www.figma.com/blog/how-we-built-the-figma-plugin-system/


申博|网络安全巴士站声明:该文看法仅代表作者自己,与本平台无关。版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明怎样平安的运转第三方javascript代码(上)
喜欢 (0)
[]
分享 (0)
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址