文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Dart 中 JS 互操作的历史,你知道吗?

2024-11-30 00:17

关注

从 Dart 诞生之初,互操作性就是一个核心重点。2011 年 Dart 首次发布时,它被设计为可嵌入和多平台的。它可以运行在独立的虚拟机上,嵌入到浏览器中,并编译为 JavaScript。2015 年 Flutter 出现时,我们也准备将其嵌入其中。现在,我们也很高兴能将 WasmGC 运行时作为目标。

起初,我们很快就暴露了嵌入 Dart 的各个平台的功能。这就是我们的 SDK 平台特定库出现的方式:dart:io 暴露了虚拟机上的文件系统,dart:html 暴露了 Web 上的浏览器 API,等等。这些库在外观和感觉上都与普通的 Dart 库无异,但其背后却隐藏着一些复杂的底层本地原语,以使它们能正常工作。这是我们发明的第一种互操作形式。它具有很强的表现力,但仅限于 SDK 库。

在 Web 上,开发人员需要访问的不仅仅是浏览器 API。因此,我们开始研究如何开放互操作性,以覆盖更多目标。作为起点,我们在 2013 年推出了 dart:js,以实现对 JavaScript 库的访问。

// 用于说明 Dart/JS 互操作的简短 JavaScript 代码示例
window.myTopLevel = {
  field1: 0,
  method2() {
    return this.field1;
  }
}
// 通过“dart:js”访问(2013)
import 'dart:js' as js;

void main() {
  // 这一行有一个错字!哎呀 :(
  var object = js.context['myTopLevl'];
  object['field1'] = 1;
  // 此调用因 noSuchMethod 失败,因为 method2 返回一个 int,哎呀
  object.callMethod('method2', []).substr(1);
}

我们当时就知道,dart:js 并不是我们想要的编程模型。你必须使用字符串来访问 JavaScript 中的名称--别提在编译时发现问题了,也别提代码自动补全了!实现成本也很高。大多数操作都严重依赖盒和深度拷贝。因此,我们在 2014 年和 2015 年继续起草各种想法,直到 package:js 的 v0.6 版本发布。

// 通过 `package:js` 访问 (2015)
import 'package:js/js.dart';

// @JS 注解允许我们声明 API 签名:
@JS()
class MyObject {
  external int get field1;
  external void set field1(int value);
  external String method2();
}

@JS()
external MyObject get myTopLevel;

void main() {
  // 访问代码不容易出错:分析器可以检查
  // 这些符号与声明相匹配,而且我们还能获得代码补全! 
  var object = myTopLevel;
  object.field1 = 1;
  // 但是没有检查类型,这就在一个 int 上调用了子串,这是不正确的。
  object.method2().substring(1);
}

有了 package:js,我们终于有了高效、用户友好的开放式 API。你可以在抽象类上添加一些注解,然后就可以访问 JavaScript API 了。这一切就像魔法一样神奇,直到它失效。使用 package:js 有很多无法实现的功能:直接访问浏览器 API、重命名成员、转换、附加 Dart 逻辑等等。为了弥补这些不足,我们还提供了 dart:js_util--一个类似于 dart:js 的轻量级、高效的底层 API 作为备用。package:js 中的所有限制确实困扰着我们,但我们束手无策。我们需要更多的 Dart 语言来做得更好。

大约在那个时候,我们已经在致力于对语言进行有史以来最大的改变——我们让 Dart 听起来更有趣。讽刺的是,当我们在 2018 年发布带有 Dart 2.0 的新类型系统时,互操作性变得更糟!除了这些早期的限制之外,使 package:js 变得特别的魔法也有一个黑暗的一面——它无法检查类型的有效性。这意味着我们的互操作性是我们原本健全的语言中不健全的根源。

之后,我们的工作重心发生了变化,转而集中精力改进 Dart 和 JS-interop。我们遵循明确的原则(习惯化、表现力强、组合性强、精确、平易近人、务实、非神化和完整),转向以类型和静态分派为基础的设计,并对 Dart 语言提出了挑战。接下来的发展是并行的。

那一年,我们为 WasmGC 引入了编译功能,并利用 JS 互操作在其上运行 Flutter web 等丰富的框架。这引发了 JS Types 的工作,以在编程模型中明确定义 Dart 和 JS 的边界,并找到在 Wasm 和 JS 编译目标中使用 JS 的一致方法。我们还开始了扩展类型语言实验--这是 Dart 3.3 中推出的一项功能,它在 Dart 语言和 JS 互操作之间架起了一座桥梁。多年来,JS 互操作的行为(如类型擦除)与 Dart 中的任何其他行为都不匹配。有了扩展类型,JS 互操作终于可以习以为常,并在 Dart 开发工具中获得应有的支持。

尽管一路走来经历了许多转变和转折,但有一件事在整个十年中始终如一:我们的 Dart 社区的积极参与。社区成员采取了早期步骤测试并为 dart:js 做出贡献,然后影响 package:js 的设计。他们编写了工具来解决功能差距 (package:js_wrapping[1]),并尝试通过自动生成 Dart API 来提高生产力的方法 (package:js_facade_gen[2] 、 package:js_bindings[3] 、 package:typings[4])

最后,我们已经到了 2024 年了。我们在 Dart 3.3 中发布了 dart:js_interop 以及 package:web ,这是 Dart 中 JS 互操作的最新解决方案,使将 Flutter 编译为 Wasm 成为可能。

// 通过 `dart:js_interop` 访问 (2024)
import 'dart:js_interop';

// 声明使用扩展类型,这与 package:js
// 声明非常相似。主要区别在于:它们是静态调度的。
extension type MyObject._(JSObject _) implements JSObject {
  external int get field1;
  external void set field1(int value);
  external String method2();
}

@JS()
external MyObject get myTopLevel;

void main() {
  var object = myTopLevel;
  object.field1 = 1;
  // At last, access is sound - this line fails with a type error
  // when returning from method2.
  object.method2().substring(1);
}

今天,我们很高兴庆祝 Dart/JS 互操作的新形式及其所带来的未来。了解我们的过去,我们确信这不是旅程的终点,而是我们历史上令人兴奋的时刻。

我们迫不及待地想看看您将用它构建什么!

原文:https://medium.com/dartlang/history-of-js-interop-in-dart-98b06991158f

参考资料

[1]package:js_wrapping: https://github.com/a14n/dart-js-wrapping

[2]package:js_facade_gen: https://github.com/dart-archive/js_facade_gen

[3]package:js_bindings: https://pub.dev/packages/js_bindings

[4]package:typings: https://pub.dev/packages/typings

来源:独立开发者张张内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯