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,一经查实,立即删除!

相关文章

【笔记】Teach less, learn more

文章目录 核心概念针对学习的理念知识高级知识生成器:WHWM四问基础知识与导出知识 案例小学数学小学语文经济学教育学物理学 核心概念 学习方法:以学科大图景为目标的以批判性思维和系联性思考为指导的理解型学习。 学科大图景:一个学科大概…

hashmap ArrayList基础使用 java

hashmap 1 hashmap1.1 hashmap基础使用1.2 遍历hashmap 2 ArrayList2.1 ArrayList基础使用2.2 ArrayList遍历 |--> Collection接口: 单列集合,用来存储一个一个对象。--> list接口:存储有序,可重复的数据。--> ArrayList、LinkList vector-->…

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…

基于STM32技术的智慧超市系统研究

基于STM32技术的智慧超市系统研究 **摘要&#xff1a;**随着物联网技术的飞速发展&#xff0c;智慧超市作为零售业的一种新兴模式&#xff0c;正越来越受到关注。本文以STM32技术为基础&#xff0c;设计并实现了一套智慧超市系统。论文详细介绍了系统的架构、功能设计以及实现…

导入导出之使用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;导致访问或更改文件存在局限性…

MySQL 常见和不常见的所有查询语句

介绍&#xff1a; MySQL 是一个功能强大的关系型数据库管理系统&#xff0c;支持丰富的查询语句&#xff0c;用于从数据库中检索、插入、更新和删除数据。本文将介绍 MySQL 中常见和不常见的所有查询语句&#xff0c;并为每个语句提供示例。 常见查询语句&#xff1a; 1.sel…

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

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

【leetcode面试经典150题】29.三数之和(C++)

【leetcode面试经典150题】专栏系列将为准备暑期实习生以及秋招的同学们提高在面试时的经典面试算法题的思路和想法。本专栏将以一题多解和精简算法思路为主&#xff0c;题解使用C语言。&#xff08;若有使用其他语言的同学也可了解题解思路&#xff0c;本质上语法内容一致&…

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);…

salesforce为不同的profile设置不同的域名,不同域名之间账号不互通

在Salesforce中&#xff0c;你可以通过设置不同的 My Domain 来实现不同的 profile 使用不同的域名&#xff0c;并确保这些域名之间的账号不互通。My Domain 是 Salesforce 提供的定制域名功能&#xff0c;允许你为 Salesforce 组织设置自定义的域名。 以下是一般的步骤&#…

nginx配置nacos返向代理

要配置Nginx作为反向代理服务器以便通过https访问Nacos集群&#xff0c;并且同时支持http到https的重定向&#xff0c;你需要编写一个Nginx配置文件。这个配置文件不仅需要处理SSL终端和重定向&#xff0c;还需要将流量代理到你的Nacos集群。 以下是一个基本的Nginx配置示例&a…

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)# 将结果转换为列表…

【Hadoop】Hive导入导出数据指南

穿新衣吧 剪新发型呀 轻松一下Windows98 打扮漂亮 18岁是天堂 我们的生活甜得像糖 穿新衣吧 剪新发型呀 轻松一下Windows98 以后的路不再会有痛苦 我们的未来该有多酷 &#x1f3b5; 房东的猫《new boy》 Apache Hive 是一个基于Hadoop的数据仓库工具&…

【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…