Run dartdevk against its own compiled SDK and packages

Currently we test dartdevk against SDK/packages that were compiled with
dartdevc (DDC+Analyzer). This CL migrates to having those files compiled
with DDC+Kernel. dartdevc testing is unchanged.

Most of the fixes are around things like special optimized annotations
used in our SDK code, that were not understood by DDK. Also some inline
JS type annoations were not correct.

Change-Id: Iccf4427e4b9beffd6d97a4be654253d91f6cb89e
Reviewed-on: https://dart-review.googlesource.com/57800
Reviewed-by: Vijay Menon <vsm@google.com>
This commit is contained in:
Jenny Messerly 2018-06-08 19:18:34 +00:00
parent bdbf872079
commit 976aa4074b
28 changed files with 505 additions and 433 deletions

View file

@ -21,8 +21,7 @@ Future main(List<String> args) async {
await new _CompilerWorker(parsedArgs.args).run();
} else {
var result = await compile(parsedArgs.args);
var succeeded = result.result;
exitCode = succeeded ? 0 : 1;
exitCode = result.success ? 0 : 1;
}
}
@ -45,8 +44,7 @@ Future runBatch(List<String> batchArgs) async {
try {
var result = await compile(args, compilerState: compilerState);
compilerState = result.compilerState;
var succeeded = result.result;
outcome = succeeded ? 'PASS' : 'FAIL';
outcome = result.success ? 'PASS' : 'FAIL';
} catch (e, s) {
outcome = 'CRASH';
print('Unhandled exception:');
@ -82,7 +80,7 @@ class _CompilerWorker extends AsyncWorkerLoop {
output.writeln(message.toString());
}));
return new WorkResponse()
..exitCode = result.result ? 0 : 1
..exitCode = result.success ? 0 : 1
..output = output.toString();
}
}

View file

@ -1654,7 +1654,7 @@ class CodeGenerator extends Object
// Pass along all arguments verbatim, and let the callee handle them.
// TODO(jmesserly): we'll need something different once we have
// rest/spread support, but this should work for now.
var params = _emitFormalParameters(node.parameters?.parameters);
var params = _emitParameters(node.parameters?.parameters);
fun = new JS.Fun(
params,
@ -1671,7 +1671,7 @@ class CodeGenerator extends Object
if (init != null) body.add(init);
body.add(_visitStatement(node.body));
var params = _emitFormalParameters(node.parameters?.parameters);
var params = _emitParameters(node.parameters?.parameters);
fun = new JS.Fun(params, new JS.Block(body), returnType: returnType);
}
@ -2272,7 +2272,7 @@ class CodeGenerator extends Object
JS.Expression _emitConstructor(ConstructorDeclaration node,
List<VariableDeclaration> fields, JS.Expression className) {
var params = _emitFormalParameters(node.parameters?.parameters);
var params = _emitParameters(node.parameters?.parameters);
var savedFunction = _currentFunction;
_currentFunction = node.body;
@ -2584,7 +2584,7 @@ class CodeGenerator extends Object
if (node.isGetter) {
return new JS.Fun([], js.block('{ return this.#; }', [name]));
} else if (node.isSetter) {
var params = _emitFormalParameters(node.parameters?.parameters);
var params = _emitParameters(node.parameters?.parameters);
return new JS.Fun(
params, js.block('{ this.# = #; }', [name, params.last]));
} else {
@ -2788,7 +2788,7 @@ class CodeGenerator extends Object
// normal function (sync), vs (sync*, async, async*)
var isSync = !(element.isAsynchronous || element.isGenerator);
var formals = _emitFormalParameters(parameters?.parameters);
var formals = _emitParameters(parameters?.parameters);
var typeFormals = _emitTypeFormals(type.typeFormals);
if (_reifyGeneric(element)) formals.insertAll(0, typeFormals);
@ -2917,7 +2917,7 @@ class CodeGenerator extends Object
var params = parameters?.parameters;
var jsParams = _emitFormalParameters(
var jsParams = _emitParameters(
params?.where((p) => isPotentiallyMutated(body, p.element)));
var gen = emitGeneratorFn(jsParams);
@ -4092,8 +4092,7 @@ class CodeGenerator extends Object
return jsParams;
}
List<JS.Parameter> _emitFormalParameters(
Iterable<FormalParameter> parameters) {
List<JS.Parameter> _emitParameters(Iterable<FormalParameter> parameters) {
if (parameters == null) return [];
var result = <JS.Parameter>[];
@ -6315,7 +6314,7 @@ class CodeGenerator extends Object
@override
visitExtendsClause(node) => _unreachable(node);
/// Unused, see [_emitFormalParameters].
/// Unused, see [_emitParameters].
@override
visitFormalParameterList(node) => _unreachable(node);

View file

@ -11,8 +11,10 @@ import 'package:build_integration/file_system/multi_root.dart';
import 'package:front_end/src/api_prototype/standard_file_system.dart';
import 'package:front_end/src/api_unstable/ddc.dart' as fe;
import 'package:kernel/kernel.dart';
import 'package:kernel/text/ast_to_text.dart' as kernel show Printer;
import 'package:kernel/binary/ast_to_binary.dart' as kernel show BinaryPrinter;
import 'package:path/path.dart' as path;
import 'package:source_maps/source_maps.dart';
import 'package:source_maps/source_maps.dart' show SourceMapBuilder;
import '../compiler/js_names.dart' as JS;
import '../compiler/module_builder.dart';
@ -98,11 +100,11 @@ Uri stringToCustomUri(String s, List<Uri> roots, String scheme) {
class CompilerResult {
final fe.InitializedCompilerState compilerState;
final bool result;
final bool success;
CompilerResult(this.compilerState, this.result);
CompilerResult(this.compilerState, this.success);
CompilerResult.noState(this.result) : compilerState = null;
CompilerResult.noState(this.success) : compilerState = null;
}
Future<CompilerResult> _compile(List<String> args,
@ -113,9 +115,31 @@ Future<CompilerResult> _compile(List<String> args,
abbr: 'h', help: 'Display this message.', negatable: false)
..addOption('out', abbr: 'o', help: 'Output file (required).')
..addOption('packages', help: 'The package spec file to use.')
..addFlag('summarize',
help: 'emit API summary in a .dill file', defaultsTo: true)
// TODO(jmesserly): should default to `false` and be hidden.
// For now this is very helpful in debugging the compiler.
..addFlag('summarize-text',
help: 'emit API summary in a .js.txt file', defaultsTo: true)
// TODO(jmesserly): add verbose help to show hidden options
..addOption('dart-sdk-summary',
help: 'The path to the Dart SDK summary file.', hide: true)
// TODO(jmesserly): this help description length is too long.
//
// Also summary-input-dir and custom-app-scheme should be removed.
// They are undocumented and not necessary.
//
// URIs can be passed to `--summary` (including relative ones if desired),
// and we can easily add logic to prevert absolute file URIs in source maps.
//
// It appears to have been added in this change, but none of the flags are
// described there:
// https://github.com/dart-lang/sdk/commit/226602dc189555d9a43785c2a2f599b1622c1890
//
// Looking at the code, it appears to be solving a similar problem as
// `--module-root` in our old Analyzer-based backend.
// See https://github.com/dart-lang/sdk/issues/32272 for context on removing
// --module-root.
..addMultiOption('summary',
abbr: 's',
help: 'path to a summary of a transitive dependency of this module.\n'
@ -186,8 +210,9 @@ Future<CompilerResult> _compile(List<String> args,
var fileSystem = new MultiRootFileSystem(
customScheme, multiRoots, StandardFileSystem.instance);
var oldCompilerState = compilerState;
compilerState = await fe.initializeCompiler(
compilerState,
oldCompilerState,
stringToUri(sdkSummaryPath),
stringToUri(packageFile),
summaryUris,
@ -206,13 +231,29 @@ Future<CompilerResult> _compile(List<String> args,
String output = argResults['out'];
var file = new File(output);
if (!file.parent.existsSync()) file.parent.createSync(recursive: true);
await file.parent.create(recursive: true);
// TODO(jmesserly): Save .dill file so other modules can link in this one.
//await writeComponentToBinary(component, output);
// Useful for debugging:
writeComponentToText(component, path: output + '.txt');
// Output files can be written in parallel, so collect the futures.
var outFiles = <Future>[];
if (argResults['summarize'] as bool) {
// TODO(jmesserly): CFE mutates the Kernel tree, so we can't save the dill
// file if we successfully reused a cached library. If compiler state is
// unchanged, it means we used the cache.
//
// In that case, we need to unbind canonical names, because they could be
// bound already from the previous compile.
if (identical(compilerState, oldCompilerState)) {
component.unbindCanonicalNames();
}
var sink = new File(path.withoutExtension(output) + '.dill').openWrite();
new kernel.BinaryPrinter(sink).writeComponentFile(component);
outFiles.add(sink.flush().then((_) => sink.close()));
}
if (argResults['summarize-text'] as bool) {
var sink = new File(output + '.txt').openWrite();
new kernel.Printer(sink, showExternal: false).writeComponentFile(component);
outFiles.add(sink.flush().then((_) => sink.close()));
}
var compiler = new ProgramCompiler(component,
declaredVariables: declaredVariables,
@ -226,14 +267,14 @@ Future<CompilerResult> _compile(List<String> args,
jsUrl: path.toUri(output).toString(),
mapUrl: path.toUri(output + '.map').toString(),
customScheme: customScheme);
file.writeAsStringSync(jsCode.code);
outFiles.add(file.writeAsString(jsCode.code));
if (jsCode.sourceMap != null) {
file = new File(output + '.map');
if (!file.parent.existsSync()) file.parent.createSync(recursive: true);
file.writeAsStringSync(json.encode(jsCode.sourceMap));
outFiles.add(
new File(output + '.map').writeAsString(json.encode(jsCode.sourceMap)));
}
await Future.wait(outFiles);
return new CompilerResult(compilerState, true);
}

View file

@ -712,7 +712,7 @@ class ProgramCompiler extends Object
for (var ctor in superclass.constructors) {
var savedUri = _currentUri;
_currentUri = ctor.enclosingClass.fileUri;
var jsParams = _emitFormalParameters(ctor.function);
var jsParams = _emitParameters(ctor.function);
_currentUri = savedUri;
var ctorBody = <JS.Statement>[];
if (mixinCtor != null) ctorBody.add(mixinCtor);
@ -1171,7 +1171,8 @@ class ProgramCompiler extends Object
]));
}
var extMembers = _classProperties.extensionMethods;
var extMethods = _classProperties.extensionMethods;
var extAccessors = _classProperties.extensionAccessors;
var staticMethods = <JS.Property>[];
var instanceMethods = <JS.Property>[];
var staticGetters = <JS.Property>[];
@ -1235,7 +1236,8 @@ class ProgramCompiler extends Object
var property = new JS.Property(_declareMemberName(member), type);
var signatures = getSignatureList(member);
signatures.add(property);
if (!member.isStatic && extMembers.contains(name)) {
if (!member.isStatic &&
(extMethods.contains(name) || extAccessors.contains(name))) {
signatures.add(new JS.Property(
_declareMemberName(member, useExtension: true), type));
}
@ -1343,7 +1345,7 @@ class ProgramCompiler extends Object
Constructor node, List<Field> fields, JS.Expression className) {
var savedUri = _currentUri;
_currentUri = node.fileUri ?? savedUri;
var params = _emitFormalParameters(node.function);
var params = _emitParameters(node.function);
var body = _withCurrentFunction(
node.function,
() => _superDisallowed(
@ -1415,7 +1417,7 @@ class ProgramCompiler extends Object
return js.statement('#.#.call(this, #);', [
className,
_constructorName(ctor.name.name),
_emitArgumentList(node.arguments)
_emitArgumentList(node.arguments, types: false)
]);
}
@ -1431,7 +1433,7 @@ class ProgramCompiler extends Object
args = [];
} else {
ctor = superInit.target;
args = _emitArgumentList(superInit.arguments);
args = _emitArgumentList(superInit.arguments, types: false);
}
// We can skip the super call if it's empty. Most commonly this happens for
// things that extend Object, and don't have any field initializers or their
@ -1598,7 +1600,7 @@ class ProgramCompiler extends Object
var savedUri = _currentUri;
for (var m in c.procedures) {
_currentUri = m.fileUri ?? savedUri;
if (m.isForwardingStub) {
if (_isForwardingStub(m)) {
// TODO(jmesserly): is there any other kind of forwarding stub?
jsMethods.addAll(_emitCovarianceCheckStub(m));
} else if (m.isFactory) {
@ -1636,6 +1638,27 @@ class ProgramCompiler extends Object
return jsMethods.where((m) => m != null).toList();
}
bool _isForwardingStub(Procedure member) {
if (member.isForwardingStub || member.isForwardingSemiStub) {
if (_currentLibrary.importUri.scheme != 'dart') return true;
// TODO(jmesserly): external methods in the SDK seem to get incorrectly
// tagged as forwarding stubs even if they are patched. Perhaps there is
// an ordering issue in CFE. So for now we pattern match to see if it
// looks like an actual forwarding stub.
//
// We may be able to work around this in a cleaner way by simply emitting
// the code, and letting the normal covariance check logic handle things.
// But currently we use _emitCovarianceCheckStub to work around some
// issues in the stubs.
var body = member.function.body;
if (body is ReturnStatement) {
var expr = body.expression;
return expr is SuperMethodInvocation || expr is SuperPropertySet;
}
}
return false;
}
/// Emits a method, getter, or setter.
JS.Method _emitMethodDeclaration(Procedure member) {
if (member.isAbstract) {
@ -1665,7 +1688,7 @@ class ProgramCompiler extends Object
if (node.isGetter) {
return new JS.Fun([], js.block('{ return this.#; }', [name]));
} else if (node.isSetter) {
var params = _emitFormalParameters(node.function);
var params = _emitParameters(node.function);
return new JS.Fun(
params, js.block('{ this.# = #; }', [name, params.last]));
} else {
@ -1681,13 +1704,13 @@ class ProgramCompiler extends Object
// ensure soundness of the super member, so we must lookup the super
// member and determine checks ourselves.
// - it generates getter stubs, but these are not used
if (member.isGetter) return [];
if (member.isGetter) return const [];
var enclosingClass = member.enclosingClass;
var superMember = member.forwardingStubSuperTarget ??
member.forwardingStubInterfaceTarget;
if (superMember == null) return [];
if (superMember == null) return const [];
substituteType(DartType t) {
return _getTypeFromClass(t, superMember.enclosingClass, enclosingClass);
@ -1698,16 +1721,15 @@ class ProgramCompiler extends Object
if (superMember is Field && superMember.isGenericCovariantImpl ||
superMember is Procedure &&
isCovariant(superMember.function.positionalParameters[0])) {
return [];
return const [];
}
var setterType = substituteType(superMember.setterType);
if (types.isTop(setterType)) return const [];
return [
new JS.Method(
name,
js.fun('function(x) { return super.# = #; }', [
name,
_emitImplicitCast(new JS.Identifier('x'),
substituteType(superMember.setterType))
]),
js.fun('function(x) { return super.# = #; }',
[name, _emitImplicitCast(new JS.Identifier('x'), setterType)]),
isSetter: true),
new JS.Method(name, js.fun('function() { return super.#; }', [name]),
isGetter: true)
@ -1759,16 +1781,11 @@ class ProgramCompiler extends Object
}
}
if (namedParameters.isNotEmpty) jsParams.add(namedArgumentTemp);
if (body.isEmpty) return const []; // No checks were needed.
if (typeFormals.isEmpty) {
body.add(js.statement('return super.#(#);', [name, jsParams]));
} else {
body.add(
js.statement('return super.#(#)(#);', [name, typeFormals, jsParams]));
}
var fn = new JS.Fun(jsParams, new JS.Block(body));
return [new JS.Method(name, fn)];
if (namedParameters.isNotEmpty) jsParams.add(namedArgumentTemp);
body.add(js.statement('return super.#(#);', [name, jsParams]));
return [new JS.Method(name, new JS.Fun(jsParams, new JS.Block(body)))];
}
/// Emits a Dart factory constructor to a JS static method.
@ -1776,10 +1793,8 @@ class ProgramCompiler extends Object
if (isUnsupportedFactoryConstructor(node)) return null;
var function = node.function;
return new JS.Method(
_constructorName(node.name.name),
new JS.Fun(
_emitFormalParameters(function), _emitFunctionBody(function)),
return new JS.Method(_constructorName(node.name.name),
new JS.Fun(_emitParameters(function), _emitFunctionBody(function)),
isStatic: true)
..sourceInformation = _nodeEnd(node.fileEndOffset);
}
@ -1913,7 +1928,7 @@ class ProgramCompiler extends Object
js.call('Symbol.iterator'),
js.call('function() { return new #.JsIterator(this.#); }', [
runtimeModule,
_emitMemberName('iterator', type: iterable.asInterfaceType)
_emitMemberName('iterator', memberClass: coreTypes.iterableClass)
]) as JS.Fun);
}
@ -2110,10 +2125,10 @@ class ProgramCompiler extends Object
/// helper, that checks for null. The user defined method is called '=='.
///
JS.Expression _emitMemberName(String name,
{DartType type,
bool isStatic: false,
{bool isStatic: false,
bool useExtension,
NamedNode member}) {
Member member,
Class memberClass}) {
// Static members skip the rename steps and may require JS interop renames.
if (isStatic) {
return _emitStaticMemberName(name, member);
@ -2140,7 +2155,8 @@ class ProgramCompiler extends Object
return emitPrivateNameSymbol(_currentLibrary, name);
}
useExtension ??= _isSymbolizedMember(type, name);
memberClass ??= member?.enclosingClass;
useExtension ??= _isSymbolizedMember(memberClass, name);
name = JS.memberNameForDartMember(
name, member is Procedure && member.isExternal);
if (useExtension) {
@ -2169,38 +2185,29 @@ class ProgramCompiler extends Object
/// Note, this is an underlying assumption here that, if another native type
/// subtypes this one, it also forwards this member to its underlying native
/// one without renaming.
bool _isSymbolizedMember(DartType type, String name) {
while (type is TypeParameterType) {
type = (type as TypeParameterType).bound;
}
if (type == null ||
type == const DynamicType() ||
type == coreTypes.objectClass) {
bool _isSymbolizedMember(Class c, String name) {
if (c == null) {
return isObjectMember(name);
} else if (type is InterfaceType) {
var c = _typeRep.getImplementationClass(type) ?? type.classNode;
if (_extensionTypes.isNativeClass(c)) {
var member = _lookupForwardedMember(c, name);
// Fields on a native class are implicitly native.
// Methods/getters/setters are marked external/native.
if (member is Field || member is Procedure && member.isExternal) {
var jsName = getAnnotationName(member, isJSName);
return jsName != null && jsName != name;
} else {
// Non-external members must be symbolized.
return true;
}
}
// If the receiver *may* be a native type (i.e., an interface allowed to
// be implemented by a native class), conservatively symbolize - we don't
// know whether it'll be implemented via forwarding.
// TODO(vsm): Consider CHA here to be less conservative.
return _extensionTypes.isNativeInterface(c);
} else if (type is FunctionType) {
return true;
}
return false;
c = _typeRep.getImplementationClass(c.rawType) ?? c;
if (_extensionTypes.isNativeClass(c)) {
var member = _lookupForwardedMember(c, name);
// Fields on a native class are implicitly native.
// Methods/getters/setters are marked external/native.
if (member is Field || member is Procedure && member.isExternal) {
var jsName = getAnnotationName(member, isJSName);
return jsName != null && jsName != name;
} else {
// Non-external members must be symbolized.
return true;
}
}
// If the receiver *may* be a native type (i.e., an interface allowed to
// be implemented by a native class), conservatively symbolize - we don't
// know whether it'll be implemented via forwarding.
// TODO(vsm): Consider CHA here to be less conservative.
return _extensionTypes.isNativeInterface(c);
}
var _forwardingCache = new HashMap<Class, Map<String, Member>>();
@ -2634,9 +2641,13 @@ class ProgramCompiler extends Object
JS.Fun _emitFunction(FunctionNode f, String name) {
// normal function (sync), vs (sync*, async, async*)
var isSync = f.asyncMarker == AsyncMarker.Sync;
var formals = _emitFormalParameters(f);
var formals = _emitParameters(f);
var typeFormals = _emitTypeFormals(f.typeParameters);
formals.insertAll(0, typeFormals);
var parent = f.parent;
if (_reifyGenericFunction(parent is Member ? parent : null)) {
formals.insertAll(0, typeFormals);
}
// TODO(jmesserly): need a way of determining if parameters are
// potentially mutated in Kernel. For now we assume all parameters are.
@ -2654,9 +2665,14 @@ class ProgramCompiler extends Object
return new JS.Fun(formals, code);
}
// TODO(jmesserly): rename _emitParameters
List<JS.Parameter> _emitFormalParameters(FunctionNode f) {
var result = f.positionalParameters.map(_emitVariableDef).toList();
List<JS.Parameter> _emitParameters(FunctionNode f) {
var positional = f.positionalParameters;
var result = new List<JS.Parameter>.from(positional.map(_emitVariableDef));
if (positional.isNotEmpty &&
f.requiredParameterCount == positional.length &&
positional.last.annotations.any(isJsRestAnnotation)) {
result.last = new JS.RestParameter(result.last);
}
if (f.namedParameters.isNotEmpty) result.add(namedArgumentTemp);
return result;
}
@ -2730,7 +2746,7 @@ class ProgramCompiler extends Object
//
// In the future, we might be able to simplify this, see:
// https://github.com/dart-lang/sdk/issues/28320
var jsParams = _emitFormalParameters(function);
var jsParams = _emitParameters(function);
var gen = emitGeneratorFn((fnBody) => jsParams =
jsParams.where(JS.findMutatedVariables(fnBody).contains).toList());
if (jsParams.isNotEmpty) gen = js.call('() => #(#)', [gen, jsParams]);
@ -2880,6 +2896,12 @@ class ProgramCompiler extends Object
bool _annotatedNullCheck(List<Expression> annotations) =>
annotations.any(_nullableInference.isNullCheckAnnotation);
bool _reifyGenericFunction(Member m) =>
m == null ||
m.enclosingLibrary.importUri.scheme != 'dart' ||
!m.annotations
.any((a) => isBuiltinAnnotation(a, '_js_helper', 'NoReifyGeneric'));
JS.Statement _nullParameterCheck(JS.Expression param) {
var call = runtimeCall('argumentError((#))', [param]);
return js.statement('if (# == null) #;', [param, call]);
@ -3628,32 +3650,36 @@ class ProgramCompiler extends Object
JS.Expression _emitPropertyGet(Expression receiver, Member member,
[String memberName]) {
memberName ??= member.name.name;
var receiverType = receiver.getStaticType(types);
// TODO(jmesserly): should tearoff of `.call` on a function type be
// encoded as a different node, or possibly eliminated?
// (Regardless, we'll still need to handle the callable JS interop classes.)
if (memberName == 'call' && _isDirectCallable(receiverType)) {
if (memberName == 'call' &&
_isDirectCallable(receiver.getStaticType(types))) {
// Tearoff of `call` on a function type is a no-op;
return _visitExpression(receiver);
}
var jsName =
_emitMemberName(memberName, type: receiverType, member: member);
var jsName = _emitMemberName(memberName, member: member);
var jsReceiver = _visitExpression(receiver);
// TODO(jmesserly): we need to mark an end span for property accessors so
// they can be hovered. Unfortunately this is not possible as Kernel does
// not store this data.
if (member == null) {
if (isObjectMember(memberName)) {
if (isNullable(receiver)) {
// If the receiver is nullable, use a helper so calls like
// `null.hashCode` and `null.runtimeType` will work.
// Also method tearoffs like `null.toString`.
if (_isObjectMethod(memberName)) {
return runtimeCall('bind(#, #)', [jsReceiver, jsName]);
}
return runtimeCall('#(#)', [memberName, jsReceiver]);
}
// Otherwise generate this as a normal typed property get.
} else if (member == null) {
return runtimeCall('dload$_replSuffix(#, #)', [jsReceiver, jsName]);
}
if (_isObjectMemberCall(receiver, memberName)) {
if (_isObjectMethod(memberName)) {
return runtimeCall('bind(#, #)', [jsReceiver, jsName]);
} else {
return runtimeCall('#(#)', [memberName, jsReceiver]);
}
} else if (_reifyTearoff(member)) {
if (_reifyTearoff(member)) {
return runtimeCall('bind(#, #)', [jsReceiver, jsName]);
} else {
return new JS.PropertyAccess(jsReceiver, jsName);
@ -3668,8 +3694,8 @@ class ProgramCompiler extends Object
JS.Expression _emitPropertySet(
Expression receiver, Member member, Expression value,
[String memberName]) {
var jsName = _emitMemberName(memberName ?? member.name.name,
type: receiver.getStaticType(types), member: member);
var jsName =
_emitMemberName(memberName ?? member.name.name, member: member);
var jsReceiver = _visitExpression(receiver);
var jsValue = _visitExpression(value);
@ -3748,13 +3774,13 @@ class ProgramCompiler extends Object
}
var jsReceiver = _visitExpression(receiver);
var args = _emitArgumentList(arguments);
var receiverType = receiver.getStaticType(types);
var args = _emitArgumentList(arguments, target: target);
bool isCallingDynamicField = target is Member &&
target.hasGetter &&
_isDynamicOrFunction(target.getterType);
if (name == 'call') {
var receiverType = receiver.getStaticType(types);
if (isCallingDynamicField || _isDynamicOrFunction(receiverType)) {
return _emitDynamicInvoke(jsReceiver, null, args, arguments);
} else if (_isDirectCallable(receiverType)) {
@ -3763,13 +3789,17 @@ class ProgramCompiler extends Object
}
}
var jsName = _emitMemberName(name, type: receiverType, member: target);
if (target == null || isCallingDynamicField) {
return _emitDynamicInvoke(jsReceiver, jsName, args, arguments);
}
if (_isObjectMemberCall(receiver, name)) {
var jsName = _emitMemberName(name, member: target);
if (isObjectMember(name)) {
assert(arguments.types.isEmpty); // Object methods don't take type args.
return runtimeCall('#(#, #)', [name, jsReceiver, args]);
if (isNullable(receiver)) {
// If the receiver is nullable, use a helper so calls like
// `null.toString()` will work.
return runtimeCall('#(#, #)', [name, jsReceiver, args]);
}
// Otherwise generate this as a normal typed method call.
} else if (target == null || isCallingDynamicField) {
return _emitDynamicInvoke(jsReceiver, jsName, args, arguments);
}
// TODO(jmesserly): remove when Kernel desugars this for us.
// Handle `o.m(a)` where `o.m` is a getter returning a class with `call`.
@ -3827,7 +3857,7 @@ class ProgramCompiler extends Object
var c = from.classNode;
var member = hierarchy.getInterfaceMember(c, new Name("call"));
if (member is Procedure && !member.isAccessor && !usesJSInterop(c)) {
return _emitMemberName('call', type: from, member: member);
return _emitMemberName('call', member: member);
}
return null;
}
@ -3838,19 +3868,20 @@ class ProgramCompiler extends Object
JS.Expression _emitUnaryOperator(
Expression expr, Member target, InvocationExpression node) {
var op = node.name.name;
var dispatchType = expr.getStaticType(types);
if (_typeRep.unaryOperationIsPrimitive(dispatchType)) {
if (op == '~') {
if (_typeRep.isNumber(dispatchType)) {
return _coerceBitOperationResultToUnsigned(
node, js.call('~#', notNull(expr)));
if (target != null) {
var dispatchType = target.enclosingClass.rawType;
if (_typeRep.unaryOperationIsPrimitive(dispatchType)) {
if (op == '~') {
if (_typeRep.isNumber(dispatchType)) {
return _coerceBitOperationResultToUnsigned(
node, js.call('~#', notNull(expr)));
}
return _emitOperatorCall(expr, target, op, []);
}
return _emitOperatorCall(expr, target, op, []);
if (op == 'unary-') op = '-';
return js.call('$op#', notNull(expr));
}
if (op == 'unary-') op = '-';
return js.call('$op#', notNull(expr));
}
return _emitOperatorCall(expr, target, op, []);
}
@ -4004,76 +4035,82 @@ class ProgramCompiler extends Object
var op = node.name.name;
if (op == '==') return _emitEqualityOperator(left, target, right);
var leftType = left.getStaticType(types);
var rightType = right.getStaticType(types);
// TODO(jmesserly): using the target type here to work around:
// https://github.com/dart-lang/sdk/issues/33293
if (target != null) {
var targetClass = target.enclosingClass;
var leftType = targetClass.rawType;
var rightType = right.getStaticType(types);
if (_typeRep.binaryOperationIsPrimitive(leftType, rightType) ||
leftType == types.stringType && op == '+') {
// special cases where we inline the operation
// these values are assumed to be non-null (determined by the checker)
// TODO(jmesserly): it would be nice to just inline the method from core,
// instead of special cases here.
JS.Expression binary(String code) {
return js.call(code, [notNull(left), notNull(right)]);
}
if (_typeRep.binaryOperationIsPrimitive(leftType, rightType) ||
leftType == types.stringType && op == '+') {
// special cases where we inline the operation
// these values are assumed to be non-null (determined by the checker)
// TODO(jmesserly): it would be nice to just inline the method from core,
// instead of special cases here.
JS.Expression binary(String code) {
return js.call(code, [notNull(left), notNull(right)]);
}
JS.Expression bitwise(String code) {
return _coerceBitOperationResultToUnsigned(node, binary(code));
}
JS.Expression bitwise(String code) {
return _coerceBitOperationResultToUnsigned(node, binary(code));
}
switch (op) {
case '~/':
// `a ~/ b` is equivalent to `(a / b).truncate()`
return js.call('(# / #).#()', [
notNull(left),
notNull(right),
_emitMemberName('truncate', type: leftType)
]);
switch (op) {
case '~/':
// `a ~/ b` is equivalent to `(a / b).truncate()`
return js.call('(# / #).#()', [
notNull(left),
notNull(right),
_emitMemberName('truncate', memberClass: targetClass)
]);
case '%':
// TODO(sra): We can generate `a % b + 0` if both are non-negative
// (the `+ 0` is to coerce -0.0 to 0).
return _emitOperatorCall(left, target, op, [right]);
case '%':
// TODO(sra): We can generate `a % b + 0` if both are non-negative
// (the `+ 0` is to coerce -0.0 to 0).
return _emitOperatorCall(left, target, op, [right]);
case '&':
return bitwise('# & #');
case '&':
return bitwise('# & #');
case '|':
return bitwise('# | #');
case '|':
return bitwise('# | #');
case '^':
return bitwise('# ^ #');
case '^':
return bitwise('# ^ #');
case '>>':
int shiftCount = _asIntInRange(right, 0, 31);
if (_is31BitUnsigned(left) && shiftCount != null) {
return binary('# >> #');
}
if (_isDefinitelyNonNegative(left) && shiftCount != null) {
return binary('# >>> #');
}
// If the context selects out only bits that can't be affected by the
// sign position we can use any JavaScript shift, `(x >> 6) & 3`.
if (shiftCount != null &&
_parentMasksToWidth(node, 31 - shiftCount)) {
return binary('# >> #');
}
return _emitOperatorCall(left, target, op, [right]);
case '>>':
int shiftCount = _asIntInRange(right, 0, 31);
if (_is31BitUnsigned(left) && shiftCount != null) {
return binary('# >> #');
}
if (_isDefinitelyNonNegative(left) && shiftCount != null) {
return binary('# >>> #');
}
// If the context selects out only bits that can't be affected by the
// sign position we can use any JavaScript shift, `(x >> 6) & 3`.
if (shiftCount != null &&
_parentMasksToWidth(node, 31 - shiftCount)) {
return binary('# >> #');
}
return _emitOperatorCall(left, target, op, [right]);
case '<<':
if (_is31BitUnsigned(node)) {
// Result is 31 bit unsigned which implies the shift count was small
// enough not to pollute the sign bit.
return binary('# << #');
}
if (_asIntInRange(right, 0, 31) != null) {
return _coerceBitOperationResultToUnsigned(node, binary('# << #'));
}
return _emitOperatorCall(left, target, op, [right]);
case '<<':
if (_is31BitUnsigned(node)) {
// Result is 31 bit unsigned which implies the shift count was small
// enough not to pollute the sign bit.
return binary('# << #');
}
if (_asIntInRange(right, 0, 31) != null) {
return _coerceBitOperationResultToUnsigned(
node, binary('# << #'));
}
return _emitOperatorCall(left, target, op, [right]);
default:
// TODO(vsm): When do Dart ops not map to JS?
return binary('# $op #');
default:
// TODO(vsm): When do Dart ops not map to JS?
return binary('# $op #');
}
}
}
@ -4083,7 +4120,8 @@ class ProgramCompiler extends Object
JS.Expression _emitEqualityOperator(
Expression left, Member target, Expression right,
{bool negated = false}) {
var leftType = left.getStaticType(types);
var targetClass = target?.enclosingClass;
var leftType = targetClass?.rawType ?? left.getStaticType(types);
// Conceptually `x == y` in Dart is defined as:
//
@ -4101,14 +4139,15 @@ class ProgramCompiler extends Object
// TODO(leafp,jmesserly): we could use class hierarchy analysis to check
// if `operator ==` was overridden, similar to how we devirtualize private
// fields.
//
// If we know that the left type uses identity for equality, we can
// sometimes emit better code, either `===` or `==`.
var isEnum = leftType is InterfaceType && leftType.classNode.isEnum;
var usesIdentity = _typeRep.isPrimitive(leftType) ||
isEnum ||
_isNull(left) ||
_isNull(right);
// If we know that the left type uses identity for equality, we can
// sometimes emit better code, either `===` or `==`.
if (usesIdentity) {
return _emitCoreIdenticalCall([left, right], negated: negated);
}
@ -4125,7 +4164,7 @@ class ProgramCompiler extends Object
// Otherwise we emit a call to the == method.
return js.call(negated ? '!#[#](#)' : '#[#](#)', [
_visitExpression(left),
_emitMemberName('==', type: leftType),
_emitMemberName('==', memberClass: targetClass),
_visitExpression(right)
]);
}
@ -4139,8 +4178,7 @@ class ProgramCompiler extends Object
Expression receiver, Member target, String name, List<Expression> args) {
// TODO(jmesserly): calls that don't pass `element` are probably broken for
// `super` calls from disallowed super locations.
var type = receiver.getStaticType(types);
var memberName = _emitMemberName(name, type: type, member: target);
var memberName = _emitMemberName(name, member: target);
if (target == null) {
// dynamic dispatch
var dynamicHelper = const {'[]': 'dindex', '[]=': 'dsetindex'}[name];
@ -4164,15 +4202,15 @@ class ProgramCompiler extends Object
// TODO(jmesserly): optimize super operators for kernel
@override
visitSuperMethodInvocation(SuperMethodInvocation node) {
return new JS.Call(_emitSuperTarget(node.interfaceTarget),
_emitArgumentList(node.arguments));
var target = node.interfaceTarget;
return new JS.Call(_emitSuperTarget(target),
_emitArgumentList(node.arguments, target: target));
}
/// Emits the [JS.PropertyAccess] for accessors or method calls to
/// [jsTarget].[jsName], replacing `super` if it is not allowed in scope.
JS.PropertyAccess _emitSuperTarget(Member member, {bool setter: false}) {
var type = member.enclosingClass.rawType;
var jsName = _emitMemberName(member.name.name, type: type, member: member);
var jsName = _emitMemberName(member.name.name, member: member);
if (member is Field && !virtualFields.isVirtual(member)) {
return new JS.PropertyAccess(new JS.This(), jsName);
}
@ -4246,7 +4284,7 @@ class ProgramCompiler extends Object
}
var fn = _emitStaticTarget(target);
var args = _emitArgumentList(node.arguments);
var args = _emitArgumentList(node.arguments, target: target);
return new JS.Call(fn, args);
}
@ -4296,13 +4334,25 @@ class ProgramCompiler extends Object
JS.Expression _emitStaticTarget(Member target) {
var c = target.enclosingClass;
if (c != null) {
// A static native element should just forward directly to the
// JS type's member.
if (target is Procedure && target.isStatic && target.isExternal) {
var nativeName = _extensionTypes.getNativePeers(c);
if (nativeName.isNotEmpty) {
var memberName = getAnnotationName(target, isJSName) ??
_emitStaticMemberName(target.name.name, target);
return runtimeCall('global.#.#', [nativeName[0], memberName]);
}
}
return new JS.PropertyAccess(_emitStaticClassName(c),
_emitStaticMemberName(target.name.name, target));
}
return _emitTopLevelName(target);
}
List<JS.Expression> _emitArgumentList(Arguments node, {bool types: true}) {
List<JS.Expression> _emitArgumentList(Arguments node,
{bool types: true, Member target}) {
types = types && _reifyGenericFunction(target);
var args = <JS.Expression>[];
if (types) {
for (var typeArg in node.types) {
@ -4531,7 +4581,7 @@ class ProgramCompiler extends Object
}
JS.Expression _emitObjectLiteral(Arguments node) {
var args = _emitArgumentList(node);
var args = _emitArgumentList(node, types: false);
if (args.isEmpty) return js.call('{}');
assert(args.single is JS.ObjectInitializer);
return args.single;
@ -4677,8 +4727,10 @@ class ProgramCompiler extends Object
nativeSymbol
]);
} else {
return js.call('#.new(#)',
[_emitConstructorAccess(coreTypes.symbolClass.rawType), name]);
return js.call('new #.new(#)', [
_emitConstructorAccess(coreTypes.internalSymbolClass.rawType),
name
]);
}
}
@ -4914,16 +4966,6 @@ class ProgramCompiler extends Object
_reifyFunctionType(member.function);
}
/// Everything in Dart is an Object and supports the 4 members on Object,
/// so we have to use a runtime helper to handle values such as `null` and
/// native types.
///
/// For example `null.toString()` is legal in Dart, so we need to generate
/// that as `dart.toString(obj)`.
bool _isObjectMemberCall(Expression target, String memberName) {
return isObjectMember(memberName) && isNullable(target);
}
/// Returns the name value of the `JSExportName` annotation (when compiling
/// the SDK), or `null` if there's none. This is used to control the name
/// under which functions are compiled and exported.

View file

@ -83,8 +83,10 @@ bool isBuiltinAnnotation(
Expression value, String libraryName, String expectedName) {
if (value is ConstructorInvocation) {
var c = value.target.enclosingClass;
return c.name == expectedName &&
c.enclosingLibrary.importUri.toString() == libraryName;
if (c.name == expectedName) {
var uri = c.enclosingLibrary.importUri;
return uri.scheme == 'dart' && uri.path == libraryName;
}
}
return false;
}

View file

@ -83,7 +83,7 @@ class NativeTypeSet {
void _addExtensionTypesForLibrary(String library, List<String> classNames) {
var sdk = coreTypes.index;
for (var className in classNames) {
_addExtensionType(sdk.getClass(library, className), true);
_addExtensionType(sdk.getClass(library, className));
}
}

View file

@ -310,13 +310,13 @@ class ClassPropertyModel {
///
/// By tracking the set of seen members, we can visit superclasses and mixins
/// and ultimately collect every most-derived member exposed by a given type.
void _findExtensionMembers(Class class_, HashSet<String> seenConcreteMembers,
Set<String> allNatives) {
void _findExtensionMembers(
Class c, HashSet<String> seenConcreteMembers, Set<String> allNatives) {
// We only visit each most derived concrete member.
// To avoid visiting an overridden superclass member, we skip members
// we've seen, and visit starting from the class, then mixins in
// reverse order, then superclasses.
for (var m in class_.members) {
for (var m in c.members) {
var name = m.name.name;
if (m.isAbstract || m is Constructor) continue;
if (m is Procedure) {
@ -338,8 +338,11 @@ class ClassPropertyModel {
/// types.
void _collectNativeMembers(Class c, Set<String> members) {
if (extensionTypes.hasNativeSubtype(c)) {
for (var m in c.procedures) {
if (!m.name.isPrivate && !m.isStatic) members.add(m.name.name);
for (var m in c.members) {
if (!m.name.isPrivate &&
(m is Procedure && !m.isStatic || m is Field && !m.isStatic)) {
members.add(m.name.name);
}
}
}
var m = c.mixedInClass;

View file

@ -77,9 +77,15 @@ class DevCompilerTarget extends Target {
// to the file where the class resides, or the file where the method we're
// mocking resides).
Expression createInvocation(String name, List<Expression> positional) {
var ctor = coreTypes.invocationClass.procedures
// TODO(jmesserly): this uses the implementation _Invocation class,
// because the CFE does not resolve the redirecting factory constructors
// like it would for user code. Our code generator expects all redirecting
// factories to be resolved to the real constructor.
var ctor = coreTypes.index
.getClass('dart:core', '_Invocation')
.constructors
.firstWhere((c) => c.name.name == name);
return new StaticInvocation(ctor, new Arguments(positional));
return new ConstructorInvocation(ctor, new Arguments(positional));
}
if (name.startsWith('get:')) {
@ -96,6 +102,8 @@ class DevCompilerTarget extends Target {
if (isGeneric) {
ctorArgs.add(new ListLiteral(
arguments.types.map((t) => new TypeLiteral(t)).toList()));
} else {
ctorArgs.add(new NullLiteral());
}
ctorArgs.add(new ListLiteral(arguments.positional));
if (arguments.named.isNotEmpty) {
@ -105,7 +113,7 @@ class DevCompilerTarget extends Target {
.toList(),
keyType: coreTypes.symbolClass.rawType));
}
return createInvocation(isGeneric ? 'genericMethod' : 'method', ctorArgs);
return createInvocation('method', ctorArgs);
}
@override

View file

@ -69,7 +69,7 @@ class DevCompilerRunner implements CompilerRunner {
try {
var result = await compile(args, compilerState: context.compilerState);
context.compilerState = result.compilerState;
succeeded = result.result;
succeeded = result.success;
} catch (e, s) {
print('Unhandled exception:');
print(e);

View file

@ -3,13 +3,10 @@ import 'dart:async';
import 'dart:io';
import 'package:args/args.dart';
import 'package:front_end/src/api_prototype/compilation_message.dart';
import 'package:front_end/src/api_prototype/compiler_options.dart';
import 'package:front_end/src/api_prototype/summary_generator.dart';
import 'package:path/path.dart' as p;
import 'package:dev_compiler/src/analyzer/command.dart' as analyzer;
import 'package:dev_compiler/src/kernel/target.dart';
import 'package:dev_compiler/src/analyzer/command.dart' as dartdevc;
import 'package:dev_compiler/src/kernel/command.dart' as dartdevk;
final String scriptDirectory = p.dirname(p.fromUri(Platform.script));
@ -27,8 +24,6 @@ String kernelSummary;
/// packages will be placed in a "pkg" subdirectory of this.
String outputDirectory;
String get pkgDirectory => p.join(outputDirectory, "pkg");
/// Compiles the packages that the DDC tests use to JS into the given output
/// directory.
///
@ -70,8 +65,6 @@ Future main(List<String> arguments) async {
kernelSummary = argResults["kernel-sdk"] as String;
outputDirectory = argResults["output"] as String;
new Directory(pkgDirectory).createSync(recursive: true);
// Build leaf packages. These have no other package dependencies.
// Under pkg.
@ -108,7 +101,6 @@ Future main(List<String> arguments) async {
if (!isTravis) {
await compileModule('unittest', deps: [
'matcher',
'path',
'stack_trace'
], libs: [
@ -135,81 +127,35 @@ void _usageError(ArgParser parser, [String message]) {
/// [libs] and [deps] on other modules.
Future compileModule(String module,
{List<String> libs = const [], List<String> deps = const []}) async {
if (analyzerSummary != null) compileModuleUsingAnalyzer(module, libs, deps);
if (kernelSummary != null) await compileKernelSummary(module, libs, deps);
}
makeArgs(bool kernel) {
var pkgDirectory = p.join(outputDirectory, kernel ? 'pkg_kernel' : 'pkg');
new Directory(pkgDirectory).createSync(recursive: true);
void compileModuleUsingAnalyzer(
String module, List<String> libraries, List<String> dependencies) {
var args = [
'--dart-sdk-summary=$analyzerSummary',
'-o${pkgDirectory}/$module.js',
// There is always a library that matches the module.
'package:$module/$module.dart'
];
// Add any additional libraries.
for (var lib in libraries) {
args.add('package:$module/$lib.dart');
var args = [
'--dart-sdk-summary=${kernel ? kernelSummary : analyzerSummary}',
'-o${pkgDirectory}/$module.js',
'package:$module/$module.dart'
];
for (var lib in libs) {
args.add('package:$module/$lib.dart');
}
for (var dep in deps) {
args.add('-s${pkgDirectory}/$dep.${kernel ? "dill" : "sum"}');
}
if (kernel) {
args.add('--summary-input-dir=$pkgDirectory');
}
return args;
}
// Add summaries for any modules this depends on.
for (var dep in dependencies) {
args.add('-s${pkgDirectory}/$dep.sum');
if (analyzerSummary != null) {
var args = makeArgs(false);
var exitCode = dartdevc.compile(args);
if (exitCode != 0) exit(exitCode);
}
var exitCode = analyzer.compile(args);
if (exitCode != 0) exit(exitCode);
}
Future compileKernelSummary(
String module, List<String> libraries, List<String> dependencies) async {
var succeeded = true;
void errorHandler(CompilationMessage error) {
if (error.severity == Severity.error) succeeded = false;
}
var options = new CompilerOptions()
..sdkSummary = p.toUri(kernelSummary)
..packagesFileUri = _uriInRepo(".packages")
..strongMode = true
..debugDump = true
..onError = errorHandler
..reportMessages = true
..target = new DevCompilerTarget();
// There is always a library that matches the module.
var inputs = [Uri.parse("package:$module/$module.dart")];
// Add any other libraries too.
for (var lib in libraries) {
inputs.add(Uri.parse("package:$module/$lib.dart"));
}
// Add summaries for any modules this depends on.
var uris = <Uri>[];
for (var dep in dependencies) {
uris.add(p.toUri(p.absolute(p.join(pkgDirectory, "$dep.dill"))));
}
options.inputSummaries = uris;
// Compile the summary.
var bytes = await summaryFor(inputs, options);
var dillFile = new File(p.join(pkgDirectory, "$module.dill"));
if (succeeded) {
dillFile.writeAsBytesSync(bytes);
} else {
// Don't leave the previous version of the file on failure.
if (dillFile.existsSync()) dillFile.deleteSync();
stderr.writeln("Could not generate kernel summary for $module.");
exit(1);
if (kernelSummary != null) {
var args = makeArgs(true);
var result = await dartdevk.compile(args);
if (!result.success) exit(1);
}
}
Uri _uriInRepo(String pathInRepo) {
// Walk up to repo root.
var result = p.join(scriptDirectory, "../../../");
result = p.join(result, pathInRepo);
return p.toUri(p.absolute(p.normalize(result)));
}

View file

@ -59,7 +59,11 @@ void main(List<String> args) {
ProcessResult runDdc(String command, List<String> args) {
if (debug) {
// Use unbuilt script. This only works from a source checkout.
args.insertAll(0, ['--preview-dart-2', '--enable-asserts', path.join(ddcPath, 'bin', '${command}.dart')]);
args.insertAll(0, [
'--preview-dart-2',
'--enable-asserts',
path.join(ddcPath, 'bin', '${command}.dart')
]);
command = dartBinary;
} else {
// Use built snapshot.
@ -86,8 +90,17 @@ void main(List<String> args) {
mod = 'amd';
break;
}
var sdkJsPath = path.join(dartSdk, 'lib', 'dev_compiler', mod);
String sdkJsPath;
if (debug) {
var sdkRoot = path.dirname(path.dirname(ddcPath));
var buildDir = path.join(sdkRoot, Platform.isMacOS ? 'xcodebuild' : 'out');
var genDir = path.join(buildDir, 'ReleaseX64', 'gen', 'utils', 'dartdevc');
sdkJsPath = path.join(genDir, kernel ? 'kernel' : 'js', mod);
} else {
var suffix = kernel ? path.join('kernel', mod) : mod;
sdkJsPath = path.join(dartSdk, 'lib', 'dev_compiler', suffix);
}
ProcessResult result;
if (kernel) {
var ddcSdk = path.join(dartSdk, 'lib', '_internal', 'ddc_sdk.dill');

View file

@ -63,8 +63,6 @@ fi
BASENAME=$( basename "${1%.*}")
LIBROOT=$(cd $( dirname "${1%.*}") && pwd)
export NODE_PATH=$GEN_DIR/js/common:$LIBROOT:$NODE_PATH
if [ "$KERNEL" = true ]; then
if [ ! -e $GEN_DIR/kernel/ddc_sdk.dill ]; then
@ -74,6 +72,8 @@ if [ "$KERNEL" = true ]; then
exit 1
fi
NODE_PATH=$GEN_DIR/kernel/common:$LIBROOT:$NODE_PATH
$SDK_DIR/sdk/bin/dartdevk --modules=node \
--dart-sdk-summary=$GEN_DIR/kernel/ddc_sdk.dill \
-o $LIBROOT/$BASENAME.js $*
@ -86,6 +86,8 @@ else
exit 1
fi
NODE_PATH=$GEN_DIR/js/common:$LIBROOT:$NODE_PATH
$SDK_DIR/sdk/bin/dartdevc --modules=node \
--library-root=$LIBROOT --dart-sdk-summary=$GEN_DIR/ddc_sdk.sum \
-o $LIBROOT/$BASENAME.js $*

View file

@ -63,8 +63,6 @@ fi
BASENAME=$( basename "${1%.*}")
LIBROOT=$(cd $( dirname "${1%.*}") && pwd)
export NODE_PATH=$GEN_DIR/js/common:$LIBROOT:$NODE_PATH
if [ "$KERNEL" = true ]; then
if [ ! -e $GEN_DIR/kernel/ddc_sdk.dill ]; then
@ -74,6 +72,8 @@ if [ "$KERNEL" = true ]; then
exit 1
fi
NODE_PATH=$GEN_DIR/kernel/common:$LIBROOT:$NODE_PATH
dart -c $SDK_DIR/pkg/dev_compiler/bin/dartdevk.dart --modules=node \
--dart-sdk-summary=$GEN_DIR/kernel/ddc_sdk.dill \
-o $LIBROOT/$BASENAME.js $*
@ -86,6 +86,8 @@ else
exit 1
fi
NODE_PATH=$GEN_DIR/js/common:$LIBROOT:$NODE_PATH
dart -c $SDK_DIR/pkg/dev_compiler/bin/dartdevc.dart --modules=node \
--library-root=$LIBROOT --dart-sdk-summary=$GEN_DIR/ddc_sdk.sum \
-o $LIBROOT/$BASENAME.js $*

View file

@ -28,8 +28,8 @@ void mixinMembers(to, from) {
void _copyMembers(to, from) {
var names = getOwnNamesAndSymbols(from);
for (var i = 0, n = JS('int', '#.length', names); i < n; ++i) {
var name = JS('', '#[#]', names, i);
for (int i = 0, n = JS('!', '#.length', names); i < n; ++i) {
String name = JS('', '#[#]', names, i);
if (name == 'constructor') continue;
_copyMember(to, from, name);
}
@ -38,14 +38,14 @@ void _copyMembers(to, from) {
void _copyMember(to, from, name) {
var desc = getOwnPropertyDescriptor(from, name);
if (JS('bool', '# == Symbol.iterator', name)) {
if (JS('!', '# == Symbol.iterator', name)) {
// On native types, Symbol.iterator may already be present.
// TODO(jmesserly): investigate if we still need this.
// If so, we need to find a better solution.
// See https://github.com/dart-lang/sdk/issues/28324
var existing = getOwnPropertyDescriptor(to, name);
if (existing != null) {
if (JS('bool', '#.writable', existing)) {
if (JS('!', '#.writable', existing)) {
JS('', '#[#] = #.value', to, name, desc);
}
return;
@ -201,18 +201,18 @@ getType(obj) =>
bool isJsInterop(obj) {
if (obj == null) return false;
if (JS('bool', 'typeof # === "function"', obj)) {
if (JS('!', 'typeof # === "function"', obj)) {
// A function is a Dart function if it has runtime type information.
return JS('bool', '#[#] == null', obj, _runtimeType);
return JS('!', '#[#] == null', obj, _runtimeType);
}
// Primitive types are not JS interop types.
if (JS('bool', 'typeof # !== "object"', obj)) return false;
if (JS('!', 'typeof # !== "object"', obj)) return false;
// Extension types are not considered JS interop types.
// Note that it is still possible to call typed JS interop methods on
// extension types but the calls must be statically typed.
if (JS('bool', '#[#] != null', obj, _extensionType)) return false;
return JS('bool', '!($obj instanceof $Object)');
if (JS('!', '#[#] != null', obj, _extensionType)) return false;
return JS('!', '!($obj instanceof $Object)');
}
/// Get the type of a method from a type using the stored signature
@ -227,7 +227,7 @@ getSetterType(type, name) {
if (setters != null) {
var type = JS('', '#[#]', setters, name);
if (type != null) {
if (JS('bool', '# instanceof Array', type)) {
if (JS('!', '# instanceof Array', type)) {
// The type has metadata attached. Pull out just the type.
// TODO(jmesserly): remove when we remove mirrors
return JS('', '#[0]', type);
@ -238,7 +238,7 @@ getSetterType(type, name) {
var fields = getFields(type);
if (fields != null) {
var fieldInfo = JS('', '#[#]', fields, name);
if (fieldInfo != null && JS('bool', '!#.isFinal', fieldInfo)) {
if (fieldInfo != null && JS<bool>('!', '!#.isFinal', fieldInfo)) {
return JS('', '#.type', fieldInfo);
}
}
@ -285,14 +285,14 @@ void setStaticSetterSignature(f, sigF) =>
_getMembers(type, kind) {
var sig = JS('', '#[#]', type, kind);
return JS('bool', 'typeof # == "function"', sig)
? JS('', '#[#] = #', type, kind, sig())
return JS<bool>('!', 'typeof # == "function"', sig)
? JS('', '#[#] = #()', type, kind, sig)
: sig;
}
bool _hasMember(type, kind, name) {
var sig = _getMembers(type, kind);
return sig != null && JS('bool', '# in #', name, sig);
return sig != null && JS<bool>('!', '# in #', name, sig);
}
bool hasMethod(type, name) => _hasMember(type, _methodSig, name);
@ -307,14 +307,14 @@ final dartx = JS('', 'dartx');
/// Install properties in prototype-first order. Properties / descriptors from
/// more specific types should overwrite ones from less specific types.
void _installProperties(jsProto, dartType, installedParent) {
if (JS('bool', '# === #', dartType, Object)) {
if (JS('!', '# === #', dartType, Object)) {
_installPropertiesForObject(jsProto);
return;
}
// If the extension methods of the parent have been installed on the parent
// of [jsProto], the methods will be available via prototype inheritance.
var dartSupertype = JS('', '#.__proto__', dartType);
if (JS('bool', '# !== #', dartSupertype, installedParent)) {
if (JS('!', '# !== #', dartSupertype, installedParent)) {
_installProperties(jsProto, dartSupertype, installedParent);
}
@ -350,7 +350,7 @@ _applyExtension(jsType, dartExtType) {
var jsProto = JS('', '#.prototype', jsType);
if (jsProto == null) return;
if (JS('bool', '# === #', dartExtType, Object)) {
if (JS('!', '# === #', dartExtType, Object)) {
_installPropertiesForGlobalObject(jsProto);
return;
}
@ -359,7 +359,7 @@ _applyExtension(jsType, dartExtType) {
jsProto, dartExtType, JS('', '#[#]', jsProto, _extensionType));
// Mark the JS type's instances so we can easily check for extensions.
if (JS('bool', '# !== #', dartExtType, JSFunction)) {
if (JS('!', '# !== #', dartExtType, JSFunction)) {
JS('', '#[#] = #', jsProto, _extensionType, dartExtType);
}
JS('', '#[#] = #[#]', jsType, _methodSig, dartExtType, _methodSig);

View file

@ -23,22 +23,22 @@ void ignoreAllErrors(bool flag) {
}
argumentError(value) {
if (JS('bool', 'dart.__trapRuntimeErrors')) JS('', 'debugger');
if (JS('!', 'dart.__trapRuntimeErrors')) JS('', 'debugger');
throw new ArgumentError.value(value);
}
throwUnimplementedError(String message) {
if (JS('bool', 'dart.__trapRuntimeErrors')) JS('', 'debugger');
if (JS('!', 'dart.__trapRuntimeErrors')) JS('', 'debugger');
throw new UnimplementedError(message);
}
assertFailed(message) {
if (JS('bool', 'dart.__trapRuntimeErrors')) JS('', 'debugger');
if (JS('!', 'dart.__trapRuntimeErrors')) JS('', 'debugger');
throw new AssertionErrorImpl(message);
}
throwCyclicInitializationError([Object field]) {
if (JS('bool', 'dart.__trapRuntimeErrors')) JS('', 'debugger');
if (JS('!', 'dart.__trapRuntimeErrors')) JS('', 'debugger');
throw new CyclicInitializationError(field);
}
@ -46,7 +46,7 @@ throwNullValueError() {
// TODO(vsm): Per spec, we should throw an NSM here. Technically, we ought
// to thread through method info, but that uglifies the code and can't
// actually be queried ... it only affects how the error is printed.
if (JS('bool', 'dart.__trapRuntimeErrors')) JS('', 'debugger');
if (JS('!', 'dart.__trapRuntimeErrors')) JS('', 'debugger');
throw new NoSuchMethodError(
null, new Symbol('<Unexpected Null Value>'), null, null, null);
}

View file

@ -98,7 +98,7 @@ dloadRepl(obj, field) => dload(obj, replNameLookup(obj, field), false);
// implemented by the Object base class as those methods can always be
// statically resolved.
dload(obj, field, [mirrors = undefined]) {
if (JS('bool', 'typeof # == "function" && # == "call"', obj, field)) {
if (JS('!', 'typeof # == "function" && # == "call"', obj, field)) {
return obj;
}
var f = _canonicalMember(obj, field);
@ -111,7 +111,7 @@ dload(obj, field, [mirrors = undefined]) {
if (hasMethod(type, f)) return bind(obj, f, null);
// Always allow for JS interop objects.
if (!JS('bool', '#', mirrors) && isJsInterop(obj)) {
if (!JS<bool>('!', '#', mirrors) && isJsInterop(obj)) {
return JS('', '#[#]', obj, f);
}
}
@ -143,12 +143,12 @@ dput(obj, field, value, [mirrors = undefined]) {
if (f != null) {
var setterType = getSetterType(getType(obj), f);
if (setterType != null) {
if (JS('bool', '#', mirrors))
if (JS('!', '#', mirrors))
setterType = _stripGenericArguments(setterType);
return JS('', '#[#] = #._check(#)', obj, f, setterType, value);
}
// Always allow for JS interop objects.
if (!JS('bool', '#', mirrors) && isJsInterop(obj)) {
if (!JS<bool>('!', '#', mirrors) && isJsInterop(obj)) {
return JS('', '#[#] = #', obj, f, value);
}
}
@ -161,15 +161,15 @@ dput(obj, field, value, [mirrors = undefined]) {
/// actuals.
bool _checkApply(FunctionType type, List actuals, namedActuals) {
// Check for too few required arguments.
var actualsCount = JS('int', '#.length', actuals);
int actualsCount = JS('!', '#.length', actuals);
var required = type.args;
var requiredCount = JS('int', '#.length', required);
int requiredCount = JS('!', '#.length', required);
if (actualsCount < requiredCount) return false;
// Check for too many postional arguments.
var extras = actualsCount - requiredCount;
var optionals = type.optionals;
if (extras > JS('int', '#.length', optionals)) return false;
if (extras > JS<int>('!', '#.length', optionals)) return false;
// Check if we have invalid named arguments.
Iterable names;
@ -177,7 +177,7 @@ bool _checkApply(FunctionType type, List actuals, namedActuals) {
if (namedActuals != null) {
names = getOwnPropertyNames(namedActuals);
for (var name in names) {
if (!JS('bool', '#.hasOwnProperty(#)', named, name)) return false;
if (!JS('!', '#.hasOwnProperty(#)', named, name)) return false;
}
}
// Now that we know the signature matches, we can perform type checks.
@ -222,17 +222,19 @@ _toDisplayName(name) => JS('', '''(() => {
})()''');
Symbol _dartSymbol(name) {
return (JS('bool', 'typeof # === "symbol"', name))
return (JS<bool>('!', 'typeof # === "symbol"', name))
? JS('Symbol', '#(new #.new(#, #))', const_, PrivateSymbol,
_toSymbolName(name), name)
: JS('Symbol', '#(#.new(#))', const_, Symbol, _toDisplayName(name));
: JS('Symbol', '#(new #.new(#))', const_, internal.Symbol,
_toDisplayName(name));
}
Symbol _setterSymbol(name) {
return (JS('bool', 'typeof # === "symbol"', name))
return (JS<bool>('!', 'typeof # === "symbol"', name))
? JS('Symbol', '#(new #.new(# + "=", #))', const_, PrivateSymbol,
_toSymbolName(name), name)
: JS('Symbol', '#(#.new(# + "="))', const_, Symbol, _toDisplayName(name));
: JS('Symbol', '#(new #.new(# + "="))', const_, internal.Symbol,
_toDisplayName(name));
}
_checkAndCall(f, ftype, obj, typeArgs, args, named, displayName) =>
@ -358,7 +360,7 @@ _dhelperRepl(obj, field, Function(Object) callback) {
/// Shared code for dsend, dindex, and dsetindex.
callMethod(obj, name, typeArgs, args, named, displayName) {
if (JS('bool', 'typeof # == "function" && # == "call"', obj, name)) {
if (JS('!', 'typeof # == "function" && # == "call"', obj, name)) {
return dgcall(obj, typeArgs, args, named);
}
var symbol = _canonicalMember(obj, name);
@ -434,12 +436,13 @@ final _ignoreTypeFailure = JS('', '''(() => {
});
})()''');
@notNull
@JSExportName('is')
bool instanceOf(obj, type) {
if (obj == null) {
return JS('bool', '# == # || #', type, Null, _isTop(type));
return JS('!', '# == # || #', type, Null, _isTop(type));
}
return JS('#', '!!#', isSubtype(getReifiedType(obj), type));
return JS('!', '!!#', isSubtype(getReifiedType(obj), type));
}
@JSExportName('as')
@ -448,7 +451,7 @@ cast(obj, type, @notNull bool isImplicit) {
var actual = getReifiedType(obj);
var result = isSubtype(actual, type);
if (JS(
'bool',
'!',
'# === true || # === null && # && '
'dart.__ignoreWhitelistedErrors && #(#, #)',
result,
@ -484,7 +487,7 @@ void booleanConversionFailed(obj) {
asInt(obj) {
if (obj == null) return null;
if (JS('bool', 'Math.floor(#) != #', obj, obj)) {
if (JS('!', 'Math.floor(#) != #', obj, obj)) {
castError(obj, JS('', '#', int), false);
}
return obj;
@ -527,7 +530,7 @@ constMap<K, V>(JSArray elements) {
}
bool dassert(value) {
if (JS('bool', '# != null && #[#] instanceof #', value, value, _runtimeType,
if (JS('!', '# != null && #[#] instanceof #', value, value, _runtimeType,
AbstractFunctionType)) {
value = dcall(value, []);
}
@ -542,8 +545,8 @@ Map _primitiveErrorCache;
const _maxErrorCache = 10;
bool _isJsError(exception) {
return JS('bool', '#.Error != null && # instanceof #.Error', global_,
exception, global_);
return JS('!', '#.Error != null && # instanceof #.Error', global_, exception,
global_);
}
// Record/return the JS error for an exception. If an error was already
@ -552,7 +555,7 @@ recordJsError(exception, [newError]) {
if (_isJsError(exception)) return exception;
var useExpando =
exception != null && JS('bool', 'typeof # == "object"', exception);
exception != null && JS<bool>('!', 'typeof # == "object"', exception);
var error;
if (useExpando) {
error = JS('', '#[#]', exception, _error);
@ -734,23 +737,12 @@ bool equals(x, y) {
// function minimal.
// This pattern resulted from performance testing; it found that dispatching
// was the fastest solution, even for primitive types.
return JS('bool', '# == null ? # == null : #[#](#)', x, y, x,
return JS('!', '# == null ? # == null : #[#](#)', x, y, x,
extensionSymbol('_equals'), y);
}
int hashCode(obj) {
return obj == null ? 0 : JS('int', '#[#]', obj, extensionSymbol('hashCode'));
}
hashKey(k) {
if (k == null) return 0;
switch (JS('String', 'typeof #', k)) {
case "object":
case "function":
return JS('int', '#[#] & 0x3ffffff', k, extensionSymbol('hashCode'));
}
// For primitive types we can store the key directly in an ES6 Map.
return k;
return obj == null ? 0 : JS('!', '#[#]', obj, extensionSymbol('hashCode'));
}
@JSExportName('toString')
@ -779,7 +771,7 @@ noSuchMethod(obj, Invocation invocation) {
/// The default implementation of `noSuchMethod` to match `Object.noSuchMethod`.
defaultNoSuchMethod(obj, Invocation i) {
if (JS('bool', 'dart.__trapRuntimeErrors')) JS('', 'debugger');
if (JS('!', 'dart.__trapRuntimeErrors')) JS('', 'debugger');
throw new NoSuchMethodError.withInvocation(obj, i);
}
@ -808,14 +800,14 @@ final JsIterator = JS('', '''
_canonicalMember(obj, name) {
// Private names are symbols and are already canonical.
if (JS('bool', 'typeof # === "symbol"', name)) return name;
if (JS('!', 'typeof # === "symbol"', name)) return name;
if (obj != null && JS('bool', '#[#] != null', obj, _extensionType)) {
if (obj != null && JS<bool>('!', '#[#] != null', obj, _extensionType)) {
return JS('', 'dartx.#', name);
}
// Check for certain names that we can't use in JS
if (JS('bool', '# == "constructor" || # == "prototype"', name, name)) {
if (JS('!', '# == "constructor" || # == "prototype"', name, name)) {
JS('', '# = "+" + #', name, name);
}
return name;

View file

@ -85,10 +85,10 @@ getFunctionType(obj) {
/// different from the user-visible Type object returned by calling
/// `runtimeType` on some Dart object.
getReifiedType(obj) {
switch (JS('String', 'typeof #', obj)) {
switch (JS<String>('!', 'typeof #', obj)) {
case "object":
if (obj == null) return JS('', '#', Null);
if (JS('bool', '# instanceof #', obj, Object)) {
if (JS('!', '# instanceof #', obj, Object)) {
return JS('', '#.constructor', obj);
}
var result = JS('', '#[#]', obj, _extensionType);
@ -118,7 +118,7 @@ getReifiedType(obj) {
Type wrapType(type) {
// If we've already wrapped this type once, use the previous wrapper. This
// way, multiple references to the same type return an identical Type.
if (JS('bool', '#.hasOwnProperty(#)', type, _typeObject)) {
if (JS('!', '#.hasOwnProperty(#)', type, _typeObject)) {
return JS('', '#[#]', type, _typeObject);
}
return JS('Type', '#[#] = #', type, _typeObject, new WrappedType(type));
@ -141,7 +141,7 @@ List getModuleNames() {
}
String getSourceMap(module) {
return JS('String', '#.get(#)', _loadedSourceMaps, module);
return JS<String>('!', '#.get(#)', _loadedSourceMaps, module);
}
/// Return all library objects in the specified module.

View file

@ -10,6 +10,7 @@ import 'dart:collection';
import 'dart:_foreign_helper' show JS, JSExportName, rest, spread;
import 'dart:_interceptors' show JSArray, jsNull, JSFunction;
import 'dart:_internal' as internal show Symbol;
import 'dart:_js_helper'
show
AssertionErrorImpl,

View file

@ -79,7 +79,7 @@ class DynamicType extends TypeRep {
check_T(object) => object;
}
bool _isJsObject(obj) => JS('bool', '# === #', getReifiedType(obj), jsobject);
bool _isJsObject(obj) => JS('!', '# === #', getReifiedType(obj), jsobject);
class LazyJSType extends TypeRep {
final Function() _rawJSType;
@ -106,7 +106,7 @@ class LazyJSType extends TypeRep {
bool isRawType(obj) {
var raw = _raw();
if (raw != null) return JS('bool', '# instanceof #', obj, raw);
if (raw != null) return JS('!', '# instanceof #', obj, raw);
// Treat as anonymous: return true for any JS object.
return _isJsObject(obj);
}
@ -302,7 +302,7 @@ class FunctionType extends AbstractFunctionType {
// identical function types that don't canonicalize
// to the same object since we won't fall into this
// fast path.
if (extra == null && JS('bool', '#.length < 3', args)) {
if (extra == null && JS<bool>('!', '#.length < 3', args)) {
return _createSmall(returnType, args);
}
args = _canonicalizeArray(args, _fnTypeArrayArgMap);
@ -311,7 +311,7 @@ class FunctionType extends AbstractFunctionType {
if (extra == null) {
keys = [returnType, args];
create = () => new FunctionType(returnType, args, [], JS('', '{}'));
} else if (JS('bool', '# instanceof Array', extra)) {
} else if (JS('!', '# instanceof Array', extra)) {
var optionals =
_canonicalizeArray(JS('', '#', extra), _fnTypeArrayArgMap);
keys = [returnType, args, optionals];
@ -327,9 +327,9 @@ class FunctionType extends AbstractFunctionType {
List _process(List array) {
var result = [];
for (var i = 0; JS('bool', '# < #.length', i, array); ++i) {
for (var i = 0; JS<bool>('!', '# < #.length', i, array); ++i) {
var arg = JS('', '#[#]', array, i);
if (JS('bool', '# instanceof Array', arg)) {
if (JS('!', '# instanceof Array', arg)) {
JS('', '#.push(#.slice(1))', metadata, arg);
JS('', '#.push(#[0])', result, arg);
} else {
@ -360,7 +360,7 @@ class FunctionType extends AbstractFunctionType {
var result = <String, Object>{};
var names = getOwnPropertyNames(named);
JS('', '#.sort()', names);
for (var i = 0; JS('bool', '# < #.length', i, names); ++i) {
for (var i = 0; JS<bool>('!', '# < #.length', i, names); ++i) {
String name = JS('!', '#[#]', names, i);
result[name] = JS('', '#[#]', named, name);
}
@ -371,28 +371,28 @@ class FunctionType extends AbstractFunctionType {
if (_stringValue != null) return _stringValue;
var buffer = '(';
for (var i = 0; JS('bool', '# < #.length', i, args); ++i) {
for (var i = 0; JS<bool>('!', '# < #.length', i, args); ++i) {
if (i > 0) {
buffer += ', ';
}
buffer += typeName(JS('', '#[#]', args, i));
}
if (JS('bool', '#.length > 0', optionals)) {
if (JS('bool', '#.length > 0', args)) buffer += ', ';
if (JS('!', '#.length > 0', optionals)) {
if (JS('!', '#.length > 0', args)) buffer += ', ';
buffer += '[';
for (var i = 0; JS('bool', '# < #.length', i, optionals); ++i) {
for (var i = 0; JS<bool>('!', '# < #.length', i, optionals); ++i) {
if (i > 0) {
buffer += ', ';
}
buffer += typeName(JS('', '#[#]', optionals, i));
}
buffer += ']';
} else if (JS('bool', 'Object.keys(#).length > 0', named)) {
if (JS('bool', '#.length > 0', args)) buffer += ', ';
} else if (JS('!', 'Object.keys(#).length > 0', named)) {
if (JS('!', '#.length > 0', args)) buffer += ', ';
buffer += '{';
var names = getOwnPropertyNames(named);
JS('', '#.sort()', names);
for (var i = 0; JS('bool', '# < #.length', i, names); ++i) {
for (var i = 0; JS<bool>('!', '# < #.length', i, names); ++i) {
if (i > 0) {
buffer += ', ';
}
@ -410,11 +410,11 @@ class FunctionType extends AbstractFunctionType {
@JSExportName('is')
bool is_T(obj) {
if (JS('bool', 'typeof # == "function"', obj)) {
if (JS('!', 'typeof # == "function"', obj)) {
var actual = JS('', '#[#]', obj, _runtimeType);
// If there's no actual type, it's a JS function.
// Allow them to subtype all Dart function types.
return JS('bool', '# == null || !!#', actual, isSubtype(actual, this));
return JS('!', '# == null || !!#', actual, isSubtype(actual, this));
}
return false;
}
@ -429,7 +429,7 @@ class FunctionType extends AbstractFunctionType {
@JSExportName('as')
as_T(obj, [@notNull bool isImplicit = false]) {
if (obj == null) return obj;
if (JS('bool', 'typeof # == "function"', obj)) {
if (JS('!', 'typeof # == "function"', obj)) {
var actual = JS('', '#[#]', obj, _runtimeType);
// If there's no actual type, it's a JS function.
// Allow them to subtype all Dart function types.
@ -466,14 +466,14 @@ class Typedef extends AbstractFunctionType {
for (int i = 0, n = JS('!', '#.length', typeArgs); i < n; ++i) {
if (i > 0) result += ', ';
var typeArg = JS('', '#[#]', typeArgs, i);
if (JS('bool', '# !== #', typeArg, _dynamic)) allDynamic = false;
if (JS('!', '# !== #', typeArg, _dynamic)) allDynamic = false;
result += typeName(typeArg);
}
result += '>';
return allDynamic ? name : result;
}
String get name => JS('String', '#', _name);
String get name => JS('!', '#', _name);
AbstractFunctionType get functionType {
var ft = _functionType;
@ -507,7 +507,7 @@ class GenericFunctionType extends AbstractFunctionType {
GenericFunctionType(instantiateTypeParts, this._instantiateTypeBounds)
: _instantiateTypeParts = instantiateTypeParts,
formalCount = JS('int', '#.length', instantiateTypeParts);
formalCount = JS('!', '#.length', instantiateTypeParts);
List<TypeVariable> get typeFormals {
if (_typeFormals != null) return _typeFormals;
@ -548,7 +548,7 @@ class GenericFunctionType extends AbstractFunctionType {
if (i != 0) s += ", ";
s += JS<String>('!', '#[#].name', typeFormals, i);
var bound = typeBounds[i];
if (JS('bool', '# !== # && # !== #', bound, dynamic, bound, Object)) {
if (JS('!', '# !== # && # !== #', bound, dynamic, bound, Object)) {
s += " extends $bound";
}
}
@ -635,24 +635,25 @@ class GenericFunctionType extends AbstractFunctionType {
return defaults;
}
@notNull
@JSExportName('is')
bool is_T(obj) {
if (JS('bool', 'typeof # == "function"', obj)) {
if (JS('!', 'typeof # == "function"', obj)) {
var actual = JS('', '#[#]', obj, _runtimeType);
return JS('bool', '# != null && !!#', actual, isSubtype(actual, this));
return JS('!', '# != null && !!#', actual, isSubtype(actual, this));
}
return false;
}
@JSExportName('as')
as_T(obj) {
if (obj == null || JS('bool', '#', is_T(obj))) return obj;
if (obj == null || is_T(obj)) return obj;
return castError(obj, this, false);
}
@JSExportName('_check')
check_T(obj) {
if (obj == null || JS('bool', '#', is_T(obj))) return obj;
if (obj == null || is_T(obj)) return obj;
return castError(obj, this, true);
}
}
@ -715,7 +716,7 @@ getFunctionTypeMirror(AbstractFunctionType type) {
bool isType(obj) => JS('', '#[#] === #', obj, _runtimeType, Type);
void checkTypeBound(type, bound, name) {
if (JS('bool', '#', isSubtype(type, bound))) return;
if (JS('!', '#', isSubtype(type, bound))) return;
throwTypeError('type `$type` does not extend `$bound`'
' of `$name`.');
@ -835,12 +836,12 @@ bool isSubtype(t1, t2) {
// code generator happy though.
var map;
bool result;
if (JS('bool', '!#.hasOwnProperty(#)', t1, _subtypeCache)) {
if (JS('!', '!#.hasOwnProperty(#)', t1, _subtypeCache)) {
JS('', '#[#] = # = new Map()', t1, _subtypeCache, map);
} else {
map = JS('', '#[#]', t1, _subtypeCache);
result = JS('bool|Null', '#.get(#)', map, t2);
if (JS('bool', '# !== void 0', result)) return result;
if (JS('!', '# !== void 0', result)) return result;
}
result =
JS('bool|Null', '# === # || #(#, #, true)', t1, t2, _isSubtype, t1, t2);
@ -850,13 +851,15 @@ bool isSubtype(t1, t2) {
final _subtypeCache = JS('', 'Symbol("_subtypeCache")');
_isBottom(type) => JS('bool', '# == # || # == #', type, bottom, type, Null);
@notNull
bool _isBottom(type) => JS('!', '# == # || # == #', type, bottom, type, Null);
_isTop(type) {
@notNull
bool _isTop(type) {
if (_isFutureOr(type)) {
return _isTop(JS('', '#[0]', getGenericArgs(type)));
}
return JS('bool', '# == # || # == # || # == #', type, Object, type, dynamic,
return JS('!', '# == # || # == # || # == #', type, Object, type, dynamic,
type, void_);
}
@ -979,7 +982,7 @@ bool _isSubtype(t1, t2, isCovariant) => JS('', '''(() => {
return ${_isFunctionSubtype(t1, t2, isCovariant)};
})()''');
_isInterfaceSubtype(t1, t2, isCovariant) => JS('', '''(() => {
bool _isInterfaceSubtype(t1, t2, isCovariant) => JS('', '''(() => {
// We support Dart's covariant generics with the caveat that we do not
// substitute bottom for dynamic in subtyping rules.
// I.e., given T1, ..., Tn where at least one Ti != dynamic we disallow:

View file

@ -39,13 +39,13 @@ final Function(Object) getOwnPropertySymbols =
/// This error indicates a strong mode specific failure, other than a type
/// assertion failure (TypeError) or CastError.
void throwTypeError(String message) {
if (JS('bool', 'dart.__trapRuntimeErrors')) JS('', 'debugger');
if (JS('!', 'dart.__trapRuntimeErrors')) JS('', 'debugger');
throw new TypeErrorImpl(message);
}
/// This error indicates a bug in the runtime or the compiler.
void throwInternalError(String message) {
if (JS('bool', 'dart.__trapRuntimeErrors')) JS('', 'debugger');
if (JS('!', 'dart.__trapRuntimeErrors')) JS('', 'debugger');
JS('', 'throw Error(#)', message);
}
@ -103,14 +103,14 @@ copyTheseProperties(to, from, names) {
copyProperty(to, from, name) {
var desc = getOwnPropertyDescriptor(from, name);
if (JS('bool', '# == Symbol.iterator', name)) {
if (JS('!', '# == Symbol.iterator', name)) {
// On native types, Symbol.iterator may already be present.
// TODO(jmesserly): investigate if we still need this.
// If so, we need to find a better solution.
// See https://github.com/dart-lang/sdk/issues/28324
var existing = getOwnPropertyDescriptor(to, name);
if (existing != null) {
if (JS('bool', '#.writable', existing)) {
if (JS('!', '#.writable', existing)) {
JS('', '#[#] = #.value', to, name, desc);
}
return;

View file

@ -22,10 +22,18 @@ Future main(List<String> args) async {
var parserOptions = parser.parse(args);
var rest = parserOptions.rest;
Directory.current = path.dirname(path.dirname(path.fromUri(Platform.script)));
var ddcPath = path.dirname(path.dirname(path.fromUri(Platform.script)));
Directory.current = ddcPath;
var outputPath =
path.absolute(rest.length > 0 ? rest[0] : 'gen/sdk/kernel/ddc_sdk.dill');
String outputPath;
if (rest.isNotEmpty) {
outputPath = path.absolute(rest[0]);
} else {
var sdkRoot = path.absolute(path.dirname(path.dirname(ddcPath)));
var buildDir = path.join(sdkRoot, Platform.isMacOS ? 'xcodebuild' : 'out');
var genDir = path.join(buildDir, 'ReleaseX64', 'gen', 'utils', 'dartdevc');
outputPath = path.join(genDir, 'kernel', 'ddc_sdk.dill');
}
var inputPath = path.absolute('tool/input_sdk');
var target = new DevCompilerTarget();

View file

@ -401,7 +401,7 @@ regress_r21715_test: RuntimeError # Requires fixed-size int64 support.
typed_data_with_limited_ints_test: Skip # Requires fixed-size int64 support.
[ $runtime != none && ($compiler == dartdevc || $compiler == dartdevk) ]
bigint_test: Pass, Slow
bigint_test: Pass, Slow, Timeout
compare_to2_test: RuntimeError # Issue 30170
date_time10_test: RuntimeError # Issue 29921
error_stack_trace_test/nullThrown: RuntimeError # .stackTrace not present for exception caught from 'throw null;'

View file

@ -298,9 +298,9 @@ async_return_types_test/wrongReturnType: MissingCompileTimeError
bad_override_test/01: MissingCompileTimeError
bad_override_test/02: MissingCompileTimeError
bad_override_test/03: MissingCompileTimeError
built_in_identifier_type_annotation_test/dynamic-funarg: RuntimeError # Issue 32194
built_in_identifier_type_annotation_test/dynamic-funret: RuntimeError # Issue 32194
built_in_identifier_type_annotation_test/dynamic-list: RuntimeError # Issue 32194
built_in_identifier_type_annotation_test/dynamic-funarg: RuntimeError # Issue 30450, test name contains hyphen
built_in_identifier_type_annotation_test/dynamic-funret: RuntimeError # Issue 30450, test name contains hyphen
built_in_identifier_type_annotation_test/dynamic-list: RuntimeError # Issue 30450, test name contains hyphen
call_method_as_cast_test/06: RuntimeError # Kernel allows classes to subtype `Function` so DDK elides the explicit cast.
call_method_implicit_tear_off_implements_function_test/05: RuntimeError # Kernel is missing the implicit `call` tearoff for assignment `Function`
call_method_implicit_tear_off_implements_function_test/06: RuntimeError # Kernel is missing the implicit `call` tearoff for assignment `Function`

View file

@ -4,6 +4,7 @@
[ $compiler == dartdevc ]
html/element_types_keygen_test: CompileTimeError # Chrome 57 keygen removed
html/mediasource_test: RuntimeError # Issue 29922
html/xhr_test: Pass, Slow
[ $compiler == dartdevk ]
@ -31,6 +32,7 @@ html/interactive_geolocation_test: Skip # Requires allowing geo location.
html/client_rect_test: Pass, RuntimeError # Issue 31019
html/css_test: Pass, RuntimeError # Issue 31019
html/fileapi_entry_test: Pass, RuntimeError # Issue 31019
html/interactive_media_test: Skip # Requires interactive camera, microphone permissions.
[ $system == windows && ($compiler == dartdevc || $compiler == dartdevk) ]
html/xhr_test: Skip # Times out. Issue 21527
@ -88,7 +90,6 @@ html/js_typed_interop_type3_test/*: RuntimeError # Issue 30947
html/js_typed_interop_type_test: RuntimeError # Issue 30947
html/js_util_test: RuntimeError # Issue 29922
html/media_stream_test: RuntimeError # Issue 29922
html/mediasource_test: RuntimeError # Issue 29922
html/no_linked_scripts_htmltest: Skip # Issue 29919
html/notification_permission_test: Timeout # Issue 32002
html/scripts_htmltest: Skip # Issue 29919

View file

@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'utils.dart';
import 'configuration.dart' show Compiler;
String dart2jsHtml(String title, String scriptPath) {
return """
@ -40,10 +41,12 @@ String dart2jsHtml(String title, String scriptPath) {
/// The [testName] is the short name of the test without any subdirectory path
/// or extension, like "math_test". The [testJSDir] is the relative path to the
/// build directory where the dartdevc-generated JS file is stored.
String dartdevcHtml(String testName, String testJSDir, String buildDir) {
String dartdevcHtml(String testName, String testJSDir, Compiler compiler) {
var isKernel = compiler == Compiler.dartdevk;
var sdkPath = isKernel ? 'kernel/amd/dart_sdk' : 'js/amd/dart_sdk';
var pkgDir = isKernel ? 'pkg_kernel' : 'pkg';
var packagePaths = testPackages
.map((package) => ' "$package": "/root_dart/$buildDir/gen/utils/'
'dartdevc/pkg/$package",')
.map((p) => ' "$p": "/root_build/gen/utils/dartdevc/$pkgDir/$p",')
.join("\n");
return """
@ -69,7 +72,7 @@ String dartdevcHtml(String testName, String testJSDir, String buildDir) {
var require = {
baseUrl: "/root_dart/$testJSDir",
paths: {
"dart_sdk": "/root_build/gen/utils/dartdevc/js/amd/dart_sdk",
"dart_sdk": "/root_build/gen/utils/dartdevc/$sdkPath",
$packagePaths
},
waitSeconds: 30,

View file

@ -605,13 +605,14 @@ class DevKernelCompilerConfiguration extends CompilerConfiguration {
.toNativePath();
var summaryInputDir = new Path(_configuration.buildDirectory)
.append("/gen/utils/dartdevc/pkg")
.append("/gen/utils/dartdevc/pkg_kernel")
.absolute
.toNativePath();
args.addAll([
"--dart-sdk-summary",
sdkSummary,
"--no-summarize",
"-o",
outputFile,
inputFile,
@ -622,7 +623,7 @@ class DevKernelCompilerConfiguration extends CompilerConfiguration {
// get recompiled into the test's own module.
for (var package in testPackages) {
var summary = new Path(_configuration.buildDirectory)
.append("/gen/utils/dartdevc/pkg/$package.dill")
.append("/gen/utils/dartdevc/pkg_kernel/$package.dill")
.absolute
.toNativePath();
args.add("-s");

View file

@ -1061,7 +1061,7 @@ class StandardTestSuite extends TestSuite {
// Always run with synchronous starts of `async` functions.
// If we want to make this dependent on other parameters or flags,
// this flag could be become conditional.
content = dartdevcHtml(nameNoExt, jsDir, buildDir);
content = dartdevcHtml(nameNoExt, jsDir, configuration.compiler);
}
}

View file

@ -128,6 +128,7 @@ prebuilt_dart_action("dartdevc_patch_sdk") {
# tools/patch_sdk.dart and then change this to use generate_patch_sdk().
deps = [
":dartdevc_files_stamp",
":dartdevc_sdk_patch_stamp",
# The patch script uses several packages, including analyzer, so consider
# it dirty if any of those change.
@ -252,6 +253,11 @@ create_timestamp_file("dartdevc_files_stamp") {
output = "$target_gen_dir/dartdevc_files.stamp"
}
create_timestamp_file("dartdevc_sdk_patch_stamp") {
path = rebase_path("../../pkg/dev_compiler/tool/input_sdk")
output = "$target_gen_dir/dartdevc_sdk_patch_stamp.stamp"
}
# Compiles the packages used by the tests to JS with dartdevc so that they are
# available for loading by the tests.
prebuilt_dart_action("dartdevc_test_pkg") {
@ -318,6 +324,7 @@ prebuilt_dart_action("dartdevc_test_pkg") {
prebuilt_dart_action("dartdevk_sdk") {
deps = [
":dartdevc_files_stamp",
":dartdevc_sdk_patch_stamp",
]
inputs = [