mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 01:13:04 +00:00
Add dart:js_util library and tests to ddc. This library is already added to dart2js and dartium.
BUG= R=jmesserly@google.com Review URL: https://codereview.chromium.org/2269963005 .
This commit is contained in:
parent
9d8ae169de
commit
87577db2b2
|
@ -20,6 +20,7 @@ dart_library.library('dart_sdk', null, /* Imports */[
|
|||
const core = Object.create(null);
|
||||
const isolate = Object.create(null);
|
||||
const js = Object.create(null);
|
||||
const js_util = Object.create(null);
|
||||
const math = Object.create(null);
|
||||
const mirrors = Object.create(null);
|
||||
const typed_data = Object.create(null);
|
||||
|
@ -629,6 +630,7 @@ dart_library.library('dart_sdk', null, /* Imports */[
|
|||
let dynamicAnddynamicAndFnToObject = () => (dynamicAnddynamicAndFnToObject = dart.constFn(dart.definiteFunctionType(core.Object, [dart.dynamic, dart.dynamic, dynamicTodynamic()])))();
|
||||
let FToF = () => (FToF = dart.constFn(dart.definiteFunctionType(F => [F, [F]])))();
|
||||
let FunctionToFunction = () => (FunctionToFunction = dart.constFn(dart.definiteFunctionType(core.Function, [core.Function])))();
|
||||
let FunctionAndListTodynamic = () => (FunctionAndListTodynamic = dart.constFn(dart.definiteFunctionType(dart.dynamic, [core.Function, core.List])))();
|
||||
let TAndTToT = () => (TAndTToT = dart.constFn(dart.definiteFunctionType(T => [T, [T, T]])))();
|
||||
let TAndTToT$ = () => (TAndTToT$ = dart.constFn(dart.definiteFunctionType(T => [T, [T, T]])))();
|
||||
let numAndnumTodouble = () => (numAndnumTodouble = dart.constFn(dart.definiteFunctionType(core.double, [core.num, core.num])))();
|
||||
|
@ -33773,6 +33775,109 @@ dart_library.library('dart_sdk', null, /* Imports */[
|
|||
return ret;
|
||||
};
|
||||
dart.fn(js.allowInteropCaptureThis, FunctionToFunction());
|
||||
js_util.jsify = function(object) {
|
||||
if (!core.Map.is(object) && !core.Iterable.is(object)) {
|
||||
dart.throw(new core.ArgumentError("object must be a Map or Iterable"));
|
||||
}
|
||||
return js_util._convertDataTree(object);
|
||||
};
|
||||
dart.fn(js_util.jsify, dynamicTodynamic$());
|
||||
js_util._convertDataTree = function(data) {
|
||||
let _convertedObjects = collection.HashMap.identity();
|
||||
function _convert(o) {
|
||||
if (dart.test(_convertedObjects.containsKey(o))) {
|
||||
return _convertedObjects.get(o);
|
||||
}
|
||||
if (core.Map.is(o)) {
|
||||
let convertedMap = {};
|
||||
_convertedObjects.set(o, convertedMap);
|
||||
for (let key of o[dartx.keys]) {
|
||||
convertedMap[key] = _convert(o[dartx.get](key));
|
||||
}
|
||||
return convertedMap;
|
||||
} else if (core.Iterable.is(o)) {
|
||||
let convertedList = [];
|
||||
_convertedObjects.set(o, convertedList);
|
||||
convertedList[dartx.addAll](o[dartx.map](dart.dynamic)(_convert));
|
||||
return convertedList;
|
||||
} else {
|
||||
return o;
|
||||
}
|
||||
}
|
||||
dart.fn(_convert, dynamicTodynamic$());
|
||||
return _convert(data);
|
||||
};
|
||||
dart.fn(js_util._convertDataTree, dynamicTodynamic$());
|
||||
js_util.newObject = function() {
|
||||
return {};
|
||||
};
|
||||
dart.fn(js_util.newObject, VoidTodynamic$());
|
||||
js_util.hasProperty = function(o, name) {
|
||||
return name in o;
|
||||
};
|
||||
dart.fn(js_util.hasProperty, dynamicAnddynamicTodynamic$());
|
||||
js_util.getProperty = function(o, name) {
|
||||
return o[name];
|
||||
};
|
||||
dart.fn(js_util.getProperty, dynamicAnddynamicTodynamic$());
|
||||
js_util.setProperty = function(o, name, value) {
|
||||
return o[name] = value;
|
||||
};
|
||||
dart.fn(js_util.setProperty, dynamicAnddynamicAnddynamicTodynamic());
|
||||
js_util.callMethod = function(o, method, args) {
|
||||
return o[method].apply(o, args);
|
||||
};
|
||||
dart.fn(js_util.callMethod, dynamicAndStringAndListTodynamic());
|
||||
js_util.instanceof = function(o, type) {
|
||||
return o instanceof type;
|
||||
};
|
||||
dart.fn(js_util.instanceof, dynamicAndFunctionTodynamic());
|
||||
js_util.callConstructor = function(constr, arguments$) {
|
||||
if (arguments$ == null) {
|
||||
return new constr();
|
||||
}
|
||||
if (arguments$ instanceof Array) {
|
||||
let argumentCount = arguments$.length;
|
||||
switch (argumentCount) {
|
||||
case 0:
|
||||
{
|
||||
return new constr();
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
let arg0 = arguments$[0];
|
||||
return new constr(arg0);
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
let arg0 = arguments$[0];
|
||||
let arg1 = arguments$[1];
|
||||
return new constr(arg0, arg1);
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
let arg0 = arguments$[0];
|
||||
let arg1 = arguments$[1];
|
||||
let arg2 = arguments$[2];
|
||||
return new constr(arg0, arg1, arg2);
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
let arg0 = arguments$[0];
|
||||
let arg1 = arguments$[1];
|
||||
let arg2 = arguments$[2];
|
||||
let arg3 = arguments$[3];
|
||||
return new constr(arg0, arg1, arg2, arg3);
|
||||
}
|
||||
}
|
||||
}
|
||||
let args = [null];
|
||||
args[dartx.addAll](arguments$);
|
||||
let factoryFunction = constr.bind.apply(constr, args);
|
||||
String(factoryFunction);
|
||||
return new factoryFunction();
|
||||
};
|
||||
dart.fn(js_util.callConstructor, FunctionAndListTodynamic());
|
||||
math.E = 2.718281828459045;
|
||||
math.LN10 = 2.302585092994046;
|
||||
math.LN2 = 0.6931471805599453;
|
||||
|
@ -84098,6 +84203,7 @@ dart_library.library('dart_sdk', null, /* Imports */[
|
|||
exports.core = core;
|
||||
exports.isolate = isolate;
|
||||
exports.js = js;
|
||||
exports.js_util = js_util;
|
||||
exports.math = math;
|
||||
exports.mirrors = mirrors;
|
||||
exports.typed_data = typed_data;
|
||||
|
|
|
@ -2629,6 +2629,7 @@
|
|||
'js_function_getter_trust_types_test': 'unittest',
|
||||
'js_interop_1_test': 'unittest',
|
||||
'js_test': 'unittest',
|
||||
'js_util_test': 'unittest',
|
||||
'js_typed_interop_anonymous2_exp_test': 'unittest',
|
||||
'js_typed_interop_anonymous2_test': 'unittest',
|
||||
'js_typed_interop_anonymous_exp_test': 'unittest',
|
||||
|
|
347
pkg/dev_compiler/test/codegen/lib/html/js_util_test.dart
Normal file
347
pkg/dev_compiler/test/codegen/lib/html/js_util_test.dart
Normal file
|
@ -0,0 +1,347 @@
|
|||
// 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.
|
||||
|
||||
@JS()
|
||||
library js_native_test;
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:html';
|
||||
import 'dart:typed_data' show ByteBuffer, Int32List;
|
||||
import 'dart:indexed_db' show IdbFactory, KeyRange;
|
||||
|
||||
import 'package:js/js.dart';
|
||||
import 'package:js/js_util.dart' as js_util;
|
||||
|
||||
import 'package:unittest/unittest.dart';
|
||||
import 'package:unittest/html_individual_config.dart';
|
||||
|
||||
_injectJs() {
|
||||
final script = new ScriptElement();
|
||||
script.type = 'text/javascript';
|
||||
script.innerHtml = r"""
|
||||
var x = 42;
|
||||
|
||||
var _x = 123;
|
||||
|
||||
var myArray = ["value1"];
|
||||
|
||||
function returnThis() {
|
||||
return this;
|
||||
}
|
||||
|
||||
function getTypeOf(o) {
|
||||
return typeof(o);
|
||||
}
|
||||
|
||||
function Foo(a) {
|
||||
this.a = a;
|
||||
}
|
||||
|
||||
Foo.b = 38;
|
||||
|
||||
Foo.prototype.bar = function() {
|
||||
return this.a;
|
||||
}
|
||||
Foo.prototype.toString = function() {
|
||||
return "I'm a Foo a=" + this.a;
|
||||
}
|
||||
|
||||
var container = new Object();
|
||||
container.Foo = Foo;
|
||||
|
||||
function checkMap(m, key, value) {
|
||||
if (m.hasOwnProperty(key))
|
||||
return m[key] == value;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
""";
|
||||
document.body.append(script);
|
||||
}
|
||||
|
||||
@JS()
|
||||
external bool checkMap(m, String, value);
|
||||
|
||||
@JS('JSON.stringify')
|
||||
external String stringify(o);
|
||||
|
||||
@JS('Node')
|
||||
external get JSNodeType;
|
||||
|
||||
@JS('Element')
|
||||
external get JSElementType;
|
||||
|
||||
@JS('Text')
|
||||
external get JSTextType;
|
||||
|
||||
@JS('HTMLCanvasElement')
|
||||
external get JSHtmlCanvasElementType;
|
||||
|
||||
@JS()
|
||||
class Foo {
|
||||
external Foo(num a);
|
||||
|
||||
external num get a;
|
||||
external num bar();
|
||||
}
|
||||
|
||||
@JS('Foo')
|
||||
external get JSFooType;
|
||||
|
||||
@JS()
|
||||
@anonymous
|
||||
class ExampleTypedLiteral {
|
||||
external factory ExampleTypedLiteral({a, b, JS$_c, JS$class});
|
||||
|
||||
external get a;
|
||||
external get b;
|
||||
external get JS$_c;
|
||||
external set JS$_c(v);
|
||||
// Identical to JS$_c but only accessible within the library.
|
||||
external get _c;
|
||||
external get JS$class;
|
||||
external set JS$class(v);
|
||||
}
|
||||
|
||||
@JS("Object.prototype.hasOwnProperty")
|
||||
external get _hasOwnProperty;
|
||||
|
||||
bool hasOwnProperty(o, String name) {
|
||||
return js_util.callMethod(_hasOwnProperty, 'call', [o, name]);
|
||||
}
|
||||
|
||||
main() {
|
||||
_injectJs();
|
||||
useHtmlIndividualConfiguration();
|
||||
|
||||
group('js_util.jsify()', () {
|
||||
test('convert a List', () {
|
||||
final list = [1, 2, 3, 4, 5, 6, 7, 8];
|
||||
var array = js_util.jsify(list);
|
||||
expect(array is List, isTrue);
|
||||
expect(identical(array, list), isFalse);
|
||||
expect(array.length, equals(list.length));
|
||||
for (var i = 0; i < list.length; i++) {
|
||||
expect(array[i], equals(list[i]));
|
||||
}
|
||||
});
|
||||
|
||||
test('convert an Iterable', () {
|
||||
final set = new Set.from([1, 2, 3, 4, 5, 6, 7, 8]);
|
||||
var array = js_util.jsify(set);
|
||||
expect(array is List, isTrue);
|
||||
expect(array.length, equals(set.length));
|
||||
for (var i = 0; i < array.length; i++) {
|
||||
expect(set.contains(array[i]), isTrue);
|
||||
}
|
||||
});
|
||||
|
||||
test('convert a Map', () {
|
||||
var map = {'a': 1, 'b': 2, 'c': 3};
|
||||
var jsMap = js_util.jsify(map);
|
||||
expect(jsMap is! List, isTrue);
|
||||
for (var key in map.keys) {
|
||||
expect(checkMap(jsMap, key, map[key]), isTrue);
|
||||
}
|
||||
});
|
||||
|
||||
test('deep convert a complex object', () {
|
||||
final object = {
|
||||
'a': [
|
||||
1,
|
||||
[2, 3]
|
||||
],
|
||||
'b': {'c': 3, 'd': new Foo(42)},
|
||||
'e': null
|
||||
};
|
||||
var jsObject = js_util.jsify(object);
|
||||
expect(js_util.getProperty(jsObject, 'a')[0], equals(object['a'][0]));
|
||||
expect(
|
||||
js_util.getProperty(jsObject, 'a')[1][0], equals(object['a'][1][0]));
|
||||
expect(
|
||||
js_util.getProperty(jsObject, 'a')[1][1], equals(object['a'][1][1]));
|
||||
expect(js_util.getProperty(js_util.getProperty(jsObject, 'b'), 'c'),
|
||||
equals(object['b']['c']));
|
||||
expect(js_util.getProperty(js_util.getProperty(jsObject, 'b'), 'd'),
|
||||
equals(object['b']['d']));
|
||||
expect(
|
||||
js_util.callMethod(
|
||||
js_util.getProperty(js_util.getProperty(jsObject, 'b'), 'd'),
|
||||
'bar', []),
|
||||
equals(42));
|
||||
expect(js_util.getProperty(jsObject, 'e'), isNull);
|
||||
});
|
||||
|
||||
test('throws if object is not a Map or Iterable', () {
|
||||
expect(() => js_util.jsify('a'),
|
||||
throwsA(new isInstanceOf<ArgumentError>()));
|
||||
});
|
||||
});
|
||||
|
||||
group('js_util.newObject', () {
|
||||
test('create', () {
|
||||
expect(identical(js_util.newObject(), js_util.newObject()), isFalse);
|
||||
});
|
||||
|
||||
test('callMethod', () {
|
||||
var o = js_util.newObject();
|
||||
expect(js_util.callMethod(o, 'toString', []), equals('[object Object]'));
|
||||
expect(stringify(o), equals('{}'));
|
||||
});
|
||||
|
||||
test('properties', () {
|
||||
var o = js_util.newObject();
|
||||
expect(js_util.hasProperty(o, 'foo bar'), isFalse);
|
||||
expect(js_util.hasProperty(o, 'toString'), isTrue);
|
||||
expect(hasOwnProperty(o, 'toString'), isFalse);
|
||||
expect(hasOwnProperty(o, 'foo bar'), isFalse);
|
||||
js_util.setProperty(o, 'foo bar', 42);
|
||||
expect(hasOwnProperty(o, 'foo bar'), isTrue);
|
||||
expect(js_util.getProperty(o, 'foo bar'), equals(42));
|
||||
expect(js_util.hasProperty(o, 'foo bar'), isTrue);
|
||||
expect(stringify(o), equals('{"foo bar":42}'));
|
||||
});
|
||||
});
|
||||
|
||||
group('hasProperty', () {
|
||||
test('typed object', () {
|
||||
var f = new Foo(42);
|
||||
expect(js_util.hasProperty(f, 'a'), isTrue);
|
||||
expect(js_util.hasProperty(f, 'toString'), isTrue);
|
||||
js_util.setProperty(f, '__proto__', null);
|
||||
expect(js_util.hasProperty(f, 'toString'), isFalse);
|
||||
});
|
||||
test('typed literal', () {
|
||||
var l =
|
||||
new ExampleTypedLiteral(a: 'x', b: 42, JS$_c: null, JS$class: true);
|
||||
expect(js_util.hasProperty(l, 'a'), isTrue);
|
||||
expect(js_util.hasProperty(l, 'b'), isTrue);
|
||||
expect(js_util.hasProperty(l, '_c'), isTrue);
|
||||
expect(l.JS$_c, isNull);
|
||||
expect(js_util.hasProperty(l, 'class'), isTrue);
|
||||
// JS$_c escapes to _c so the property JS$_c will not exist on the object.
|
||||
expect(js_util.hasProperty(l, r'JS$_c'), isFalse);
|
||||
expect(js_util.hasProperty(l, r'JS$class'), isFalse);
|
||||
expect(l.JS$class, isTrue);
|
||||
|
||||
l = new ExampleTypedLiteral(a: null);
|
||||
expect(js_util.hasProperty(l, 'a'), isTrue);
|
||||
expect(js_util.hasProperty(l, 'b'), isFalse);
|
||||
expect(js_util.hasProperty(l, '_c'), isFalse);
|
||||
expect(js_util.hasProperty(l, 'class'), isFalse);
|
||||
|
||||
l = new ExampleTypedLiteral(JS$_c: 74);
|
||||
expect(js_util.hasProperty(l, '_c'), isTrue);
|
||||
expect(l.JS$_c, equals(74));
|
||||
});
|
||||
});
|
||||
|
||||
group('getProperty', () {
|
||||
test('typed object', () {
|
||||
var f = new Foo(42);
|
||||
expect(js_util.getProperty(f, 'a'), equals(42));
|
||||
expect(js_util.getProperty(f, 'toString') is Function, isTrue);
|
||||
js_util.setProperty(f, '__proto__', null);
|
||||
expect(js_util.getProperty(f, 'toString'), isNull);
|
||||
});
|
||||
|
||||
test('typed literal', () {
|
||||
var l = new ExampleTypedLiteral(a: 'x', b: 42, JS$_c: 7, JS$class: true);
|
||||
expect(js_util.getProperty(l, 'a'), equals('x'));
|
||||
expect(js_util.getProperty(l, 'b'), equals(42));
|
||||
expect(js_util.getProperty(l, '_c'), equals(7));
|
||||
expect(l.JS$_c, equals(7));
|
||||
expect(js_util.getProperty(l, 'class'), isTrue);
|
||||
expect(js_util.getProperty(l, r'JS$_c'), isNull);
|
||||
expect(js_util.getProperty(l, r'JS$class'), isNull);
|
||||
});
|
||||
});
|
||||
|
||||
group('setProperty', () {
|
||||
test('typed object', () {
|
||||
var f = new Foo(42);
|
||||
expect(js_util.getProperty(f, 'a'), equals(42));
|
||||
js_util.setProperty(f, 'a', 100);
|
||||
expect(f.a, equals(100));
|
||||
expect(js_util.getProperty(f, 'a'), equals(100));
|
||||
});
|
||||
|
||||
test('typed literal', () {
|
||||
var l = new ExampleTypedLiteral();
|
||||
js_util.setProperty(l, 'a', 'foo');
|
||||
expect(js_util.getProperty(l, 'a'), equals('foo'));
|
||||
expect(l.a, equals('foo'));
|
||||
js_util.setProperty(l, 'a', l);
|
||||
expect(identical(l.a, l), isTrue);
|
||||
var list = ['arr'];
|
||||
js_util.setProperty(l, 'a', list);
|
||||
expect(identical(l.a, list), isTrue);
|
||||
l.JS$class = 42;
|
||||
expect(l.JS$class, equals(42));
|
||||
js_util.setProperty(l, 'class', 100);
|
||||
expect(l.JS$class, equals(100));
|
||||
});
|
||||
});
|
||||
|
||||
group('callMethod', () {
|
||||
test('html object', () {
|
||||
var canvas = new Element.tag('canvas');
|
||||
expect(
|
||||
identical(canvas.getContext('2d'),
|
||||
js_util.callMethod(canvas, 'getContext', ['2d'])),
|
||||
isTrue);
|
||||
});
|
||||
|
||||
test('typed object', () {
|
||||
var f = new Foo(42);
|
||||
expect(js_util.callMethod(f, 'bar', []), equals(42));
|
||||
});
|
||||
});
|
||||
|
||||
group('instanceof', () {
|
||||
test('html object', () {
|
||||
var canvas = new Element.tag('canvas');
|
||||
expect(js_util.instanceof(canvas, JSNodeType), isTrue);
|
||||
expect(js_util.instanceof(canvas, JSTextType), isFalse);
|
||||
expect(js_util.instanceof(canvas, JSElementType), isTrue);
|
||||
expect(js_util.instanceof(canvas, JSHtmlCanvasElementType), isTrue);
|
||||
var div = new Element.tag('div');
|
||||
expect(js_util.instanceof(div, JSNodeType), isTrue);
|
||||
expect(js_util.instanceof(div, JSTextType), isFalse);
|
||||
expect(js_util.instanceof(div, JSElementType), isTrue);
|
||||
expect(js_util.instanceof(div, JSHtmlCanvasElementType), isFalse);
|
||||
|
||||
var text = new Text('foo');
|
||||
expect(js_util.instanceof(text, JSNodeType), isTrue);
|
||||
expect(js_util.instanceof(text, JSTextType), isTrue);
|
||||
expect(js_util.instanceof(text, JSElementType), isFalse);
|
||||
});
|
||||
|
||||
test('typed object', () {
|
||||
var f = new Foo(42);
|
||||
expect(js_util.instanceof(f, JSFooType), isTrue);
|
||||
expect(js_util.instanceof(f, JSNodeType), isFalse);
|
||||
});
|
||||
|
||||
test('typed literal', () {
|
||||
var l = new ExampleTypedLiteral();
|
||||
expect(js_util.instanceof(l, JSFooType), isFalse);
|
||||
});
|
||||
});
|
||||
|
||||
group('callConstructor', () {
|
||||
test('html object', () {
|
||||
var textNode = js_util.callConstructor(JSTextType, ['foo']);
|
||||
expect(js_util.instanceof(textNode, JSTextType), isTrue);
|
||||
expect(textNode is Text, isTrue);
|
||||
expect(textNode.text, equals('foo'));
|
||||
});
|
||||
|
||||
test('typed object', () {
|
||||
Foo f = js_util.callConstructor(JSFooType, [42]);
|
||||
expect(f.a, equals(42));
|
||||
});
|
||||
});
|
||||
}
|
|
@ -37,6 +37,7 @@ main(List<String> arguments) {
|
|||
'dart:core',
|
||||
'dart:isolate',
|
||||
'dart:js',
|
||||
'dart:js_util',
|
||||
'dart:math',
|
||||
'dart:mirrors',
|
||||
'dart:typed_data',
|
||||
|
|
|
@ -76,6 +76,12 @@ const Map<String, LibraryInfo> LIBRARIES = const {
|
|||
maturity: Maturity.STABLE,
|
||||
dart2jsPath: "js/dart2js/js_dart2js.dart"),
|
||||
|
||||
"js_util": const LibraryInfo(
|
||||
"js_util/dartium/js_util_dartium.dart",
|
||||
categories: "Client",
|
||||
maturity: Maturity.STABLE,
|
||||
dart2jsPath: "js_util/dart2js/js_util_dart2js.dart"),
|
||||
|
||||
"math": const LibraryInfo(
|
||||
"math/math.dart",
|
||||
maturity: Maturity.STABLE,
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
// Copyright (c) 2016, 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.
|
||||
|
||||
/// Utility methods to efficiently manipulate typed JSInterop objects in cases
|
||||
/// where the name to call is not known at runtime. You should only use these
|
||||
/// methods when the same effect cannot be achieved with @JS annotations.
|
||||
/// These methods would be extension methods on JSObject if Dart supported
|
||||
/// extension methods.
|
||||
library dart.js_util;
|
||||
|
||||
import 'dart:_foreign_helper' show JS;
|
||||
import 'dart:collection' show HashMap;
|
||||
|
||||
/// WARNING: performance of this method is much worse than other uitil
|
||||
/// methods in this library. Only use this method as a last resort.
|
||||
///
|
||||
/// Recursively converts a JSON-like collection of Dart objects to a
|
||||
/// collection of JavaScript objects and returns a [JsObject] proxy to it.
|
||||
///
|
||||
/// [object] must be a [Map] or [Iterable], the contents of which are also
|
||||
/// converted. Maps and Iterables are copied to a new JavaScript object.
|
||||
/// Primitives and other transferrable values are directly converted to their
|
||||
/// JavaScript type, and all other objects are proxied.
|
||||
jsify(object) {
|
||||
if ((object is! Map) && (object is! Iterable)) {
|
||||
throw new ArgumentError("object must be a Map or Iterable");
|
||||
}
|
||||
return _convertDataTree(object);
|
||||
}
|
||||
|
||||
_convertDataTree(data) {
|
||||
var _convertedObjects = new HashMap.identity();
|
||||
|
||||
_convert(o) {
|
||||
if (_convertedObjects.containsKey(o)) {
|
||||
return _convertedObjects[o];
|
||||
}
|
||||
if (o is Map) {
|
||||
final convertedMap = JS('=Object', '{}');
|
||||
_convertedObjects[o] = convertedMap;
|
||||
for (var key in o.keys) {
|
||||
JS('=Object', '#[#]=#', convertedMap, key, _convert(o[key]));
|
||||
}
|
||||
return convertedMap;
|
||||
} else if (o is Iterable) {
|
||||
var convertedList = [];
|
||||
_convertedObjects[o] = convertedList;
|
||||
convertedList.addAll(o.map(_convert));
|
||||
return convertedList;
|
||||
} else {
|
||||
return o;
|
||||
}
|
||||
}
|
||||
|
||||
return _convert(data);
|
||||
}
|
||||
|
||||
newObject() => JS('=Object', '{}');
|
||||
|
||||
hasProperty(o, name) => JS('bool', '# in #', name, o);
|
||||
getProperty(o, name) => JS('Object', '#[#]', o, name);
|
||||
setProperty(o, name, value) => JS('', '#[#]=#', o, name, value);
|
||||
|
||||
callMethod(o, String method, List args) =>
|
||||
JS('Object', '#[#].apply(#, #)', o, method, o, args);
|
||||
|
||||
instanceof(o, Function type) => JS('bool', '# instanceof #', o, type);
|
||||
callConstructor(Function constr, List arguments) {
|
||||
if (arguments == null) {
|
||||
return JS('Object', 'new #()', constr);
|
||||
}
|
||||
|
||||
if (JS('bool', '# instanceof Array', arguments)) {
|
||||
int argumentCount = JS('int', '#.length', arguments);
|
||||
switch (argumentCount) {
|
||||
case 0:
|
||||
return JS('Object', 'new #()', constr);
|
||||
|
||||
case 1:
|
||||
var arg0 = JS('', '#[0]', arguments);
|
||||
return JS('Object', 'new #(#)', constr, arg0);
|
||||
|
||||
case 2:
|
||||
var arg0 = JS('', '#[0]', arguments);
|
||||
var arg1 = JS('', '#[1]', arguments);
|
||||
return JS('Object', 'new #(#, #)', constr, arg0, arg1);
|
||||
|
||||
case 3:
|
||||
var arg0 = JS('', '#[0]', arguments);
|
||||
var arg1 = JS('', '#[1]', arguments);
|
||||
var arg2 = JS('', '#[2]', arguments);
|
||||
return JS('Object', 'new #(#, #, #)', constr, arg0, arg1, arg2);
|
||||
|
||||
case 4:
|
||||
var arg0 = JS('', '#[0]', arguments);
|
||||
var arg1 = JS('', '#[1]', arguments);
|
||||
var arg2 = JS('', '#[2]', arguments);
|
||||
var arg3 = JS('', '#[3]', arguments);
|
||||
return JS(
|
||||
'Object', 'new #(#, #, #, #)', constr, arg0, arg1, arg2, arg3);
|
||||
}
|
||||
}
|
||||
|
||||
// The following code solves the problem of invoking a JavaScript
|
||||
// constructor with an unknown number arguments.
|
||||
// First bind the constructor to the argument list using bind.apply().
|
||||
// The first argument to bind() is the binding of 't', so add 'null' to
|
||||
// the arguments list passed to apply().
|
||||
// After that, use the JavaScript 'new' operator which overrides any binding
|
||||
// of 'this' with the new instance.
|
||||
var args = [null]..addAll(arguments);
|
||||
var factoryFunction = JS('', '#.bind.apply(#, #)', constr, constr, args);
|
||||
// Without this line, calling factoryFunction as a constructor throws
|
||||
JS('String', 'String(#)', factoryFunction);
|
||||
// This could return an UnknownJavaScriptObject, or a native
|
||||
// object for which there is an interceptor
|
||||
return JS('Object', 'new #()', factoryFunction);
|
||||
|
||||
// TODO(sra): Investigate:
|
||||
//
|
||||
// var jsObj = JS('', 'Object.create(#.prototype)', constr);
|
||||
// JS('', '#.apply(#, #)', constr, jsObj,
|
||||
// []..addAll(arguments.map(_convertToJS)));
|
||||
// return _wrapToDart(jsObj);
|
||||
}
|
Loading…
Reference in a new issue