diff --git a/pkg/compiler/lib/src/js_emitter/old_emitter/emitter.dart b/pkg/compiler/lib/src/js_emitter/old_emitter/emitter.dart index fd49c22f886..0ea1989c086 100644 --- a/pkg/compiler/lib/src/js_emitter/old_emitter/emitter.dart +++ b/pkg/compiler/lib/src/js_emitter/old_emitter/emitter.dart @@ -304,8 +304,8 @@ class OldEmitter implements Emitter { /** Needs defineClass to be defined. */ jsAst.Expression buildInheritFrom() { - return js(r''' - var inheritFrom = function() { + jsAst.Expression result = js(r''' + function() { function tmp() {} var hasOwnProperty = Object.prototype.hasOwnProperty; return function (constructor, superConstructor) { @@ -323,6 +323,10 @@ class OldEmitter implements Emitter { }; }() '''); + if (compiler.hasIncrementalSupport) { + result = js(r'self.$dart_unsafe_eval.inheritFrom = #', [result]); + } + return js(r'var inheritFrom = #', [result]); } /// Code that needs to be run before first invocation of diff --git a/pkg/compiler/lib/src/universe/universe.dart b/pkg/compiler/lib/src/universe/universe.dart index e5e3915d851..5b60d70850b 100644 --- a/pkg/compiler/lib/src/universe/universe.dart +++ b/pkg/compiler/lib/src/universe/universe.dart @@ -747,6 +747,13 @@ class TypedSelector extends Selector { new Map>(); factory TypedSelector(TypeMask mask, Selector selector, World world) { + if (!world.hasClosedWorldAssumption) { + bool isNullable = mask.isNullable; + mask = world.compiler.typesTask.dynamicType; + if (isNullable) { + mask = mask.nullable(); + } + } // TODO(johnniwinther): Allow more TypeSelector kinds during resoluton. assert(world.isClosed || mask.isExact); if (selector.mask == mask) return selector; diff --git a/pkg/compiler/lib/src/warnings.dart b/pkg/compiler/lib/src/warnings.dart index 5d872d01063..f98667248e7 100644 --- a/pkg/compiler/lib/src/warnings.dart +++ b/pkg/compiler/lib/src/warnings.dart @@ -4,7 +4,7 @@ part of dart2js; -const DONT_KNOW_HOW_TO_FIX = ""; +const DONT_KNOW_HOW_TO_FIX = "Computer says no!"; /** * The messages in this file should meet the following guide lines: diff --git a/pkg/compiler/lib/src/world.dart b/pkg/compiler/lib/src/world.dart index 4391cdb3fc3..70bdcaa6ac3 100644 --- a/pkg/compiler/lib/src/world.dart +++ b/pkg/compiler/lib/src/world.dart @@ -96,6 +96,10 @@ abstract class ClassWorld { /// Returns `true` if any subclass of [superclass] implements [type]. bool hasAnySubclassThatImplements(ClassElement superclass, ClassElement type); + + /// Returns `true` if closed-world assumptions can be made, that is, + /// incremental compilation isn't enabled. + bool get hasClosedWorldAssumption; } class World implements ClassWorld { @@ -521,4 +525,6 @@ class World implements ClassWorld { } return functionsThatMightBePassedToApply.contains(element); } + + bool get hasClosedWorldAssumption => !compiler.hasIncrementalSupport; } diff --git a/pkg/dart2js_incremental/lib/library_updater.dart b/pkg/dart2js_incremental/lib/library_updater.dart index c206760c08d..df7a85a6dd0 100644 --- a/pkg/dart2js_incremental/lib/library_updater.dart +++ b/pkg/dart2js_incremental/lib/library_updater.dart @@ -417,7 +417,14 @@ class LibraryUpdater extends JsFeatures { } for (ClassElementX cls in newClasses) { - // TODO(ahe): Set up superclasses. + if (cls.isObject) continue; + jsAst.Node classAccess = namer.elementAccess(cls); + jsAst.Node superAccess = namer.elementAccess(cls.superclass); + + updates.add( + js.statement( + r'self.$dart_unsafe_eval.inheritFrom(#, #)', + [classAccess, superAccess])); } for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { diff --git a/tests/try/web/incremental_compilation_update_test.dart b/tests/try/web/incremental_compilation_update_test.dart index 9ce598642fd..ffea9182652 100644 --- a/tests/try/web/incremental_compilation_update_test.dart +++ b/tests/try/web/incremental_compilation_update_test.dart @@ -482,6 +482,60 @@ main() { """, const ['a', 'b', 'c']), ], + + // Test that a newly instantiated class is handled. + const [ + const ProgramResult( + r""" +class A { + get name => 'A.m'; + + m() { + print('Called $name'); + } +} + +class B extends A { + get name => 'B.m'; +} + +var instance; +main() { + if (instance == null) { + instance = new A(); +// } else { +// instance = new B(); + } + instance.m(); +} +""", + const ['Called A.m']), + const ProgramResult( + r""" +class A { + get name => 'A.m'; + + m() { + print('Called $name'); + } +} + +class B extends A { + get name => 'B.m'; +} + +var instance; +main() { + if (instance == null) { + instance = new A(); + } else { + instance = new B(); + } + instance.m(); +} +""", + const ['Called B.m']), + ], ]; void main() {