4
4
5
5
library dev_compiler.src.codegen.module_builder;
6
6
7
+ import 'package:path/path.dart' show relative;
8
+
7
9
import '../js/js_ast.dart' as JS;
8
10
import '../js/js_ast.dart' show js;
9
11
import '../options.dart' show ModuleFormat;
10
12
11
13
/// Helper that builds JS modules in a given [ModuleFormat] .
12
14
abstract class ModuleBuilder {
13
- final String _jsPath;
14
- final String _jsModuleValue;
15
- final JS .Identifier _exportsVar;
16
15
final List <String > _exports = < String > [];
17
16
final List <_ModuleImport > _imports = < _ModuleImport > [];
18
17
19
- ModuleBuilder ._(this ._jsPath, this ._jsModuleValue, this ._exportsVar );
18
+ ModuleBuilder ._();
20
19
21
20
/// Returns a [format] -specific [ModuleBuilder] .
22
21
/// - [jsPath] is the path of the module being built.
@@ -25,13 +24,12 @@ abstract class ModuleBuilder {
25
24
/// library directive). It is null in any other case.
26
25
/// - [exportsVar] is the name of the object on which items are exported. Lazy
27
26
/// variables and constants are assumed to be declared on this instance.
28
- factory ModuleBuilder (String jsPath, String jsModuleValue,
29
- JS .Identifier exportsVar, ModuleFormat format) {
27
+ factory ModuleBuilder (ModuleFormat format) {
30
28
switch (format) {
31
29
case ModuleFormat .legacy:
32
- return new LegacyModuleBuilder (jsPath, jsModuleValue, exportsVar );
30
+ return new LegacyModuleBuilder ();
33
31
case ModuleFormat .es6:
34
- return new ES6ModuleBuilder (jsPath, jsModuleValue, exportsVar );
32
+ return new ES6ModuleBuilder ();
35
33
}
36
34
}
37
35
@@ -48,7 +46,8 @@ abstract class ModuleBuilder {
48
46
}
49
47
50
48
/// Builds a program out of menu items.
51
- JS .Program build (List <JS .ModuleItem > moduleItems);
49
+ JS .Program build (String jsPath, String jsModuleValue,
50
+ JS .Identifier exportsVar, Iterable <JS .ModuleItem > moduleItems);
52
51
}
53
52
54
53
class _ModuleImport {
@@ -63,14 +62,14 @@ class _ModuleImport {
63
62
64
63
/// Generates modules for with DDC's `dart_library.js` loading mechanism.
65
64
class LegacyModuleBuilder extends ModuleBuilder {
66
- LegacyModuleBuilder (jsPath, _jsModuleValue, _exportsVar)
67
- : super ._(jsPath, _jsModuleValue, _exportsVar);
65
+ LegacyModuleBuilder () : super ._();
68
66
69
- JS .Program build (List <JS .ModuleItem > moduleItems) {
67
+ JS .Program build (String jsPath, String jsModuleValue,
68
+ JS .Identifier exportsVar, List <JS .ModuleItem > moduleItems) {
70
69
// TODO(jmesserly): it would be great to run the renamer on the body,
71
70
// then figure out if we really need each of these parameters.
72
71
// See ES6 modules: https://github.com/dart-lang/dev_compiler/issues/34
73
- var params = [_exportsVar ];
72
+ var params = [exportsVar ];
74
73
var lazyParams = [];
75
74
76
75
var imports = < JS .Expression > [];
@@ -90,16 +89,16 @@ class LegacyModuleBuilder extends ModuleBuilder {
90
89
// TODO(jmesserly): make these immutable in JS?
91
90
for (var name in _exports) {
92
91
moduleStatements
93
- .add (js.statement ('#.# = #;' , [_exportsVar , name, name]));
92
+ .add (js.statement ('#.# = #;' , [exportsVar , name, name]));
94
93
}
95
94
}
96
95
97
96
var module =
98
97
js.call ("function(#) { 'use strict'; #; }" , [params, moduleStatements]);
99
98
100
99
var moduleDef = js.statement ("dart_library.library(#, #, #, #, #)" , [
101
- js.string (_jsPath , "'" ),
102
- _jsModuleValue ?? new JS .LiteralNull (),
100
+ js.string (jsPath , "'" ),
101
+ jsModuleValue ?? new JS .LiteralNull (),
103
102
js.commentExpression (
104
103
"Imports" , new JS .ArrayInitializer (imports, multiline: true )),
105
104
js.commentExpression ("Lazy imports" ,
@@ -110,25 +109,31 @@ class LegacyModuleBuilder extends ModuleBuilder {
110
109
}
111
110
}
112
111
112
+ String _relativeModuleName (String moduleName, {String from}) {
113
+ var relativeName = relative ('/' + moduleName, from: '/' + from + '/..' );
114
+ return relativeName.startsWith ('.' ) ? relativeName : './$relativeName ' ;
115
+ }
116
+
113
117
/// Generates ES6 modules.
114
118
// TODO(ochafik): Break strong dep cycles to accommodate the Closure Compiler.
115
119
class ES6ModuleBuilder extends ModuleBuilder {
116
- ES6ModuleBuilder (jsPath, _jsModuleValue, _exportsVar)
117
- : super ._(jsPath, _jsModuleValue, _exportsVar);
120
+ ES6ModuleBuilder () : super ._();
118
121
119
- JS .Program build (List <JS .ModuleItem > moduleItems) {
122
+ JS .Program build (String jsPath, String jsModuleValue,
123
+ JS .Identifier exportsVar, Iterable <JS .ModuleItem > moduleItems) {
120
124
var moduleStatements = < JS .ModuleItem > [
121
125
// Lazy declarations may reference exports.
122
- js.statement ("const # = {};" , [_exportsVar ])
126
+ js.statement ("const # = {};" , [exportsVar ])
123
127
];
124
128
125
129
// TODO(jmesserly): it would be great to run the renamer on the body,
126
130
// then figure out if we really need each of these parameters.
127
131
// See ES6 modules: https://github.com/dart-lang/dev_compiler/issues/34
128
132
for (var i in _imports) {
133
+ var moduleName = js.string (_relativeModuleName (i.name, from: jsPath));
129
134
// TODO(ochafik): laziness, late binding, etc, to support Closure...
130
135
moduleStatements.add (new JS .ImportDeclaration (
131
- defaultBinding: i.libVar, from: js. string (i.name) ));
136
+ defaultBinding: i.libVar, from: moduleName ));
132
137
}
133
138
134
139
moduleStatements.addAll (_flattenBlocks (moduleItems));
@@ -138,12 +143,12 @@ class ES6ModuleBuilder extends ModuleBuilder {
138
143
// TODO(jmesserly): make these immutable in JS?
139
144
for (var name in _exports) {
140
145
moduleStatements
141
- .add (js.statement ('#.# = #;' , [_exportsVar , name, name]));
146
+ .add (js.statement ('#.# = #;' , [exportsVar , name, name]));
142
147
}
143
148
moduleStatements
144
- .add (new JS .ExportDeclaration (_exportsVar , isDefault: true ));
149
+ .add (new JS .ExportDeclaration (exportsVar , isDefault: true ));
145
150
}
146
- // TODO(ochafik): What to do of _jsModuleValue ?
151
+ // TODO(ochafik): What to do of jsModuleValue ?
147
152
return new JS .Program (moduleStatements);
148
153
}
149
154
}
@@ -155,4 +160,5 @@ class ES6ModuleBuilder extends ModuleBuilder {
155
160
// are generated from [JSCodegenVisitor], instead of composing them with
156
161
// [_statements]).
157
162
Iterable <JS .ModuleItem > _flattenBlocks (List <JS .ModuleItem > stats) =>
158
- stats.expand ((item) => item is JS .Block ? item.statements : [item]);
163
+ stats.expand ((item) => item is JS .Block
164
+ ? _flattenBlocks (item.statements) : [item]);
0 commit comments