Dart 中 JS 互操作的历史

Gemini 生成的 AI 图像

由于在 Dart 3.3 中达到了令人兴奋的 JavaScript 互操作里程碑,Wasm 的支持刚刚登陆当前的 Flutter 测试版。为了庆祝这一里程碑,我们回顾了 Dart 和 JavaScript 互操作性长达十年的历程。

从 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 签名:
()
class MyObject {external int get field1;external void set field1(int value);external String method2();
}()
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 语言提出了挑战。接下来的发展是并行的。

  • 2019 年,Dart 2.7 添加了静态扩展方法。您可以将自定义 Dart 逻辑附加到 JS 互操作类并转换值,例如将 JS Promise 转换为 Dart Future ,而无需使用包装器。

  • 2021 年,我们发布了 @staticInteroppackage:js v0.6.4。最后,JS 互操作具有足够的表现力 - 您可以公开以前由 dart:html 等 SDK 库专门管理的浏览器 API。

  • 2023 年,当我们在 Dart 3.0 中放弃了不健全的空安全性时,我们终于看到了我们所取得的进步,我们的设计和 @staticInterop 的工作清楚地表明,我们已经准备好解决长期存在的健全性差距。

那一年,我们为 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),并尝试通过自动生成 Dart API 来提高生产力的方法 (package:js_facade_gen 、 package:js_bindings 、 package:typings)

最后,我们已经到了 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();
}()
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_interop 是一种静态、健全、惯用、富有表现力且一致的互操作形式,基于能够公开任何 JavaScript 或浏览器 API 的扩展类型。
  • package:web 使用 dart:js_interop 完成 13 年前 dart:html 曾经做过的事情,但是 JavaScript 和 WasmGC 都支持这种方式。

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

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


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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/811017.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

golangci-lint 报错

File is not gci-ed with --skip-generated -s standard,default (gci) golangci-lint 报错上面的错解决办法: 1. 文件换行需要换成"LF" 而不是"CRLF" ---->>> 我用的goland IDE,随便在这个文件删除一个空行&#xff…

20240412,引用,函数高级

老子什么时候能找到一个很爱我还和我一样喜欢看日出日落的对象 一&#xff0c;引用 给变量起别名&#xff0c;数据类型 & 别名原名&#xff1b;引用一定要初始化&#xff0c;初始化之后不能更改 #include <iostream> using namespace std; int main() {int a 10;i…

导入导出之使用EasyExcel快速进行表格导出

使用 EasyExcel 快速进行表格导入导出操作 在日常工作中&#xff0c;表格的导入和导出是常见的需求。针对这种情况&#xff0c;EasyExcel 提供了便捷的解决方案&#xff0c;可以快速地实现 Excel 表格的导入和导出操作。本文将介绍如何使用 EasyExcel 进行表格导出&#xff0c…

Linux权限的讲解

目录 1、用户的分级 2、用户的身份 3、文件的权限属性 3.1 文件类型 4、chmod 4.1 用八进制形式更改权限 5、chown与chgrp 6、umask 结语 前言&#xff1a; 在Linux下虽然一切都是文件&#xff0c;但是由于文件的权限不一样&#xff0c;导致访问或更改文件存在局限性…

Web App 入门指南:构建预测模型 App 的利器(shiny)

Web App 入门指南&#xff1a;构建预测模型 App 的利器 简介 近年来&#xff0c;随着机器学习和人工智能技术的快速发展&#xff0c;预测模型在各行各业得到了广泛应用。为了方便地部署和使用预测模型&#xff0c;将模型构建成 Web App 是一种非常好的选择。Web App 无需下载…

Bitmap OOM

老机器Bitmap预读仍然OOM&#xff0c;无奈增加一段&#xff0c;终于不崩溃了。 if (Build.VERSION.SDK_INT < 21)size 2; 完整代码&#xff1a; Bitmap bitmap; try {//Log.e(Thread.currentThread().getStackTrace()[2] "", surl);URL url new URL(surl);…

python|map

# 定义一个平方函数 def square(x): return x ** 2 # 创建一个数字列表 numbers [1, 2, 3, 4, 5] # 使用 map 函数将平方函数应用于列表中的每个元素 squares map(square, numbers) #将numbers绑定上一个函数 print(type(square)) print(square)# 将结果转换为列表…

【CSS】背景模糊,不模糊主体文字

问题 背景模糊&#xff0c;不模糊文本 效果图 t1 t2 t3 实现思路 自定义css变量存储图片地址&#xff0c;方便后期更改使用伪元素实现背景模糊达到不遮挡主体文本 transform: scale(1.5)吧图片放大1.5倍&#xff0c;避免设置背景模糊出现白边。 overflow: hidden 超出隐藏&…

上海人工智能实验室的书生·浦语大模型学习笔记(第二期第三课——下篇)

书生浦语是上海人工智能实验室和商汤科技联合研发的一款大模型&#xff0c;这次有机会参与试用&#xff0c;特记录每次学习情况。 一、基础作业 2、在 InternLM Studio 上部署茴香豆技术助手 本次选用 InternLM2-Chat-7B 作为本地基础模型&#xff0c;同时用智浦的GLM作为远…

论文分享 | FAST'23 阿里云提出的针对SMR优化的存储引擎SMRSTORE

今天分享的一篇最近阅读的论文是FAST23的SMRstore: A Storage Engine for Cloud Object Storage on HM-SMR Drives。 https://www.usenix.org/conference/fast23/presentation/zhou 这篇文章是由阿里巴巴公司完成的&#xff0c;在这篇文章中&#xff0c;团队针对SMR的特性提出了…

C++ AVL树底层实现原理

&#x1f493;博主CSDN主页:麻辣韭菜&#x1f493;   ⏩专栏分类&#xff1a;C知识分享⏪   &#x1f69a;代码仓库:C高阶&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习更多C知识   &#x1f51d;&#x1f51d; 目录 前言 AVL 树 1.1 AVL树的概念 1.2 AVL树…

[大模型]Qwen1.5-7B-Chat FastApi 部署调用

Qwen1.5-7B-Chat FastApi 部署调用 环境准备 在 Autodl 平台中租赁一个 3090 等 24G 显存的显卡机器&#xff0c;如下图所示镜像选择 PyTorch–>2.0.0–>3.8(ubuntu20.04)–>11.8&#xff08;11.3 版本以上的都可以&#xff09;。 接下来打开刚刚租用服务器的 Jupyt…

vivado 使用 ILA 默认仪表板

使用 ILA 默认仪表板 ILA 仪表板 &#xff08; 请参阅下图 &#xff09; 是给定 ILA 核相关的所有状态和控制信息的集中显示位置。刷新硬件器件并首次检测到 ILA 核时 &#xff0c; 将自动打开该核的默认 ILA 仪表板。如果需要手动打开或重新打开此仪表板 &#xff0c; 只…

性能优化 - 你知道CSS有哪些优化方案吗

难度级别:中高级及以上 提问概率:70% CSS是前端开发工作中必不可少的技能之一,同时也是网页开发中必不可少的重要元素之一。但很多人所开发的项目本身对性能要求并不高,再加上项目周期紧张,久而久之,也就容易养成不考虑细节的习惯,觉得C…

每日OJ题_01背包①_牛客DP41 【模板】01背包(滚动数组优化)

目录 牛客DP41 【模板】01背包 问题一解析 问题二解析 解析代码 滚动数组优化代码 牛客DP41 【模板】01背包 【模板】01背包_牛客题霸_牛客网 #include <iostream> using namespace std;int main() {int a, b;while (cin >> a >> b) { // 注意 while 处…

软件杯 深度学习人体语义分割在弹幕防遮挡上的实现 - python

文章目录 1 前言1 课题背景2 技术原理和方法2.1基本原理2.2 技术选型和方法 3 实例分割4 实现效果5 最后 1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 深度学习人体语义分割在弹幕防遮挡上的应用 该项目较为新颖&#xff0c;适合作为竞…

二叉树学习

树 树是n个结点的有限集合&#xff0c;当n0时为空树&#xff0c;在任意一颗非空的树中&#xff0c;有且只有一个特定的称为根的结点&#xff0c;当n>1时&#xff0c;其余结点又可以分为m个不相交的有限集&#xff0c;其中每一个集合又是一棵树&#xff0c;并且称为根的子树…

【Java探索之旅】从输入输出到猜数字游戏

&#x1f3a5; 屿小夏 &#xff1a; 个人主页 &#x1f525;个人专栏 &#xff1a; Java编程秘籍 &#x1f304; 莫道桑榆晚&#xff0c;为霞尚满天&#xff01; 文章目录 &#x1f4d1;前言一、输入输出1.1 输出到控制台1.2 从键盘输入 二、猜数字游戏2.1 所需知识&#xff1a…

《猎灵online》游戏完整源码(源码+客户端+服务端+文档+工具),云盘下载

《猎灵》是一款由国内知名开发运营开发的大型3D魔幻网游&#xff0c;《猎灵》研发团队突破诸多瓶颈&#xff0c;首创“全自由无限制PK”&#xff0c;让玩家拒绝无意义等待&#xff0c;自由作战不受任何束缚&#xff0c;真正的实现想战就战&#xff0c;游戏创建了六界神魔乱斗的…

Amazon SageMaker:让机器学习变得更简单、更强大

授权说明&#xff1a;本篇文章授权活动官方亚马逊云科技文章转发、改写权&#xff0c;包括不限于在 亚马逊云科技开发者社区, 知乎&#xff0c;自媒体平台&#xff0c;第三方开发者媒体等亚马逊云科技官方渠道。 前言&#xff1a; 在大数据时代的浪潮中&#xff0c;数据不再只是…