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

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

Issue 1071393007: fuse List and js Array together and a few other misc fixes. (Closed) Base URL: git@github.com:dart-lang/dart-dev-compiler.git@master
Patch Set: ptal Created 5 years, 8 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 | « lib/runtime/dart_runtime.js ('k') | test/dart_codegen/expect/core/list.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; 7 import 'dart:collection' show HashSet, HashMap;
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 256 matching lines...) Expand 10 before | Expand all | Expand 10 after
267 var type = node.element.type; 267 var type = node.element.type;
268 if (_pendingClasses.remove(node.element) == null) return null; 268 if (_pendingClasses.remove(node.element) == null) return null;
269 269
270 var name = type.name; 270 var name = type.name;
271 var result = js.statement('let # = dart.typedef(#, () => #);', [ 271 var result = js.statement('let # = dart.typedef(#, () => #);', [
272 new JS.Identifier(name), 272 new JS.Identifier(name),
273 js.string(name, "'"), 273 js.string(name, "'"),
274 _emitTypeName(node.element.type, lowerTypedef: true) 274 _emitTypeName(node.element.type, lowerTypedef: true)
275 ]); 275 ]);
276 276
277 return _finishClassDef(type, result); 277 return _finishClassDef(type, result, null);
278 } 278 }
279 279
280 @override 280 @override
281 JS.Expression visitTypeName(TypeName node) => _emitTypeName(node.type); 281 JS.Expression visitTypeName(TypeName node) => _emitTypeName(node.type);
282 282
283 @override 283 @override
284 JS.Statement visitClassTypeAlias(ClassTypeAlias node) { 284 JS.Statement visitClassTypeAlias(ClassTypeAlias node) {
285 // If we've already emitted this class, skip it. 285 // If we've already emitted this class, skip it.
286 var type = node.element.type; 286 var type = node.element.type;
287 if (_pendingClasses.remove(node.element) == null) return null; 287 if (_pendingClasses.remove(node.element) == null) return null;
288 288
289 var name = node.name.name; 289 var name = node.name.name;
290 var heritage = 290 var heritage =
291 js.call('dart.mixin(#)', [_visitList(node.withClause.mixinTypes)]); 291 js.call('dart.mixin(#)', [_visitList(node.withClause.mixinTypes)]);
292 var classDecl = new JS.ClassDeclaration( 292 var classDecl = new JS.ClassDeclaration(
293 new JS.ClassExpression(new JS.Identifier(name), heritage, [])); 293 new JS.ClassExpression(new JS.Identifier(name), heritage, []));
294 294
295 return _finishClassDef(type, classDecl); 295 return _finishClassDef(type, classDecl, null);
296 } 296 }
297 297
298 JS.Statement _emitJsType(String dartClassName, DartObjectImpl jsName) { 298 JS.Statement _emitJsType(String dartClassName, DartObjectImpl jsName) {
299 var jsTypeName = getConstantField(jsName, 'name', types.stringType); 299 var jsTypeName = getConstantField(jsName, 'name', types.stringType);
300 300
301 if (jsTypeName != null && jsTypeName != dartClassName) { 301 if (jsTypeName != null && jsTypeName != dartClassName) {
302 // We export the JS type as if it was a Dart type. For example this allows 302 // We export the JS type as if it was a Dart type. For example this allows
303 // `dom.InputElement` to actually be HTMLInputElement. 303 // `dom.InputElement` to actually be HTMLInputElement.
304 // TODO(jmesserly): if we had the JsName on the Element, we could just 304 // TODO(jmesserly): if we had the JsName on the Element, we could just
305 // generate it correctly when we refer to it. 305 // generate it correctly when we refer to it.
306 if (isPublic(dartClassName)) _addExport(dartClassName); 306 if (isPublic(dartClassName)) _addExport(dartClassName);
307 return js.statement('let # = #;', [dartClassName, jsTypeName]); 307 return js.statement('let # = #;', [dartClassName, jsTypeName]);
308 } 308 }
309 return null; 309 return null;
310 } 310 }
311 311
312 @override 312 @override
313 JS.Statement visitClassDeclaration(ClassDeclaration node) { 313 JS.Statement visitClassDeclaration(ClassDeclaration node) {
314 // If we've already emitted this class, skip it. 314 // If we've already emitted this class, skip it.
315 var classElem = node.element; 315 var classElem = node.element;
316 var type = classElem.type; 316 var type = classElem.type;
317 if (_pendingClasses.remove(classElem) == null) return null; 317 if (_pendingClasses.remove(classElem) == null) return null;
318 318
319 var jsName = getAnnotationValue(node, _isJsNameAnnotation); 319 var jsName = getAnnotationValue(node, _isJsNameAnnotation);
320
320 if (jsName != null) return _emitJsType(node.name.name, jsName); 321 if (jsName != null) return _emitJsType(node.name.name, jsName);
321 322
322 var ctors = <ConstructorDeclaration>[]; 323 var ctors = <ConstructorDeclaration>[];
323 var fields = <FieldDeclaration>[]; 324 var fields = <FieldDeclaration>[];
324 var staticFields = <FieldDeclaration>[]; 325 var staticFields = <FieldDeclaration>[];
325 for (var member in node.members) { 326 for (var member in node.members) {
326 if (member is ConstructorDeclaration) { 327 if (member is ConstructorDeclaration) {
327 ctors.add(member); 328 ctors.add(member);
328 } else if (member is FieldDeclaration) { 329 } else if (member is FieldDeclaration) {
329 (member.isStatic ? staticFields : fields).add(member); 330 (member.isStatic ? staticFields : fields).add(member);
330 } 331 }
331 } 332 }
332 333
333 var classExpr = new JS.ClassExpression(new JS.Identifier(type.name), 334 var classExpr = new JS.ClassExpression(new JS.Identifier(type.name),
334 _classHeritage(node), _emitClassMethods(node, ctors, fields)); 335 _classHeritage(node), _emitClassMethods(node, ctors, fields));
335 336
336 var body = 337 var body =
337 _finishClassMembers(classElem, classExpr, ctors, fields, staticFields); 338 _finishClassMembers(classElem, classExpr, ctors, fields, staticFields);
338 339
339 return _finishClassDef(type, body); 340 var jsPeer = getAnnotationValue(node, _isJsPeerInterface);
341 String jsPeerName = null;
342 if (jsPeer != null) {
343 jsPeerName = getConstantField(jsPeer, 'name', types.stringType);
344 }
345
346 return _finishClassDef(type, body, jsPeerName);
340 } 347 }
341 348
342 @override 349 @override
343 JS.Statement visitEnumDeclaration(EnumDeclaration node) => 350 JS.Statement visitEnumDeclaration(EnumDeclaration node) =>
344 _unimplementedCall("Unimplemented enum: $node").toStatement(); 351 _unimplementedCall("Unimplemented enum: $node").toStatement();
345 352
346 /// Given a class element and body, complete the class declaration. 353 /// Given a class element and body, complete the class declaration.
347 /// This handles generic type parameters, laziness (in library-cycle cases), 354 /// This handles generic type parameters, laziness (in library-cycle cases),
348 /// and ensuring dependencies are loaded first. 355 /// and ensuring dependencies are loaded first.
349 JS.Statement _finishClassDef(ParameterizedType type, JS.Statement body) { 356 JS.Statement _finishClassDef(
357 ParameterizedType type, JS.Statement body, String jsPeerName) {
350 var name = type.name; 358 var name = type.name;
351 var genericName = '$name\$'; 359 var genericName = '$name\$';
352 360
353 JS.Statement genericDef; 361 JS.Statement genericDef;
354 JS.Expression genericInst; 362 JS.Expression genericInst;
355 if (type.typeParameters.isNotEmpty) { 363 if (type.typeParameters.isNotEmpty) {
356 genericDef = _emitGenericClassDef(type, body); 364 genericDef = _emitGenericClassDef(type, body);
357 var target = genericName; 365 var target = genericName;
358 if (_needQualifiedName(type.element)) { 366 if (_needQualifiedName(type.element)) {
359 target = js.call('#.#', [_exportsVar, genericName]); 367 target = js.call('#.#', [_exportsVar, genericName]);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
398 var classDefs = <JS.Statement>[]; 406 var classDefs = <JS.Statement>[];
399 if (type is InterfaceType) { 407 if (type is InterfaceType) {
400 _emitClassIfNeeded(classDefs, type.superclass); 408 _emitClassIfNeeded(classDefs, type.superclass);
401 for (var m in type.element.mixins) { 409 for (var m in type.element.mixins) {
402 _emitClassIfNeeded(classDefs, m); 410 _emitClassIfNeeded(classDefs, m);
403 } 411 }
404 } else if (type is FunctionType) { 412 } else if (type is FunctionType) {
405 _emitClassIfNeeded(classDefs, types.functionType); 413 _emitClassIfNeeded(classDefs, types.functionType);
406 } 414 }
407 classDefs.add(body); 415 classDefs.add(body);
416 if (jsPeerName != null) {
417 classDefs.add(js.statement(
418 'dart.copyProperties(dart.global.#.prototype, #.prototype);', [
419 _propertyName(jsPeerName),
420 name
421 ]));
422 }
408 return _statement(classDefs); 423 return _statement(classDefs);
409 } 424 }
410 425
411 void _emitClassIfNeeded(List<JS.Statement> defs, DartType base) { 426 void _emitClassIfNeeded(List<JS.Statement> defs, DartType base) {
412 // We can only emit classes from this library. 427 // We can only emit classes from this library.
413 if (base.element.library != currentLibrary) return; 428 if (base.element.library != currentLibrary) return;
414 429
415 var baseNode = _pendingClasses[base.element]; 430 var baseNode = _pendingClasses[base.element];
416 if (baseNode != null) defs.add(visitClassDeclaration(baseNode)); 431 if (baseNode != null) defs.add(visitClassDeclaration(baseNode));
417 } 432 }
(...skipping 1908 matching lines...) Expand 10 before | Expand all | Expand 10 after
2326 JS.Expression _extensionMethodName(String name, LibraryElement library) { 2341 JS.Expression _extensionMethodName(String name, LibraryElement library) {
2327 var extName = '\$$name'; 2342 var extName = '\$$name';
2328 if (library == currentLibrary) { 2343 if (library == currentLibrary) {
2329 // TODO(jacobr): need to do a better job ensuring that extension method 2344 // TODO(jacobr): need to do a better job ensuring that extension method
2330 // name symbols do not conflict with other symbols before we can let 2345 // name symbols do not conflict with other symbols before we can let
2331 // user defined libraries define extension methods. 2346 // user defined libraries define extension methods.
2332 if (_extensionMethodNames.add(extName)) { 2347 if (_extensionMethodNames.add(extName)) {
2333 _pendingSymbols.add(new JS.Identifier(extName)); 2348 _pendingSymbols.add(new JS.Identifier(extName));
2334 _addExport(extName); 2349 _addExport(extName);
2335 } 2350 }
2351 return new JS.Identifier(extName);
2336 } 2352 }
2337 return js.call('#.#', [_libraryName(library), _propertyName(extName)]); 2353 return js.call('#.#', [_libraryName(library), _propertyName(extName)]);
2338 } 2354 }
2339 2355
2340 bool _externalOrNative(node) => 2356 bool _externalOrNative(node) =>
2341 node.externalKeyword != null || _functionBody(node) is NativeFunctionBody; 2357 node.externalKeyword != null || _functionBody(node) is NativeFunctionBody;
2342 2358
2343 FunctionBody _functionBody(node) => 2359 FunctionBody _functionBody(node) =>
2344 node is FunctionDeclaration ? node.functionExpression.body : node.body; 2360 node is FunctionDeclaration ? node.functionExpression.body : node.body;
2345 2361
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
2418 assert(uri.scheme == 'package'); 2434 assert(uri.scheme == 'package');
2419 // filepath is good here, we want the output to start with a directory 2435 // filepath is good here, we want the output to start with a directory
2420 // matching the package name. 2436 // matching the package name.
2421 } 2437 }
2422 return filepath; 2438 return filepath;
2423 } 2439 }
2424 2440
2425 // TODO(jmesserly): validate the library. See issue #135. 2441 // TODO(jmesserly): validate the library. See issue #135.
2426 bool _isJsNameAnnotation(DartObjectImpl value) => value.type.name == 'JsName'; 2442 bool _isJsNameAnnotation(DartObjectImpl value) => value.type.name == 'JsName';
2427 2443
2444 bool _isJsPeerInterface(DartObjectImpl value) =>
2445 value.type.name == 'JsPeerInterface';
2446
2428 // TODO(jacobr): we would like to do something like the following 2447 // TODO(jacobr): we would like to do something like the following
2429 // but we don't have summary support yet. 2448 // but we don't have summary support yet.
2430 // bool _supportJsExtensionMethod(AnnotatedNode node) => 2449 // bool _supportJsExtensionMethod(AnnotatedNode node) =>
2431 // _getAnnotation(node, "SupportJsExtensionMethod") != null; 2450 // _getAnnotation(node, "SupportJsExtensionMethod") != null;
OLDNEW
« no previous file with comments | « lib/runtime/dart_runtime.js ('k') | test/dart_codegen/expect/core/list.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698