高级脚本弹幕@CommentCoreLibrary

终于放假了有时间继续研发CommentCoreLibrary了。之前就有所研究高级弹幕的可行性,安全问题和兼容问题,经过一些思考终于在新的实验性平台上实现了代码弹幕的基本还原!(卧槽!)

一、安全性/沙箱

随便让一些代码在浏览器里运行是非常危险且可怕的。而代码弹幕却需要带给用户一个相对较大的活动空间,却又需要保持代码的安全性。所以沙箱(Sandboxing)设计成为了重要的第一关。有关JS沙箱,有那么两三种当时在考虑范围内。一个是通过JS实现一个 JS解释器,这样用户代码就在虚拟的解释器里面运行,而外部则可以开放一些指定的API 供其调用。然而经过一番实验发现现有的很多JS下的JS解释器速度非常慢,或者占用内存不少(比如有的用LLVM编译的,然后再用Emscripten运行的。会时不时带着浏览器崩溃。。。

于是就开始考虑第二种非常奇妙的沙箱策略:通过 HTML5 的 Web Worker(线程)实现。HTML5的Web Worker是一个允许Javascript开线程,并行计算的一个API,不过把它用于Sandbox实在是太棒了。因为Worker是独立线程,设计者为了避免各种赛跑问题选择了一个“通讯调用模式”的调度模式。这就使Worker里面的代码无法访问任何DOM或者浏览器内的信息,而它于网页通过发送 message (postMessage , onMessage)实现双向无状态交互。这就很有效的形成了一个干净的 JS 空间。

示意图在这种设计下,我们将会有一套API听取Worker传回的信息,和一套API在Worker里面载入用来模拟Bilibili播放器给出的 API。这样即使Worker里面的代码进行了恶意操作,也只能通过API与外部交流,所以有效的把破坏面积降低了很多(最多破坏就是产生死循环,而 Worker 可以被强制结束。)

二、兼容层

为了实现API兼容我们需要把绘制操作和建立操作分开。绘制操作,建立DOM元素需要由总控调度  bscripter (CCLScripting模块)进行,而产生元素产生绘制命令则需要Worker传达信息。所以我们建立了一些虚拟化的双向对应元素。即在总控和Worker里面各有一份某个元素,二者使用同一个ID。交流时,Worker需要调用某个方法的话,就会发送一个 API请求包含元素的ID,总控则会找出自己保存的那份对象,然后执行相应的方法。总控(DOM)产生的一些事件(Event)则会由总控传递回给相应的Worker,而Worker内部的Runtime解析出回调方法是哪一个,然后调用。

这样以来可以实现一个双向抽象化的兼容层。

三、SVG绘制/按钮回调

高级代码弹幕的一大重点就是回调事件和绘制弹幕。这两大块分别都在新的 bscripter里面实现了,两者都是通过单向发起请求另一方完成。SVG绘制是双方都建立SVG虚拟对象,Worker端调用绘图函数发出绘制请求,bscripter收到请求调用 SVG对象响应的方法实现DOM下绘制。而回调函数恰恰相反,首先Worker建立一个运行时回调“派送中心”,回调函数实际上都挂在派送中心而不是每个对象上。这时如果bscripter对应的对象上触发了回调事件,这个事件会被转运到Worker里面,然后运行时负责调度具体哪个回调函数运行。

综合上面各点,就实现了抽象化的B站高级代码弹幕兼容性API。剩下的就是具体填充API的各个部分,实现更高的还原度。

四、垃圾回收

Worker完成后我们需要回收并结束。判断Worker不在需要的方法比较弱,但是也有点逻辑。简单说就是每次总控删除一个视觉元素就会告诉 Worker,当所有的视觉元素都被删除,Worker就没有与外界通讯的条件了,也就可以回收掉了。不过这里还有一个问题就是定时器。所以我们不仅统计对象对应,还统计回调函数对应,删除一个对象会删掉所有其回调函数,那么如果我们令定时器也是一个回调函数的话,只有在定时器都跑完**且**对象都被删掉时才会没有任何的回调函数。所以只要保证没有对应对象,且回调函数也都被删干净了,Worker就能自行了断了。

有关B站代码弹幕测试可以到 http://jabbany.github.io/CommentCoreLibrary/experimental/scripting/ 自行玩玩,目前还只有最基础的SVG绘图能力和最基础的按钮回调(比如按钮的onclick点击之后产生新的按钮)

 

20 Comments

  1. 想用CommentCoreLibrary做个聊天室,文字弹幕能发送了,可图片弹幕因该如何配置?
    文档给了一个 配置项:Array[x,y,opacity,duration,url]
    url是对应图片的url吗?咱试了,没成功。
    求大牛指教。

    回复

    1. 图片因为目前没有de-facto API所以一直坑着没做呢(于是版本一直没到1.0)。不过你要是想自己试试的话,可以参考 CoreComment.ts ,创造一个类继承 CoreComment(参考滚动弹幕),然后在constructor里面设计一个传入图片URL的方法(或者,比如其它的图片信息),设计一下怎么构造DOM(基本都可以参考CoreComment自带的),然后在 CommentCoreLibrary.js 里面选一个mode号,加一个case,然后在这个case里面构造这个新的类,就可以了。空间规划什么的,默认的就会自动兼容新的弹幕种类。。。

      回复

  2. 好久不见,无意点进来一看JA你都更新了这么多东西了
    当时的html5播放器终于看到曙光了嘛
    话说有几个小问题,想找你麻花藤却发现你根本不在线呢…
    还在用webQQ为了安全吗

    回复

    1. 因为。。。。一直不用QQ所以一直不登录。。。平常也不用什么即时通讯软件(太麻烦╮(╯_╰)╭,尤其是时差,所以一般都用邮件)。前一阵(几天)还有人问Q号,因为登录实在太少我都不宣传有。总觉得腾讯不靠谱。

      弹幕播放器这东西都是慢慢来的,社区上现在也比较活跃,各种BUG都能逐步得到指正和修复。

      回复

      1. 弹幕是通过时间轴监听派发的,所以不用专门记录,因为时间轴监听本来也会读取Current time. 弹幕会在每一次收到监听信号的时候,派发所有期间的弹幕。

        回复

    1. 不要急嘛。。。播放器目前都是在各种测试阶段。。。WP插件也是。毕竟正式推出前要做很多测试尽量解决各种BUG。。。

      回复

        1. wwww嗯,一定加油的呢!CCL现在是唯一一个支持代码弹幕的HTML5库,真是爽。。。(而且现在API开发很灵活,可扩展性强,以后还未必局限于 Bili 的 API呢(现在就更多的是在实现各种“兼容”的包装层。。。可以说是虚拟了一套B站的代码弹幕API))

          回复

发表评论

电子邮件地址不会被公开。 必填项已用*标注