在 JavaScript 中使用 C 程序(2)

var buf = new UInt8Array(100); buf[0] = 123; // set alert(buf[0]); // get

然而 [] 操作符在 JS 里是无法重写的,因此难以将其变成 setter 和 getter。况且不支持 TypedArray 的都是低版本 IE,更不用考虑 ES6 的那些特征。

于是琢磨 IE 的私有接口。比如用 onpropertychange 事件来模拟 setter。不过这样做效率极低,而且 getter 仍不易实现。

经过一番考虑,决定不用钩子的方式,而是直接从源头上解决:修改语法!

我们用正则,找出源码中的赋值操作:

HEAP[index] = val;

替换成:

HEAP_SET(index, val);

类似的,将读取操作:

HEAP[index]

替换成:

HEAP_GET(index)

这样,原先的索引操作,就变成函数调用了。我们就能接管内存的读写,并且没有任何兼容性问题!

然后实现 8、16、32 位有无符号的读写。通过 JS 的 Array 来模拟,非常简单。

在 JavaScript 中使用 C 程序

麻烦的是模拟 Float32 和 Float64 两个类型。不过本次 C 程序中并未用到浮点,所以就暂不实现了。

到此,兼容性问题就解决了。

大功告成

解决了这些缺陷,我们就可以愉快的在 JS 中使用 C 逻辑了。

作为脚本,只关心采集哪些数据。这样 JS 代码就非常的优雅:

在 JavaScript 中使用 C 程序

数据的储存、加密、编码,这些底层数据操作,则通过 C 实现。

在 JavaScript 中使用 C 程序

编译时使用 -Os 优化体积。最终的 JS 混淆压缩之后,还不到 2 KB,十分小巧精炼。

在 JavaScript 中使用 C 程序

更完美的是,我们只需维护一份代码,即可同时编译出前端和后端的版本。

于是,这个「前后端 WAF」开发就容易多了。

在 JavaScript 中使用 C 程序

所有的编码/解码算法,都由 C 实现。然后分别编译成前端运行的 JS 代码,和后端 lua 模块,供 nginx-lua 使用。

测试版

事实上,还有第三个版本 —— 本地版,用来测试算法逻辑。

这样就无需启动 WebServer、打开浏览器来调试了。只需模拟一些数据,运行程序即可测试,非常轻量。

同时借助 IDE,调试起来更容易。

小结

每一门语言都有各自的优缺点。将不同语言的优势相互结合,可以程序变得更优雅、更完美。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/61049d6d4eccfce164f0603ee0f72c85.html