Version 1.2.0-dev.5.6
svn merge -c 32629 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 32685 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 32692 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 32702 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
git-svn-id: http://dart.googlecode.com/svn/trunk@32712 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/sdk/lib/_internal/compiler/implementation/deferred_load.dart b/sdk/lib/_internal/compiler/implementation/deferred_load.dart
index b1de78e..47ea3a1b 100644
--- a/sdk/lib/_internal/compiler/implementation/deferred_load.dart
+++ b/sdk/lib/_internal/compiler/implementation/deferred_load.dart
@@ -541,10 +541,13 @@
// For each deferred import we find out which outputUnits to load.
for (Import import in _allDeferredImports.keys) {
+ if (import == _fakeMainImport) continue;
hunksToLoad[importDeferName(import)] = new Set<OutputUnit>();
for (OutputUnit outputUnit in allOutputUnits) {
if (outputUnit == mainOutputUnit) continue;
- hunksToLoad[importDeferName(import)].add(outputUnit);
+ if (outputUnit.imports.contains(import)) {
+ hunksToLoad[importDeferName(import)].add(outputUnit);
+ }
}
}
}
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
index 444f6d0..3d58931 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
@@ -142,8 +142,13 @@
Map<ClassElement, ClassElement> implementationClasses;
Element getNativeInterceptorMethod;
+ bool needToInitializeIsolateAffinityTag = false;
bool needToInitializeDispatchProperty = false;
+ /// Holds the method "getIsolateAffinityTag" when dart:_js_helper has been
+ /// loaded.
+ FunctionElement getIsolateAffinityTagMarker;
+
final Namer namer;
/**
@@ -801,6 +806,7 @@
TreeElements elements = compiler.globalDependencies;
enqueue(enqueuer, getNativeInterceptorMethod, elements);
enqueueClass(enqueuer, jsPlainJavaScriptObjectClass, elements);
+ needToInitializeIsolateAffinityTag = true;
needToInitializeDispatchProperty = true;
}
@@ -1552,6 +1558,8 @@
mustPreserveNames = true;
} else if (element == preserveMetadataMarker) {
mustRetainMetadata = true;
+ } else if (element == getIsolateAffinityTagMarker) {
+ needToInitializeIsolateAffinityTag = true;
}
customElementsAnalysis.registerStaticUse(element, enqueuer);
}
@@ -1612,6 +1620,9 @@
} else if (uri == Uri.parse('dart:_js_names')) {
preserveNamesMarker =
library.find('preserveNames');
+ } else if (uri == Uri.parse('dart:_js_helper')) {
+ getIsolateAffinityTagMarker =
+ library.find('getIsolateAffinityTag');
}
return new Future.value();
}
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart b/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart
index a9f6407..33804f6 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart
@@ -739,6 +739,8 @@
return 'String';
} else if (cls == backend.jsArrayClass) {
return 'List';
+ } else if (cls == backend.jsNullClass) {
+ return 'Null';
} else {
return null;
}
diff --git a/sdk/lib/_internal/compiler/implementation/js_emitter/code_emitter_task.dart b/sdk/lib/_internal/compiler/implementation/js_emitter/code_emitter_task.dart
index 2f81f2d..531d1e6 100644
--- a/sdk/lib/_internal/compiler/implementation/js_emitter/code_emitter_task.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_emitter/code_emitter_task.dart
@@ -972,20 +972,51 @@
return "${namer.isolateAccess(isolateMain)}($mainAccess)";
}
- jsAst.Expression generateDispatchPropertyInitialization() {
+ /**
+ * Emits code that sets `init.isolateTag` to a unique string.
+ */
+ jsAst.Expression generateIsolateAffinityTagInitialization() {
return js('!#', js.fun([], [
- js('var objectProto = Object.prototype'),
+
+ // On V8, the 'intern' function converts a string to a symbol, which
+ // makes property access much faster.
+ new jsAst.FunctionDeclaration(new jsAst.VariableDeclaration('intern'),
+ js.fun(['s'], [
+ js('var o = {}'),
+ js('o[s] = 1'),
+ js.return_(js('Object.keys(convertToFastObject(o))[0]'))])),
+
+
+ js('init.getIsolateTag = #',
+ js.fun(['name'],
+ js.return_('intern("___dart_" + name + init.isolateTag)'))),
+
+ // To ensure that different programs loaded into the same context (page)
+ // use distinct dispatch properies, we place an object on `Object` to
+ // contain the names already in use.
+ js('var tableProperty = "___dart_isolate_tags_"'),
+ js('var usedProperties = Object[tableProperty] ||'
+ '(Object[tableProperty] = Object.create(null))'),
+
+ js('var rootProperty = "_${generateIsolateTagRoot()}"'),
js.for_('var i = 0', null, 'i++', [
- js('var property = "${generateDispatchPropertyName(0)}"'),
- js.if_('i > 0', js('property = rootProperty + "_" + i')),
- js.if_('!(property in objectProto)',
- js.return_(
- js('init.dispatchPropertyName = property')))])])());
+ js('property = intern(rootProperty + "_" + i + "_")'),
+ js.if_('!(property in usedProperties)', [
+ js('usedProperties[property] = 1'),
+ js('init.isolateTag = property'),
+ new jsAst.Break(null)])])])
+ ());
+
}
- String generateDispatchPropertyName(int seed) {
+ jsAst.Expression generateDispatchPropertyNameInitialization() {
+ return js(
+ 'init.dispatchPropertyName = init.getIsolateTag("dispatch_record")');
+ }
+
+ String generateIsolateTagRoot() {
// TODO(sra): MD5 of contributing source code or URIs?
- return '___dart_dispatch_record_ZxYxX_${seed}_';
+ return 'ZxYxX';
}
emitMain(CodeBuffer buffer) {
@@ -999,12 +1030,21 @@
} else {
mainCall = '${namer.isolateAccess(main)}()';
}
- if (backend.needToInitializeDispatchProperty) {
+
+ if (backend.needToInitializeIsolateAffinityTag) {
buffer.write(
- jsAst.prettyPrint(generateDispatchPropertyInitialization(),
+ jsAst.prettyPrint(generateIsolateAffinityTagInitialization(),
compiler));
buffer.write(N);
}
+ if (backend.needToInitializeDispatchProperty) {
+ assert(backend.needToInitializeIsolateAffinityTag);
+ buffer.write(
+ jsAst.prettyPrint(generateDispatchPropertyNameInitialization(),
+ compiler));
+ buffer.write(N);
+ }
+
addComment('BEGIN invoke [main].', buffer);
// This code finds the currently executing script by listening to the
// onload event of all script tags and getting the first script which
diff --git a/sdk/lib/_internal/compiler/implementation/resolution/members.dart b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
index 4ab41ca..f97438c 100644
--- a/sdk/lib/_internal/compiler/implementation/resolution/members.dart
+++ b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
@@ -803,7 +803,7 @@
element.origin.ensureResolved(compiler);
// Ensure that the type is computed.
element.computeType(compiler);
- // Copy class hiearchy from origin.
+ // Copy class hierarchy from origin.
element.supertype = element.origin.supertype;
element.interfaces = element.origin.interfaces;
element.allSupertypesAndSelf = element.origin.allSupertypesAndSelf;
diff --git a/sdk/lib/_internal/lib/js_helper.dart b/sdk/lib/_internal/lib/js_helper.dart
index 92b23ad..cef540b 100644
--- a/sdk/lib/_internal/lib/js_helper.dart
+++ b/sdk/lib/_internal/lib/js_helper.dart
@@ -978,6 +978,7 @@
if (JS('bool', '# == "num"', className)) return const JSNumber();
if (JS('bool', '# == "bool"', className)) return const JSBool();
if (JS('bool', '# == "List"', className)) return const JSArray();
+ if (JS('bool', '# == "Null"', className)) return const JSNull();
return JS('var', 'init.allClasses[#]', className);
}
@@ -3055,3 +3056,15 @@
int int32b = JS("int", "(Math.random() * 0x100000000) >>> 0");
return int32a + int32b * 0x100000000;
}
+
+/**
+ * Returns a property name for placing data on JavaScript objects shared between
+ * DOM isolates. This happens when multiple programs are loaded in the same
+ * JavaScript context (i.e. page). The name is based on [name] but with an
+ * additional part that is unique for each isolate.
+ *
+ * The form of the name is '___dart_$name_$id'.
+ */
+String getIsolateAffinityTag(String name) {
+ return JS('String', 'init.getIsolateTag(#)', name);
+}
diff --git a/sdk/lib/_internal/lib/js_mirrors.dart b/sdk/lib/_internal/lib/js_mirrors.dart
index 6b58b6f..0154824 100644
--- a/sdk/lib/_internal/lib/js_mirrors.dart
+++ b/sdk/lib/_internal/lib/js_mirrors.dart
@@ -878,10 +878,11 @@
/// reflective information to know how to to invoke a specific member.
get _classInvocationCache {
String cacheName = Primitives.mirrorInvokeCacheName;
- var cache = JS('', r'#.constructor[#]', reflectee, cacheName);
+ var cacheHolder = (reflectee == null) ? getInterceptor(null) : reflectee;
+ var cache = JS('', r'#.constructor[#]', cacheHolder, cacheName);
if (cache == null) {
cache = JsCache.allocate();
- JS('void', r'#.constructor[#] = #', reflectee, cacheName, cache);
+ JS('void', r'#.constructor[#] = #', cacheHolder, cacheName, cache);
}
return cache;
}
@@ -1070,7 +1071,7 @@
// interceptor between multiple different instances of [InstanceMirror].
var interceptor = getInterceptor(object);
if (!useEval) return _newInterceptGetterNoEvalFn(name, interceptor);
- String className = JS('String', '#.constructor.name', object);
+ String className = JS('String', '#.constructor.name', interceptor);
var body = "(function $className\$$name(o){return i.$name(o)})";
return JS('', '(function(b,i){return eval(b)})(#,#)', body, interceptor);
}
diff --git a/sdk/lib/js/dart2js/js_dart2js.dart b/sdk/lib/js/dart2js/js_dart2js.dart
index 576cb234..39b6c2a 100644
--- a/sdk/lib/js/dart2js/js_dart2js.dart
+++ b/sdk/lib/js/dart2js/js_dart2js.dart
@@ -94,7 +94,8 @@
import 'dart:_foreign_helper' show JS, DART_CLOSURE_TO_JS;
import 'dart:_interceptors' show JavaScriptObject, UnknownJavaScriptObject;
-import 'dart:_js_helper' show Primitives, convertDartClosureToJS;
+import 'dart:_js_helper' show Primitives, convertDartClosureToJS,
+ getIsolateAffinityTag;
final JsObject context = _wrapToDart(Primitives.computeGlobalThis());
@@ -451,8 +452,10 @@
}
// property added to a Dart object referencing its JS-side DartObject proxy
-const _DART_OBJECT_PROPERTY_NAME = r'_$dart_dartObject';
-const _DART_CLOSURE_PROPERTY_NAME = r'_$dart_dartClosure';
+final String _DART_OBJECT_PROPERTY_NAME =
+ getIsolateAffinityTag(r'_$dart_dartObject');
+final String _DART_CLOSURE_PROPERTY_NAME =
+ getIsolateAffinityTag(r'_$dart_dartClosure');
// property added to a JS object referencing its Dart-side JsObject proxy
const _JS_OBJECT_PROPERTY_NAME = r'_$dart_jsObject';
diff --git a/tests/compiler/dart2js/deferred_load_graph_segmentation_test.dart b/tests/compiler/dart2js/deferred_load_graph_segmentation_test.dart
index dc3c7ae..20a663c 100644
--- a/tests/compiler/dart2js/deferred_load_graph_segmentation_test.dart
+++ b/tests/compiler/dart2js/deferred_load_graph_segmentation_test.dart
@@ -65,6 +65,26 @@
// InputElement is native, so it should not appear on a classList
Expect.isFalse(outputClassLists[outputUnitForElement(inputElement)]
.contains(inputElement));
+
+ var hunksToLoad = compiler.deferredLoadTask.hunksToLoad;
+ var hunksLib1 = new Set.from(hunksToLoad["lib1"].map((o) => o.name));
+ var hunksLib2 = new Set.from(hunksToLoad["lib2"].map((o) => o.name));
+ var hunksLib4_1 = new Set.from(hunksToLoad["lib4_1"].map((o) => o.name));
+ var hunksLib4_2 = new Set.from(hunksToLoad["lib4_2"].map((o) => o.name));
+ Expect.equals(hunksLib1.length, 2);
+ Expect.isTrue(hunksLib1.contains("lib1"));
+ Expect.isTrue(hunksLib1.contains("lib1_lib2") ||
+ hunksLib1.contains("lib2_lib1"));
+ Expect.isTrue(hunksLib2.contains("lib2"));
+ Expect.equals(hunksLib2.length, 2);
+ Expect.isTrue(hunksLib2.contains("lib1_lib2") ||
+ hunksLib1.contains("lib2_lib1"));
+ Expect.isTrue(hunksLib4_1.contains("lib4_1"));
+ Expect.equals(hunksLib4_1.length, 1);
+ Expect.isTrue(hunksLib4_2.contains("lib4_2"));
+ Expect.equals(hunksLib4_2.length, 1);
+ Expect.equals(hunksToLoad["main"], null);
+
}));
}
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index 662d9a9..38b41b7 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -146,8 +146,6 @@
bit_operations_test: RuntimeError, OK # Issue 1533
expect_test: RuntimeError, OK # Issue 13080
-null_test/none: RuntimeError # Issue 12482
-
[ ($compiler == dart2js || $compiler == dart2dart) && $checked ]
cyclic_typedef_test/07: Crash # Issue 15237
diff --git a/tests/language/null2_test.dart b/tests/language/null2_test.dart
new file mode 100644
index 0000000..16d3a83
--- /dev/null
+++ b/tests/language/null2_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Second dart test program.
+
+import "package:expect/expect.dart";
+
+// Magic incantation to avoid the compiler recognizing the constant values
+// at compile time. If the result is computed at compile time, the dynamic code
+// will not be tested.
+confuse(x) {
+ try {
+ if (new DateTime.now().millisecondsSinceEpoch == 42) x = 42;
+ throw [x];
+ } on dynamic catch (e) { return e[0]; }
+ return 42;
+}
+
+main() {
+ Expect.equals("Null", null.runtimeType.toString());
+ Expect.equals("Null", confuse(null).runtimeType.toString());
+}
diff --git a/tests/language/null_test.dart b/tests/language/null_test.dart
index c499c50..83ffd7b 100644
--- a/tests/language/null_test.dart
+++ b/tests/language/null_test.dart
@@ -37,7 +37,10 @@
// at compile time. If the result is computed at compile time, the dynamic code
// will not be tested.
confuse(x) {
- try { throw [x]; } on dynamic catch (e) { return e[0]; }
+ try {
+ if (new DateTime.now().millisecondsSinceEpoch == 42) x = 42;
+ throw [x];
+ } on dynamic catch (e) { return e[0]; }
return 42;
}
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index fa7539b..bfa79c3 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -78,7 +78,6 @@
mirrors/mirrors_test: RuntimeError # TODO(ahe): I'm working on fixing this.
mirrors/mixin_test: RuntimeError # Issue 12464
mirrors/mixin_application_test/none: RuntimeError # Issue 12464
-mirrors/null_test : RuntimeError # Issue 12129
mirrors/parameter_test/none: RuntimeError # Issue 6490
mirrors/parameter_metadata_test: RuntimeError # Issue 10905
mirrors/private_symbol_test: CompileTimeError # Issue 13597
@@ -108,6 +107,7 @@
typed_data/setRange_3_test: Fail # Safari doesn't fully implement spec for TypedArray.set
typed_data/setRange_4_test: Fail # Safari doesn't fully implement spec for TypedArray.set
mirrors/to_string_test: Fail # Safari bug TODO(ahe): Add bug number if able to submit bug.
+mirrors/null_test: Fail # http://dartbug.com/16831
[ $compiler == dart2js && $runtime == chromeOnAndroid ]
typed_data/setRange_2_test: RuntimeError # TODO(dart2js-team): Please triage this failure.
@@ -175,7 +175,8 @@
# implement timer (currently only in d8)
[ $compiler == dart2js && $minified ]
-mirrors/intercepted_superclass_test: RuntimeError # Issue 16389
+mirrors/intercepted_superclass_test: RuntimeError # Issue 16804
+mirrors/null_test/00: RuntimeError # Issue 16804. Please remove the multi-test comments when this test starts succeeding.
[ $compiler == dart2dart ]
mirrors/*: Skip # http://dartbug.com/11511
diff --git a/tests/lib/mirrors/null2_test.dart b/tests/lib/mirrors/null2_test.dart
new file mode 100644
index 0000000..4c5590d
--- /dev/null
+++ b/tests/lib/mirrors/null2_test.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library test.null_test;
+
+import 'dart:mirrors';
+
+import 'package:expect/expect.dart';
+
+main() {
+ InstanceMirror nullMirror = reflect(null);
+ for (int i = 0; i < 10; i++) {
+ Expect.isTrue(nullMirror.getField(#hashCode).reflectee is int);
+ }
+}
diff --git a/tests/lib/mirrors/null_test.dart b/tests/lib/mirrors/null_test.dart
index 72f5e23..d0069d2 100644
--- a/tests/lib/mirrors/null_test.dart
+++ b/tests/lib/mirrors/null_test.dart
@@ -28,8 +28,8 @@
ClassMirror NullMirror = nullMirror.type;
Expect.equals(reflectClass(Null), NullMirror);
Expect.equals(#Null, NullMirror.simpleName);
- Expect.equals(#Object, NullMirror.superclass.simpleName);
- Expect.equals(null, NullMirror.superclass.superclass);
+ Expect.equals(#Object, NullMirror.superclass.simpleName); /// 00: ok
+ Expect.equals(null, NullMirror.superclass.superclass); /// 00: continued
Expect.listEquals([], NullMirror.superinterfaces);
Expect.equals(currentMirrorSystem().libraries[Uri.parse('dart:core')],
NullMirror.owner);
diff --git a/tools/VERSION b/tools/VERSION
index 0ff063f..a101173 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -28,4 +28,4 @@
MINOR 2
PATCH 0
PRERELEASE 5
-PRERELEASE_PATCH 7
+PRERELEASE_PATCH 8