作者 / Michael Thomsen, Dart & Flutter Product Manager, Google
我們已經(jīng)正式發(fā)布了 Dart SDK 的 2.15 版本,該版本新增了可快速并發(fā)的工作器 isolate、新的構(gòu)造函數(shù)拆分 (tear-off) 語言特性、經(jīng)過改進(jìn)的 dart:core 庫枚舉支持、package 發(fā)布者相關(guān)的新功能,等等。
工作器 isolate 的快速并發(fā)
如今,幾乎所有現(xiàn)代設(shè)備都使用多核 CPU,可以并行執(zhí)行多個任務(wù)。對于大多數(shù) Dart 程序來說,這些內(nèi)核的使用情況對開發(fā)者而言是透明的: 默認(rèn)情況下,Dart 運(yùn)行時系統(tǒng)在單個內(nèi)核上運(yùn)行所有的 Dart 代碼,不過會使用其他內(nèi)核來執(zhí)行系統(tǒng)級任務(wù),比如異步輸入/輸出,包括寫入文件或者調(diào)用網(wǎng)絡(luò)等。
不過您自己的 Dart 代碼可能也需要并發(fā)運(yùn)行。例如,您可能需要展示一個連續(xù)的動畫,同時執(zhí)行一個長時間運(yùn)行的任務(wù),比如解析一個大型 JSON 文件。如果額外任務(wù)花了太長時間,就可能會導(dǎo)致界面卡頓或延遲。如果將這些額外的任務(wù)移動到另一個單獨(dú)的內(nèi)核,動畫就可以在主執(zhí)行線程上繼續(xù)運(yùn)行而不受干擾。
Dart 的并發(fā)模型基于 isolate,isolate 是一種相互隔離的獨(dú)立執(zhí)行單元,這是為了避免出現(xiàn)與共享內(nèi)存相關(guān)的大量并發(fā)編程錯誤,如數(shù)據(jù)爭用等競態(tài)條件。Dart 通過禁止在 isolate 之間共享任何可變對象來避免這些錯誤,并使用消息傳遞在 isolate 之間交換狀態(tài)。在 Dart 2.15 中,我們對 isolate 進(jìn)行了許多實質(zhì)性的改進(jìn)。
Dart 中的并發(fā) https://dart.dev/guides/language/concurrency
競態(tài)條件 https://en.wikipedia.org/wiki/Race_condition#In_software
在 isolate 間發(fā)送多條消息 https://dart.dev/guides/language/concurrency#sending-multiple-messages-between-isolates
我們首先重新設(shè)計和實現(xiàn)了 isolate 的工作方式,引入了一個新概念: isolate 組。Isolate 組中的 isolate 共享各種內(nèi)部數(shù)據(jù)結(jié)構(gòu),這些數(shù)據(jù)結(jié)構(gòu)則表示正在運(yùn)行的程序。這使得組中的單個 isolate 變得更加輕便。如今,因為不需要初始化程序結(jié)構(gòu),在現(xiàn)有 isolate 組中啟動額外的 isolate 比之前快 100 多倍,并且產(chǎn)生的 isolate 所消耗的內(nèi)存減少了 10 至 100 倍。
雖然 isolate 組仍然阻止在 isolate 間共享訪問可變對象,但由于 isolate 組使用共享堆實現(xiàn),這也讓其擁有了更多的功能。我們可以將對象從一個 isolate 傳遞到另一個 isolate,這可用于執(zhí)行返回大量內(nèi)存數(shù)據(jù)的任務(wù)的工作器 isolate。例如,工作器 isolate 通過網(wǎng)絡(luò)調(diào)用獲得數(shù)據(jù),將該數(shù)據(jù)解析為大型 JSON 對象圖,然后將這個 JSON 圖返回到主 isolate 中。在推出 Dart 2.15 之前,執(zhí)行該操作需要深度復(fù)制,如果復(fù)制花費(fèi)的時間超過幀預(yù)算時間,就會導(dǎo)致界面卡頓。
在 Dart 2.15 中,工作器 isolate 可以調(diào)用 Isolate.exit(),將其結(jié)果作為參數(shù)傳遞。然后,Dart 運(yùn)行時將包含結(jié)果的內(nèi)存數(shù)據(jù)從工作器 isolate 傳遞到主 isolate 中,無需復(fù)制,且主 isolate 可以在固定時間內(nèi)接收結(jié)果。我們已經(jīng)在 Flutter 2.8 中更新了 compute() 實用函數(shù),來利用 Isolate.exit()。如果您已經(jīng)在使用 compute(),那么在升級到 Flutter 2.8 后,您將自動獲得這些性能提升。
Isolate.exit() https://api.dart.cn/stable/2.15.0/dart-isolate/Isolate/exit.html
compute() https://api.flutter-io.cn/flutter/foundation/compute-constant.html
最后,我們還重新設(shè)計了 isolate 消息傳遞機(jī)制的實現(xiàn)方式,使得中小型消息的傳遞速度提高了大約 8 倍。發(fā)送消息的速度明顯更快,而接收信息幾乎總是在恒定的時間內(nèi)完成。另外,我們擴(kuò)展了 isolate 可以相互發(fā)送的對象種類,增加了對函數(shù)類型、閉包和堆棧跟蹤對象的支持。請參閱 SendPort.send() 的 API 文檔了解詳情:
https://api.dart.cn/stable/2.15.0/dart-isolate/SendPort/send.html
要了解有關(guān)如何使用 isolate 的更多信息,請參閱我們?yōu)?Dart 2.15 添加的官方文檔 Dart 中的并發(fā),以及更多代碼示例。
Dart 中的并發(fā) https://dart.cn/guides/language/concurrency
代碼示例 https://github.com/dart-lang/samples/tree/master/isolates
新語言特性:構(gòu)造函數(shù)拆分
在 Dart 中,您可以使用函數(shù)名稱創(chuàng)建一個函數(shù)對象,該對象指向另一個對象的函數(shù)。在以下示例中,main() 方法的第二行演示了將 g 指向 m.greet 的語法:
class Greeter { final String name; Greeter(this.name); void greet(String who) { print('$name says: Hello $who!'); }}void main() { final m = Greeter('Michael'); final g = m.greet; // g holds a function pointer to m.greet. g('Leaf'); // Invokes and prints "Michael says: Hello Leaf!"}
在使用 Dart 核心庫時,這種函數(shù)指針 (也被稱為函數(shù)拆分) 經(jīng)常出現(xiàn)。下面是通過傳遞函數(shù)指針在 iterable 上調(diào)用 foreach() 的示例:
final m = Greeter('Michael');['Lasse', 'Bob', 'Erik'].forEach(m.greet);// Prints "Michael says: Hello Lasse!", "Michael says: Hello Bob!",// "Michael says: Hello Erik!"
在之前的版本中,Dart SDK 不支持創(chuàng)建構(gòu)造函數(shù)的拆分 (語言問題 #216)。這就有點(diǎn)煩人,因為在許多情況下,例如構(gòu)建 Flutter 界面時,就需要用到構(gòu)造函數(shù)的拆分。從 Dart 2.15 開始,我們支持這種語法。以下是構(gòu)建包含三個 Text widget 的 Column widget 的示例,通過調(diào)用 .map() 將 Text 構(gòu)造函數(shù)的拆分傳遞給 Column 的子項。
class FruitWidget extends StatelessWidget { @override Widget build(BuildContext context) { return Column( children: ['Apple', 'Orange'].map(Text.new).toList()); }}
#216: 允許像傳遞方法一樣傳遞構(gòu)造函數(shù)
https://github.com/dart-lang/language/issues/2
Text.new 指 Text 類的默認(rèn)構(gòu)造函數(shù)。您也可以引用命名構(gòu)造函數(shù),例如 .map(Text.rich)。
相關(guān)語言變化
在實現(xiàn)構(gòu)造函數(shù)拆分時,我們也借此機(jī)會修復(fù)了現(xiàn)有的函數(shù)指針功能中的一些不一致問題?,F(xiàn)在可以特化泛型方法來創(chuàng)建非泛型方法:
T id(T value) => value;var intId = id ; // New in 2.15.int Function(int) intId = id; // Pre-2.15 workaround.
您甚至可以特化一個泛型函數(shù)對象來創(chuàng)建一個非泛型函數(shù)對象:
const fo = id; // Tear off `id`, creating a function object.const c1 = fo; // New in 2.15; error before.
最后,Dart 2.15 清理了涉及泛型的類型字面量:
var y = List; // Already supported.var z = List; // New in 2.15.var z = typeOf >(); // Pre-2.15 workaround.
改進(jìn) dart:core 庫中的枚舉
我們?yōu)?dart:core 庫的枚舉 API 添加了許多優(yōu)化 (語言問題 #1511)?,F(xiàn)在您可以通過 .name 獲取每個枚舉值的 String 值:
enum MyEnum { one, two, three}void main() { print(MyEnum.one.name); // Prints "one".}
#1511: 為枚舉值添加 name 實例屬性 https://github.com/dart-lang/language/issues/1511
還可以按名稱查找枚舉值:
print(MyEnum.values.byName('two') == MyEnum.two); // Prints "true".
最后,您可以獲得所有名稱-值對的映射:
final map = MyEnum.values.asNameMap();print(map['three'] == MyEnum.three); // Prints "true".
請參閱此 Flutter PR 查看這些新 API 的使用示例:
https://github.com/flutter/flutter/pull/94496/files
壓縮指針
Dart 2.15 增加了對壓縮指針的支持,這樣,如果只需要支持 32 位的地址空間 (最多 4 GB 內(nèi)存),則 64 位 SDK 可以使用更加節(jié)省空間的指針表示形式。壓縮指針顯著減少了內(nèi)存占用,在對 Google Pay 應(yīng)用的內(nèi)部測試中,我們發(fā)現(xiàn) Dart 堆的體積減少了大約 10%。
壓縮指針意味著無法處理 4 GB 以上的可用 RAM,因此該功能只存在于 Dart SDK 的配置選項中,只能在構(gòu)建 SDK 時由 Dart SDK 的嵌入器啟用。Flutter SDK 2.8 版已為 Android 構(gòu)建啟用此配置,F(xiàn)lutter 團(tuán)隊正在考慮在后續(xù)版本中為 iOS 構(gòu)建啟用此配置:
https://github.com/flutter/flutter/issues/94753
Dart SDK 中包含 Dart DevTools
以往 Dart SDK 不提供調(diào)試和性能工具的 DevTools 套件,您需要單獨(dú)下載。從 Dart 2.15 開始,下載 Dart SDK 時也會獲取 DevTools,無需進(jìn)一步的安裝步驟。有關(guān)在 Dart 命令行應(yīng)用中使用 DevTools 的更多信息,請參閱 DevTools 文檔:
https://dart.dev/tools/dart-devtools#using-devtools-with-a-command-line-app
DevTools套件
https://dart.dev/tools/dart-devtools#
面向 package 發(fā)布者的新 pub 功能
Dart 2.15 SDK 在 dart pub 開發(fā)者命令和 pub.devpackage repo 中還新增了兩個功能。 首先,為 package 發(fā)布者新增了一個安全功能,用于檢測發(fā)布者在 pub package 中意外發(fā)布 secret,例如 Cloud 或 CI 憑據(jù)。在了解到 GitHub repo 中每天都有數(shù)以千計的 secret 被泄露后,我們便決定添加這個泄露檢測功能。
公共 GitHub repo 的 secret 泄漏有多嚴(yán)重?
https://www.ndss-symposium.org/wp-content/uploads/2019/02/ndss2019_04B-3_Meli_paper.pdf
泄露檢測作為 dart pub publish 命令中的預(yù)發(fā)布驗證的一部分運(yùn)行。如果它在即將發(fā)布的文件中檢測到潛在的 secret,publish 命令會退出,而不進(jìn)行發(fā)布,并打印如下輸出:
Publishing my_package 1.0.0 to https://pub.dartlang.org:Package validation found the following errors:* line 1, column 1 of lib/key.pem: Potential leak of Private Key detected.?1 │ ┌ - - -BEGIN PRIVATE KEY - - -2 │ │ H0M6xpM2q+53wmsN/eYLdgtjgBd3DBmHtPilCkiFICXyaA8z9LkJ3 │ └ - - -END PRIVATE KEY - - -?* line 2, column 23 of lib/my_package.dart: Potential leak of Google OAuth Refresh Token detected.?2 │ final refreshToken = "1//042ys8uoFwZrkCgYIARAAGAQSNwF-L9IrXmFYE-sfKefSpoCnyqEcsHX97Y90KY-p8TPYPPnY2IPgRXdy0QeVw7URuF5u9oUeIF0";
在極少數(shù)情況下,此項檢測可能會出現(xiàn)誤報,將您實際上打算發(fā)布的內(nèi)容或文件標(biāo)記為潛在泄露。在這些情況下,您可以將文件添加到許可名單中:
https://dart.cn/tools/pub/pubspec#false_secrets
其次,我們還為發(fā)布者添加了另一個功能:撤銷已發(fā)布的 package 版本。當(dāng)發(fā)布了有問題的 package 版本時,我們通常的建議是發(fā)布一個小幅升級的新版本來修復(fù)意外問題。但在極少數(shù)情況下,例如您尚未修復(fù)這些問題,或是您在原打算只發(fā)布一個次要版本時意外發(fā)布了一個主要版本,那么您就可以使用新的 package 撤銷功能,作為最后的補(bǔ)救方法。此功能在 pub.dev 的管理界面中提供:
撤銷 package 版本
https://dart.cn/tools/pub/publishing#retract
在 package 版本被撤銷后,pub 客戶端在 pub get 或 pub upgrade 中將不再解析該版本。如果有開發(fā)者已經(jīng)解析該撤銷的版本 (并存在于他們的 pubspec.lock 文件中),他們將在下次運(yùn)行 pub 時看到警告:
$ dart pub getResolving dependencies…mypkg 0.0.181-buggy (retracted, 0.0.182-fixed available)Got dependencies!
檢測雙向 Unicode 字符的安全性分析 (CVE-2021–22567)
最近發(fā)現(xiàn)了一個涉及雙向 Unicode 字符的通用編程語言漏洞 (CVE-2021–42574)。這個漏洞影響了大多數(shù)支持 Unicode 的現(xiàn)代編程語言。下面的 Dart 源代碼演示了這個問題:
main() { final accessLevel = 'user'; if (accessLevel == 'user .?// Check if admin? ?') { print('You are a regular user.'); } else { print('You are an admin.'); }}
CVE-2021–42574 https://nvd.nist.gov/vuln/detail/CVE-2021-42574
您可能會認(rèn)為該程序會打印出 You are a regular user.,但實際上它打印出的是 You are an admin.!通過使用包含雙向 Unicode 字符的字符串,您就可能會造成這一漏洞。這些雙向字符針對在同一行的文本,可以將文本的方向由從左到右更改為從右到左,反之亦然。雙向字符文本在屏幕上的呈現(xiàn)與實際文本內(nèi)容截然不同。您可以進(jìn)一步查看此 GitHub gist 示例:
https://gist.github.com/mit-mit/7dda00ca6278ce7d2555f78d59d9e67b?h=1
針對此漏洞的緩解措施包括使用檢測雙向 Unicode 字符的工具 (編輯器、代碼審查工具等),以便開發(fā)者發(fā)現(xiàn)它們,并在知情的情況下使用這些字符。上面提到的 GitHub gist 文件查看器便是發(fā)現(xiàn)這些字符的工具的一個例子。
Dart 2.15 引入了進(jìn)一步的緩解措施 (Dart 安全建議CVE-2021–22567)。現(xiàn)在,Dart 分析器會掃描雙向 Unicode 字符,并標(biāo)記對它們的任何使用:
$ dart analyzeAnalyzing cvetest... 2.6sinfo ? bin/cvetest.dart:4:27 ? The Unicode code point 'U+202E' changes the appearance of text from how it's interpreted by the compiler. Try removing the code point or using the Unicode escape sequence 'u202E'. ? text_direction_code_point_in_literal
Dart 安全建議 CVE-2021–22567 https://github.com/dart-lang/sdk/security/advisories/GHSA-8pcp-6qc9-rqmv
我們建議用 Unicode 轉(zhuǎn)義序列替換這些字符,這樣它們就可在任何文本編輯器或查看器中顯示出來。或者,如果您確實正當(dāng)使用了這些字符,您可以在使用這些字符的代碼行之前添加覆蓋語句來禁用警告:
// ignore: text_direction_code_point_in_literal
使用第三方 pub 服務(wù)器時的 pub.dev 憑據(jù)漏洞 (CVE-2021–22568)
我們也發(fā)布了第二個與 pub.dev 相關(guān)的 Dart 安全建議:CVE-2021–22568。此建議針對可能將 package 發(fā)布到第三方 pub package 服務(wù)器 (例如私人或公司內(nèi)部 package 服務(wù)器) 的 package 發(fā)布者。僅將 package 發(fā)布到公開 pub.dev repo (標(biāo)準(zhǔn)配置) 的開發(fā)者不受此漏洞的影響。
CVE-2021–22568 https://github.com/dart-lang/sdk/security/advisories/GHSA-r32f-vhjp-qhj7
如果您已經(jīng)將 package 發(fā)布至第三方 repo,那么漏洞是:用于在第三方 repo 進(jìn)行身份驗證的 OAuth2 臨時 (一小時) 訪問令牌可能被誤用,以在公開 pub.dev repo 上進(jìn)行身份驗證。因此惡意的第三方 pub 服務(wù)器可能會使用訪問令牌,在 pub.dev 上冒充您,并發(fā)布 package。如果您已經(jīng)將 package 發(fā)布到一個不受信任的第三方 package repo,請考慮審查您的帳號在 pub.dev 公開 package repo 上的所有活動。我們推薦您使用 pub.dev 活動日志進(jìn)行查看:
https://pub.dev/my-activity-log
最后
希望您喜歡已經(jīng)推出的 Dart 2.15 中的新功能。這是我們今年的最后一個版本,我們想借此機(jī)會表達(dá)我們對美妙的 Dart 生態(tài)系統(tǒng)的感謝。感謝大家的寶貴反饋,以及對我們一直以來的支持,感謝大家在過去的一年中在 pub.dev 上發(fā)布的數(shù)千個 package,它們豐富了我們的生態(tài)系統(tǒng)。我們迫切期待明年再次投入工作,我們計劃在 2022 年推出很多激動人心的內(nèi)容。預(yù)祝大家新年快樂,好好享受即將到來的假期吧!
原文標(biāo)題:Dart 2.15 現(xiàn)已發(fā)布
文章出處:【微信公眾號:谷歌開發(fā)者】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
-
函數(shù)
+關(guān)注
關(guān)注
3文章
4260瀏覽量
62231 -
SDK
+關(guān)注
關(guān)注
3文章
1015瀏覽量
45607 -
GitHub
+關(guān)注
關(guān)注
3文章
461瀏覽量
16327
原文標(biāo)題:Dart 2.15 現(xiàn)已發(fā)布
文章出處:【微信號:Google_Developers,微信公眾號:谷歌開發(fā)者】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論