fix #31781, fromEnvironment constants in DDK

Change-Id: I5915677204c0b02321e8db6a34e870b6ac63179d
Reviewed-on: https://dart-review.googlesource.com/32681
Commit-Queue: Jenny Messerly <jmesserly@google.com>
Reviewed-by: Vijay Menon <vsm@google.com>
This commit is contained in:
Jenny Messerly 2018-01-05 13:52:13 -08:00 committed by commit-bot@chromium.org
parent 7434bf6b73
commit 0add93f98e
4 changed files with 60 additions and 57 deletions

View file

@ -118,6 +118,7 @@ class ModuleCompiler {
// TODO(vsm): Should this be hardcoded?
context.declaredVariables.define('dart.library.html', 'true');
context.declaredVariables.define('dart.library.io', 'false');
context.declaredVariables.define('dart.library.ui', 'false');
if (!context.analysisOptions.strongMode) {
throw new ArgumentError('AnalysisContext must be strong mode');

View file

@ -153,7 +153,8 @@ Future<CompilerResult> _compile(List<String> args,
.toList();
var sdkSummaryPath = argResults['dart-sdk-summary'] ??
path.absolute(ddcPath, 'gen', 'sdk', 'ddc_sdk.dill');
path.join(path.dirname(path.dirname(Platform.resolvedExecutable)), 'lib',
'_internal', 'ddc_sdk.dill');
var packageFile =
argResults['packages'] ?? path.absolute(ddcPath, '..', '..', '.packages');
@ -367,5 +368,14 @@ Map<String, String> parseAndRemoveDeclaredVariables(List<String> args) {
i++;
}
}
// Add platform defined variables
declaredVariables['dart.isVM'] = 'false';
// TODO(vsm): Should this be hardcoded?
declaredVariables['dart.library.html'] = 'true';
declaredVariables['dart.library.io'] = 'false';
declaredVariables['dart.library.ui'] = 'false';
return declaredVariables;
}

View file

@ -4336,56 +4336,64 @@ class ProgramCompiler
@override
visitConstructorInvocation(ConstructorInvocation node) {
var target = node.target;
var targetName = target.name;
var ctor = node.target;
var args = node.arguments;
var ctorClass = ctor.enclosingClass;
if (_isObjectLiteral(ctorClass)) return _emitObjectLiteral(args);
var enclosingClass = target.enclosingClass;
if (node.isConst &&
targetName.name == 'fromEnvironment' &&
target.enclosingLibrary == coreTypes.coreLibrary &&
args.positional.length == 1) {
var varName = (args.positional[0] as StringLiteral).value;
var value = declaredVariables[varName];
var defaultArg = args.named.isNotEmpty ? args.named[0].value : null;
if (enclosingClass == coreTypes.stringClass) {
value ??= (defaultArg as StringLiteral)?.value;
return value != null ? js.escapedString(value) : new JS.LiteralNull();
} else if (enclosingClass == coreTypes.intClass) {
var intValue = int.parse(value ?? '',
onError: (_) => (defaultArg as IntLiteral)?.value);
return intValue != null ? js.number(intValue) : new JS.LiteralNull();
} else if (enclosingClass == coreTypes.boolClass) {
if (value == "true") return js.boolean(true);
if (value == "false") return js.boolean(false);
return js
.boolean(defaultArg != null && (defaultArg as BoolLiteral)?.value);
} else {
return _emitInvalidNode(
node, '${enclosingClass}.fromEnvironment constant');
}
JS.Expression emitNew() {
return new JS.New(_emitConstructorName(node.constructedType, ctor),
_emitArgumentList(args, types: false));
}
return _emitConstructorInvocation(
target, node.constructedType, args, node.isConst);
return node.isConst ? _emitConst(emitNew) : emitNew();
}
JS.Expression _emitFactoryInvocation(StaticInvocation node) {
var args = node.arguments;
var target = node.target;
var c = target.enclosingClass;
var type =
c.typeParameters.isEmpty ? c.rawType : new InterfaceType(c, args.types);
var ctor = node.target;
var ctorClass = ctor.enclosingClass;
var type = ctorClass.typeParameters.isEmpty
? ctorClass.rawType
: new InterfaceType(ctorClass, args.types);
if (node.isConst &&
ctor.name.name == 'fromEnvironment' &&
ctor.enclosingLibrary == coreTypes.coreLibrary &&
args.positional.length == 1 &&
// TODO(jmesserly): this does not correctly handle when the arguments to
// fromEnvironment are constant non-literal values.
args.positional[0] is BasicLiteral &&
(args.named.isEmpty || args.named[0].value is BasicLiteral)) {
var varName = (args.positional[0] as StringLiteral).value;
var value = declaredVariables[varName];
var defaultArg = args.named.isNotEmpty ? args.named[0].value : null;
if (ctorClass == coreTypes.stringClass) {
if (value != null) return js.escapedString(value);
return _visitExpression(defaultArg) ?? new JS.LiteralNull();
} else if (ctorClass == coreTypes.intClass) {
var intValue = int.parse(value ?? '', onError: (_) => null);
if (intValue != null) return js.number(intValue);
return _visitExpression(defaultArg) ?? new JS.LiteralNull();
} else if (ctorClass == coreTypes.boolClass) {
if (value == "true") return js.boolean(true);
if (value == "false") return js.boolean(false);
return _visitExpression(defaultArg) ?? js.boolean(false);
} else {
return _emitInvalidNode(node, '$ctorClass.fromEnvironment constant');
}
}
if (args.positional.isEmpty &&
args.named.isEmpty &&
c.enclosingLibrary.importUri.scheme == 'dart') {
ctorClass.enclosingLibrary.importUri.scheme == 'dart') {
// Skip the slow SDK factory constructors when possible.
switch (c.name) {
switch (ctorClass.name) {
case 'Map':
case 'HashMap':
case 'LinkedHashMap':
if (target.name == '') {
if (ctor.name == '') {
return js.call('new #.new()', _emitMapImplType(type));
} else if (target.name == 'identity') {
} else if (ctor.name == 'identity') {
return js.call(
'new #.new()', _emitMapImplType(type, identity: true));
}
@ -4393,15 +4401,15 @@ class ProgramCompiler
case 'Set':
case 'HashSet':
case 'LinkedHashSet':
if (target.name == '') {
if (ctor.name == '') {
return js.call('new #.new()', _emitSetImplType(type));
} else if (target.name == 'identity') {
} else if (ctor.name == 'identity') {
return js.call(
'new #.new()', _emitSetImplType(type, identity: true));
}
break;
case 'List':
if (target.name == '' && type is InterfaceType) {
if (ctor.name == '' && type is InterfaceType) {
return _emitList(type.typeArguments[0], []);
}
break;
@ -4410,28 +4418,13 @@ class ProgramCompiler
JS.Expression emitNew() {
// Native factory constructors are JS constructors - use new here.
return new JS.Call(_emitConstructorName(type, target),
return new JS.Call(_emitConstructorName(type, ctor),
_emitArgumentList(args, types: false));
}
return node.isConst ? _emitConst(emitNew) : emitNew();
}
JS.Expression _emitConstructorInvocation(
Constructor ctor, InterfaceType type, Arguments arguments, bool isConst) {
var enclosingClass = ctor.enclosingClass;
if (_isObjectLiteral(enclosingClass)) {
return _emitObjectLiteral(arguments);
}
JS.Expression emitNew() {
return new JS.New(_emitConstructorName(type, ctor),
_emitArgumentList(arguments, types: false));
}
return isConst ? _emitConst(emitNew) : emitNew();
}
JS.Expression _emitMapImplType(InterfaceType type, {bool identity}) {
var typeArgs = type.typeArguments;
if (typeArgs.isEmpty) return _emitType(type);

View file

@ -737,7 +737,6 @@ truncdiv_test: RuntimeError # Issue 29920
callable_test/none: RuntimeError # Expect.throws(TypeError) fails: Did not throw
conditional_import_string_test: RuntimeError # Unsupported operation: String.fromEnvironment can only be used as a const constructor
conditional_import_test: RuntimeError # Unsupported operation: bool.fromEnvironment can only be used as a const constructor
constant_string_interpolation2_test: RuntimeError # TypeError: Cannot read property 'Symbol(dartx.toString)' of null
cyclic_type_test/00: RuntimeError # Expect.equals(expected: <Derived>, actual: <dynamic>) fails.
cyclic_type_test/01: RuntimeError # Expect.equals(at index 0: Expected <Derived<Derived<int>>...>, Found: <dynamic>) fails.
deferred_closurize_load_library_test: RuntimeError # NoSuchMethodError: method not found: 'then'