Skip to content

Commit d96c01d

Browse files
authored
Use extension types and generics internally (#184)
Migrate @staticInterop to extension types, which enables us to use generic arguments to JSArray and JSPromise.
1 parent 975e55c commit d96c01d

File tree

7 files changed

+61
-155
lines changed

7 files changed

+61
-155
lines changed

tool/generator/filesystem_api.dart

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,25 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5+
// TODO(srujzs): Remove this workaround once we use an SDK version that contains
6+
// https://github.com/dart-lang/sdk/issues/54801.
7+
@JS()
8+
library;
9+
510
import 'dart:js_interop';
611

712
@JS()
813
external FileSystem get fs;
914

10-
@JS()
11-
@anonymous
12-
@staticInterop
13-
class JSMkdirOptions {
15+
extension type JSMkdirOptions._(JSObject _) implements JSObject {
1416
external factory JSMkdirOptions({JSBoolean? recursive});
1517
}
1618

17-
@JS()
18-
@anonymous
19-
@staticInterop
20-
class JSReadFileOptions {
19+
extension type JSReadFileOptions._(JSObject _) implements JSObject {
2120
external factory JSReadFileOptions({JSString? encoding});
2221
}
2322

24-
@JS()
25-
@staticInterop
26-
class FileSystem {}
27-
28-
// TODO(joshualitt): Replace `void` with `JSVoid`
29-
extension FileSystemExtension on FileSystem {
23+
extension type FileSystem._(JSObject _) implements JSObject {
3024
external JSBoolean existsSync(JSString path);
3125

3226
@JS('mkdirSync')

tool/generator/generate_bindings.dart

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,21 @@ import 'dart:js_interop';
66

77
import 'translator.dart';
88
import 'util.dart';
9+
import 'webidl_api.dart' as webidl;
910
import 'webref_css_api.dart';
1011
import 'webref_idl_api.dart';
1112

1213
/// Generate CSS property names for setting / getting CSS properties in JS.
1314
Future<List<String>> _generateCSSStyleDeclarations() async {
1415
final cssStyleDeclarations = <String>{};
15-
final array = objectEntries(await css.listAll().toDart as JSObject);
16+
final array = objectEntries(await css.listAll().toDart);
1617
for (var i = 0; i < array.length; i++) {
17-
final entry = array[i] as JSArray;
18-
final data = entry[1] as CSSEntries;
18+
final entry = array[i] as JSArray<CSSEntries>;
19+
final data = entry[1];
1920
final properties = data.properties;
2021
if (properties != null) {
2122
for (var j = 0; j < properties.length; j++) {
22-
final property = properties[j] as CSSEntry;
23+
final property = properties[j];
2324
// There are three cases for [styleDeclaration]:
2425
// 1) Length == 1, a single word CSS property.
2526
// 2) Length == 2, a kebab case property + a camel case property.
@@ -32,7 +33,7 @@ Future<List<String>> _generateCSSStyleDeclarations() async {
3233
}
3334
// For now we ignore browser specific properties.
3435
if (length == 3) continue;
35-
final style = (styleDeclaration[length - 1] as JSString).toDart;
36+
final style = styleDeclaration[length - 1].toDart;
3637
if (style.contains('-')) {
3738
throw Exception('Unexpected style declaration $styleDeclaration');
3839
}
@@ -49,11 +50,11 @@ Future<TranslationResult> generateBindings(
4950
final cssStyleDeclarations = await _generateCSSStyleDeclarations();
5051
final translator =
5152
Translator(packageRoot, librarySubDir, cssStyleDeclarations);
52-
final array = objectEntries(await idl.parseAll().toDart as JSObject);
53+
final array = objectEntries(await idl.parseAll().toDart);
5354
for (var i = 0; i < array.length; i++) {
54-
final entry = array[i] as JSArray;
55+
final entry = array[i] as JSArray<JSAny?>;
5556
final shortname = (entry[0] as JSString).toDart;
56-
final ast = entry[1] as JSArray;
57+
final ast = entry[1] as JSArray<webidl.Node>;
5758
translator.collect(shortname, ast);
5859
}
5960
translator.setOrUpdateInterfacelikes();

tool/generator/translator.dart

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -287,21 +287,21 @@ class _Parameter {
287287
class _OverridableMember {
288288
final List<_Parameter> parameters = [];
289289

290-
_OverridableMember(JSArray rawParameters) {
290+
_OverridableMember(JSArray<idl.Argument> rawParameters) {
291291
for (var i = 0; i < rawParameters.length; i++) {
292-
parameters.add(_Parameter(rawParameters[i] as idl.Argument));
292+
parameters.add(_Parameter(rawParameters[i]));
293293
}
294294
}
295295

296-
void _processParameters(JSArray thoseParameters) {
296+
void _processParameters(JSArray<idl.Argument> thoseParameters) {
297297
// Assume if we have extra arguments beyond what was provided in some other
298298
// method, that these are all optional.
299299
final thatLength = thoseParameters.length;
300300
for (var i = thatLength; i < parameters.length; i++) {
301301
parameters[i].isOptional = true;
302302
}
303303
for (var i = 0; i < thatLength; i++) {
304-
final argument = thoseParameters[i] as idl.Argument;
304+
final argument = thoseParameters[i];
305305
if (i >= parameters.length) {
306306
// We assume these parameters must be optional, regardless of what the
307307
// IDL says.
@@ -361,9 +361,9 @@ class _PartialInterfacelike {
361361
return partialInterfacelike;
362362
}
363363

364-
void _processMembers(JSArray nodeMembers) {
364+
void _processMembers(JSArray<idl.Member> nodeMembers) {
365365
for (var i = 0; i < nodeMembers.length; i++) {
366-
final member = nodeMembers[i] as idl.Member;
366+
final member = nodeMembers[i];
367367
final type = member.type;
368368
switch (type) {
369369
case 'constructor':
@@ -532,14 +532,14 @@ class Translator {
532532
}
533533
}
534534

535-
void collect(String shortName, JSArray ast) {
535+
void collect(String shortName, JSArray<idl.Node> ast) {
536536
final libraryPath = '$_librarySubDir/${shortName.kebabToSnake}.dart';
537537
assert(!_libraries.containsKey(libraryPath));
538538

539539
final library = _Library(this, '$packageRoot/$libraryPath');
540540

541541
for (var i = 0; i < ast.length; i++) {
542-
library.add(ast[i] as idl.Node);
542+
library.add(ast[i]);
543543
}
544544

545545
if (_shouldGenerate(shortName, library)) {

tool/generator/util.dart

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@ import 'filesystem_api.dart';
88

99
// TODO(joshualitt): Let's find a better place for these.
1010
@JS('Object.entries')
11-
external JSArray objectEntries(JSObject o);
11+
external JSArray<JSAny?> objectEntries(JSObject o);
1212

13-
extension JSArrayExtension on JSArray {
14-
external JSAny? operator [](int i);
13+
// TODO(srujzs): Remove once this is in dart:js_interop.
14+
extension JSArrayExtension<T extends JSAny?> on JSArray<T> {
15+
external T operator [](int i);
1516
external int get length;
1617
}
1718

tool/generator/webidl_api.dart

Lines changed: 24 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,7 @@
44

55
import 'dart:js_interop';
66

7-
@JS()
8-
@staticInterop
9-
class IDLType {}
10-
11-
extension IDLTypeExtension on IDLType {
7+
extension type IDLType._(JSObject _) implements JSObject {
128
external String? get type;
139
external String get generic;
1410
external JSAny get idlType;
@@ -18,21 +14,13 @@ extension IDLTypeExtension on IDLType {
1814

1915
/// The abstract node interface in the IDL AST. All nodes that can occur at the
2016
/// root of the IDL inherit from [Node].
21-
@JS()
22-
@staticInterop
23-
class Node {}
24-
25-
extension NodeExtension on Node {
17+
extension type Node._(JSObject _) implements JSObject {
2618
external String get type;
2719
}
2820

2921
/// The abstract node interface for named nodes in the IDL. Most root nodes have
3022
/// names, with the exception of `includes`.
31-
@JS()
32-
@staticInterop
33-
class Named extends Node {}
34-
35-
extension NamedExtension on Named {
23+
extension type Named._(JSObject _) implements Node {
3624
external String get name;
3725
}
3826

@@ -43,69 +31,39 @@ extension NamedExtension on Named {
4331
/// * callback interface
4432
/// * dictionary
4533
/// To disambiguate, use the `type` getter.
46-
@JS()
47-
@staticInterop
48-
class Interfacelike extends Named {}
49-
50-
extension InterfaceExtension on Interfacelike {
34+
extension type Interfacelike._(JSObject _) implements Named {
5135
external bool get partial;
52-
external JSArray get members;
36+
external JSArray<Member> get members;
5337
external String? get inheritance;
5438
}
5539

56-
@JS()
57-
@staticInterop
58-
class Callback extends Named {}
59-
60-
extension CallbackExtension on Callback {
40+
extension type Callback._(JSObject _) implements Named {
6141
external IDLType get idlType;
62-
external JSArray get arguments;
42+
external JSArray<Argument> get arguments;
6343
}
6444

65-
@JS()
66-
@staticInterop
67-
class EnumValue {}
68-
69-
extension EnumValueExtension on EnumValue {
45+
extension type EnumValue._(JSObject _) implements JSObject {
7046
external String get type;
7147
external String get value;
7248
}
7349

74-
@JS()
75-
@staticInterop
76-
class Enum extends Named {}
77-
78-
@JS()
79-
@staticInterop
80-
class Typedef extends Named {}
50+
extension type Enum._(JSObject _) implements Named {}
8151

82-
extension TypedefExtension on Typedef {
52+
extension type Typedef._(JSObject _) implements Named {
8353
external IDLType get idlType;
8454
}
8555

86-
@JS()
87-
@staticInterop
88-
class Includes extends Node {}
89-
90-
extension IncludesExtension on Includes {
56+
extension type Includes._(JSObject _) implements Node {
9157
external String get target;
9258
external String get includes;
9359
}
9460

9561
/// All members inherit from the [Member] node.
96-
@JS()
97-
@staticInterop
98-
class Member {}
99-
100-
extension MemberExtension on Member {
62+
extension type Member._(JSObject _) implements JSObject {
10163
external String get type;
10264
}
10365

104-
@JS()
105-
@staticInterop
106-
class Argument {}
107-
108-
extension ArgumentExtension on Argument {
66+
extension type Argument._(JSObject _) implements JSObject {
10967
external String get type;
11068
@JS('default')
11169
external Value? get defaultValue;
@@ -115,63 +73,39 @@ extension ArgumentExtension on Argument {
11573
external String get name;
11674
}
11775

118-
@JS()
119-
@staticInterop
120-
class Operation extends Member {}
121-
122-
extension OperationExtension on Operation {
76+
extension type Operation._(JSObject _) implements Member {
12377
external String get special;
12478
external IDLType get idlType;
12579
external String get name;
126-
external JSArray get arguments;
80+
external JSArray<Argument> get arguments;
12781
}
12882

129-
@JS()
130-
@staticInterop
131-
class Constructor extends Member {}
132-
133-
extension ConstructorExtension on Constructor {
134-
external JSArray get arguments;
83+
extension type Constructor._(JSObject _) implements Member {
84+
external JSArray<Argument> get arguments;
13585
}
13686

137-
@JS()
138-
@staticInterop
139-
class Attribute extends Member {}
140-
141-
extension AttributeExtension on Attribute {
87+
extension type Attribute._(JSObject _) implements Member {
14288
external String get special;
14389
external bool get readonly;
14490
external IDLType get idlType;
14591
external String get name;
14692
}
14793

148-
@JS()
149-
@staticInterop
150-
class Field extends Member {}
151-
152-
extension FieldExtension on Field {
94+
extension type Field._(JSObject _) implements Member {
15395
external String get name;
15496
external bool get required;
15597
external IDLType get idlType;
15698
@JS('default')
15799
external Value? get defaultValue;
158100
}
159101

160-
@JS()
161-
@staticInterop
162-
class Value {}
163-
164-
extension ValueExtension on Value {
102+
extension type Value._(JSObject _) implements JSObject {
165103
external String get type;
166104
external JSAny? get value;
167105
external bool? get negative;
168106
}
169107

170-
@JS()
171-
@staticInterop
172-
class Constant extends Member {}
173-
174-
extension ConstantExtension on Constant {
108+
extension type Constant._(JSObject _) implements Member {
175109
external IDLType get idlType;
176110
external String get name;
177111
external Value get value;
@@ -182,23 +116,15 @@ extension ConstantExtension on Constant {
182116
/// * async iterable<>
183117
/// * maplike<>
184118
/// * setlike<>
185-
@JS()
186-
@staticInterop
187-
class MemberDeclaration {}
188-
189-
extension MemberDeclarationExtension on MemberDeclaration {
119+
extension type MemberDeclaration._(JSObject _) implements JSObject {
190120
external String get type;
191121
external IDLType get idlType;
192122
external bool get readonly;
193123
external bool get async;
194-
external JSArray get arguments;
124+
external JSArray<Argument> get arguments;
195125
}
196126

197-
@JS()
198-
@staticInterop
199-
class EOF {}
200-
201-
extension EOFExtension on EOF {
127+
extension type EOF._(JSObject _) implements JSObject {
202128
external String get type;
203129
external String get value;
204130
}

0 commit comments

Comments
 (0)