From cf64111b3ad4714bf1187015951fba9053722492 Mon Sep 17 00:00:00 2001 From: Wu Tingfeng Date: Tue, 30 Sep 2025 11:44:08 +0800 Subject: [PATCH 01/10] fix: catch UnknownJSTypeError for node and chrome platform. --- lib/src/platform_check/web.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/src/platform_check/web.dart b/lib/src/platform_check/web.dart index 59ef673f..ea362344 100644 --- a/lib/src/platform_check/web.dart +++ b/lib/src/platform_check/web.dart @@ -16,7 +16,8 @@ class PlatformWeb extends Platform { try { Random.secure(); useBuiltInRng = true; - } on UnsupportedError { + } catch (_) { + // throws UnknownJsTypeError. See 'dart:_js_types'. useBuiltInRng = false; } } From c52438328997bffc9cf6b42dcf862e8eb873c611 Mon Sep 17 00:00:00 2001 From: Wu Tingfeng Date: Thu, 2 Oct 2025 10:38:36 +0800 Subject: [PATCH 02/10] fix: Increase timeout for chrome workflow. --- .github/workflows/chrome.workflow.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/chrome.workflow.yml b/.github/workflows/chrome.workflow.yml index 4e5bbafd..d7162520 100644 --- a/.github/workflows/chrome.workflow.yml +++ b/.github/workflows/chrome.workflow.yml @@ -37,4 +37,4 @@ jobs: run: dart pub get - name: Test chrome - run: dart test -j 1 -p chrome + run: dart test --timeout 2x -j 1 -p chrome From a7e2e7e2135b1e1960300be4f81d3519357fac18 Mon Sep 17 00:00:00 2001 From: Wu Tingfeng Date: Thu, 2 Oct 2025 19:05:46 +0800 Subject: [PATCH 03/10] fix: Handle errors more specifically. --- lib/src/platform_check/web.dart | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/src/platform_check/web.dart b/lib/src/platform_check/web.dart index ea362344..2fe3895f 100644 --- a/lib/src/platform_check/web.dart +++ b/lib/src/platform_check/web.dart @@ -13,12 +13,18 @@ class PlatformWeb extends Platform { static bool useBuiltInRng = false; PlatformWeb() { + useBuiltInRng = false; try { Random.secure(); useBuiltInRng = true; - } catch (_) { - // throws UnknownJsTypeError. See 'dart:_js_types'. - useBuiltInRng = false; + } on UnsupportedError { + // Random.secure() normally throws this error if + // no cryptographically secure random number source is available. + } catch (e) { + // For Node.js with dart2js compiler, the following error is expected. + if (e.runtimeType.toString() == 'UnknownJsTypeError') { + // This error is internal to 'dart:_js_helper'. + } } } From 55f04229dc77fc8c771e29c9cb9089af64196380 Mon Sep 17 00:00:00 2001 From: Wu Tingfeng Date: Fri, 3 Oct 2025 06:50:25 +0800 Subject: [PATCH 04/10] fix: rethrow unknown exception. --- lib/src/platform_check/web.dart | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/src/platform_check/web.dart b/lib/src/platform_check/web.dart index 2fe3895f..b23a7382 100644 --- a/lib/src/platform_check/web.dart +++ b/lib/src/platform_check/web.dart @@ -21,9 +21,10 @@ class PlatformWeb extends Platform { // Random.secure() normally throws this error if // no cryptographically secure random number source is available. } catch (e) { - // For Node.js with dart2js compiler, the following error is expected. - if (e.runtimeType.toString() == 'UnknownJsTypeError') { - // This error is internal to 'dart:_js_helper'. + // For Node.js with dart2js compiler, the UnknownJsTypeError error is expected. + // This error is internal to 'dart:_js_helper' so we need to inspect the runtimeType. + if (!(e.runtimeType.toString() == 'UnknownJsTypeError')) { + rethrow; } } } @@ -55,7 +56,8 @@ class _JsBuiltInEntropySource implements EntropySource { @override Uint8List getBytes(int len) { return Uint8List.fromList( - List.generate(len, (i) => _src.nextInt(256))); + List.generate(len, (i) => _src.nextInt(256)), + ); } } From c61b370f152ce8208380a18a7d96c8e38f59721f Mon Sep 17 00:00:00 2001 From: Wu Tingfeng Date: Wed, 17 Dec 2025 20:38:43 +0800 Subject: [PATCH 05/10] Avoid dart:js_interop_unsafe --- lib/src/platform_check/node_crypto.dart | 19 +++++++++++-------- lib/src/platform_check/web.dart | 14 ++++++-------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/lib/src/platform_check/node_crypto.dart b/lib/src/platform_check/node_crypto.dart index 5f798a87..a556920a 100644 --- a/lib/src/platform_check/node_crypto.dart +++ b/lib/src/platform_check/node_crypto.dart @@ -1,17 +1,20 @@ /// Wrapper for needed NodeJS Crypto library function and require. -library nodecryto; +library nodecrypto; import 'dart:js_interop'; -import 'dart:js_interop_unsafe'; @JS() -external JSObject require(String id); +@staticInterop +class Crypto {} + +extension on Crypto { + external JSUint8Array randomBytes(int size); +} @JS() -@staticInterop +external Crypto require(String id); + class NodeCrypto { - static JSAny randomFillSync(JSAny buf) { - final crypto = require('crypto'); - return crypto.callMethod('randomFillSync'.toJS, buf); - } + static JSUint8Array randomBytes(int size) => + require('crypto').randomBytes(size); } diff --git a/lib/src/platform_check/web.dart b/lib/src/platform_check/web.dart index b23a7382..4ef5ffc4 100644 --- a/lib/src/platform_check/web.dart +++ b/lib/src/platform_check/web.dart @@ -55,20 +55,18 @@ class _JsBuiltInEntropySource implements EntropySource { @override Uint8List getBytes(int len) { - return Uint8List.fromList( - List.generate(len, (i) => _src.nextInt(256)), - ); + final Uint8List bytes = Uint8List(len); + for (int i = 0; i < len; i++) { + bytes[i] = _src.nextInt(256); + } + return bytes; } } /// class _JsNodeEntropySource implements EntropySource { @override - Uint8List getBytes(int len) { - var list = Uint8List(len); - NodeCrypto.randomFillSync(list.buffer.toJS); - return list; - } + Uint8List getBytes(int len) => NodeCrypto.randomBytes(len).toDart; } Platform getPlatform() => PlatformWeb.instance; From 7fa38c7c8dc1f37b39c61a10c14c854abf99576e Mon Sep 17 00:00:00 2001 From: Wu Tingfeng Date: Fri, 19 Dec 2025 22:30:16 +0800 Subject: [PATCH 06/10] Use process.versions.node. --- lib/src/platform_check/node_crypto.dart | 21 +++++++++++++++++ lib/src/platform_check/web.dart | 30 ++++++------------------- 2 files changed, 28 insertions(+), 23 deletions(-) diff --git a/lib/src/platform_check/node_crypto.dart b/lib/src/platform_check/node_crypto.dart index a556920a..0d07d3cf 100644 --- a/lib/src/platform_check/node_crypto.dart +++ b/lib/src/platform_check/node_crypto.dart @@ -3,6 +3,27 @@ library nodecrypto; import 'dart:js_interop'; +@JS() +@staticInterop +class Process {} + +@JS() +@staticInterop +class Versions {} + +@JS('process') +external Process? get _process; + +extension on Process { + external Versions? get versions; +} + +extension on Versions { + external JSAny get node; +} + +bool get isNodeJS => (_process?.versions)?.node != null; + @JS() @staticInterop class Crypto {} diff --git a/lib/src/platform_check/web.dart b/lib/src/platform_check/web.dart index 4ef5ffc4..3fd14037 100644 --- a/lib/src/platform_check/web.dart +++ b/lib/src/platform_check/web.dart @@ -10,24 +10,9 @@ import 'platform_check.dart'; class PlatformWeb extends Platform { static final PlatformWeb instance = PlatformWeb(); - static bool useBuiltInRng = false; + static bool useBuiltInRng = !isNodeJS; - PlatformWeb() { - useBuiltInRng = false; - try { - Random.secure(); - useBuiltInRng = true; - } on UnsupportedError { - // Random.secure() normally throws this error if - // no cryptographically secure random number source is available. - } catch (e) { - // For Node.js with dart2js compiler, the UnknownJsTypeError error is expected. - // This error is internal to 'dart:_js_helper' so we need to inspect the runtimeType. - if (!(e.runtimeType.toString() == 'UnknownJsTypeError')) { - rethrow; - } - } - } + const PlatformWeb(); @override bool get isNative => false; @@ -39,13 +24,12 @@ class PlatformWeb extends Platform { EntropySource platformEntropySource() { if (useBuiltInRng) { return _JsBuiltInEntropySource(); - } else { - // - // Assume that if we cannot get a built in Secure RNG then we are - // probably on NodeJS. - // - return _JsNodeEntropySource(); } + // + // Assume that if we cannot get a built in Secure RNG then we are + // probably on NodeJS. + // + return _JsNodeEntropySource(); } } From ca998ba3ba500b0aca89626bffe9873296c34d25 Mon Sep 17 00:00:00 2001 From: Wu Tingfeng Date: Fri, 19 Dec 2025 22:45:18 +0800 Subject: [PATCH 07/10] refactor: remove obsolete comment. --- lib/src/platform_check/web.dart | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/lib/src/platform_check/web.dart b/lib/src/platform_check/web.dart index 3fd14037..9aa52b8c 100644 --- a/lib/src/platform_check/web.dart +++ b/lib/src/platform_check/web.dart @@ -21,16 +21,8 @@ class PlatformWeb extends Platform { String get platform => 'web'; @override - EntropySource platformEntropySource() { - if (useBuiltInRng) { - return _JsBuiltInEntropySource(); - } - // - // Assume that if we cannot get a built in Secure RNG then we are - // probably on NodeJS. - // - return _JsNodeEntropySource(); - } + EntropySource platformEntropySource() => + useBuiltInRng ? _JsBuiltInEntropySource() : _JsNodeEntropySource(); } // Uses the built in entropy source From 020101f1f81097926d360d0ebad3923f638926db Mon Sep 17 00:00:00 2001 From: Wu Tingfeng Date: Sat, 20 Dec 2025 08:45:07 +0800 Subject: [PATCH 08/10] refactor: remove unused parentheses. --- lib/src/platform_check/node_crypto.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/platform_check/node_crypto.dart b/lib/src/platform_check/node_crypto.dart index 0d07d3cf..49563d11 100644 --- a/lib/src/platform_check/node_crypto.dart +++ b/lib/src/platform_check/node_crypto.dart @@ -22,7 +22,7 @@ extension on Versions { external JSAny get node; } -bool get isNodeJS => (_process?.versions)?.node != null; +bool get isNodeJS => _process?.versions?.node != null; @JS() @staticInterop From 9e973ab3100ab903429632e7d603550a9a9e695d Mon Sep 17 00:00:00 2001 From: Wu Tingfeng Date: Sat, 20 Dec 2025 12:21:04 +0800 Subject: [PATCH 09/10] refactor: check for Node + Dart2JS. --- lib/src/platform_check/node_crypto.dart | 4 +++- lib/src/platform_check/web.dart | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/src/platform_check/node_crypto.dart b/lib/src/platform_check/node_crypto.dart index 49563d11..18aff685 100644 --- a/lib/src/platform_check/node_crypto.dart +++ b/lib/src/platform_check/node_crypto.dart @@ -3,6 +3,8 @@ library nodecrypto; import 'dart:js_interop'; +const bool isWASM = bool.fromEnvironment('dart.tool.dart2wasm'); + @JS() @staticInterop class Process {} @@ -22,7 +24,7 @@ extension on Versions { external JSAny get node; } -bool get isNodeJS => _process?.versions?.node != null; +bool get isNodeDart2JS => _process?.versions?.node != null && !isWASM; @JS() @staticInterop diff --git a/lib/src/platform_check/web.dart b/lib/src/platform_check/web.dart index 9aa52b8c..a331d49a 100644 --- a/lib/src/platform_check/web.dart +++ b/lib/src/platform_check/web.dart @@ -10,7 +10,7 @@ import 'platform_check.dart'; class PlatformWeb extends Platform { static final PlatformWeb instance = PlatformWeb(); - static bool useBuiltInRng = !isNodeJS; + static bool useBuiltInRng = !isNodeDart2JS; const PlatformWeb(); From a3a6f2485735c1b9d1dc16a70b1eda9350936b99 Mon Sep 17 00:00:00 2001 From: Wu Tingfeng Date: Sat, 20 Dec 2025 17:02:36 +0800 Subject: [PATCH 10/10] fix: check dart2js. --- lib/src/platform_check/node_crypto.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/src/platform_check/node_crypto.dart b/lib/src/platform_check/node_crypto.dart index 18aff685..3d20b24d 100644 --- a/lib/src/platform_check/node_crypto.dart +++ b/lib/src/platform_check/node_crypto.dart @@ -3,7 +3,7 @@ library nodecrypto; import 'dart:js_interop'; -const bool isWASM = bool.fromEnvironment('dart.tool.dart2wasm'); +const bool isDart2JS = bool.fromEnvironment('dart.tool.dart2js'); @JS() @staticInterop @@ -24,7 +24,7 @@ extension on Versions { external JSAny get node; } -bool get isNodeDart2JS => _process?.versions?.node != null && !isWASM; +bool get isNodeDart2JS => _process?.versions?.node != null && isDart2JS; @JS() @staticInterop