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

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: Rebased 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
« no previous file with comments | « lib/runtime/dart_utils.js ('k') | lib/src/compiler.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 19 matching lines...) Expand all
30 import '../utils.dart'; 30 import '../utils.dart';
31 31
32 import 'code_generator.dart'; 32 import 'code_generator.dart';
33 import 'js_field_storage.dart'; 33 import 'js_field_storage.dart';
34 import 'js_interop.dart'; 34 import 'js_interop.dart';
35 import 'js_names.dart' as JS; 35 import 'js_names.dart' as JS;
36 import 'js_metalet.dart' as JS; 36 import 'js_metalet.dart' as JS;
37 import 'js_module_item_order.dart'; 37 import 'js_module_item_order.dart';
38 import 'js_printer.dart' show writeJsLibrary; 38 import 'js_printer.dart' show writeJsLibrary;
39 import 'side_effect_analysis.dart'; 39 import 'side_effect_analysis.dart';
40 import 'package:collection/equality.dart';
40 41
41 // Various dynamic helpers we call. 42 // Various dynamic helpers we call.
42 // If renaming these, make sure to check other places like the 43 // If renaming these, make sure to check other places like the
43 // _runtime.js file and comments. 44 // _runtime.js file and comments.
44 // TODO(jmesserly): ideally we'd have a "dynamic call" dart library we can 45 // TODO(jmesserly): ideally we'd have a "dynamic call" dart library we can
45 // import and generate calls to, rather than dart_runtime.js 46 // import and generate calls to, rather than dart_runtime.js
46 const DPUT = 'dput'; 47 const DPUT = 'dput';
47 const DLOAD = 'dload'; 48 const DLOAD = 'dload';
48 const DINDEX = 'dindex'; 49 const DINDEX = 'dindex';
49 const DSETINDEX = 'dsetindex'; 50 const DSETINDEX = 'dsetindex';
50 const DCALL = 'dcall'; 51 const DCALL = 'dcall';
51 const DSEND = 'dsend'; 52 const DSEND = 'dsend';
52 53
54 const ListEquality _listEquality = const ListEquality();
55
53 class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator { 56 class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
54 final AbstractCompiler compiler; 57 final AbstractCompiler compiler;
55 final CodegenOptions options; 58 final CodegenOptions options;
56 final TypeRules rules; 59 final TypeRules rules;
57 final LibraryElement currentLibrary; 60 final LibraryElement currentLibrary;
58 61
59 /// The global extension type table. 62 /// The global extension type table.
60 final HashSet<ClassElement> _extensionTypes; 63 final HashSet<ClassElement> _extensionTypes;
61 64
62 /// Information that is precomputed for this library, indicates which fields 65 /// Information that is precomputed for this library, indicates which fields
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 ConstFieldVisitor _constField; 100 ConstFieldVisitor _constField;
98 101
99 ModuleItemLoadOrder _loader; 102 ModuleItemLoadOrder _loader;
100 103
101 /// _interceptors.JSArray<E>, used for List literals. 104 /// _interceptors.JSArray<E>, used for List literals.
102 ClassElement _jsArray; 105 ClassElement _jsArray;
103 106
104 /// The default value of the module object. See [visitLibraryDirective]. 107 /// The default value of the module object. See [visitLibraryDirective].
105 String _jsModuleValue; 108 String _jsModuleValue;
106 109
110 bool _isDartUtils;
111
107 Map<String, DartType> _objectMembers; 112 Map<String, DartType> _objectMembers;
108 113
109 JSCodegenVisitor(AbstractCompiler compiler, this.rules, this.currentLibrary, 114 JSCodegenVisitor(AbstractCompiler compiler, this.rules, this.currentLibrary,
110 this._extensionTypes, this._fieldsNeedingStorage) 115 this._extensionTypes, this._fieldsNeedingStorage)
111 : compiler = compiler, 116 : compiler = compiler,
112 options = compiler.options.codegenOptions, 117 options = compiler.options.codegenOptions,
113 _types = compiler.context.typeProvider { 118 _types = compiler.context.typeProvider {
114 _loader = new ModuleItemLoadOrder(_emitModuleItem); 119 _loader = new ModuleItemLoadOrder(_emitModuleItem);
115 120
116 var context = compiler.context; 121 var context = compiler.context;
117 var src = context.sourceFactory.forUri('dart:_interceptors'); 122 var src = context.sourceFactory.forUri('dart:_interceptors');
118 var interceptors = context.computeLibraryElement(src); 123 var interceptors = context.computeLibraryElement(src);
119 _jsArray = interceptors.getType('JSArray'); 124 _jsArray = interceptors.getType('JSArray');
125 _isDartUtils = currentLibrary.source.uri.toString() == 'dart:_utils';
120 126
121 _objectMembers = getObjectMemberMap(types); 127 _objectMembers = getObjectMemberMap(types);
122 } 128 }
123 129
124 TypeProvider get types => rules.provider; 130 TypeProvider get types => rules.provider;
125 131
126 JS.Program emitLibrary(LibraryUnit library) { 132 JS.Program emitLibrary(LibraryUnit library) {
127 // Modify the AST to make coercions explicit. 133 // Modify the AST to make coercions explicit.
128 new CoercionReifier(library, rules).reify(); 134 new CoercionReifier(library, rules).reify();
129 135
(...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, 195 // 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. 196 // then figure out if we really need each of these parameters.
191 // See ES6 modules: https://github.com/dart-lang/dev_compiler/issues/34 197 // See ES6 modules: https://github.com/dart-lang/dev_compiler/issues/34
192 var params = [_exportsVar, _runtimeLibVar]; 198 var params = [_exportsVar, _runtimeLibVar];
193 var processImport = 199 var processImport =
194 (LibraryElement library, JS.TemporaryId temp, List list) { 200 (LibraryElement library, JS.TemporaryId temp, List list) {
195 params.add(temp); 201 params.add(temp);
196 list.add(js.string(compiler.getModuleName(library.source.uri), "'")); 202 list.add(js.string(compiler.getModuleName(library.source.uri), "'"));
197 }; 203 };
198 204
199 var imports = <JS.Expression>[js.string('dart/_runtime')]; 205 var needsDartRuntime = !_isDartUtils;
206
207 var imports = <JS.Expression>[];
208 var moduleStatements = <JS.Statement>[];
209 if (needsDartRuntime) {
210 imports.add(js.string('dart/_runtime'));
211
212 var dartxImport =
213 js.statement("let # = #.dartx;", [_dartxVar, _runtimeLibVar]);
214 moduleStatements.add(dartxImport);
215 }
216 moduleStatements.addAll(_moduleItems);
217
200 _imports.forEach((library, temp) { 218 _imports.forEach((library, temp) {
201 if (_loader.libraryIsLoaded(library)) { 219 if (_loader.libraryIsLoaded(library)) {
202 processImport(library, temp, imports); 220 processImport(library, temp, imports);
203 } 221 }
204 }); 222 });
205 223
206 var lazyImports = <JS.Expression>[]; 224 var lazyImports = <JS.Expression>[];
207 _imports.forEach((library, temp) { 225 _imports.forEach((library, temp) {
208 if (!_loader.libraryIsLoaded(library)) { 226 if (!_loader.libraryIsLoaded(library)) {
209 processImport(library, temp, lazyImports); 227 processImport(library, temp, lazyImports);
210 } 228 }
211 }); 229 });
212 230
213 var dartxImport = 231 var module =
214 js.statement("let # = #.dartx;", [_dartxVar, _runtimeLibVar]); 232 js.call("function(#) { 'use strict'; #; }", [params, moduleStatements]);
215
216 var module = js.call("function(#) { 'use strict'; #; #; }",
217 [params, dartxImport, _moduleItems]);
218 233
219 var moduleDef = js.statement("dart_library.library(#, #, #, #, #)", [ 234 var moduleDef = js.statement("dart_library.library(#, #, #, #, #)", [
220 js.string(jsPath, "'"), 235 js.string(jsPath, "'"),
221 _jsModuleValue ?? new JS.LiteralNull(), 236 _jsModuleValue ?? new JS.LiteralNull(),
222 js.commentExpression( 237 js.commentExpression(
223 "Imports", new JS.ArrayInitializer(imports, multiline: true)), 238 "Imports", new JS.ArrayInitializer(imports, multiline: true)),
224 js.commentExpression("Lazy imports", 239 js.commentExpression("Lazy imports",
225 new JS.ArrayInitializer(lazyImports, multiline: true)), 240 new JS.ArrayInitializer(lazyImports, multiline: true)),
226 module 241 module
227 ]); 242 ]);
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
282 .map((i) => i.name) 297 .map((i) => i.name)
283 .where((s) => !currentLibNames.containsKey(s)) 298 .where((s) => !currentLibNames.containsKey(s))
284 .map((s) => js.string(s, "'"))); 299 .map((s) => js.string(s, "'")));
285 } 300 }
286 if (hide != null) { 301 if (hide != null) {
287 hiddenNames.addAll(hide.hiddenNames.map((i) => js.string(i.name, "'"))); 302 hiddenNames.addAll(hide.hiddenNames.map((i) => js.string(i.name, "'")));
288 } 303 }
289 args.add(new JS.ArrayInitializer(shownNames)); 304 args.add(new JS.ArrayInitializer(shownNames));
290 args.add(new JS.ArrayInitializer(hiddenNames)); 305 args.add(new JS.ArrayInitializer(hiddenNames));
291 } 306 }
292 _moduleItems.add(js.statement('dart.export(#);', [args])); 307 _moduleItems.add(js.statement('dart.export_(#);', [args]));
293 } 308 }
294 309
295 JS.Identifier _initSymbol(JS.Identifier id) { 310 JS.Identifier _initSymbol(JS.Identifier id) {
296 var s = 311 var s =
297 js.statement('const # = $_SYMBOL(#);', [id, js.string(id.name, "'")]); 312 js.statement('const # = $_SYMBOL(#);', [id, js.string(id.name, "'")]);
298 _moduleItems.add(s); 313 _moduleItems.add(s);
299 return id; 314 return id;
300 } 315 }
301 316
302 // TODO(jmesserly): this is a temporary workaround for `Symbol` in core, 317 // TODO(jmesserly): this is a temporary workaround for `Symbol` in core,
(...skipping 975 matching lines...) Expand 10 before | Expand all | Expand 10 after
1278 // Add these later so we can use getter/setter syntax. 1293 // Add these later so we can use getter/setter syntax.
1279 _properties.add(node); 1294 _properties.add(node);
1280 return null; 1295 return null;
1281 } 1296 }
1282 1297
1283 var body = <JS.Statement>[]; 1298 var body = <JS.Statement>[];
1284 _flushLibraryProperties(body); 1299 _flushLibraryProperties(body);
1285 1300
1286 var name = node.name.name; 1301 var name = node.name.name;
1287 1302
1303 var fn = _visit(node.functionExpression);
1304 bool needsTagging = true;
1305
1306 if (currentLibrary.source.isInSystemLibrary &&
1307 _isInlineJSFunction(node.functionExpression)) {
1308 fn = _simplifyPassThroughArrowFunCallBody(fn);
1309 needsTagging = !_isDartUtils;
1310 }
1311
1288 var id = new JS.Identifier(name); 1312 var id = new JS.Identifier(name);
1289 body.add(annotate( 1313 body.add(annotate(new JS.FunctionDeclaration(id, fn), node.element));
1290 new JS.FunctionDeclaration(id, _visit(node.functionExpression)), 1314 if (needsTagging) {
1291 node.element)); 1315 body.add(_emitFunctionTagged(id, node.element.type, topLevel: true)
1292 body.add(_emitFunctionTagged(id, node.element.type, topLevel: true) 1316 .toStatement());
1293 .toStatement()); 1317 }
1294 1318
1295 if (isPublic(name)) _addExport(name); 1319 if (isPublic(name)) _addExport(name);
1296 return _statement(body); 1320 return _statement(body);
1297 } 1321 }
1298 1322
1323 bool _isInlineJSFunction(FunctionExpression functionExpression) {
1324 bool isJsInvocation(Expression expr) =>
1325 expr is MethodInvocation && isInlineJS(expr.methodName.staticElement);
1326
1327 var body = functionExpression.body;
1328 if (body is ExpressionFunctionBody) {
1329 return isJsInvocation(body.expression);
1330 } else if (body is BlockFunctionBody) {
1331 if (body.block.statements.length == 1) {
1332 var stat = body.block.statements.single;
1333 if (stat is ReturnStatement) {
1334 return isJsInvocation(stat.expression);
1335 }
1336 }
1337 }
1338 return false;
1339 }
1340
1341 // Simplify `(args) => ((x, y) => { ... })(x, y)` to `(args) => { ... }`.
1342 // Note: we don't check if the top-level args match the ones passed through
1343 // the arrow function, which allows silently passing args through to the
1344 // body (which only works if we don't do weird renamings of Dart params).
1345 JS.Fun _simplifyPassThroughArrowFunCallBody(JS.Fun fn) {
1346 String getIdent(JS.Node node) => node is JS.Identifier ? node.name : null;
1347 List<String> getIdents(List params) =>
1348 params.map(getIdent).toList(growable: false);
1349
1350 if (fn.body is JS.Block && fn.body.statements.length == 1) {
1351 var stat = fn.body.statements.single;
1352 if (stat is JS.Return && stat.value is JS.Call) {
1353 JS.Call call = stat.value;
1354 if (call.target is JS.ArrowFun) {
1355 var passedArgs = getIdents(call.arguments);
1356 JS.ArrowFun innerFun = call.target;
1357 if (_listEquality.equals(getIdents(innerFun.params), passedArgs)) {
1358 return new JS.Fun(fn.params, innerFun.body);
1359 }
1360 }
1361 }
1362 }
1363 return fn;
1364 }
1365
1299 JS.Method _emitTopLevelProperty(FunctionDeclaration node) { 1366 JS.Method _emitTopLevelProperty(FunctionDeclaration node) {
1300 var name = node.name.name; 1367 var name = node.name.name;
1301 return annotate( 1368 return annotate(
1302 new JS.Method(_propertyName(name), _visit(node.functionExpression), 1369 new JS.Method(_propertyName(name), _visit(node.functionExpression),
1303 isGetter: node.isGetter, isSetter: node.isSetter), 1370 isGetter: node.isGetter, isSetter: node.isSetter),
1304 node.element); 1371 node.element);
1305 } 1372 }
1306 1373
1307 bool _executesAtTopLevel(AstNode node) { 1374 bool _executesAtTopLevel(AstNode node) {
1308 var ancestor = node.getAncestor((n) => n is FunctionBody || 1375 var ancestor = node.getAncestor((n) => n is FunctionBody ||
(...skipping 2041 matching lines...) Expand 10 before | Expand all | Expand 10 after
3350 3417
3351 /// A special kind of element created by the compiler, signifying a temporary 3418 /// A special kind of element created by the compiler, signifying a temporary
3352 /// variable. These objects use instance equality, and should be shared 3419 /// variable. These objects use instance equality, and should be shared
3353 /// everywhere in the tree where they are treated as the same variable. 3420 /// everywhere in the tree where they are treated as the same variable.
3354 class TemporaryVariableElement extends LocalVariableElementImpl { 3421 class TemporaryVariableElement extends LocalVariableElementImpl {
3355 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); 3422 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name);
3356 3423
3357 int get hashCode => identityHashCode(this); 3424 int get hashCode => identityHashCode(this);
3358 bool operator ==(Object other) => identical(this, other); 3425 bool operator ==(Object other) => identical(this, other);
3359 } 3426 }
OLDNEW
« no previous file with comments | « lib/runtime/dart_utils.js ('k') | lib/src/compiler.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698