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

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()
85 JS.TemporaryId _self;
86
87 final _privateNames = 84 final _privateNames =
88 new HashMap<LibraryElement, HashMap<String, JS.TemporaryId>>(); 85 new HashMap<LibraryElement, HashMap<String, JS.TemporaryId>>();
89 final _initializingFormalTemps = 86 final _initializingFormalTemps =
90 new HashMap<ParameterElement, JS.TemporaryId>(); 87 new HashMap<ParameterElement, JS.TemporaryId>();
91 88
92 final _dartxVar = new JS.Identifier('dartx'); 89 final _dartxVar = new JS.Identifier('dartx');
93 final _runtimeLibVar = new JS.Identifier('dart'); 90 final _runtimeLibVar = new JS.Identifier('dart');
94 final namedArgumentTemp = new JS.TemporaryId('opts'); 91 final namedArgumentTemp = new JS.TemporaryId('opts');
95 92
96 final _hasDeferredSupertype = new HashSet<ClassElement>(); 93 final _hasDeferredSupertype = new HashSet<ClassElement>();
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
217 _libraries[library] = libraryTemp; 214 _libraries[library] = libraryTemp;
218 items.add(new JS.ExportDeclaration( 215 items.add(new JS.ExportDeclaration(
219 js.call('const # = Object.create(null)', [libraryTemp]))); 216 js.call('const # = Object.create(null)', [libraryTemp])));
220 217
221 // dart:_runtime has a magic module that holds extenstion method symbols. 218 // dart:_runtime has a magic module that holds extenstion method symbols.
222 // TODO(jmesserly): find a cleaner design for this. 219 // TODO(jmesserly): find a cleaner design for this.
223 if (_isDartRuntime(library)) { 220 if (_isDartRuntime(library)) {
224 items.add(new JS.ExportDeclaration( 221 items.add(new JS.ExportDeclaration(
225 js.call('const # = Object.create(null)', [_dartxVar]))); 222 js.call('const # = Object.create(null)', [_dartxVar])));
226 } 223 }
227
228 if (findAnnotation(library, isPublicJSAnnotation) != null) {
229 _self = new JS.TemporaryId('self');
230 items.add(js.statement('const # = window;', [_self]));
231 }
232 } 224 }
233 225
234 // Collect all Element -> Node mappings, in case we need to forward declare 226 // Collect all Element -> Node mappings, in case we need to forward declare
235 // any nodes. 227 // any nodes.
236 var nodes = new HashMap<Element, AstNode>.identity(); 228 var nodes = new HashMap<Element, AstNode>.identity();
237 var sdkBootstrappingFns = new List<FunctionElement>(); 229 var sdkBootstrappingFns = new List<FunctionElement>();
238 for (var unit in compilationUnits) { 230 for (var unit in compilationUnits) {
239 if (_isDartRuntime(unit.element.library)) { 231 if (_isDartRuntime(unit.element.library)) {
240 sdkBootstrappingFns.addAll(unit.element.functions); 232 sdkBootstrappingFns.addAll(unit.element.functions);
241 } 233 }
(...skipping 27 matching lines...) Expand all
269 switch (options.moduleFormat) { 261 switch (options.moduleFormat) {
270 case ModuleFormat.legacy: 262 case ModuleFormat.legacy:
271 return new LegacyModuleBuilder().build(module); 263 return new LegacyModuleBuilder().build(module);
272 case ModuleFormat.node: 264 case ModuleFormat.node:
273 return new NodeModuleBuilder().build(module); 265 return new NodeModuleBuilder().build(module);
274 case ModuleFormat.es6: 266 case ModuleFormat.es6:
275 return module; 267 return module;
276 } 268 }
277 } 269 }
278 270
271 List<String> _getJSName(Element e) {
272 if (findAnnotation(e.library, isPublicJSAnnotation) == null) {
273 return null;
274 }
275
276 var libraryJSName = getAnnotationName(e.library, isPublicJSAnnotation);
277 var libraryPrefix = [];
278 if (libraryJSName != null && libraryJSName.isNotEmpty) {
279 libraryPrefix.addAll(libraryJSName.split('.'));
280 }
281
282 var elementJSName;
283 if (findAnnotation(e, isPublicJSAnnotation) != null) {
284 elementJSName = getAnnotationName(e, isPublicJSAnnotation) ?? '';
285 }
286 if (e is TopLevelVariableElement &&
287 e.getter != null &&
288 (e.getter.isExternal ||
289 findAnnotation(e.getter, isPublicJSAnnotation) != null)) {
290 elementJSName = getAnnotationName(e.getter, isPublicJSAnnotation) ?? '';
291 }
292 if (elementJSName == null) return null;
293
294 var elementJSParts = [];
295 if (elementJSName.isNotEmpty) {
296 elementJSParts.addAll(elementJSName.split('.'));
297 } else {
298 elementJSParts.add(e.name);
299 }
300
301 return libraryPrefix..addAll(elementJSParts);
302 }
303
304 JS.Expression _emitJSInterop(Element e) {
305 var jsName = _getJSName(e);
306 if (jsName == null) return null;
307 var fullName = ['global']..addAll(jsName);
308 var access = _runtimeLibVar;
309 for (var part in fullName) {
310 access = new JS.PropertyAccess(access, js.string(part));
311 }
312 return access;
313 }
314
279 /// Flattens blocks in [items] to a single list. 315 /// Flattens blocks in [items] to a single list.
280 /// 316 ///
281 /// This will not flatten blocks that are marked as being scopes. 317 /// This will not flatten blocks that are marked as being scopes.
282 void _copyAndFlattenBlocks( 318 void _copyAndFlattenBlocks(
283 List<JS.ModuleItem> result, Iterable<JS.ModuleItem> items) { 319 List<JS.ModuleItem> result, Iterable<JS.ModuleItem> items) {
284 for (var item in items) { 320 for (var item in items) {
285 if (item is JS.Block && !item.isScope) { 321 if (item is JS.Block && !item.isScope) {
286 _copyAndFlattenBlocks(result, item.statements); 322 _copyAndFlattenBlocks(result, item.statements);
287 } else { 323 } else {
288 result.add(item); 324 result.add(item);
(...skipping 2045 matching lines...) Expand 10 before | Expand all | Expand 10 after
2334 if (jsArgs != null) { 2370 if (jsArgs != null) {
2335 var genericName = _emitTopLevelName(element, suffix: '\$'); 2371 var genericName = _emitTopLevelName(element, suffix: '\$');
2336 return js.call('#(#)', [genericName, jsArgs]); 2372 return js.call('#(#)', [genericName, jsArgs]);
2337 } 2373 }
2338 } 2374 }
2339 2375
2340 return _emitTopLevelName(element); 2376 return _emitTopLevelName(element);
2341 } 2377 }
2342 2378
2343 JS.PropertyAccess _emitTopLevelName(Element e, {String suffix: ''}) { 2379 JS.PropertyAccess _emitTopLevelName(Element e, {String suffix: ''}) {
2344 if (e is TopLevelVariableElement && 2380 var interop = _emitJSInterop(e);
2345 e.getter != null && 2381 if (interop != null) return interop;
2346 findAnnotation(e.getter, isPublicJSAnnotation) != null) {
2347 var annotationName = getAnnotationName(e.getter, isPublicJSAnnotation);
2348 var name = annotationName ?? e.name;
2349 JS.PropertyAccess result = null;
2350 for (var segment in name.split('.')) {
2351 result = new JS.PropertyAccess(result ?? _self, js.string(segment));
2352 }
2353 return result;
2354 }
2355 String name = getJSExportName(e) + suffix; 2382 String name = getJSExportName(e) + suffix;
2356 return new JS.PropertyAccess( 2383 return new JS.PropertyAccess(
2357 emitLibraryName(e.library), _propertyName(name)); 2384 emitLibraryName(e.library), _propertyName(name));
2358 } 2385 }
2359 2386
2360 @override 2387 @override
2361 JS.Expression visitAssignmentExpression(AssignmentExpression node) { 2388 JS.Expression visitAssignmentExpression(AssignmentExpression node) {
2362 var left = node.leftHandSide; 2389 var left = node.leftHandSide;
2363 var right = node.rightHandSide; 2390 var right = node.rightHandSide;
2364 if (node.operator.type == TokenType.EQ) return _emitSet(left, right); 2391 if (node.operator.type == TokenType.EQ) return _emitSet(left, right);
(...skipping 671 matching lines...) Expand 10 before | Expand all | Expand 10 after
3036 return getter 3063 return getter
3037 ? parent.getGetter(element.name) 3064 ? parent.getGetter(element.name)
3038 : parent.getSetter(element.name); 3065 : parent.getSetter(element.name);
3039 } 3066 }
3040 return null; 3067 return null;
3041 } 3068 }
3042 3069
3043 JS.Expression _emitConstructorName( 3070 JS.Expression _emitConstructorName(
3044 ConstructorElement element, DartType type, SimpleIdentifier name) { 3071 ConstructorElement element, DartType type, SimpleIdentifier name) {
3045 var classElem = element.enclosingElement; 3072 var classElem = element.enclosingElement;
3046 if (findAnnotation(classElem, isPublicJSAnnotation) != null) { 3073 var interop = _emitJSInterop(classElem);
3047 var annotationName = getAnnotationName(classElem, isPublicJSAnnotation); 3074 if (interop != null) return interop;
3048 var typeName = js.string(annotationName ?? classElem.name);
3049 return new JS.PropertyAccess(_self, typeName);
3050 }
3051 var typeName = _emitType(type); 3075 var typeName = _emitType(type);
3052 if (name != null || element.isFactory) { 3076 if (name != null || element.isFactory) {
3053 var namedCtor = _constructorName(element); 3077 var namedCtor = _constructorName(element);
3054 return new JS.PropertyAccess(typeName, namedCtor); 3078 return new JS.PropertyAccess(typeName, namedCtor);
3055 } 3079 }
3056 return typeName; 3080 return typeName;
3057 } 3081 }
3058 3082
3059 @override 3083 @override
3060 visitConstructorName(ConstructorName node) { 3084 visitConstructorName(ConstructorName node) {
(...skipping 1432 matching lines...) Expand 10 before | Expand all | Expand 10 after
4493 } 4517 }
4494 4518
4495 bool isLibraryPrefix(Expression node) => 4519 bool isLibraryPrefix(Expression node) =>
4496 node is SimpleIdentifier && node.staticElement is PrefixElement; 4520 node is SimpleIdentifier && node.staticElement is PrefixElement;
4497 4521
4498 LibraryElement _getLibrary(AnalysisContext c, String uri) => 4522 LibraryElement _getLibrary(AnalysisContext c, String uri) =>
4499 c.computeLibraryElement(c.sourceFactory.forUri(uri)); 4523 c.computeLibraryElement(c.sourceFactory.forUri(uri));
4500 4524
4501 bool _isDartRuntime(LibraryElement l) => 4525 bool _isDartRuntime(LibraryElement l) =>
4502 l.isInSdk && l.source.uri.toString() == 'dart:_runtime'; 4526 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