forked from dart-lang/web
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcli.dart
More file actions
131 lines (118 loc) · 4.63 KB
/
Copy pathcli.dart
File metadata and controls
131 lines (118 loc) · 4.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:collection';
import 'dart:io';
import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/element/element2.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:io/ansi.dart' as ansi;
import 'package:path/path.dart' as p;
final bindingsGeneratorPath = p.fromUri(Platform.script.resolve('../lib/src'));
Future<void> compileDartMain({String? langVersion, String? dir}) async {
await runProc(
Platform.executable,
[
'compile',
'js',
'--enable-asserts',
'--server-mode',
if (langVersion != null) '-DlanguageVersion=$langVersion',
'dart_main.dart',
'-o',
'dart_main.js',
],
workingDirectory: dir ?? bindingsGeneratorPath,
);
}
Future<Process> runProcWithResult(String executable, List<String> arguments,
{required String workingDirectory}) async {
print(ansi.styleBold.wrap(['*', executable, ...arguments].join(' ')));
return Process.start(
executable,
arguments,
runInShell: Platform.isWindows,
workingDirectory: workingDirectory,
);
}
Future<void> runProc(String executable, List<String> arguments,
{required String workingDirectory, bool detached = false}) async {
print(ansi.styleBold.wrap(['*', executable, ...arguments].join(' ')));
final proc = await Process.start(
executable,
arguments,
mode: detached ? ProcessStartMode.detached : ProcessStartMode.inheritStdio,
runInShell: Platform.isWindows,
workingDirectory: workingDirectory,
);
final procExit = await proc.exitCode;
if (procExit != 0) {
throw ProcessException(executable, arguments, 'Process failed', procExit);
}
}
Future<File> createJsTypeSupertypeContext() async {
final contextFile =
await File(p.join(bindingsGeneratorPath, '_js_supertypes_src.dart'))
.create();
await contextFile.writeAsString('''
import 'dart:js_interop';
@JS()
external JSPromise get promise;
''');
return contextFile;
}
/// Generates a map of the JS type hierarchy defined in `dart:js_interop` that's
/// used by both translators.
Future<void> generateJsTypeSupertypes(String contextFile) async {
// Use a file that uses `dart:js_interop` for analysis.
final contextCollection =
AnalysisContextCollection(includedPaths: [contextFile]);
final dartJsInterop = (await contextCollection.contexts.single.currentSession
.getLibraryByUri('dart:js_interop') as LibraryElementResult)
.element2;
final definedNames = dartJsInterop.exportNamespace.definedNames2;
// `SplayTreeMap` to avoid moving types around in `dart:js_interop` affecting
// the code generation.
final jsTypeSupertypes = SplayTreeMap<String, String?>();
for (final name in definedNames.keys) {
final element = definedNames[name];
if (element is ExtensionTypeElement2) {
// JS types are any extension type that starts with 'JS' in
// `dart:js_interop`.
bool isJSType(InterfaceElement2 element) =>
element is ExtensionTypeElement2 &&
element.library2 == dartJsInterop &&
element.name3!.startsWith('JS');
if (!isJSType(element)) continue;
String? parentJsType;
final supertype = element.supertype;
final immediateSupertypes = <InterfaceType>[
if (supertype != null) supertype,
...element.interfaces,
]..removeWhere((supertype) => supertype.isDartCoreObject);
// We should have at most one non-trivial supertype.
assert(immediateSupertypes.length <= 1);
for (final supertype in immediateSupertypes) {
if (isJSType(supertype.element3)) {
parentJsType = "'${supertype.element3.name3!}'";
}
}
// Ensure that the hierarchy forms a tree.
assert((parentJsType == null) == (name == 'JSAny'));
jsTypeSupertypes["'$name'"] = parentJsType;
}
}
final jsTypeSupertypesScript = '''
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// Do not modify by hand.
const Map<String, String?> jsTypeSupertypes = {
${jsTypeSupertypes.entries.map((e) => " ${e.key}: ${e.value},").join('\n')}
};
''';
final jsTypeSupertypesPath =
p.join(bindingsGeneratorPath, 'js_type_supertypes.dart');
await File(jsTypeSupertypesPath).writeAsString(jsTypeSupertypesScript);
}