JavascriptCore是使用在ReactNative和iOS平台上的Javascript引擎。
目前 JavaScript 引擎还有 Google 的 V8 ,Mozilla 的 SpiderMonkey。
目前 浏览器都用 大部分用 WebKit 内核做自己的引擎。

WebKit引擎

现在使用WebKit的主要两个浏览器Sfari和Chromium(Chorme的开源项目)。WebKit起源于KDE的开源项目Konqueror的分支,由苹果公司用于Sfari浏览器。其一条分支发展成为Chorme的内核,2013年Google在此基础上开发了新的Blink内核。
webkit是sfari、chrome等浏览器的排版引擎,各部分架构图如下
跨平台实现基础(一)JsCore 原理和实践

当然Android是同个类的是JavascriptInterace.

iOS

JavascriptCore

业界流行的动态化方案,如Facebook的RN,阿里的Weex 都采用了前端系的DSL方案,而它们在iOS系统上能够顺利的运行,都离不开一个背后的功臣:JavaScriptCore(以下简称JSCore),它建立起了OC和JS 两门语言之间沟通的桥梁。无论是这些流行的动态化方案,还是WebView Hybrid方案,亦或是之前广泛流行的JSPatch,JSCore都在其中发挥了举足轻重的作用。作为一名iOS开发工程师,了解JSCore已经逐渐成为了必备技能之一。

JavaScriptCore是一个优化的VM。 JavaScriptCore由以下构建块组成:词法分析器,解析器,启动解释器(LLInt),基线JIT,低延迟优化JIT(DFG)和高并发优化JIT(FTL)。

Lexer:词法分析器,生成 tokens,大部分代码都在 parser/Lexer.cpp 里。

Parser:语法分析,基于 Lexer 的 tokens 生成语法树。手写了个 recusive descent parser 递归下降解析器,代码主要在 parser/Parser.cpp 里。

LLInt:Low Level Interpreter 执行 Parser 生成的 Byte code。代码在 llint/ 里,使用汇编,在 offlineasm/ 里,可以编译为 x86 和 ARMv7 的汇编和 C 代码。LLInt 希望达成除了词法和语法分析外零启动消耗,同时遵守用 JIT 在调用,堆栈和起存器的约定。

Baseline JIT:实时编译,性能不好用这个。在函数调用了 6 次,或者某段代码循环了大于100次会被触发。BaseLine JIT 的代码在 jit/ 里。BaseLine JIT 还对几乎所有堆的访问执行了复杂的多态内联高速缓存(Polymorphic inline caches)。多态内联缓存是 Smalltalk 社区优化动态分发的一个经典技术。

DFG JIT:低延迟优化 JIT,更差性能就用这个生成更优化的机器码来执行。在函数被调用了60次或者代码循环了1000次会触发。在 LLInt 和 Baseline JIT 中会收集一些包括最近参数,堆以及返回值中的数据等轻量级的性能信息,方便 DFG 进行类型判断。先获取类型信息可以减少大量的类型检查,推测失败 DFG 会取消优化,也叫 OSR exit。取消可以是同步的也可以是异步的。取消后会回到 Baseline JIT,退回一定次数会进行重新优化,收集更多统计信息,看情况再次调用 DFG。重新优化使用的是指数式回退策略应对一些怪异的代码。DFG 代码在 dfg/ 里。
FTL:高吞吐量优化 JIT,全称 Faster Than Light,DFG 高层优化配合 B3 底层优化。以前全称是 Fourth Tier LLVM 底层优化使用的是 LLVM。B3 对 LLVM 做了裁剪,对 JavaScriptCore 做了特性处理,B3 IR 的接口和 LLVM IR 很类似。B3 对 LLVM 的替换主要是考虑减少内存开销,LLVM 主要是针对编译器,编译器在这方面优化动力必然没有 JIT 需求高。B3 IR 将指针改成了更紧凑的整数来表示引用关系。不可变的常用的信息使用固定大小的结构来表示,其它的都放到另外的地方。紧凑的数据放到数组中,更多的数组更少的链表。这样形成的 IR 更省内存。Filip Pizlo 主导的这个改动,DFG JIT 也是他弄的,为了能够更多的减少内存上的开销,他利用在 DFG 里已经做的 InsertionSet 将 LLVM IR 里的 def-use 干掉了,大概思路是把单向链表里批量插入新 IR 节点先放到 InsertionSet 里,在下次遍历 IR 时再批量插入。Filip Pizlo 还把 DFG 里的 UpsilonValue 替代 LLVM SSA 组成部分。B3 后面会把 LLVM 的寄存器分配算法 Greedy 一直到 B3 中。

再来看看JsCore的核心类

JSContext 代表JS的执行环境,通过-evaluateScript:方法就可以执行JS代码

JSValue 封装了JS与OC中的对应的类型,以及调用JS的API等

JSExport 是一个协议,遵守此协议,就可以定义我们自己的协议,在协议中声明的API都会在JS中暴露出来,才能调用

跨平台实现基础(一)JsCore 原理和实践

在 Native 中开启多个线程来异步执行不同API ,也就意味着开发者可创建多个 JSVirtualMachine VM,同时相互隔离不影响,这样保证了并行地执行不同 JS 任务。

在一个 JSVirtualMachine 中还可以关联多个 JSContext,并通过 JSValue( 来和 Native 进行数据传递通信,同时可以通过 JSExport,将 Native 中遵守此解析的类的方法和属性转换为 JS 的接口供其调用。

好了知道JsCore核心后,我们看看怎么使用。

总体来说,JavaScriptCore的API是非常简单的,主要操作步骤如下:

1.get一个JSContext。

_jsContext = [_webView valueForKeyPath: @"documentView.webView.mainFrame.javaScriptContext"];
  1. 处理解释某个JS 调起的方法,比如log
  _jsContext[@"log"] = ^() { NSArray *args = [JSContext currentArguments]; for (id obj in args) { 
        //需要注意这里的obj都还是
        JSValue NSLog(@"%@",obj);
         } };

3.调用JS端执行某个JS方法

[_jsContext evaluateScript:@"log('arg1')"]; [_jsContext evaluateScript:@"logCallback('arg1')"];

4.重定义某个JS端的方法

[_jsContext evaluateScript:@"checkAPI = function(){\ return [\ 'selectImage',\ 'startRecord',\ 'login',\ ];\ }"];

ios 详细jsCore请移步:https://trac.webkit.org/wiki/JavaScriptCore

iOS与JS 交互的解决方案

比较著名的实现有基于jsCore的 JavascriptBridge。

https://github.com/marcuswestin/WebViewJavascriptBridge

当然我们自己也可以实现一个类似的框架

OC 里面执行 JS

比如我们算算我的年纪

JSContext *jsContext = [[JSContext alloc] init];
  [jsContext evaluateScript:@"var name = tamic"];
  [jsContext evaluateScript:@"var computeAge = function(value)
                             { if (name == tamic) return  29 }"];
  JSValue *value = [jsContext evaluateScript:@"computeAge(num)"];
  int  age = [value  toInt32];

JS调用OC

//Block block其实就等于android 的接口回调,可以将代码块做参数传进去,以”getTamicName"为名传递给JavaScript上下文

  JSContext *jsContext = [webView valueForKeyPath:
            @"documentView.webView.mainFrame.javaScriptContext"];
   jsContext[@"getTamicName"] = ^() {
       NSArray *args = [JSContext currentArguments];
       for (JSValue *obj in args) {
           NSLog(@"%@", obj);
       }
    };

写在最后

到此我们学习Jscore的原理和js和OC的通讯, 下篇,我们接着讲Android中 的 JavascriptInterace。

更多我的技术文章 关注开发者技术前线公众号。

相关文章:

  • 2022-01-04
  • 2021-11-27
  • 2021-11-20
  • 2021-10-26
  • 2021-11-27
  • 2022-01-09
  • 2021-08-07
猜你喜欢
  • 2021-10-16
  • 2021-11-27
  • 2021-08-19
  • 2021-11-27
  • 2021-11-27
  • 2021-10-01
相关资源
相似解决方案