Skip to content

Commit 3568f00

Browse files
committed
feat(core, web): migrate web to js_interop to be compatible with WASM
1 parent 6c6c589 commit 3568f00

File tree

9 files changed

+166
-243
lines changed

9 files changed

+166
-243
lines changed

packages/firebase_core/firebase_core_web/lib/firebase_core_web.dart

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,16 @@
66
library firebase_core_web;
77

88
import 'dart:async';
9-
import 'dart:html';
109
import 'dart:js';
10+
import 'dart:js_interop';
1111
import 'dart:js_util';
1212

1313
import 'package:firebase_core_platform_interface/firebase_core_platform_interface.dart';
14-
import 'package:firebase_core_web/src/interop/js.dart';
14+
import 'package:firebase_core_web/src/interop/package_web_tweaks.dart';
1515
import 'package:flutter_web_plugins/flutter_web_plugins.dart';
1616
import 'package:js/js_util.dart' as js_util;
1717
import 'package:meta/meta.dart';
18+
import 'package:web/web.dart' as web;
1819

1920
import 'src/interop/core.dart' as firebase;
2021

packages/firebase_core/firebase_core_web/lib/src/firebase_core_web.dart

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -104,27 +104,26 @@ class FirebaseCoreWeb extends FirebasePlatform {
104104
/// document.
105105
@visibleForTesting
106106
Future<void> injectSrcScript(String src, String windowVar) async {
107-
DomTrustedScriptUrl? trustedUrl;
108-
final trustedPolicyName = _defaultTrustedPolicyName + windowVar;
109-
if (trustedTypes != null) {
110-
console.debug(
111-
'TrustedTypes available. Creating policy:',
112-
trustedPolicyName,
107+
web.TrustedScriptURL? trustedUrl;
108+
final trustedTypePolicyName = _defaultTrustedPolicyName + windowVar;
109+
if (web.window.nullableTrustedTypes != null) {
110+
web.console.debug(
111+
'TrustedTypes available. Creating policy: $trustedTypePolicyName'.toJS,
113112
);
114-
final DomTrustedTypePolicyFactory factory = trustedTypes!;
115113
try {
116-
final DomTrustedTypePolicy policy = factory.createPolicy(
117-
trustedPolicyName,
118-
DomTrustedTypePolicyOptions(
119-
createScriptURL: allowInterop((String url) => src),
114+
final web.TrustedTypePolicy policy =
115+
web.window.trustedTypes.createPolicy(
116+
trustedTypePolicyName,
117+
web.TrustedTypePolicyOptions(
118+
createScriptURL: ((JSString url) => src).toJS,
120119
),
121120
);
122-
trustedUrl = policy.createScriptURL(src);
121+
trustedUrl = policy.createScriptURLNoArgs(src);
123122
} catch (e) {
124-
rethrow;
123+
throw TrustedTypesException(e.toString());
125124
}
126125
}
127-
ScriptElement script = ScriptElement();
126+
web.HTMLScriptElement script = web.HTMLScriptElement();
128127
script.type = 'text/javascript';
129128
script.crossOrigin = 'anonymous';
130129
script.text = '''
@@ -134,8 +133,8 @@ class FirebaseCoreWeb extends FirebasePlatform {
134133
};
135134
''';
136135

137-
assert(document.head != null);
138-
document.head!.append(script);
136+
assert(web.document.head != null);
137+
web.document.head!.append(script);
139138

140139
Completer completer = Completer();
141140

@@ -367,3 +366,15 @@ R guardNotInitialized<R>(R Function() cb) {
367366
_handleException(error, stackTrace);
368367
}
369368
}
369+
370+
/// Exception thrown if the Trusted Types feature is supported, enabled, and it
371+
/// has prevented this loader from injecting the JS SDK.
372+
class TrustedTypesException implements Exception {
373+
///
374+
TrustedTypesException(this.message);
375+
376+
/// The message of the exception
377+
final String message;
378+
@override
379+
String toString() => 'TrustedTypesException: $message';
380+
}

packages/firebase_core/firebase_core_web/lib/src/interop/app_interop.dart

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,14 @@
99
library firebase_interop.core.app;
1010

1111
import 'package:js/js.dart';
12+
1213
import 'core_interop.dart';
1314

1415
@JS('FirebaseApp')
15-
abstract class AppJsImpl {
16+
@staticInterop
17+
abstract class AppJsImpl {}
18+
19+
extension AppJsImplExtension on AppJsImpl {
1620
external String get name;
1721
external FirebaseOptions get options;
1822
}

packages/firebase_core/firebase_core_web/lib/src/interop/core_interop.dart

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@
88
@JS('firebase_core')
99
library firebase_interop.core;
1010

11+
import 'dart:js_interop';
12+
1113
import 'package:firebase_core_web/firebase_core_web_interop.dart';
12-
import 'package:js/js.dart';
1314

1415
@JS()
15-
external List<AppJsImpl> getApps();
16+
// TODO FIX
17+
List<AppJsImpl> getApps() => throw UnimplementedError();
1618

1719
/// The current SDK version.
1820
///
@@ -27,15 +29,18 @@ external AppJsImpl initializeApp(FirebaseOptions options, [String? name]);
2729
external AppJsImpl getApp([String? name]);
2830

2931
@JS()
30-
external PromiseJsImpl<void> deleteApp(AppJsImpl app);
32+
external JSPromise deleteApp(AppJsImpl app);
3133

3234
/// FirebaseError is a subclass of the standard Error object.
3335
/// In addition to a message string, it contains a string-valued code.
3436
///
3537
/// See: <https://firebase.google.com/docs/reference/js/firebase.FirebaseError>.
3638
@JS()
3739
@anonymous
38-
abstract class FirebaseError {
40+
@staticInterop
41+
abstract class FirebaseError {}
42+
43+
extension FirebaseErrorExtension on FirebaseError {
3944
external String get code;
4045
external String get message;
4146
external String get name;
@@ -48,6 +53,7 @@ abstract class FirebaseError {
4853
/// A structure for options provided to Firebase.
4954
@JS()
5055
@anonymous
56+
@staticInterop
5157
class FirebaseOptions {
5258
external factory FirebaseOptions({
5359
String? apiKey,
@@ -59,7 +65,9 @@ class FirebaseOptions {
5965
String? measurementId,
6066
String? appId,
6167
});
68+
}
6269

70+
extension FirebaseOptionsExtension on FirebaseOptions {
6371
external String get apiKey;
6472
external set apiKey(String s);
6573
external String get authDomain;

packages/firebase_core/firebase_core_web/lib/src/interop/js.dart

Lines changed: 0 additions & 141 deletions
This file was deleted.
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
// Copied from https://github.com/flutter/packages/google_identity_services_web/lib/src/js_interop/package_web_tweaks.dart
6+
7+
/// Provides some useful tweaks to `package:web`.
8+
library package_web_tweaks;
9+
10+
import 'dart:js_interop';
11+
12+
import 'package:web/web.dart' as web;
13+
14+
/// This extension gives web.window a nullable getter to the `trustedTypes`
15+
/// property, which needs to be used to check for feature support.
16+
extension NullableTrustedTypesGetter on web.Window {
17+
///
18+
@JS('trustedTypes')
19+
external web.TrustedTypePolicyFactory? get nullableTrustedTypes;
20+
}
21+
22+
/// This extension allows a trusted type policy to create a script URL without
23+
/// the `args` parameter (which in Chrome currently fails).
24+
extension CreateScriptUrlWithoutArgs on web.TrustedTypePolicy {
25+
///
26+
@JS('createScriptURL')
27+
external web.TrustedScriptURL createScriptURLNoArgs(
28+
String input,
29+
);
30+
}
31+
32+
/// This extension allows setting a TrustedScriptURL as the src of a script element,
33+
/// which currently only accepts a string.
34+
extension TrustedTypeSrcAttribute on web.HTMLScriptElement {
35+
///
36+
@JS('src')
37+
external set srcTT(web.TrustedScriptURL value);
38+
}

packages/firebase_core/firebase_core_web/lib/src/interop/utils/es6_interop.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import 'package:js/js.dart';
1313
import 'func.dart';
1414

1515
@JS('Promise')
16+
@staticInterop
1617
class PromiseJsImpl<T> {
1718
external PromiseJsImpl(Function resolver);
1819
external PromiseJsImpl then([Func1? onResolve, Func1? onReject]);

0 commit comments

Comments
 (0)