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

Side by Side Diff: lib/src/compiler/code_generator.dart

Issue 1993813003: implement top-level JS annotated getters (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 4 years, 7 months 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 | « no previous file | test/browser/language_tests.js » ('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 import 'dart:collection' show HashMap, HashSet; 5 import 'dart:collection' show HashMap, HashSet;
6 import 'dart:math' show min, max; 6 import 'dart:math' show min, max;
7 7
8 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; 8 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator;
9 import 'package:analyzer/dart/ast/ast.dart'; 9 import 'package:analyzer/dart/ast/ast.dart';
10 import 'package:analyzer/dart/ast/token.dart' show Token, TokenType; 10 import 'package:analyzer/dart/ast/token.dart' show Token, TokenType;
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
74 /// Usually a [SimpleIdentifier], but it can also be other expressions 74 /// Usually a [SimpleIdentifier], but it can also be other expressions
75 /// that are safe to evaluate multiple times, such as `this`. 75 /// that are safe to evaluate multiple times, such as `this`.
76 Expression _cascadeTarget; 76 Expression _cascadeTarget;
77 77
78 /// The variable for the current catch clause 78 /// The variable for the current catch clause
79 SimpleIdentifier _catchParameter; 79 SimpleIdentifier _catchParameter;
80 80
81 /// In an async* function, this represents the stream controller parameter. 81 /// In an async* function, this represents the stream controller parameter.
82 JS.TemporaryId _asyncStarController; 82 JS.TemporaryId _asyncStarController;
83 83
84 /// The top-level reference to 'self' if this is a library tagged with @JS() 84 /// A mapping of libraries to the contents of their corresponding
85 JS.TemporaryId _self; 85 /// library-level @JS() annotation, if the library is annotated. The
86 /// @JS annotation contains a dot-separated identifier or is empty. The
87 /// library is then associated with a list of Strings, which represents
88 /// the list of dotted identifiers.
89 final _libraryJsPrefixes = new HashMap<LibraryElement, List<String>>();
Jennifer Messerly 2016/05/19 17:38:04 BTW, we're not consistent yet, but naming conventi
Harry Terkelsen 2016/05/19 18:10:10 Done.
86 90
87 final _privateNames = 91 final _privateNames =
88 new HashMap<LibraryElement, HashMap<String, JS.TemporaryId>>(); 92 new HashMap<LibraryElement, HashMap<String, JS.TemporaryId>>();
89 final _initializingFormalTemps = 93 final _initializingFormalTemps =
90 new HashMap<ParameterElement, JS.TemporaryId>(); 94 new HashMap<ParameterElement, JS.TemporaryId>();
91 95
92 final _dartxVar = new JS.Identifier('dartx'); 96 final _dartxVar = new JS.Identifier('dartx');
93 final _runtimeLibVar = new JS.Identifier('dart'); 97 final _runtimeLibVar = new JS.Identifier('dart');
94 final namedArgumentTemp = new JS.TemporaryId('opts'); 98 final namedArgumentTemp = new JS.TemporaryId('opts');
95 99
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
219 js.call('const # = Object.create(null)', [libraryTemp]))); 223 js.call('const # = Object.create(null)', [libraryTemp])));
220 224
221 // dart:_runtime has a magic module that holds extenstion method symbols. 225 // dart:_runtime has a magic module that holds extenstion method symbols.
222 // TODO(jmesserly): find a cleaner design for this. 226 // TODO(jmesserly): find a cleaner design for this.
223 if (_isDartRuntime(library)) { 227 if (_isDartRuntime(library)) {
224 items.add(new JS.ExportDeclaration( 228 items.add(new JS.ExportDeclaration(
225 js.call('const # = Object.create(null)', [_dartxVar]))); 229 js.call('const # = Object.create(null)', [_dartxVar])));
226 } 230 }
227 231
228 if (findAnnotation(library, isPublicJSAnnotation) != null) { 232 if (findAnnotation(library, isPublicJSAnnotation) != null) {
229 _self = new JS.TemporaryId('self'); 233 var libraryJsPrefix = <String>[];
230 items.add(js.statement('const # = window;', [_self])); 234 var prefix = getAnnotationName(library, isPublicJSAnnotation);
235 if (prefix != null && !prefix.isEmpty) {
236 libraryJsPrefix.addAll(prefix.split('.'));
237 }
238 _libraryJsPrefixes[library] = libraryJsPrefix;
Jennifer Messerly 2016/05/19 17:38:04 I think you'll need to compute these on-demand, be
Harry Terkelsen 2016/05/19 18:10:10 Done.
231 } 239 }
232 } 240 }
233 241
234 // Collect all Element -> Node mappings, in case we need to forward declare 242 // Collect all Element -> Node mappings, in case we need to forward declare
235 // any nodes. 243 // any nodes.
236 var nodes = new HashMap<Element, AstNode>.identity(); 244 var nodes = new HashMap<Element, AstNode>.identity();
237 var sdkBootstrappingFns = new List<FunctionElement>(); 245 var sdkBootstrappingFns = new List<FunctionElement>();
238 for (var unit in compilationUnits) { 246 for (var unit in compilationUnits) {
239 if (_isDartRuntime(unit.element.library)) { 247 if (_isDartRuntime(unit.element.library)) {
240 sdkBootstrappingFns.addAll(unit.element.functions); 248 sdkBootstrappingFns.addAll(unit.element.functions);
(...skipping 28 matching lines...) Expand all
269 switch (options.moduleFormat) { 277 switch (options.moduleFormat) {
270 case ModuleFormat.legacy: 278 case ModuleFormat.legacy:
271 return new LegacyModuleBuilder().build(module); 279 return new LegacyModuleBuilder().build(module);
272 case ModuleFormat.node: 280 case ModuleFormat.node:
273 return new NodeModuleBuilder().build(module); 281 return new NodeModuleBuilder().build(module);
274 case ModuleFormat.es6: 282 case ModuleFormat.es6:
275 return module; 283 return module;
276 } 284 }
277 } 285 }
278 286
287 String _getJsName(Element e) {
Jennifer Messerly 2016/05/19 17:38:04 _getJSName
Harry Terkelsen 2016/05/19 18:10:10 Done.
288 if (!_libraryJsPrefixes.containsKey(e.library)) return null;
Jennifer Messerly 2016/05/19 17:38:04 I think this is where you can implement the cache,
Harry Terkelsen 2016/05/19 18:10:10 Done.
289 if (findAnnotation(e, isPublicJSAnnotation) != null) {
290 return getAnnotationName(e, isPublicJSAnnotation) ?? '';
291 }
292 if (e is TopLevelVariableElement &&
293 e.getter != null &&
294 (e.getter.isExternal ||
295 findAnnotation(e.getter, isPublicJSAnnotation) != null)) {
296 return getAnnotationName(e.getter, isPublicJSAnnotation) ?? '';
297 }
298 return null;
299 }
300
301 JS.Expression _emitJsInterop(Element e) {
Jennifer Messerly 2016/05/19 17:38:05 _emitJSInterop
Harry Terkelsen 2016/05/19 18:10:10 Done.
302 var jsName = _getJsName(e);
303 if (jsName == null) return null;
304 var name;
305 if (jsName.isEmpty) {
306 name = [e.name];
307 } else {
308 name = jsName.split('.');
309 }
310 var fullName = ['global']
311 ..addAll(_libraryJsPrefixes[e.library])
312 ..addAll(name);
313 var access = _runtimeLibVar;
314 for (var part in fullName) {
315 access = new JS.PropertyAccess(access, js.string(part));
316 }
317 return access;
318 }
319
279 /// Flattens blocks in [items] to a single list. 320 /// Flattens blocks in [items] to a single list.
280 /// 321 ///
281 /// This will not flatten blocks that are marked as being scopes. 322 /// This will not flatten blocks that are marked as being scopes.
282 void _copyAndFlattenBlocks( 323 void _copyAndFlattenBlocks(
283 List<JS.ModuleItem> result, Iterable<JS.ModuleItem> items) { 324 List<JS.ModuleItem> result, Iterable<JS.ModuleItem> items) {
284 for (var item in items) { 325 for (var item in items) {
285 if (item is JS.Block && !item.isScope) { 326 if (item is JS.Block && !item.isScope) {
286 _copyAndFlattenBlocks(result, item.statements); 327 _copyAndFlattenBlocks(result, item.statements);
287 } else { 328 } else {
288 result.add(item); 329 result.add(item);
(...skipping 2045 matching lines...) Expand 10 before | Expand all | Expand 10 after
2334 if (jsArgs != null) { 2375 if (jsArgs != null) {
2335 var genericName = _emitTopLevelName(element, suffix: '\$'); 2376 var genericName = _emitTopLevelName(element, suffix: '\$');
2336 return js.call('#(#)', [genericName, jsArgs]); 2377 return js.call('#(#)', [genericName, jsArgs]);
2337 } 2378 }
2338 } 2379 }
2339 2380
2340 return _emitTopLevelName(element); 2381 return _emitTopLevelName(element);
2341 } 2382 }
2342 2383
2343 JS.PropertyAccess _emitTopLevelName(Element e, {String suffix: ''}) { 2384 JS.PropertyAccess _emitTopLevelName(Element e, {String suffix: ''}) {
2344 if (e is TopLevelVariableElement && 2385 var interop = _emitJsInterop(e);
2345 e.getter != null && 2386 if (interop != null) return interop;
2346 findAnnotation(e.getter, isPublicJSAnnotation) != null) {
2347 var annotationName = getAnnotationName(e.getter, isPublicJSAnnotation);
2348 var name = js.string(annotationName ?? e.name);
2349 return new JS.PropertyAccess(_self, name);
2350 }
2351 String name = getJSExportName(e) + suffix; 2387 String name = getJSExportName(e) + suffix;
2352 return new JS.PropertyAccess( 2388 return new JS.PropertyAccess(
2353 emitLibraryName(e.library), _propertyName(name)); 2389 emitLibraryName(e.library), _propertyName(name));
2354 } 2390 }
2355 2391
2356 @override 2392 @override
2357 JS.Expression visitAssignmentExpression(AssignmentExpression node) { 2393 JS.Expression visitAssignmentExpression(AssignmentExpression node) {
2358 var left = node.leftHandSide; 2394 var left = node.leftHandSide;
2359 var right = node.rightHandSide; 2395 var right = node.rightHandSide;
2360 if (node.operator.type == TokenType.EQ) return _emitSet(left, right); 2396 if (node.operator.type == TokenType.EQ) return _emitSet(left, right);
(...skipping 671 matching lines...) Expand 10 before | Expand all | Expand 10 after
3032 return getter 3068 return getter
3033 ? parent.getGetter(element.name) 3069 ? parent.getGetter(element.name)
3034 : parent.getSetter(element.name); 3070 : parent.getSetter(element.name);
3035 } 3071 }
3036 return null; 3072 return null;
3037 } 3073 }
3038 3074
3039 JS.Expression _emitConstructorName( 3075 JS.Expression _emitConstructorName(
3040 ConstructorElement element, DartType type, SimpleIdentifier name) { 3076 ConstructorElement element, DartType type, SimpleIdentifier name) {
3041 var classElem = element.enclosingElement; 3077 var classElem = element.enclosingElement;
3042 if (findAnnotation(classElem, isPublicJSAnnotation) != null) { 3078 var interop = _emitJsInterop(classElem);
3043 var annotationName = getAnnotationName(classElem, isPublicJSAnnotation); 3079 if (interop != null) return interop;
Jennifer Messerly 2016/05/19 17:38:04 fyi Siggi made a change to this in: https://codere
3044 var typeName = js.string(annotationName ?? classElem.name);
3045 return new JS.PropertyAccess(_self, typeName);
3046 }
3047 var typeName = _emitType(type); 3080 var typeName = _emitType(type);
3048 if (name != null || element.isFactory) { 3081 if (name != null || element.isFactory) {
3049 var namedCtor = _constructorName(element); 3082 var namedCtor = _constructorName(element);
3050 return new JS.PropertyAccess(typeName, namedCtor); 3083 return new JS.PropertyAccess(typeName, namedCtor);
3051 } 3084 }
3052 return typeName; 3085 return typeName;
3053 } 3086 }
3054 3087
3055 @override 3088 @override
3056 visitConstructorName(ConstructorName node) { 3089 visitConstructorName(ConstructorName node) {
(...skipping 1432 matching lines...) Expand 10 before | Expand all | Expand 10 after
4489 } 4522 }
4490 4523
4491 bool isLibraryPrefix(Expression node) => 4524 bool isLibraryPrefix(Expression node) =>
4492 node is SimpleIdentifier && node.staticElement is PrefixElement; 4525 node is SimpleIdentifier && node.staticElement is PrefixElement;
4493 4526
4494 LibraryElement _getLibrary(AnalysisContext c, String uri) => 4527 LibraryElement _getLibrary(AnalysisContext c, String uri) =>
4495 c.computeLibraryElement(c.sourceFactory.forUri(uri)); 4528 c.computeLibraryElement(c.sourceFactory.forUri(uri));
4496 4529
4497 bool _isDartRuntime(LibraryElement l) => 4530 bool _isDartRuntime(LibraryElement l) =>
4498 l.isInSdk && l.source.uri.toString() == 'dart:_runtime'; 4531 l.isInSdk && l.source.uri.toString() == 'dart:_runtime';
OLDNEW
« no previous file with comments | « no previous file | test/browser/language_tests.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698