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

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

Issue 1677863002: Use default params when --destructure-named-params + fix renaming of reserved destructured params (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 4 years, 10 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 | lib/src/js/nodes.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 import 'dart:collection' show HashSet, HashMap, SplayTreeSet; 5 import 'dart:collection' show HashSet, HashMap, SplayTreeSet;
6 6
7 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; 7 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator;
8 import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator; 8 import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator;
9 import 'package:analyzer/src/generated/constant.dart'; 9 import 'package:analyzer/src/generated/constant.dart';
10 import 'package:analyzer/src/generated/element.dart'; 10 import 'package:analyzer/src/generated/element.dart';
(...skipping 945 matching lines...) Expand 10 before | Expand all | Expand 10 after
956 var params = 956 var params =
957 _emitFormalParameterList(node.parameters, allowDestructuring: false); 957 _emitFormalParameterList(node.parameters, allowDestructuring: false);
958 958
959 var fun = js.call('function(#) { return $newKeyword #(#); }', 959 var fun = js.call('function(#) { return $newKeyword #(#); }',
960 [params, _visit(redirect), params]) as JS.Fun; 960 [params, _visit(redirect), params]) as JS.Fun;
961 return annotate( 961 return annotate(
962 new JS.Method(name, fun, isStatic: true)..sourceInformation = node, 962 new JS.Method(name, fun, isStatic: true)..sourceInformation = node,
963 node.element); 963 node.element);
964 } 964 }
965 965
966 // For const constructors we need to ensure default values are
967 // available for use by top-level constant initializers.
968 ClassDeclaration cls = node.parent;
969 if (node.constKeyword != null) _loader.startTopLevel(cls.element);
970 var params = _emitFormalParameterList(node.parameters);
971 if (node.constKeyword != null) _loader.finishTopLevel(cls.element);
972
966 // Factory constructors are essentially static methods. 973 // Factory constructors are essentially static methods.
967 if (node.factoryKeyword != null) { 974 if (node.factoryKeyword != null) {
968 var body = <JS.Statement>[]; 975 var body = <JS.Statement>[];
969 var init = _emitArgumentInitializers(node, constructor: true); 976 var init = _emitArgumentInitializers(node, constructor: true);
970 if (init != null) body.add(init); 977 if (init != null) body.add(init);
971 body.add(_visit(node.body)); 978 body.add(_visit(node.body));
972 var fun = new JS.Fun( 979 var fun = new JS.Fun(params, new JS.Block(body));
973 _visit(node.parameters) as List<JS.Parameter>, new JS.Block(body));
974 return annotate( 980 return annotate(
975 new JS.Method(name, fun, isStatic: true)..sourceInformation = node, 981 new JS.Method(name, fun, isStatic: true)..sourceInformation = node,
976 node.element); 982 node.element);
977 } 983 }
978 984
979 // Code generation for Object's constructor. 985 // Code generation for Object's constructor.
980 JS.Block body; 986 JS.Block body;
981 if (isObject && 987 if (isObject &&
982 node.body is EmptyFunctionBody && 988 node.body is EmptyFunctionBody &&
983 node.constKeyword != null && 989 node.constKeyword != null &&
(...skipping 18 matching lines...) Expand all
1002 return result === void 0 ? this : result; 1008 return result === void 0 ? this : result;
1003 }''') as JS.Block; 1009 }''') as JS.Block;
1004 } else { 1010 } else {
1005 body = _emitConstructorBody(node, fields); 1011 body = _emitConstructorBody(node, fields);
1006 } 1012 }
1007 1013
1008 // We generate constructors as initializer methods in the class; 1014 // We generate constructors as initializer methods in the class;
1009 // this allows use of `super` for instance methods/properties. 1015 // this allows use of `super` for instance methods/properties.
1010 // It also avoids V8 restrictions on `super` in default constructors. 1016 // It also avoids V8 restrictions on `super` in default constructors.
1011 return annotate( 1017 return annotate(
1012 new JS.Method(name, 1018 new JS.Method(name, new JS.Fun(params, body))..sourceInformation = node,
1013 new JS.Fun(_visit(node.parameters) as List<JS.Parameter>, body))
1014 ..sourceInformation = node,
1015 node.element); 1019 node.element);
1016 } 1020 }
1017 1021
1018 JS.Expression _constructorName(ConstructorElement ctor) { 1022 JS.Expression _constructorName(ConstructorElement ctor) {
1019 var name = ctor.name; 1023 var name = ctor.name;
1020 if (name != '') { 1024 if (name != '') {
1021 return _emitMemberName(name, isStatic: true); 1025 return _emitMemberName(name, isStatic: true);
1022 } 1026 }
1023 1027
1024 // Factory default constructors use `new` as their name, for readability 1028 // Factory default constructors use `new` as their name, for readability
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
1214 if (node is ConstructorDeclaration != constructor) return null; 1218 if (node is ConstructorDeclaration != constructor) return null;
1215 1219
1216 var parameters = _parametersOf(node); 1220 var parameters = _parametersOf(node);
1217 if (parameters == null) return null; 1221 if (parameters == null) return null;
1218 1222
1219 var body = <JS.Statement>[]; 1223 var body = <JS.Statement>[];
1220 for (var param in parameters.parameters) { 1224 for (var param in parameters.parameters) {
1221 var jsParam = _visit(param.identifier); 1225 var jsParam = _visit(param.identifier);
1222 1226
1223 if (param.kind == ParameterKind.NAMED) { 1227 if (param.kind == ParameterKind.NAMED) {
1224 if (!_isDestructurableNamedParam(param)) { 1228 if (!options.destructureNamedParams) {
1225 // Parameters will be passed using their real names, not the (possibly 1229 // Parameters will be passed using their real names, not the (possibly
1226 // renamed) local variable. 1230 // renamed) local variable.
1227 var paramName = js.string(param.identifier.name, "'"); 1231 var paramName = js.string(param.identifier.name, "'");
1228 1232
1229 // TODO(ochafik): Fix `'prop' in obj` to please Closure's renaming. 1233 // TODO(ochafik): Fix `'prop' in obj` to please Closure's renaming.
1230 body.add(js.statement('let # = # && # in # ? #.# : #;', [ 1234 body.add(js.statement('let # = # && # in # ? #.# : #;', [
1231 jsParam, 1235 jsParam,
1232 _namedArgTemp, 1236 _namedArgTemp,
1233 paramName, 1237 paramName,
1234 _namedArgTemp, 1238 _namedArgTemp,
1235 _namedArgTemp, 1239 _namedArgTemp,
1236 paramName, 1240 paramName,
1237 _defaultParamValue(param), 1241 _defaultParamValue(param),
1238 ])); 1242 ]));
1239 } 1243 }
1240 } else if (param.kind == ParameterKind.POSITIONAL) { 1244 } else if (param.kind == ParameterKind.POSITIONAL &&
1245 !options.destructureNamedParams) {
1241 body.add(js.statement('if (# === void 0) # = #;', 1246 body.add(js.statement('if (# === void 0) # = #;',
1242 [jsParam, jsParam, _defaultParamValue(param)])); 1247 [jsParam, jsParam, _defaultParamValue(param)]));
1243 } 1248 }
1244 1249
1245 // TODO(jmesserly): various problems here, see: 1250 // TODO(jmesserly): various problems here, see:
1246 // https://github.com/dart-lang/dev_compiler/issues/161 1251 // https://github.com/dart-lang/dev_compiler/issues/161
1247 var paramType = param.element.type; 1252 var paramType = param.element.type;
1248 if (!constructor && _hasUnsoundTypeParameter(paramType)) { 1253 if (!constructor && _hasUnsoundTypeParameter(paramType)) {
1249 body.add(js 1254 body.add(js
1250 .statement('dart.as(#, #);', [jsParam, _emitTypeName(paramType)])); 1255 .statement('dart.as(#, #);', [jsParam, _emitTypeName(paramType)]));
(...skipping 786 matching lines...) Expand 10 before | Expand all | Expand 10 after
2037 @override 2042 @override
2038 JS.Property visitNamedExpression(NamedExpression node) { 2043 JS.Property visitNamedExpression(NamedExpression node) {
2039 assert(node.parent is ArgumentList); 2044 assert(node.parent is ArgumentList);
2040 return new JS.Property( 2045 return new JS.Property(
2041 _propertyName(node.name.label.name), _visit(node.expression)); 2046 _propertyName(node.name.label.name), _visit(node.expression));
2042 } 2047 }
2043 2048
2044 bool _isNamedParam(FormalParameter param) => 2049 bool _isNamedParam(FormalParameter param) =>
2045 param.kind == ParameterKind.NAMED; 2050 param.kind == ParameterKind.NAMED;
2046 2051
2047 /// We cannot destructure named params that clash with JS reserved names:
2048 /// see discussion in https://github.com/dart-lang/dev_compiler/issues/392.
2049 bool _isDestructurableNamedParam(FormalParameter param) =>
2050 _isNamedParam(param) &&
2051 !invalidVariableName(param.identifier.name) &&
2052 options.destructureNamedParams;
2053
2054 @override 2052 @override
2055 List<JS.Parameter> visitFormalParameterList(FormalParameterList node) => 2053 List<JS.Parameter> visitFormalParameterList(FormalParameterList node) =>
2056 _emitFormalParameterList(node); 2054 _emitFormalParameterList(node);
2057 2055
2058 List<JS.Parameter> _emitFormalParameterList(FormalParameterList node, 2056 List<JS.Parameter> _emitFormalParameterList(FormalParameterList node,
2059 {bool allowDestructuring: true}) { 2057 {bool allowDestructuring: true}) {
2060 var result = <JS.Parameter>[]; 2058 var result = <JS.Parameter>[];
2061 2059
2062 var namedVars = <JS.DestructuredVariable>[]; 2060 var namedVars = <JS.DestructuredVariable>[];
2063 var destructure = allowDestructuring && 2061 var destructure = allowDestructuring && options.destructureNamedParams;
2064 node.parameters.where(_isNamedParam).every(_isDestructurableNamedParam);
2065 var hasNamedArgsConflictingWithObjectProperties = false; 2062 var hasNamedArgsConflictingWithObjectProperties = false;
2066 var needsOpts = false; 2063 var needsOpts = false;
2067 2064
2068 for (FormalParameter param in node.parameters) { 2065 for (FormalParameter param in node.parameters) {
2069 if (param.kind == ParameterKind.NAMED) { 2066 if (param.kind == ParameterKind.NAMED) {
2070 if (destructure) { 2067 if (destructure) {
2071 if (_jsObjectProperties.contains(param.identifier.name)) { 2068 if (_jsObjectProperties.contains(param.identifier.name)) {
2072 hasNamedArgsConflictingWithObjectProperties = true; 2069 hasNamedArgsConflictingWithObjectProperties = true;
2073 } 2070 }
2071 JS.Expression name;
2072 JS.SimpleBindingPattern structure = null;
2073 String paramName = param.identifier.name;
2074 if (invalidVariableName(paramName)) {
2075 name = js.string(paramName);
2076 structure = new JS.SimpleBindingPattern(_visit(param.identifier));
2077 } else {
2078 name = _visit(param.identifier);
2079 }
2074 namedVars.add(new JS.DestructuredVariable( 2080 namedVars.add(new JS.DestructuredVariable(
2075 name: _visit(param.identifier), 2081 name: name,
2082 structure: structure,
2076 defaultValue: _defaultParamValue(param))); 2083 defaultValue: _defaultParamValue(param)));
2077 } else { 2084 } else {
2078 needsOpts = true; 2085 needsOpts = true;
2079 } 2086 }
2080 } else { 2087 } else {
2081 result.add(_visit(param)); 2088 var jsParam = _visit(param);
2089 result.add(
2090 param is DefaultFormalParameter && options.destructureNamedParams
2091 ? new JS.DestructuredVariable(
2092 name: jsParam,
2093 defaultValue: _defaultParamValue(param))
2094 : jsParam);
2082 } 2095 }
2083 } 2096 }
2084 2097
2085 if (needsOpts) { 2098 if (needsOpts) {
2086 result.add(_namedArgTemp); 2099 result.add(_namedArgTemp);
2087 } else if (namedVars.isNotEmpty) { 2100 } else if (namedVars.isNotEmpty) {
2088 // Note: `var {valueOf} = {}` extracts `Object.prototype.valueOf`, so 2101 // Note: `var {valueOf} = {}` extracts `Object.prototype.valueOf`, so
2089 // in case there are conflicting names we create an object without 2102 // in case there are conflicting names we create an object without
2090 // any prototype. 2103 // any prototype.
2091 var defaultOpts = hasNamedArgsConflictingWithObjectProperties 2104 var defaultOpts = hasNamedArgsConflictingWithObjectProperties
(...skipping 1520 matching lines...) Expand 10 before | Expand all | Expand 10 after
3612 3625
3613 /// A special kind of element created by the compiler, signifying a temporary 3626 /// A special kind of element created by the compiler, signifying a temporary
3614 /// variable. These objects use instance equality, and should be shared 3627 /// variable. These objects use instance equality, and should be shared
3615 /// everywhere in the tree where they are treated as the same variable. 3628 /// everywhere in the tree where they are treated as the same variable.
3616 class TemporaryVariableElement extends LocalVariableElementImpl { 3629 class TemporaryVariableElement extends LocalVariableElementImpl {
3617 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); 3630 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name);
3618 3631
3619 int get hashCode => identityHashCode(this); 3632 int get hashCode => identityHashCode(this);
3620 bool operator ==(Object other) => identical(this, other); 3633 bool operator ==(Object other) => identical(this, other);
3621 } 3634 }
OLDNEW
« no previous file with comments | « no previous file | lib/src/js/nodes.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698