Index: pkg/dev_compiler/lib/src/compiler/code_generator.dart |
diff --git a/pkg/dev_compiler/lib/src/compiler/code_generator.dart b/pkg/dev_compiler/lib/src/compiler/code_generator.dart |
index ef3e808719eb39089e9ed141107b44d38baaa13e..9c7ae7e2535076fb1d1bc9e04f243a19d61391db 100644 |
--- a/pkg/dev_compiler/lib/src/compiler/code_generator.dart |
+++ b/pkg/dev_compiler/lib/src/compiler/code_generator.dart |
@@ -150,6 +150,7 @@ class CodeGenerator extends Object |
final ClassElement stringClass; |
final ClassElement functionClass; |
final ClassElement privateSymbolClass; |
+ final PropertyAccessorElement _undefinedConstant; |
ConstFieldVisitor _constants; |
@@ -223,7 +224,10 @@ class CodeGenerator extends Object |
functionClass = _getLibrary(c, 'dart:core').getType('Function'), |
privateSymbolClass = |
_getLibrary(c, 'dart:_internal').getType('PrivateSymbol'), |
- dartJSLibrary = _getLibrary(c, 'dart:js') { |
+ dartJSLibrary = _getLibrary(c, 'dart:js'), |
+ _undefinedConstant = |
+ _getLibrary(c, 'dart:_runtime').publicNamespace.get('undefined') { |
+ assert(_undefinedConstant != null); |
typeRep = new JSTypeRep(rules, types); |
} |
@@ -593,7 +597,8 @@ class CodeGenerator extends Object |
for (var declaration in unit.declarations) { |
if (declaration is TopLevelVariableDeclaration) { |
inferNullableTypes(declaration); |
- if (isInternalSdk && declaration.variables.isFinal) { |
+ if (isInternalSdk && |
+ (declaration.variables.isFinal || declaration.variables.isConst)) { |
_emitInternalSdkFields(declaration.variables.variables); |
} else { |
(fields ??= []).addAll(declaration.variables.variables); |
@@ -2411,25 +2416,38 @@ class CodeGenerator extends Object |
for (var param in parameters.parameters) { |
var jsParam = _emitSimpleIdentifier(param.identifier); |
- if (!options.destructureNamedParams) { |
+ if (!options.destructureNamedParams && |
+ param.kind != ParameterKind.REQUIRED) { |
if (param.kind == ParameterKind.NAMED) { |
// Parameters will be passed using their real names, not the (possibly |
// renamed) local variable. |
var paramName = js.string(param.identifier.name, "'"); |
- |
- // TODO(ochafik): Fix `'prop' in obj` to please Closure's renaming. |
- body.add(js.statement('let # = # && # in # ? #.# : #;', [ |
- jsParam, |
- namedArgumentTemp, |
- paramName, |
- namedArgumentTemp, |
- namedArgumentTemp, |
- paramName, |
- _defaultParamValue(param), |
- ])); |
+ var defaultValue = _defaultParamValue(param); |
+ if (defaultValue != null) { |
+ // TODO(ochafik): Fix `'prop' in obj` to please Closure's renaming. |
+ body.add(js.statement('let # = # && # in # ? #.# : #;', [ |
+ jsParam, |
+ namedArgumentTemp, |
+ paramName, |
+ namedArgumentTemp, |
+ namedArgumentTemp, |
+ paramName, |
+ defaultValue, |
+ ])); |
+ } else { |
+ body.add(js.statement('let # = # && #.#;', [ |
+ jsParam, |
+ namedArgumentTemp, |
+ namedArgumentTemp, |
+ paramName, |
+ ])); |
+ } |
} else if (param.kind == ParameterKind.POSITIONAL) { |
- body.add(js.statement('if (# === void 0) # = #;', |
- [jsParam, jsParam, _defaultParamValue(param)])); |
+ var defaultValue = _defaultParamValue(param); |
+ if (defaultValue != null) { |
+ body.add(js.statement( |
+ 'if (# === void 0) # = #;', [jsParam, jsParam, defaultValue])); |
+ } |
} |
} |
@@ -2453,12 +2471,18 @@ class CodeGenerator extends Object |
JS.Expression _defaultParamValue(FormalParameter param) { |
if (param is DefaultFormalParameter && param.defaultValue != null) { |
- return _visit(param.defaultValue); |
+ var defaultValue = param.defaultValue; |
+ return _isJSUndefined(defaultValue) ? null : _visit(defaultValue); |
} else { |
return new JS.LiteralNull(); |
} |
} |
+ bool _isJSUndefined(Expression expr) { |
+ expr = expr is AsExpression ? expr.expression : expr; |
+ return expr is Identifier && expr.staticElement == _undefinedConstant; |
+ } |
+ |
JS.Fun _emitNativeFunctionBody(MethodDeclaration node) { |
String name = |
getAnnotationName(node.element, isJSAnnotation) ?? node.name.name; |
@@ -3919,18 +3943,19 @@ class CodeGenerator extends Object |
} else { |
name = _visit(param.identifier); |
} |
+ |
+ var defaultValue = _defaultParamValue(param); |
namedVars.add(new JS.DestructuredVariable( |
- name: name, |
- structure: structure, |
- defaultValue: _defaultParamValue(param))); |
+ name: name, structure: structure, defaultValue: defaultValue)); |
} else { |
needsOpts = true; |
} |
} else { |
var jsParam = _visit(param); |
- result.add(param is DefaultFormalParameter && destructure |
+ var defaultValue = _defaultParamValue(param); |
+ result.add(destructure && defaultValue != null |
? new JS.DestructuredVariable( |
- name: jsParam, defaultValue: _defaultParamValue(param)) |
+ name: jsParam, defaultValue: defaultValue) |
: jsParam); |
} |
} |
@@ -4038,7 +4063,7 @@ class CodeGenerator extends Object |
} |
/// This is not used--we emit top-level fields as we are emitting the |
- /// compilation unit, see [_emitCompilationUnit]. |
+ /// compilation unit, see [visitCompilationUnit]. |
@override |
visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) { |
assert(false); |
@@ -4099,6 +4124,9 @@ class CodeGenerator extends Object |
// TODO(jmesserly): it'd be nice to avoid this special case. |
void _emitInternalSdkFields(List<VariableDeclaration> fields) { |
for (var field in fields) { |
+ // Skip our magic undefined constant. |
+ var element = field.element as TopLevelVariableElement; |
+ if (element.getter == _undefinedConstant) continue; |
_moduleItems.add(annotate( |
js.statement('# = #;', |
[_emitTopLevelName(field.element), _visitInitializer(field)]), |