Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(483)

Side by Side Diff: lib/src/codegen/js_codegen.dart

Issue 1486473002: Convert dart_utils.js to input_sdk/lib/_internal/utils.dart (#310) (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library dev_compiler.src.codegen.js_codegen; 5 library dev_compiler.src.codegen.js_codegen;
6 6
7 import 'dart:collection' show HashSet, HashMap, SplayTreeSet; 7 import 'dart:collection' show HashSet, HashMap, SplayTreeSet;
8 8
9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; 9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator;
10 import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator; 10 import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator;
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 ConstFieldVisitor _constField; 97 ConstFieldVisitor _constField;
98 98
99 ModuleItemLoadOrder _loader; 99 ModuleItemLoadOrder _loader;
100 100
101 /// _interceptors.JSArray<E>, used for List literals. 101 /// _interceptors.JSArray<E>, used for List literals.
102 ClassElement _jsArray; 102 ClassElement _jsArray;
103 103
104 /// The default value of the module object. See [visitLibraryDirective]. 104 /// The default value of the module object. See [visitLibraryDirective].
105 String _jsModuleValue; 105 String _jsModuleValue;
106 106
107 bool _isDartUtils;
108
107 Map<String, DartType> _objectMembers; 109 Map<String, DartType> _objectMembers;
108 110
109 JSCodegenVisitor(AbstractCompiler compiler, this.rules, this.currentLibrary, 111 JSCodegenVisitor(AbstractCompiler compiler, this.rules, this.currentLibrary,
110 this._extensionTypes, this._fieldsNeedingStorage) 112 this._extensionTypes, this._fieldsNeedingStorage)
111 : compiler = compiler, 113 : compiler = compiler,
112 options = compiler.options.codegenOptions, 114 options = compiler.options.codegenOptions,
113 _types = compiler.context.typeProvider { 115 _types = compiler.context.typeProvider {
114 _loader = new ModuleItemLoadOrder(_emitModuleItem); 116 _loader = new ModuleItemLoadOrder(_emitModuleItem);
115 117
116 var context = compiler.context; 118 var context = compiler.context;
117 var src = context.sourceFactory.forUri('dart:_interceptors'); 119 var src = context.sourceFactory.forUri('dart:_interceptors');
118 var interceptors = context.computeLibraryElement(src); 120 var interceptors = context.computeLibraryElement(src);
119 _jsArray = interceptors.getType('JSArray'); 121 _jsArray = interceptors.getType('JSArray');
122 _isDartUtils = currentLibrary.isInSdk &&
Jennifer Messerly 2015/11/30 18:54:11 you shouldn't need the isInSdk check, it's just ch
123 currentLibrary.source.uri.toString() == 'dart:_utils';
120 124
121 _objectMembers = getObjectMemberMap(types); 125 _objectMembers = getObjectMemberMap(types);
122 } 126 }
123 127
124 TypeProvider get types => rules.provider; 128 TypeProvider get types => rules.provider;
125 129
126 JS.Program emitLibrary(LibraryUnit library) { 130 JS.Program emitLibrary(LibraryUnit library) {
127 // Modify the AST to make coercions explicit. 131 // Modify the AST to make coercions explicit.
128 new CoercionReifier(library, rules).reify(); 132 new CoercionReifier(library, rules).reify();
129 133
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
189 // TODO(jmesserly): it would be great to run the renamer on the body, 193 // TODO(jmesserly): it would be great to run the renamer on the body,
190 // then figure out if we really need each of these parameters. 194 // then figure out if we really need each of these parameters.
191 // See ES6 modules: https://github.com/dart-lang/dev_compiler/issues/34 195 // See ES6 modules: https://github.com/dart-lang/dev_compiler/issues/34
192 var params = [_exportsVar, _runtimeLibVar]; 196 var params = [_exportsVar, _runtimeLibVar];
193 var processImport = 197 var processImport =
194 (LibraryElement library, JS.TemporaryId temp, List list) { 198 (LibraryElement library, JS.TemporaryId temp, List list) {
195 params.add(temp); 199 params.add(temp);
196 list.add(js.string(compiler.getModuleName(library.source.uri), "'")); 200 list.add(js.string(compiler.getModuleName(library.source.uri), "'"));
197 }; 201 };
198 202
199 var imports = <JS.Expression>[js.string('dart/_runtime')]; 203 var needsDartRuntime = !_isDartUtils;
204
205 var imports = <JS.Expression>[];
206 var moduleStatements = <JS.Statement>[];
207 if (needsDartRuntime) {
208 imports.add(js.string('dart/_runtime'));
209
210 var dartxImport =
211 js.statement("let # = #.dartx;", [_dartxVar, _runtimeLibVar]);
Jennifer Messerly 2015/11/30 18:54:11 const?
212 moduleStatements.add(dartxImport);
213 }
214 moduleStatements.addAll(_moduleItems);
215
200 _imports.forEach((library, temp) { 216 _imports.forEach((library, temp) {
201 if (_loader.libraryIsLoaded(library)) { 217 if (_loader.libraryIsLoaded(library)) {
202 processImport(library, temp, imports); 218 processImport(library, temp, imports);
203 } 219 }
204 }); 220 });
205 221
206 var lazyImports = <JS.Expression>[]; 222 var lazyImports = <JS.Expression>[];
207 _imports.forEach((library, temp) { 223 _imports.forEach((library, temp) {
208 if (!_loader.libraryIsLoaded(library)) { 224 if (!_loader.libraryIsLoaded(library)) {
209 processImport(library, temp, lazyImports); 225 processImport(library, temp, lazyImports);
210 } 226 }
211 }); 227 });
212 228
213 var dartxImport = 229 var module =
214 js.statement("let # = #.dartx;", [_dartxVar, _runtimeLibVar]); 230 js.call("function(#) { 'use strict'; #; }", [params, moduleStatements]);
215
216 var module = js.call("function(#) { 'use strict'; #; #; }",
217 [params, dartxImport, _moduleItems]);
218 231
219 var moduleDef = js.statement("dart_library.library(#, #, #, #, #)", [ 232 var moduleDef = js.statement("dart_library.library(#, #, #, #, #)", [
220 js.string(jsPath, "'"), 233 js.string(jsPath, "'"),
221 _jsModuleValue ?? new JS.LiteralNull(), 234 _jsModuleValue ?? new JS.LiteralNull(),
222 js.commentExpression( 235 js.commentExpression(
223 "Imports", new JS.ArrayInitializer(imports, multiline: true)), 236 "Imports", new JS.ArrayInitializer(imports, multiline: true)),
224 js.commentExpression("Lazy imports", 237 js.commentExpression("Lazy imports",
225 new JS.ArrayInitializer(lazyImports, multiline: true)), 238 new JS.ArrayInitializer(lazyImports, multiline: true)),
226 module 239 module
227 ]); 240 ]);
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
282 .map((i) => i.name) 295 .map((i) => i.name)
283 .where((s) => !currentLibNames.containsKey(s)) 296 .where((s) => !currentLibNames.containsKey(s))
284 .map((s) => js.string(s, "'"))); 297 .map((s) => js.string(s, "'")));
285 } 298 }
286 if (hide != null) { 299 if (hide != null) {
287 hiddenNames.addAll(hide.hiddenNames.map((i) => js.string(i.name, "'"))); 300 hiddenNames.addAll(hide.hiddenNames.map((i) => js.string(i.name, "'")));
288 } 301 }
289 args.add(new JS.ArrayInitializer(shownNames)); 302 args.add(new JS.ArrayInitializer(shownNames));
290 args.add(new JS.ArrayInitializer(hiddenNames)); 303 args.add(new JS.ArrayInitializer(hiddenNames));
291 } 304 }
292 _moduleItems.add(js.statement('dart.export(#);', [args])); 305 _moduleItems.add(js.statement('dart.export_(#);', [args]));
293 } 306 }
294 307
295 JS.Identifier _initSymbol(JS.Identifier id) { 308 JS.Identifier _initSymbol(JS.Identifier id) {
296 var s = js.statement('let # = $_SYMBOL(#);', [id, js.string(id.name, "'")]); 309 var s = js.statement('let # = $_SYMBOL(#);', [id, js.string(id.name, "'")]);
297 _moduleItems.add(s); 310 _moduleItems.add(s);
298 return id; 311 return id;
299 } 312 }
300 313
301 // TODO(jmesserly): this is a temporary workaround for `Symbol` in core, 314 // TODO(jmesserly): this is a temporary workaround for `Symbol` in core,
302 // until we have better name tracking. 315 // until we have better name tracking.
(...skipping 974 matching lines...) Expand 10 before | Expand all | Expand 10 after
1277 // Add these later so we can use getter/setter syntax. 1290 // Add these later so we can use getter/setter syntax.
1278 _properties.add(node); 1291 _properties.add(node);
1279 return null; 1292 return null;
1280 } 1293 }
1281 1294
1282 var body = <JS.Statement>[]; 1295 var body = <JS.Statement>[];
1283 _flushLibraryProperties(body); 1296 _flushLibraryProperties(body);
1284 1297
1285 var name = node.name.name; 1298 var name = node.name.name;
1286 1299
1300 var fn = _visit(node.functionExpression);
1301 bool needsTagging = true;
1302 if (currentLibrary.isInSdk &&
Jennifer Messerly 2015/11/30 18:54:11 I try and avoid LibraryElement.isInSdk, because an
ochafik 2015/12/01 14:41:03 Done.
1303 _isInlineJSBody(node.functionExpression.body)) {
1304 fn = _simplifyFun(fn);
1305 needsTagging = !_isDartUtils;
1306 }
1287 var id = new JS.Identifier(name); 1307 var id = new JS.Identifier(name);
1288 body.add(annotate( 1308 body.add(annotate(
1289 new JS.FunctionDeclaration(id, _visit(node.functionExpression)), 1309 new JS.FunctionDeclaration(id, fn),
1290 node.element)); 1310 node.element));
1291 body.add(_emitFunctionTagged(id, node.element.type, topLevel: true) 1311 if (needsTagging) {
1292 .toStatement()); 1312 body.add(_emitFunctionTagged(id, node.element.type, topLevel: true)
1313 .toStatement());
1314 }
1293 1315
1294 if (isPublic(name)) _addExport(name); 1316 if (isPublic(name)) _addExport(name);
1295 return _statement(body); 1317 return _statement(body);
1296 } 1318 }
1297 1319
1320 /// Simplify `f(x) => (function() { ... })()` to `f(x) => { ... }`.
1321 ///
1322 /// This is useful for runtime utils written with JS intrinsics, e.g.
1323 /// `foo(x) => JS('', '(function() { let x = #; ... })()', x);`.
1324 JS.Fun _simplifyFun(JS.Fun fn) {
Jennifer Messerly 2015/11/30 18:54:11 love this! Regarding: JS('', '(function() { l
ochafik 2015/12/01 14:41:03 I was equally bothered by `let x = x` and the sile
1325 if (fn.body is JS.Block && fn.body.statements.length == 1) {
1326 var stat = fn.body.statements.single;
1327 if (stat is JS.Return) {
1328 if (stat.value is JS.Call) {
1329 JS.Call call = stat.value;
1330 if (call.target is JS.Fun && call.arguments.isEmpty) {
1331 JS.Fun innerFun = call.target;
1332 return new JS.Fun(fn.params, innerFun.body);
1333 }
1334 }
1335 }
1336 }
1337 return fn;
1338 }
1339
1340 bool _isInlineJSBody(FunctionBody body) {
Jennifer Messerly 2015/11/30 18:54:11 It might be nice to combine this with the simplifi
ochafik 2015/12/01 14:41:03 I can't find a very clean way to combine them (hav
1341 bool isJsInvocation(Expression expr) =>
1342 expr is MethodInvocation &&
1343 isInlineJS(expr.methodName.staticElement);
1344
1345 if (body is ExpressionFunctionBody) {
1346 return isJsInvocation(body.expression);
1347 } else if (body is BlockFunctionBody) {
1348 if (body.block.statements.length == 1) {
1349 var stat = body.block.statements.single;
1350 if (stat is ReturnStatement) {
1351 return isJsInvocation(stat.expression);
1352 }
1353 }
1354 }
1355 return false;
1356 }
1357
1298 JS.Method _emitTopLevelProperty(FunctionDeclaration node) { 1358 JS.Method _emitTopLevelProperty(FunctionDeclaration node) {
1299 var name = node.name.name; 1359 var name = node.name.name;
1300 return annotate( 1360 return annotate(
1301 new JS.Method(_propertyName(name), _visit(node.functionExpression), 1361 new JS.Method(_propertyName(name), _visit(node.functionExpression),
1302 isGetter: node.isGetter, isSetter: node.isSetter), 1362 isGetter: node.isGetter, isSetter: node.isSetter),
1303 node.element); 1363 node.element);
1304 } 1364 }
1305 1365
1306 bool _executesAtTopLevel(AstNode node) { 1366 bool _executesAtTopLevel(AstNode node) {
1307 var ancestor = node.getAncestor((n) => n is FunctionBody || 1367 var ancestor = node.getAncestor((n) => n is FunctionBody ||
(...skipping 2039 matching lines...) Expand 10 before | Expand all | Expand 10 after
3347 3407
3348 /// A special kind of element created by the compiler, signifying a temporary 3408 /// A special kind of element created by the compiler, signifying a temporary
3349 /// variable. These objects use instance equality, and should be shared 3409 /// variable. These objects use instance equality, and should be shared
3350 /// everywhere in the tree where they are treated as the same variable. 3410 /// everywhere in the tree where they are treated as the same variable.
3351 class TemporaryVariableElement extends LocalVariableElementImpl { 3411 class TemporaryVariableElement extends LocalVariableElementImpl {
3352 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); 3412 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name);
3353 3413
3354 int get hashCode => identityHashCode(this); 3414 int get hashCode => identityHashCode(this);
3355 bool operator ==(Object other) => identical(this, other); 3415 bool operator ==(Object other) => identical(this, other);
3356 } 3416 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698