Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP]: refactor: redesign bridge code base #1063

Open
wants to merge 150 commits into
base: main
Choose a base branch
from

Conversation

andycall
Copy link
Member

@andycall andycall commented Jan 6, 2022

对 bridge 的实现进行重新设计,用更好的方案解决一些固有的顽疾,并有效提升 bridge 的运行性能。

Bridge 目前存在的顽疾:

  1. 实现逻辑大量依赖 QuickJS API,完全手动管理内存很容易出问题。
  2. API 的实现依靠手写,大量重复性的体力活太多。
  3. 核心 DOM 实现逻辑目前依然采用 QuickJS 的数据结构,性能表现不佳。

基于以上问题,采用一些新的设计思路方案:

  1. 将代码库进行拆分,划分出 core 和 bindings 目录,core 负责内部逻辑的实现,bindings 负责和 QuickJS 相关的交互。
  2. 使用栈内存来管理引用计数,core 的实现逻辑均将 JSValue 分配在栈上。
  3. 采用代码生成器生成所有 API 的胶水代码。
  4. 初始化有关的数据一律静态化,比如 WrapperTypeInfo。对后面多引擎支持做准备。
  5. 重新设计并实现 DOM API
    1. EventTarget
    2. Node
    3. ContainerNode
    4. Element
    5. Document
    6. Attr
    7. CharacterData
    8. DocumentFragment
    9. Text
    10. NodeList
    11. CSSStyleDeclaration
    12. CustomElement
    13. CustomEvent
    14. DOM Selector
  6. 常用字符串静态化,在构建阶段预先分配存储。

Design Notes:

实现层与接口之间的分离

TS 类型与 C++ 类型之间的转换

依据 TS 类型的信息,生成对应调用 Converter 的代码。Converter 是一个 C++ Type Trains 类,负责将各种类型 JS 值转换为 C++ 值。

基本的类型映射关系:

JS C++
double TSDouble
int64 TSInt64
boolean TSBool
double? TSOptional<TSDouble>
double | null TSNullable<TSDouble>
double[] TSSequence<TSDouble>
type BlobPart = { name: string, value: double} TSBlobPart // 自定义类型需要独立实现转换器
any TSAny

生成器实现范例

template <>
struct Converter<TSDouble> : public ConverterBase<TSDouble> {
  static ImplType FromValue(JSContext* ctx, JSValue value) {
    assert(!JS_IsException(value));
    double v;
    JS_ToFloat64(ctx, &v, value);
    return v;
  }

  static JSValue ToValue(JSContext* ctx, double v) { return JS_NewFloat64(ctx, v); }
};

image

JS API 的装载过程

生成器生成的 API 代码需要通过装载才可以被注入到 JS 的全局环境中,供 JS 访问。

装载会在 Bridge 初始化到时候进行调用。

JS 环境中类构造函数

JS 环境大部分的 API 都是通过构造函数来创建,比如 EventTarget,Element,Node 这些都可以直接全部访问的变量。通过构造函数所创建的对象的原型都指向构造函数。

构造函数都是全局性的,即同一种类型的构造函数,在一个 JSContext 中只会存在一个。同时这些值都将存储在 ExecutionContextData 这样一个全局的对象中。

读取一个方法的过程

JS 采用原型链的方式实现继承,所以访问属性和方法会按照原型链来进行定位。

GC 回收的过程

在 bindings 目录有一个叫做 GarbageCollected 的类,所有继承它的类的内存管理均交给 JS 引擎的 GC 来承担,所以在 C++ 环境中不需要额外对这些类做内存回收操作。

GC 的回收分为两个阶段,

  1. Trace 阶段,负责追踪到哪些可能需要被回收的对象。
  2. Dispose 阶段,将需要被回收的对象进行释放,并调用 dispose 方法。

EventTarget

@andycall andycall changed the title refactor: remove XXXInstance and HostClass. [WIP]: refactor: remove XXXInstance and HostClass. Jan 6, 2022
@andycall andycall mentioned this pull request Jan 7, 2022
@andycall andycall force-pushed the refactor/remove_host_class branch from 22ff003 to 46dccea Compare May 17, 2022 09:15
feat: remove init window and init document dart methods.
@andycall andycall force-pushed the refactor/remove_host_class branch from 659212a to c0bca99 Compare May 17, 2022 12:52
@andycall andycall force-pushed the refactor/remove_host_class branch from 1090b29 to 65d6f89 Compare May 17, 2022 18:03
@andycall andycall force-pushed the refactor/remove_host_class branch from 027b27f to 6a145bd Compare May 18, 2022 00:44
@andycall andycall force-pushed the refactor/remove_host_class branch 2 times, most recently from acfa8b7 to 0652de3 Compare May 20, 2022 10:18
@andycall andycall force-pushed the refactor/remove_host_class branch from 2c8c0a1 to 05e59b9 Compare May 30, 2022 06:55
@yifei8
Copy link
Contributor

yifei8 commented Jun 11, 2022

这个pr还有问题吗?看起来做了很不错的修改,改动较大,原始团队评估能合入了么

@andycall
Copy link
Member Author

原始团队很难找到人 review 了,估计要组建新团队之后重新 review

yifei8
yifei8 previously approved these changes Jun 16, 2022
Copy link
Contributor

@yifei8 yifei8 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[ 53%] Building CXX object CMakeFiles/kraken.dir/core/dom/node_traversal.cc.o
[ 53%] Building CXX object CMakeFiles/kraken.dir/core/dom/character_data.cc.o
/Users/vivo/AndroidStudioProjects/kraken/bridge/core/dom/events/event.cc:13:64: error: cannot initialize a parameter of type 'kraken::NativeString ' with an lvalue of type
'int64_t' (aka 'long long')
AtomicString event_type = AtomicString::From(context->ctx(), native_event->type);
^~~~~~~~~~~~~~~~~~
/Users/vivo/AndroidStudioProjects/kraken/bridge/bindings/qjs/atomic_string.h:34:58: note: passing argument to parameter 'native_string' here
static AtomicString From(JSContext
ctx, NativeString* native_string);
^
/Users/vivo/AndroidStudioProjects/kraken/bridge/core/dom/events/event.cc:19:20: error: cannot cast from type 'int64_t' (aka 'long long') to pointer type
'kraken::EventTarget '
event->SetTarget(static_cast<EventTarget
>(native_event->target));
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Users/vivo/AndroidStudioProjects/kraken/bridge/core/dom/events/event.cc:20:27: error: cannot cast from type 'int64_t' (aka 'long long') to pointer type
'kraken::EventTarget '
event->SetCurrentTarget(static_cast<EventTarget
>(native_event->currentTarget));
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[ 55%] Building CXX object CMakeFiles/kraken.dir/core/dom/comment.cc.o

Copy link
Contributor

@yifei8 yifei8 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

另外:package.json 需要添加json5的依赖

@andycall andycall force-pushed the refactor/remove_host_class branch from c56d52e to 84068e4 Compare July 1, 2022 17:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants