Version 1.4.0-dev.6.4
svn merge -c 35866 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 36037 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 36038 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
git-svn-id: http://dart.googlecode.com/svn/trunk@36091 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/pkg/docgen/lib/src/models/closure.dart b/pkg/docgen/lib/src/models/closure.dart
new file mode 100644
index 0000000..2fcfa19
--- /dev/null
+++ b/pkg/docgen/lib/src/models/closure.dart
@@ -0,0 +1,35 @@
+// 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.
+
+library docgen.models.closure;
+
+import '../exports/source_mirrors.dart';
+
+import 'doc_gen_type.dart';
+import 'indexable.dart';
+import 'mirror_based.dart';
+import 'model_helpers.dart';
+import 'parameter.dart';
+
+/// A class containing the properties of a function to be called (used in our
+/// case specifically to illustrate evidence of the type of function for a
+/// parameter).
+class Closure extends MirrorBased<FunctionTypeMirror> {
+
+ /// Parameters for this method.
+ final Map<String, Parameter> parameters;
+ final DocGenType returnType;
+ final FunctionTypeMirror mirror;
+
+ Closure(FunctionTypeMirror mirror, Indexable owner)
+ : returnType = new DocGenType(mirror.returnType, owner.owningLibrary),
+ parameters = createParameters(mirror.parameters, owner),
+ mirror = mirror;
+
+ /// Generates a map describing the [Method] object.
+ Map toMap() => {
+ 'return': [returnType.toMap()],
+ 'parameters': recurseMap(parameters),
+ };
+}
\ No newline at end of file
diff --git a/pkg/docgen/lib/src/models/method.dart b/pkg/docgen/lib/src/models/method.dart
index 9483a37..f25d53b 100644
--- a/pkg/docgen/lib/src/models/method.dart
+++ b/pkg/docgen/lib/src/models/method.dart
@@ -153,4 +153,4 @@
}
bool isValidMirror(DeclarationMirror mirror) => mirror is MethodMirror;
-}
+}
\ No newline at end of file
diff --git a/pkg/docgen/lib/src/models/model_helpers.dart b/pkg/docgen/lib/src/models/model_helpers.dart
index 48babc9..e5e55a0e 100644
--- a/pkg/docgen/lib/src/models/model_helpers.dart
+++ b/pkg/docgen/lib/src/models/model_helpers.dart
@@ -28,15 +28,15 @@
/// Expand the method map [mapToExpand] into a more detailed map that
/// separates out setters, getters, constructors, operators, and methods.
Map expandMethodMap(Map<String, Method> mapToExpand) => {
- 'setters': recurseMap(filterMap(mapToExpand,
+ 'setters': recurseMap(_filterMap(mapToExpand,
(key, val) => val.mirror.isSetter)),
- 'getters': recurseMap(filterMap(mapToExpand,
+ 'getters': recurseMap(_filterMap(mapToExpand,
(key, val) => val.mirror.isGetter)),
- 'constructors': recurseMap(filterMap(mapToExpand,
+ 'constructors': recurseMap(_filterMap(mapToExpand,
(key, val) => val.mirror.isConstructor)),
- 'operators': recurseMap(filterMap(mapToExpand,
+ 'operators': recurseMap(_filterMap(mapToExpand,
(key, val) => val.mirror.isOperator)),
- 'methods': recurseMap(filterMap(mapToExpand,
+ 'methods': recurseMap(_filterMap(mapToExpand,
(key, val) => val.mirror.isRegularMethod && !val.mirror.isOperator))
};
@@ -105,7 +105,7 @@
/// Transforms the map by calling toMap on each value in it.
Map recurseMap(Map inputMap) {
- var outputMap = new SplayTreeMap();
+ var outputMap = new LinkedHashMap();
inputMap.forEach((key, value) {
if (value is Map) {
outputMap[key] = recurseMap(value);
@@ -116,14 +116,6 @@
return outputMap;
}
-Map filterMap(Map map, Function test) {
- var exported = new Map();
- map.forEach((key, value) {
- if (test(key, value)) exported[key] = value;
- });
- return exported;
-}
-
/// Read a pubspec and return the library name given a [LibraryMirror].
String getPackageName(LibraryMirror mirror) {
if (mirror.uri.scheme != 'file') return '';
@@ -149,9 +141,9 @@
Map<String, Map<String, DeclarationMirror>> calcExportedItems(
LibrarySourceMirror library) {
var exports = {};
- exports['classes'] = {};
- exports['methods'] = {};
- exports['variables'] = {};
+ exports['classes'] = new SplayTreeMap();
+ exports['methods'] = new SplayTreeMap();
+ exports['variables'] = new SplayTreeMap();
// Determine the classes, variables and methods that are exported for a
// specific dependency.
@@ -220,7 +212,7 @@
/// purposes).
Map<String, Variable> createVariables(Iterable<VariableMirror> mirrors,
Indexable owner) {
- var data = {};
+ var data = new SplayTreeMap<String, Variable>();
// TODO(janicejl): When map to map feature is created, replace the below
// with a filter. Issue(#9590).
mirrors.forEach((dart2js_mirrors.Dart2JsFieldMirror mirror) {
@@ -238,7 +230,7 @@
/// purposes).
Map<String, Method> createMethods(Iterable<MethodMirror> mirrors,
Indexable owner) {
- var group = new Map<String, Method>();
+ var group = new SplayTreeMap<String, Method>();
mirrors.forEach((MethodMirror mirror) {
if (includePrivateMembers || !mirror.isPrivate) {
group[dart2js_util.nameOf(mirror)] = new Method(mirror, owner);
@@ -265,6 +257,14 @@
value: (e) => new Generic(e));
}
+Map _filterMap(Map map, bool test(k, v)) {
+ var exported = new SplayTreeMap();
+ map.forEach((key, value) {
+ if (test(key, value)) exported[key] = value;
+ });
+ return exported;
+}
+
/// Annotations that we do not display in the viewer.
const List<String> _SKIPPED_ANNOTATIONS = const [
'metadata.DocsEditable', '_js_helper.JSName', '_js_helper.Creates',
diff --git a/pkg/docgen/lib/src/models/parameter.dart b/pkg/docgen/lib/src/models/parameter.dart
index 2f8798c..ef9d9ab 100644
--- a/pkg/docgen/lib/src/models/parameter.dart
+++ b/pkg/docgen/lib/src/models/parameter.dart
@@ -8,6 +8,7 @@
import '../exports/source_mirrors.dart';
import 'annotation.dart';
+import 'closure.dart';
import 'doc_gen_type.dart';
import 'library.dart';
import 'mirror_based.dart';
@@ -25,6 +26,9 @@
final String defaultValue;
/// List of the meta annotations on the parameter.
final List<Annotation> annotations;
+ final Library owningLibrary;
+ // Only non-null if this parameter is a function declaration.
+ Closure functionDeclaration;
Parameter(ParameterMirror mirror, Library owningLibrary)
: this.mirror = mirror,
@@ -34,16 +38,28 @@
hasDefaultValue = mirror.hasDefaultValue,
defaultValue = getDefaultValue(mirror),
type = new DocGenType(mirror.type, owningLibrary),
- annotations = createAnnotations(mirror, owningLibrary);
+ annotations = createAnnotations(mirror, owningLibrary),
+ owningLibrary = owningLibrary {
+ if (mirror.type is FunctionTypeMirror) {
+ functionDeclaration =
+ new Closure(mirror.type as FunctionTypeMirror, owningLibrary);
+ }
+ }
/// Generates a map describing the [Parameter] object.
- Map toMap() => {
- 'name': name,
- 'optional': isOptional,
- 'named': isNamed,
- 'default': hasDefaultValue,
- 'type': new List.filled(1, type.toMap()),
- 'value': defaultValue,
- 'annotations': annotations.map((a) => a.toMap()).toList()
- };
-}
+ Map toMap() {
+ var map = {
+ 'name': name,
+ 'optional': isOptional,
+ 'named': isNamed,
+ 'default': hasDefaultValue,
+ 'type': new List.filled(1, type.toMap()),
+ 'value': defaultValue,
+ 'annotations': annotations.map((a) => a.toMap()).toList()
+ };
+ if (functionDeclaration != null) {
+ map['functionDeclaration'] = functionDeclaration.toMap();
+ }
+ return map;
+ }
+}
\ No newline at end of file
diff --git a/pkg/docgen/test/constant_argument_test.dart b/pkg/docgen/test/constant_argument_test.dart
index ca735f4..6380fdd 100644
--- a/pkg/docgen/test/constant_argument_test.dart
+++ b/pkg/docgen/test/constant_argument_test.dart
@@ -42,6 +42,9 @@
var params = functionDef['parameters'] as Map<String, dynamic>;
+ expect(params.keys, orderedEquals(_PARAM_NAME_ORDER),
+ reason: 'parameter order must be maintained');
+
var vals = {};
params.forEach((paramName, paramHash) {
expect(_PARAM_VALUES, contains(paramName));
@@ -53,10 +56,19 @@
}
final _PARAM_VALUES = {
- "boolConst": "true",
"intConst": "42",
+ "boolConst": "true",
"listConst": '[true, 42, "Shanna", null, 3.14, []]',
+ "stringConst": "\"Shanna\"",
"mapConst": startsWith("Map"),
- "emptyMap": '{}',
- "stringConst": "\"Shanna\""
+ "emptyMap": '{}'
};
+
+const _PARAM_NAME_ORDER = const [
+ "intConst",
+ "boolConst",
+ "listConst",
+ "stringConst",
+ "mapConst",
+ "emptyMap"
+];
diff --git a/pkg/docgen/test/method_param_test.dart b/pkg/docgen/test/method_param_test.dart
new file mode 100644
index 0000000..a12840e
--- /dev/null
+++ b/pkg/docgen/test/method_param_test.dart
@@ -0,0 +1,28 @@
+// 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.
+
+library docgen.test.method_param;
+
+import 'package:path/path.dart' as path;
+import 'package:scheduled_test/scheduled_test.dart';
+
+import 'util.dart';
+import '../lib/docgen.dart' as gen;
+
+void main() {
+ test('method function parameters', () {
+ var lib_file = path.toUri(path.join(getMultiLibraryCodePath(), 'lib',
+ 'test_lib2.dart'));
+ return gen.getMirrorSystem([lib_file], false)
+ .then((mirrorSystem) {
+ var library = new gen.Library(mirrorSystem.libraries[lib_file]);
+
+ // Test that libraries do recursive exports correctly.
+ var funcParams = library.functions['fooFunc'].parameters;
+ expect('Symbol("dart.core.int")', library.functions['fooFunc']
+ .parameters['fooFuncParam'].functionDeclaration.parameters['x']
+ .type.mirror.qualifiedName.toString());
+ });
+ });
+}
\ No newline at end of file
diff --git a/pkg/docgen/test/multi_library_code/lib/test_lib2.dart b/pkg/docgen/test/multi_library_code/lib/test_lib2.dart
index d9fa7ee..b28f6d8 100644
--- a/pkg/docgen/test/multi_library_code/lib/test_lib2.dart
+++ b/pkg/docgen/test/multi_library_code/lib/test_lib2.dart
@@ -5,3 +5,5 @@
library test_lib2;
export 'test_lib2_foo.dart';
+
+String fooFunc(bool fooFuncParam(int x)) => 'hi';
\ No newline at end of file
diff --git a/sdk/lib/_internal/lib/js_helper.dart b/sdk/lib/_internal/lib/js_helper.dart
index 1b19fbf..2592a72 100644
--- a/sdk/lib/_internal/lib/js_helper.dart
+++ b/sdk/lib/_internal/lib/js_helper.dart
@@ -1097,16 +1097,19 @@
class JsCache {
/// Returns a JavaScript object suitable for use as a cache.
static allocate() {
- var result = JS('=Object', '{x:0}');
+ var result = JS('=Object', 'Object.create(null)');
// Deleting a property makes V8 assume that it shouldn't create a hidden
// class for [result] and map transitions. Although these map transitions
// pay off if there are many cache hits for the same keys, it becomes
// really slow when there aren't many repeated hits.
+ JS('void', '#.x=0', result);
JS('void', 'delete #.x', result);
return result;
}
- static fetch(cache, String key) => JS('', '#[#]', cache, key);
+ static fetch(cache, String key) {
+ return JS('', '#[#]', cache, key);
+ }
static void update(cache, String key, value) {
JS('void', '#[#] = #', cache, key, value);
diff --git a/sdk/lib/_internal/lib/js_mirrors.dart b/sdk/lib/_internal/lib/js_mirrors.dart
index e7ebddb..fdf7393 100644
--- a/sdk/lib/_internal/lib/js_mirrors.dart
+++ b/sdk/lib/_internal/lib/js_mirrors.dart
@@ -1064,7 +1064,7 @@
var cache = _getterCache;
if (isMissingCache(cache)) {
if ((_getterCache = --cache) != 0) return result;
- cache = _getterCache = JS('=Object', '({})');
+ cache = _getterCache = JS('=Object', 'Object.create(null)');
}
// Make sure that symbol [fieldName] has a cache probing function ($p).
diff --git a/tests/lib/mirrors/get_field_cache_test.dart b/tests/lib/mirrors/get_field_cache_test.dart
new file mode 100644
index 0000000..4c71dbc
--- /dev/null
+++ b/tests/lib/mirrors/get_field_cache_test.dart
@@ -0,0 +1,36 @@
+// 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.
+
+@MirrorsUsed(targets: const ["A", "B"])
+import 'dart:mirrors';
+
+import 'package:expect/expect.dart';
+
+class A {
+ toString() => "A";
+}
+
+class B {
+ int x = 99;
+ toString() => "B";
+}
+
+void main() {
+ var a = new A();
+ var am = reflect(a);
+ for (int i = 0; i < 10; i++) {
+ // Adds a probe function on the symbol.
+ am.getField(#toString);
+ }
+ var b = new B();
+ var bm = reflect(b);
+ for (int i = 0; i < 10; i++) {
+ // Adds a field-cache on the mirror.
+ bm.getField(#x);
+ }
+ // There is a cache now, but the cache should not contain 'toString' from
+ // JavaScript's Object.prototype.
+ var toString = bm.getField(#toString).reflectee;
+ Expect.equals("B", toString());
+}
diff --git a/tests/lib/mirrors/invocation_cache_test.dart b/tests/lib/mirrors/invocation_cache_test.dart
new file mode 100644
index 0000000..0d9624a
--- /dev/null
+++ b/tests/lib/mirrors/invocation_cache_test.dart
@@ -0,0 +1,19 @@
+// 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.
+
+@MirrorsUsed(targets: const ["A"])
+import 'dart:mirrors';
+
+import 'package:expect/expect.dart';
+
+class A {
+ toString() => "A";
+}
+
+main() {
+ // The invocation cache must not find the 'toString' from JavaScript's
+ // Object.prototype.
+ var toString = reflect(new A()).getField(#toString).reflectee;
+ Expect.equals("A", Function.apply(toString, [], {}));
+}
diff --git a/tools/VERSION b/tools/VERSION
index 962d60b..423c53d 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -28,4 +28,4 @@
MINOR 4
PATCH 0
PRERELEASE 6
-PRERELEASE_PATCH 4
+PRERELEASE_PATCH 5