mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 09:22:12 +00:00
Refactored html/js_util_test.dart and added more js_util test coverage.
Split out async, jsify, and html tests. Also split JS$ prefix test and skipped by design for ddc which doesn't support the prefix. Change-Id: I85c673d791731bbae3ff4015a7e134d9180170de Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/185281 Commit-Queue: Riley Porter <rileyporter@google.com> Reviewed-by: Sigmund Cherem <sigmund@google.com> Reviewed-by: Srujan Gaddam <srujzs@google.com>
This commit is contained in:
parent
5036e3ad2c
commit
3c02a9f1b2
|
@ -2,75 +2,19 @@
|
|||
// 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;
|
||||
// Tests the functionality of js_util with HTML objects.
|
||||
|
||||
@JS()
|
||||
library js_util_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:expect/minitest.dart';
|
||||
import 'package:async_helper/async_helper.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;
|
||||
}
|
||||
|
||||
var rejectedPromise = new Promise((resolve, reject) => reject('rejected'));
|
||||
var resolvedPromise = new Promise(resolve => resolve('resolved'));
|
||||
function getResolvedPromise() {
|
||||
return resolvedPromise;
|
||||
}
|
||||
|
||||
""";
|
||||
document.body!.append(script);
|
||||
}
|
||||
|
||||
@JS()
|
||||
external bool checkMap(m, String, value);
|
||||
|
||||
@JS('JSON.stringify')
|
||||
external String stringify(o);
|
||||
external void eval(String code);
|
||||
|
||||
@JS('Node')
|
||||
external get JSNodeType;
|
||||
|
@ -86,302 +30,61 @@ 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()
|
||||
abstract class Promise<T> {}
|
||||
|
||||
@JS()
|
||||
external Promise get resolvedPromise;
|
||||
|
||||
@JS()
|
||||
external Promise get rejectedPromise;
|
||||
|
||||
@JS()
|
||||
external Promise getResolvedPromise();
|
||||
|
||||
@JS("Object.prototype.hasOwnProperty")
|
||||
external get _hasOwnProperty;
|
||||
|
||||
bool hasOwnProperty(o, String name) {
|
||||
return js_util.callMethod(_hasOwnProperty, 'call', [o, name]);
|
||||
external Foo();
|
||||
}
|
||||
|
||||
main() {
|
||||
_injectJs();
|
||||
eval(r""" function Foo() {} """);
|
||||
|
||||
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', () {
|
||||
dynamic 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'), throwsArgumentError);
|
||||
});
|
||||
test('hasProperty', () {
|
||||
var textElement = new Text('foo');
|
||||
expect(js_util.hasProperty(textElement, 'data'), isTrue);
|
||||
});
|
||||
|
||||
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}'));
|
||||
});
|
||||
test('getProperty', () {
|
||||
var textElement = new Text('foo');
|
||||
expect(js_util.getProperty(textElement, 'data'), equals('foo'));
|
||||
});
|
||||
|
||||
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));
|
||||
});
|
||||
test('setProperty', () {
|
||||
var textElement = new Text('foo');
|
||||
js_util.setProperty(textElement, 'data', 'bar');
|
||||
expect(textElement.text, equals('bar'));
|
||||
});
|
||||
|
||||
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);
|
||||
});
|
||||
test('callMethod', () {
|
||||
var canvas = new CanvasElement();
|
||||
expect(
|
||||
identical(canvas.getContext('2d'),
|
||||
js_util.callMethod(canvas, 'getContext', ['2d'])),
|
||||
isTrue);
|
||||
});
|
||||
|
||||
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('instanceof', () {
|
||||
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);
|
||||
|
||||
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));
|
||||
});
|
||||
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);
|
||||
|
||||
var f = new Foo();
|
||||
expect(js_util.instanceof(f, JSNodeType), isFalse);
|
||||
});
|
||||
|
||||
group('callMethod', () {
|
||||
test('html object', () {
|
||||
var canvas = new CanvasElement();
|
||||
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));
|
||||
});
|
||||
});
|
||||
|
||||
Future<void> testResolvedPromise() async {
|
||||
final String result = await js_util.promiseToFuture(resolvedPromise);
|
||||
expect(result, equals('resolved'));
|
||||
}
|
||||
|
||||
Future<void> testRejectedPromise() async {
|
||||
try {
|
||||
final String result = await promiseToFuture(rejectedPromise);
|
||||
fail('expected Future to throw an error');
|
||||
} catch (error) {
|
||||
expect(error, equals('rejected'));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> testReturnRejectedPromise() async {
|
||||
final String result = await promiseToFuture(getResolvedPromise());
|
||||
expect(result, equals('resolved'));
|
||||
}
|
||||
|
||||
asyncTest(() async {
|
||||
await testResolvedPromise();
|
||||
await testRejectedPromise();
|
||||
await testReturnRejectedPromise();
|
||||
test('callConstructor', () {
|
||||
var textNode = js_util.callConstructor(JSTextType, ['foo']);
|
||||
expect(js_util.instanceof(textNode, JSTextType), isTrue);
|
||||
expect(textNode is Text, isTrue);
|
||||
expect(textNode.text, equals('foo'));
|
||||
});
|
||||
}
|
||||
|
|
59
tests/lib/js/js_util/async_test.dart
Normal file
59
tests/lib/js/js_util/async_test.dart
Normal file
|
@ -0,0 +1,59 @@
|
|||
// Copyright (c) 2021, 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_util_async_test;
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:js/js.dart';
|
||||
import 'package:js/js_util.dart' as js_util;
|
||||
import 'package:expect/minitest.dart';
|
||||
import 'package:async_helper/async_helper.dart';
|
||||
|
||||
@JS()
|
||||
external void eval(String code);
|
||||
|
||||
@JS()
|
||||
abstract class Promise<T> {}
|
||||
|
||||
@JS()
|
||||
external Promise get resolvedPromise;
|
||||
|
||||
@JS()
|
||||
external Promise get rejectedPromise;
|
||||
|
||||
@JS()
|
||||
external Promise getResolvedPromise();
|
||||
|
||||
main() {
|
||||
eval(r"""
|
||||
var rejectedPromise = new Promise((resolve, reject) => reject('rejected'));
|
||||
var resolvedPromise = new Promise(resolve => resolve('resolved'));
|
||||
function getResolvedPromise() {
|
||||
return resolvedPromise;
|
||||
}
|
||||
""");
|
||||
|
||||
Future<void> testResolvedPromise() async {
|
||||
final String result = await js_util.promiseToFuture(resolvedPromise);
|
||||
expect(result, equals('resolved'));
|
||||
}
|
||||
|
||||
Future<void> testRejectedPromise() async {
|
||||
asyncExpectThrows<String>(() => js_util.promiseToFuture(rejectedPromise),
|
||||
(String error) => error == 'rejected');
|
||||
}
|
||||
|
||||
Future<void> testReturnResolvedPromise() async {
|
||||
final String result = await js_util.promiseToFuture(getResolvedPromise());
|
||||
expect(result, equals('resolved'));
|
||||
}
|
||||
|
||||
asyncTest(() async {
|
||||
await testResolvedPromise();
|
||||
await testRejectedPromise();
|
||||
await testReturnResolvedPromise();
|
||||
});
|
||||
}
|
64
tests/lib/js/js_util/js_prefix_test.dart
Normal file
64
tests/lib/js/js_util/js_prefix_test.dart
Normal file
|
@ -0,0 +1,64 @@
|
|||
// Copyright (c) 2021, 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.
|
||||
|
||||
// Tests the functionality of the JS$ prefix for escaping keywords in JS names.
|
||||
// Currently only implemented in dart2js, expected to fail in ddc.
|
||||
|
||||
@JS()
|
||||
library js_prefix_test;
|
||||
|
||||
import 'package:js/js.dart';
|
||||
import 'package:js/js_util.dart' as js_util;
|
||||
import 'package:expect/minitest.dart';
|
||||
|
||||
@JS()
|
||||
@anonymous
|
||||
class ExampleTypedLiteral {
|
||||
external factory ExampleTypedLiteral({JS$_c, JS$class});
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
main() {
|
||||
test('hasProperty', () {
|
||||
var literal = new ExampleTypedLiteral(JS$_c: null, JS$class: true);
|
||||
expect(js_util.hasProperty(literal, '_c'), isTrue);
|
||||
expect(literal.JS$_c, isNull);
|
||||
expect(js_util.hasProperty(literal, 'class'), isTrue);
|
||||
// JS$_c escapes to _c so the property JS$_c will not exist on the object.
|
||||
expect(js_util.hasProperty(literal, r'JS$_c'), isFalse);
|
||||
expect(js_util.hasProperty(literal, r'JS$class'), isFalse);
|
||||
expect(literal.JS$class, isTrue);
|
||||
|
||||
literal = new ExampleTypedLiteral();
|
||||
expect(js_util.hasProperty(literal, '_c'), isFalse);
|
||||
expect(js_util.hasProperty(literal, 'class'), isFalse);
|
||||
|
||||
literal = new ExampleTypedLiteral(JS$_c: 74);
|
||||
expect(js_util.hasProperty(literal, '_c'), isTrue);
|
||||
expect(literal.JS$_c, equals(74));
|
||||
});
|
||||
|
||||
test('getProperty', () {
|
||||
var literal = new ExampleTypedLiteral(JS$_c: 7, JS$class: true);
|
||||
expect(js_util.getProperty(literal, '_c'), equals(7));
|
||||
expect(literal.JS$_c, equals(7));
|
||||
expect(js_util.getProperty(literal, 'class'), isTrue);
|
||||
expect(js_util.getProperty(literal, r'JS$_c'), isNull);
|
||||
expect(js_util.getProperty(literal, r'JS$class'), isNull);
|
||||
});
|
||||
|
||||
test('setProperty', () {
|
||||
var literal = new ExampleTypedLiteral();
|
||||
literal.JS$class = 42;
|
||||
expect(literal.JS$class, equals(42));
|
||||
js_util.setProperty(literal, 'class', 100);
|
||||
expect(literal.JS$class, equals(100));
|
||||
});
|
||||
}
|
104
tests/lib/js/js_util/jsify_test.dart
Normal file
104
tests/lib/js/js_util/jsify_test.dart
Normal file
|
@ -0,0 +1,104 @@
|
|||
// Copyright (c) 2021, 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.
|
||||
|
||||
// Tests the jsify functionality of the js_util library.
|
||||
|
||||
@JS()
|
||||
library js_util_jsify_test;
|
||||
|
||||
import 'package:js/js.dart';
|
||||
import 'package:js/js_util.dart' as js_util;
|
||||
import 'package:expect/minitest.dart';
|
||||
|
||||
@JS()
|
||||
external void eval(String code);
|
||||
|
||||
@JS()
|
||||
external bool checkMap(m, String, value);
|
||||
|
||||
@JS()
|
||||
class Foo {
|
||||
external Foo(num a);
|
||||
|
||||
external num get a;
|
||||
external num bar();
|
||||
}
|
||||
|
||||
main() {
|
||||
eval(r"""
|
||||
function Foo(a) {
|
||||
this.a = a;
|
||||
}
|
||||
|
||||
Foo.prototype.bar = function() {
|
||||
return this.a;
|
||||
}
|
||||
|
||||
function checkMap(m, key, value) {
|
||||
if (m.hasOwnProperty(key))
|
||||
return m[key] == value;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
""");
|
||||
|
||||
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, isFalse);
|
||||
expect(jsMap is Map, isFalse);
|
||||
for (var key in map.keys) {
|
||||
expect(checkMap(jsMap, key, map[key]), isTrue);
|
||||
}
|
||||
});
|
||||
|
||||
test('deep convert a complex object', () {
|
||||
dynamic 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]));
|
||||
|
||||
var b = js_util.getProperty(jsObject, 'b');
|
||||
expect(js_util.getProperty(b, 'c'), equals(object['b']['c']));
|
||||
var d = js_util.getProperty(b, 'd');
|
||||
expect(d, equals(object['b']['d']));
|
||||
expect(js_util.getProperty(d, 'a'), equals(42));
|
||||
expect(js_util.callMethod(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'), throwsArgumentError);
|
||||
});
|
||||
}
|
368
tests/lib/js/js_util/properties_test.dart
Normal file
368
tests/lib/js/js_util/properties_test.dart
Normal file
|
@ -0,0 +1,368 @@
|
|||
// Copyright (c) 2021, 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.
|
||||
|
||||
// Tests the functionality of object properties with the js_util library. For
|
||||
// js_util tests with HTML objects see tests/lib/html/js_util_test.dart.
|
||||
|
||||
@JS()
|
||||
library js_util_properties_test;
|
||||
|
||||
import 'package:js/js.dart';
|
||||
import 'package:js/js_util.dart' as js_util;
|
||||
import 'package:expect/minitest.dart';
|
||||
|
||||
@JS()
|
||||
external String jsFunction();
|
||||
|
||||
@JS()
|
||||
external void eval(String code);
|
||||
|
||||
@JS('JSON.stringify')
|
||||
external String stringify(o);
|
||||
|
||||
@JS('ArrayBuffer')
|
||||
external get JSArrayBufferType;
|
||||
|
||||
@JS()
|
||||
class Foo {
|
||||
external Foo(num a);
|
||||
|
||||
external num get a;
|
||||
external num bar();
|
||||
external Object get objectProperty;
|
||||
}
|
||||
|
||||
@JS('Foo')
|
||||
external get JSFooType;
|
||||
|
||||
String dartFunction() {
|
||||
return 'Dart Function';
|
||||
}
|
||||
|
||||
@JS()
|
||||
@anonymous
|
||||
class ExampleTypedLiteral {
|
||||
external factory ExampleTypedLiteral({a, b});
|
||||
|
||||
external get a;
|
||||
external get b;
|
||||
}
|
||||
|
||||
String _getBarWithSideEffect() {
|
||||
var x = 5;
|
||||
expect(x, equals(5));
|
||||
return 'bar';
|
||||
}
|
||||
|
||||
main() {
|
||||
eval(r"""
|
||||
function Foo(a) {
|
||||
this.a = a;
|
||||
}
|
||||
|
||||
Foo.b = 38;
|
||||
|
||||
Foo.prototype.list = [2, 4, 6];
|
||||
|
||||
Foo.prototype.bar = function() {
|
||||
return this.a;
|
||||
}
|
||||
|
||||
Foo.prototype.toString = function() {
|
||||
return "I'm a Foo a=" + this.a;
|
||||
}
|
||||
|
||||
Foo.prototype.fnList = [Foo.prototype.bar, Foo.prototype.toString];
|
||||
|
||||
Foo.prototype.objectProperty = {
|
||||
'c': 1,
|
||||
'list': [10, 20, 30],
|
||||
'functionProperty': function() { return 'Function Property'; }
|
||||
}
|
||||
|
||||
function jsFunction() {
|
||||
return "JS Function";
|
||||
}
|
||||
|
||||
Foo.prototype.nestedFunction = function() {
|
||||
return function() {
|
||||
return 'Nested Function';
|
||||
};
|
||||
}
|
||||
|
||||
Foo.prototype.getFirstEl = function(list) {
|
||||
return list[0];
|
||||
}
|
||||
|
||||
Foo.prototype.sumFn = function(a, b) {
|
||||
return a + b;
|
||||
}
|
||||
|
||||
Foo.prototype.getA = function(obj) {
|
||||
return obj.a;
|
||||
}
|
||||
|
||||
Foo.prototype.callFn = function(fn) {
|
||||
return fn();
|
||||
}
|
||||
""");
|
||||
|
||||
group('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(js_util.callMethod(o, 'hasOwnProperty', ['toString']), isFalse);
|
||||
expect(js_util.callMethod(o, 'hasOwnProperty', ['foo bar']), isFalse);
|
||||
js_util.setProperty(o, 'foo bar', 42);
|
||||
expect(js_util.callMethod(o, 'hasOwnProperty', ['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}'));
|
||||
});
|
||||
|
||||
test('nested properties calls', () {
|
||||
var o = js_util.newObject();
|
||||
var f = new Foo(42);
|
||||
js_util.setProperty(o, 'foo', f);
|
||||
var foo = js_util.getProperty(o, 'foo');
|
||||
expect(foo, equals(f));
|
||||
expect(js_util.hasProperty(foo, 'a'), isTrue);
|
||||
expect(js_util.getProperty(foo, 'a'), equals(42));
|
||||
js_util.setProperty(foo, 'a', 24);
|
||||
expect(js_util.getProperty(foo, 'a'), equals(24));
|
||||
});
|
||||
});
|
||||
|
||||
group('hasProperty', () {
|
||||
test('typed object', () {
|
||||
var f = new Foo(42);
|
||||
expect(js_util.hasProperty(f, 'a'), isTrue);
|
||||
expect(js_util.hasProperty(f, 'bar'), isTrue);
|
||||
expect(js_util.hasProperty(f, 'b'), isFalse);
|
||||
expect(js_util.hasProperty(f, 'toString'), isTrue);
|
||||
js_util.setProperty(f, '__proto__', null);
|
||||
expect(js_util.hasProperty(f, 'toString'), isFalse);
|
||||
});
|
||||
|
||||
test('typed literal', () {
|
||||
var literal = new ExampleTypedLiteral(a: 'x', b: 42);
|
||||
expect(js_util.hasProperty(literal, 'a'), isTrue);
|
||||
expect(js_util.hasProperty(literal, 'b'), isTrue);
|
||||
expect(js_util.hasProperty(literal, 'anything'), isFalse);
|
||||
|
||||
literal = new ExampleTypedLiteral(a: null);
|
||||
expect(js_util.hasProperty(literal, 'a'), isTrue);
|
||||
expect(js_util.hasProperty(literal, 'b'), isFalse);
|
||||
expect(js_util.hasProperty(literal, 'anything'), isFalse);
|
||||
});
|
||||
|
||||
test('complex hasProperty calls', () {
|
||||
var f = new Foo(42);
|
||||
expect(js_util.hasProperty(f.objectProperty, 'c'), isTrue);
|
||||
expect(js_util.hasProperty(f.objectProperty, 'nonexistent'), isFalse);
|
||||
|
||||
// Using a variable for the property name.
|
||||
String propertyName = 'bar';
|
||||
expect(js_util.hasProperty(f, propertyName), isTrue);
|
||||
});
|
||||
});
|
||||
|
||||
group('getProperty', () {
|
||||
test('typed object', () {
|
||||
var f = new Foo(42);
|
||||
expect(js_util.getProperty(f, 'a'), equals(42));
|
||||
expect(js_util.getProperty(f, 'b'), isNull);
|
||||
expect(js_util.getProperty(f, 'bar') is Function, isTrue);
|
||||
expect(js_util.getProperty(f, 'list') is List, isTrue);
|
||||
expect(js_util.getProperty(f, 'objectProperty') is Object, isTrue);
|
||||
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 literal = new ExampleTypedLiteral(a: 'x', b: 42);
|
||||
expect(js_util.getProperty(literal, 'a'), equals('x'));
|
||||
expect(js_util.getProperty(literal, 'b'), equals(42));
|
||||
expect(js_util.getProperty(literal, 'anything'), isNull);
|
||||
});
|
||||
|
||||
test('complex getProperty calls', () {
|
||||
var f = new Foo(42);
|
||||
|
||||
// Accessing a method property.
|
||||
expect(js_util.getProperty(f, 'bar') is Function, isTrue);
|
||||
expect(js_util.callMethod(f, 'bar', []), equals(42));
|
||||
|
||||
// Accessing list properties.
|
||||
expect(js_util.getProperty(f, 'list')[0], equals(2));
|
||||
expect(js_util.getProperty(f, 'fnList')[0] is Function, isTrue);
|
||||
expect(
|
||||
js_util.callMethod(
|
||||
js_util.getProperty(f, 'fnList')[0], 'apply', [f, []]),
|
||||
equals(42));
|
||||
|
||||
// Accessing nested object properites.
|
||||
var objectProperty = js_util.getProperty(f, 'objectProperty');
|
||||
expect(js_util.getProperty(objectProperty, 'c'), equals(1));
|
||||
expect(js_util.getProperty(objectProperty, 'list') is List, isTrue);
|
||||
expect(js_util.getProperty(objectProperty, 'list')[1], equals(20));
|
||||
expect(
|
||||
js_util.getProperty(objectProperty, 'functionProperty') is Function,
|
||||
isTrue);
|
||||
|
||||
// Using a variable for the property name.
|
||||
String propertyName = 'a';
|
||||
expect(js_util.getProperty(f, propertyName), equals(42));
|
||||
String bar = _getBarWithSideEffect();
|
||||
expect(js_util.getProperty(f, bar) is Function, isTrue);
|
||||
expect(js_util.callMethod(f, bar, []), equals(42));
|
||||
});
|
||||
});
|
||||
|
||||
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));
|
||||
|
||||
expect(js_util.getProperty(f, 'list') is List, isTrue);
|
||||
js_util.setProperty(f, 'list', [8]);
|
||||
expect(js_util.getProperty(f, 'list') is List, isTrue);
|
||||
expect(js_util.getProperty(f, 'list')[0], equals(8));
|
||||
|
||||
js_util.setProperty(f, 'newProperty', 'new');
|
||||
expect(js_util.getProperty(f, 'newProperty'), equals('new'));
|
||||
});
|
||||
|
||||
test('typed literal', () {
|
||||
var literal = new ExampleTypedLiteral();
|
||||
js_util.setProperty(literal, 'a', 'foo');
|
||||
expect(js_util.getProperty(literal, 'a'), equals('foo'));
|
||||
expect(literal.a, equals('foo'));
|
||||
js_util.setProperty(literal, 'a', literal);
|
||||
expect(identical(literal.a, literal), isTrue);
|
||||
var list = ['arr'];
|
||||
js_util.setProperty(literal, 'a', list);
|
||||
expect(identical(literal.a, list), isTrue);
|
||||
});
|
||||
|
||||
test('complex setProperty calls', () {
|
||||
var f = new Foo(42);
|
||||
|
||||
// Set function property to a num.
|
||||
expect(js_util.getProperty(f, 'bar') is Function, isTrue);
|
||||
js_util.setProperty(f, 'bar', 5);
|
||||
expect(js_util.getProperty(f, 'bar') is Function, isFalse);
|
||||
expect(js_util.getProperty(f, 'bar'), equals(5));
|
||||
|
||||
// Set property to a Dart function.
|
||||
js_util.setProperty(f, 'bar', allowInterop(dartFunction));
|
||||
expect(js_util.getProperty(f, 'bar') is Function, isTrue);
|
||||
expect(js_util.callMethod(f, 'bar', []), equals('Dart Function'));
|
||||
js_util.setProperty(f, 'bar', allowInterop(() {
|
||||
return 'Inline';
|
||||
}));
|
||||
expect(js_util.callMethod(f, 'bar', []), equals('Inline'));
|
||||
|
||||
// Set property to a JS function.
|
||||
js_util.setProperty(f, 'bar', allowInterop(jsFunction));
|
||||
expect(js_util.getProperty(f, 'bar') is Function, isTrue);
|
||||
expect(js_util.callMethod(f, 'bar', []), equals('JS Function'));
|
||||
|
||||
// Set property with nested object properties.
|
||||
js_util.setProperty(f.objectProperty, 'c', 'new val');
|
||||
expect(js_util.getProperty(f.objectProperty, 'c'), equals('new val'));
|
||||
js_util.setProperty(f.objectProperty, 'list', [1, 2, 3]);
|
||||
expect(js_util.getProperty(f.objectProperty, 'list')[1], equals(2));
|
||||
|
||||
// Using a variable for the property name.
|
||||
String propertyName = 'bar';
|
||||
js_util.setProperty(f, propertyName, 'foo');
|
||||
expect(js_util.getProperty(f, 'bar'), equals('foo'));
|
||||
String bar = _getBarWithSideEffect();
|
||||
js_util.setProperty(f, bar, 'baz');
|
||||
expect(js_util.getProperty(f, bar), equals('baz'));
|
||||
});
|
||||
});
|
||||
|
||||
group('callMethod', () {
|
||||
test('typed object', () {
|
||||
var f = new Foo(42);
|
||||
expect(js_util.callMethod(f, 'bar', []), equals(42));
|
||||
});
|
||||
|
||||
test('complex callMethod calls', () {
|
||||
var f = new Foo(42);
|
||||
|
||||
// Call a method that returns an unbound function.
|
||||
expect(js_util.callMethod(f, 'nestedFunction', []) is Function, isTrue);
|
||||
expect(js_util.callMethod(f, 'nestedFunction', [])(),
|
||||
equals('Nested Function'));
|
||||
|
||||
// Call method on a nested function property.
|
||||
expect(js_util.callMethod(f.objectProperty, 'functionProperty', []),
|
||||
equals('Function Property'));
|
||||
|
||||
// Call method with different args.
|
||||
expect(
|
||||
js_util.callMethod(f, 'getFirstEl', [
|
||||
[25, 50]
|
||||
]),
|
||||
equals(25));
|
||||
expect(js_util.callMethod(f, 'sumFn', [2, 3]), equals(5));
|
||||
expect(js_util.callMethod(f, 'getA', [f]), equals(42));
|
||||
expect(js_util.callMethod(f, 'callFn', [allowInterop(jsFunction)]),
|
||||
equals("JS Function"));
|
||||
expect(js_util.callMethod(f, 'callFn', [allowInterop(dartFunction)]),
|
||||
equals("Dart Function"));
|
||||
expect(
|
||||
js_util.callMethod(f, 'callFn', [
|
||||
allowInterop(() {
|
||||
return "inline";
|
||||
})
|
||||
]),
|
||||
equals("inline"));
|
||||
|
||||
// Using a variable for the method name.
|
||||
String methodName = 'bar';
|
||||
expect(js_util.callMethod(f, methodName, []), equals(42));
|
||||
String bar = _getBarWithSideEffect();
|
||||
expect(js_util.callMethod(f, bar, []), equals(42));
|
||||
});
|
||||
});
|
||||
|
||||
group('instanceof', () {
|
||||
test('typed object', () {
|
||||
var f = new Foo(42);
|
||||
expect(js_util.instanceof(f, JSFooType), isTrue);
|
||||
expect(js_util.instanceof(f, JSArrayBufferType), isFalse);
|
||||
});
|
||||
|
||||
test('typed literal', () {
|
||||
var literal = new ExampleTypedLiteral();
|
||||
expect(js_util.instanceof(literal, JSFooType), isFalse);
|
||||
});
|
||||
});
|
||||
|
||||
group('callConstructor', () {
|
||||
test('typed object', () {
|
||||
Foo f = js_util.callConstructor(JSFooType, [42]);
|
||||
expect(f.a, equals(42));
|
||||
});
|
||||
});
|
||||
}
|
|
@ -37,6 +37,7 @@ html/custom_elements_23127_test: Skip # Issue 29922
|
|||
html/custom_elements_test: Skip # Issue 29922
|
||||
html/notification_permission_test: Skip # Issue 32002
|
||||
isolate/*: SkipByDesign # No support for dart:isolate in dart4web (http://dartbug.com/30538)
|
||||
js/js_util/js_prefix_test: SkipByDesign # JS$ prefix not implemented on ddc.
|
||||
mirrors/*: SkipByDesign # Mirrors not supported on web in Dart 2.0.
|
||||
typed_data/int64_list_load_store_test: SkipByDesign # dartdevk/c does not support Int64List
|
||||
typed_data/typed_data_hierarchy_int64_test: SkipByDesign # dartdevk/c does not support Int64List
|
||||
|
|
|
@ -2,75 +2,19 @@
|
|||
// 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;
|
||||
// Tests the functionality of js_util with HTML objects.
|
||||
|
||||
@JS()
|
||||
library js_util_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:expect/minitest.dart';
|
||||
import 'package:async_helper/async_helper.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;
|
||||
}
|
||||
|
||||
var rejectedPromise = new Promise((resolve, reject) => reject('rejected'));
|
||||
var resolvedPromise = new Promise(resolve => resolve('resolved'));
|
||||
function getResolvedPromise() {
|
||||
return resolvedPromise;
|
||||
}
|
||||
|
||||
""";
|
||||
document.body.append(script);
|
||||
}
|
||||
|
||||
@JS()
|
||||
external bool checkMap(m, String, value);
|
||||
|
||||
@JS('JSON.stringify')
|
||||
external String stringify(o);
|
||||
external void eval(String code);
|
||||
|
||||
@JS('Node')
|
||||
external get JSNodeType;
|
||||
|
@ -86,302 +30,61 @@ 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()
|
||||
abstract class Promise<T> {}
|
||||
|
||||
@JS()
|
||||
external Promise get resolvedPromise;
|
||||
|
||||
@JS()
|
||||
external Promise get rejectedPromise;
|
||||
|
||||
@JS()
|
||||
external Promise getResolvedPromise();
|
||||
|
||||
@JS("Object.prototype.hasOwnProperty")
|
||||
external get _hasOwnProperty;
|
||||
|
||||
bool hasOwnProperty(o, String name) {
|
||||
return js_util.callMethod(_hasOwnProperty, 'call', [o, name]);
|
||||
external Foo();
|
||||
}
|
||||
|
||||
main() {
|
||||
_injectJs();
|
||||
eval(r""" function Foo() {} """);
|
||||
|
||||
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', () {
|
||||
dynamic 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'), throwsArgumentError);
|
||||
});
|
||||
test('hasProperty', () {
|
||||
var textElement = new Text('foo');
|
||||
expect(js_util.hasProperty(textElement, 'data'), isTrue);
|
||||
});
|
||||
|
||||
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}'));
|
||||
});
|
||||
test('getProperty', () {
|
||||
var textElement = new Text('foo');
|
||||
expect(js_util.getProperty(textElement, 'data'), equals('foo'));
|
||||
});
|
||||
|
||||
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));
|
||||
});
|
||||
test('setProperty', () {
|
||||
var textElement = new Text('foo');
|
||||
js_util.setProperty(textElement, 'data', 'bar');
|
||||
expect(textElement.text, equals('bar'));
|
||||
});
|
||||
|
||||
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);
|
||||
});
|
||||
test('callMethod', () {
|
||||
var canvas = new CanvasElement();
|
||||
expect(
|
||||
identical(canvas.getContext('2d'),
|
||||
js_util.callMethod(canvas, 'getContext', ['2d'])),
|
||||
isTrue);
|
||||
});
|
||||
|
||||
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('instanceof', () {
|
||||
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);
|
||||
|
||||
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));
|
||||
});
|
||||
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);
|
||||
|
||||
var f = new Foo();
|
||||
expect(js_util.instanceof(f, JSNodeType), isFalse);
|
||||
});
|
||||
|
||||
group('callMethod', () {
|
||||
test('html object', () {
|
||||
var canvas = new CanvasElement();
|
||||
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));
|
||||
});
|
||||
});
|
||||
|
||||
Future<void> testResolvedPromise() async {
|
||||
final String result = await js_util.promiseToFuture(resolvedPromise);
|
||||
expect(result, equals('resolved'));
|
||||
}
|
||||
|
||||
Future<void> testRejectedPromise() async {
|
||||
try {
|
||||
final String result = await promiseToFuture(rejectedPromise);
|
||||
fail('expected Future to throw an error');
|
||||
} catch (error) {
|
||||
expect(error, equals('rejected'));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> testReturnRejectedPromise() async {
|
||||
final String result = await promiseToFuture(getResolvedPromise());
|
||||
expect(result, equals('resolved'));
|
||||
}
|
||||
|
||||
asyncTest(() async {
|
||||
await testResolvedPromise();
|
||||
await testRejectedPromise();
|
||||
await testReturnRejectedPromise();
|
||||
test('callConstructor', () {
|
||||
var textNode = js_util.callConstructor(JSTextType, ['foo']);
|
||||
expect(js_util.instanceof(textNode, JSTextType), isTrue);
|
||||
expect(textNode is Text, isTrue);
|
||||
expect(textNode.text, equals('foo'));
|
||||
});
|
||||
}
|
||||
|
|
59
tests/lib_2/js/js_util/async_test.dart
Normal file
59
tests/lib_2/js/js_util/async_test.dart
Normal file
|
@ -0,0 +1,59 @@
|
|||
// Copyright (c) 2021, 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_util_async_test;
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:js/js.dart';
|
||||
import 'package:js/js_util.dart' as js_util;
|
||||
import 'package:expect/minitest.dart';
|
||||
import 'package:async_helper/async_helper.dart';
|
||||
|
||||
@JS()
|
||||
external void eval(String code);
|
||||
|
||||
@JS()
|
||||
abstract class Promise<T> {}
|
||||
|
||||
@JS()
|
||||
external Promise get resolvedPromise;
|
||||
|
||||
@JS()
|
||||
external Promise get rejectedPromise;
|
||||
|
||||
@JS()
|
||||
external Promise getResolvedPromise();
|
||||
|
||||
main() {
|
||||
eval(r"""
|
||||
var rejectedPromise = new Promise((resolve, reject) => reject('rejected'));
|
||||
var resolvedPromise = new Promise(resolve => resolve('resolved'));
|
||||
function getResolvedPromise() {
|
||||
return resolvedPromise;
|
||||
}
|
||||
""");
|
||||
|
||||
Future<void> testResolvedPromise() async {
|
||||
final String result = await js_util.promiseToFuture(resolvedPromise);
|
||||
expect(result, equals('resolved'));
|
||||
}
|
||||
|
||||
Future<void> testRejectedPromise() async {
|
||||
asyncExpectThrows<String>(() => js_util.promiseToFuture(rejectedPromise),
|
||||
(String error) => error == 'rejected');
|
||||
}
|
||||
|
||||
Future<void> testReturnResolvedPromise() async {
|
||||
final String result = await js_util.promiseToFuture(getResolvedPromise());
|
||||
expect(result, equals('resolved'));
|
||||
}
|
||||
|
||||
asyncTest(() async {
|
||||
await testResolvedPromise();
|
||||
await testRejectedPromise();
|
||||
await testReturnResolvedPromise();
|
||||
});
|
||||
}
|
64
tests/lib_2/js/js_util/js_prefix_test.dart
Normal file
64
tests/lib_2/js/js_util/js_prefix_test.dart
Normal file
|
@ -0,0 +1,64 @@
|
|||
// Copyright (c) 2021, 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.
|
||||
|
||||
// Tests the functionality of the JS$ prefix for escaping keywords in JS names.
|
||||
// Currently only implemented in dart2js, expected to fail in ddc.
|
||||
|
||||
@JS()
|
||||
library js_prefix_test;
|
||||
|
||||
import 'package:js/js.dart';
|
||||
import 'package:js/js_util.dart' as js_util;
|
||||
import 'package:expect/minitest.dart';
|
||||
|
||||
@JS()
|
||||
@anonymous
|
||||
class ExampleTypedLiteral {
|
||||
external factory ExampleTypedLiteral({JS$_c, JS$class});
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
main() {
|
||||
test('hasProperty', () {
|
||||
var literal = new ExampleTypedLiteral(JS$_c: null, JS$class: true);
|
||||
expect(js_util.hasProperty(literal, '_c'), isTrue);
|
||||
expect(literal.JS$_c, isNull);
|
||||
expect(js_util.hasProperty(literal, 'class'), isTrue);
|
||||
// JS$_c escapes to _c so the property JS$_c will not exist on the object.
|
||||
expect(js_util.hasProperty(literal, r'JS$_c'), isFalse);
|
||||
expect(js_util.hasProperty(literal, r'JS$class'), isFalse);
|
||||
expect(literal.JS$class, isTrue);
|
||||
|
||||
literal = new ExampleTypedLiteral();
|
||||
expect(js_util.hasProperty(literal, '_c'), isFalse);
|
||||
expect(js_util.hasProperty(literal, 'class'), isFalse);
|
||||
|
||||
literal = new ExampleTypedLiteral(JS$_c: 74);
|
||||
expect(js_util.hasProperty(literal, '_c'), isTrue);
|
||||
expect(literal.JS$_c, equals(74));
|
||||
});
|
||||
|
||||
test('getProperty', () {
|
||||
var literal = new ExampleTypedLiteral(JS$_c: 7, JS$class: true);
|
||||
expect(js_util.getProperty(literal, '_c'), equals(7));
|
||||
expect(literal.JS$_c, equals(7));
|
||||
expect(js_util.getProperty(literal, 'class'), isTrue);
|
||||
expect(js_util.getProperty(literal, r'JS$_c'), isNull);
|
||||
expect(js_util.getProperty(literal, r'JS$class'), isNull);
|
||||
});
|
||||
|
||||
test('setProperty', () {
|
||||
var literal = new ExampleTypedLiteral();
|
||||
literal.JS$class = 42;
|
||||
expect(literal.JS$class, equals(42));
|
||||
js_util.setProperty(literal, 'class', 100);
|
||||
expect(literal.JS$class, equals(100));
|
||||
});
|
||||
}
|
104
tests/lib_2/js/js_util/jsify_test.dart
Normal file
104
tests/lib_2/js/js_util/jsify_test.dart
Normal file
|
@ -0,0 +1,104 @@
|
|||
// Copyright (c) 2021, 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.
|
||||
|
||||
// Tests the jsify functionality of the js_util library.
|
||||
|
||||
@JS()
|
||||
library js_util_jsify_test;
|
||||
|
||||
import 'package:js/js.dart';
|
||||
import 'package:js/js_util.dart' as js_util;
|
||||
import 'package:expect/minitest.dart';
|
||||
|
||||
@JS()
|
||||
external void eval(String code);
|
||||
|
||||
@JS()
|
||||
external bool checkMap(m, String, value);
|
||||
|
||||
@JS()
|
||||
class Foo {
|
||||
external Foo(num a);
|
||||
|
||||
external num get a;
|
||||
external num bar();
|
||||
}
|
||||
|
||||
main() {
|
||||
eval(r"""
|
||||
function Foo(a) {
|
||||
this.a = a;
|
||||
}
|
||||
|
||||
Foo.prototype.bar = function() {
|
||||
return this.a;
|
||||
}
|
||||
|
||||
function checkMap(m, key, value) {
|
||||
if (m.hasOwnProperty(key))
|
||||
return m[key] == value;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
""");
|
||||
|
||||
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, isFalse);
|
||||
expect(jsMap is Map, isFalse);
|
||||
for (var key in map.keys) {
|
||||
expect(checkMap(jsMap, key, map[key]), isTrue);
|
||||
}
|
||||
});
|
||||
|
||||
test('deep convert a complex object', () {
|
||||
dynamic 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]));
|
||||
|
||||
var b = js_util.getProperty(jsObject, 'b');
|
||||
expect(js_util.getProperty(b, 'c'), equals(object['b']['c']));
|
||||
var d = js_util.getProperty(b, 'd');
|
||||
expect(d, equals(object['b']['d']));
|
||||
expect(js_util.getProperty(d, 'a'), equals(42));
|
||||
expect(js_util.callMethod(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'), throwsArgumentError);
|
||||
});
|
||||
}
|
368
tests/lib_2/js/js_util/properties_test.dart
Normal file
368
tests/lib_2/js/js_util/properties_test.dart
Normal file
|
@ -0,0 +1,368 @@
|
|||
// Copyright (c) 2021, 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.
|
||||
|
||||
// Tests the functionality of object properties with the js_util library. For
|
||||
// js_util tests with HTML objects see tests/lib/html/js_util_test.dart.
|
||||
|
||||
@JS()
|
||||
library js_util_properties_test;
|
||||
|
||||
import 'package:js/js.dart';
|
||||
import 'package:js/js_util.dart' as js_util;
|
||||
import 'package:expect/minitest.dart';
|
||||
|
||||
@JS()
|
||||
external String jsFunction();
|
||||
|
||||
@JS()
|
||||
external void eval(String code);
|
||||
|
||||
@JS('JSON.stringify')
|
||||
external String stringify(o);
|
||||
|
||||
@JS('ArrayBuffer')
|
||||
external get JSArrayBufferType;
|
||||
|
||||
@JS()
|
||||
class Foo {
|
||||
external Foo(num a);
|
||||
|
||||
external num get a;
|
||||
external num bar();
|
||||
external Object get objectProperty;
|
||||
}
|
||||
|
||||
@JS('Foo')
|
||||
external get JSFooType;
|
||||
|
||||
String dartFunction() {
|
||||
return 'Dart Function';
|
||||
}
|
||||
|
||||
@JS()
|
||||
@anonymous
|
||||
class ExampleTypedLiteral {
|
||||
external factory ExampleTypedLiteral({a, b});
|
||||
|
||||
external get a;
|
||||
external get b;
|
||||
}
|
||||
|
||||
String _getBarWithSideEffect() {
|
||||
var x = 5;
|
||||
expect(x, equals(5));
|
||||
return 'bar';
|
||||
}
|
||||
|
||||
main() {
|
||||
eval(r"""
|
||||
function Foo(a) {
|
||||
this.a = a;
|
||||
}
|
||||
|
||||
Foo.b = 38;
|
||||
|
||||
Foo.prototype.list = [2, 4, 6];
|
||||
|
||||
Foo.prototype.bar = function() {
|
||||
return this.a;
|
||||
}
|
||||
|
||||
Foo.prototype.toString = function() {
|
||||
return "I'm a Foo a=" + this.a;
|
||||
}
|
||||
|
||||
Foo.prototype.fnList = [Foo.prototype.bar, Foo.prototype.toString];
|
||||
|
||||
Foo.prototype.objectProperty = {
|
||||
'c': 1,
|
||||
'list': [10, 20, 30],
|
||||
'functionProperty': function() { return 'Function Property'; }
|
||||
}
|
||||
|
||||
function jsFunction() {
|
||||
return "JS Function";
|
||||
}
|
||||
|
||||
Foo.prototype.nestedFunction = function() {
|
||||
return function() {
|
||||
return 'Nested Function';
|
||||
};
|
||||
}
|
||||
|
||||
Foo.prototype.getFirstEl = function(list) {
|
||||
return list[0];
|
||||
}
|
||||
|
||||
Foo.prototype.sumFn = function(a, b) {
|
||||
return a + b;
|
||||
}
|
||||
|
||||
Foo.prototype.getA = function(obj) {
|
||||
return obj.a;
|
||||
}
|
||||
|
||||
Foo.prototype.callFn = function(fn) {
|
||||
return fn();
|
||||
}
|
||||
""");
|
||||
|
||||
group('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(js_util.callMethod(o, 'hasOwnProperty', ['toString']), isFalse);
|
||||
expect(js_util.callMethod(o, 'hasOwnProperty', ['foo bar']), isFalse);
|
||||
js_util.setProperty(o, 'foo bar', 42);
|
||||
expect(js_util.callMethod(o, 'hasOwnProperty', ['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}'));
|
||||
});
|
||||
|
||||
test('nested properties calls', () {
|
||||
var o = js_util.newObject();
|
||||
var f = new Foo(42);
|
||||
js_util.setProperty(o, 'foo', f);
|
||||
var foo = js_util.getProperty(o, 'foo');
|
||||
expect(foo, equals(f));
|
||||
expect(js_util.hasProperty(foo, 'a'), isTrue);
|
||||
expect(js_util.getProperty(foo, 'a'), equals(42));
|
||||
js_util.setProperty(foo, 'a', 24);
|
||||
expect(js_util.getProperty(foo, 'a'), equals(24));
|
||||
});
|
||||
});
|
||||
|
||||
group('hasProperty', () {
|
||||
test('typed object', () {
|
||||
var f = new Foo(42);
|
||||
expect(js_util.hasProperty(f, 'a'), isTrue);
|
||||
expect(js_util.hasProperty(f, 'bar'), isTrue);
|
||||
expect(js_util.hasProperty(f, 'b'), isFalse);
|
||||
expect(js_util.hasProperty(f, 'toString'), isTrue);
|
||||
js_util.setProperty(f, '__proto__', null);
|
||||
expect(js_util.hasProperty(f, 'toString'), isFalse);
|
||||
});
|
||||
|
||||
test('typed literal', () {
|
||||
var literal = new ExampleTypedLiteral(a: 'x', b: 42);
|
||||
expect(js_util.hasProperty(literal, 'a'), isTrue);
|
||||
expect(js_util.hasProperty(literal, 'b'), isTrue);
|
||||
expect(js_util.hasProperty(literal, 'anything'), isFalse);
|
||||
|
||||
literal = new ExampleTypedLiteral(a: null);
|
||||
expect(js_util.hasProperty(literal, 'a'), isTrue);
|
||||
expect(js_util.hasProperty(literal, 'b'), isFalse);
|
||||
expect(js_util.hasProperty(literal, 'anything'), isFalse);
|
||||
});
|
||||
|
||||
test('complex hasProperty calls', () {
|
||||
var f = new Foo(42);
|
||||
expect(js_util.hasProperty(f.objectProperty, 'c'), isTrue);
|
||||
expect(js_util.hasProperty(f.objectProperty, 'nonexistent'), isFalse);
|
||||
|
||||
// Using a variable for the property name.
|
||||
String propertyName = 'bar';
|
||||
expect(js_util.hasProperty(f, propertyName), isTrue);
|
||||
});
|
||||
});
|
||||
|
||||
group('getProperty', () {
|
||||
test('typed object', () {
|
||||
var f = new Foo(42);
|
||||
expect(js_util.getProperty(f, 'a'), equals(42));
|
||||
expect(js_util.getProperty(f, 'b'), isNull);
|
||||
expect(js_util.getProperty(f, 'bar') is Function, isTrue);
|
||||
expect(js_util.getProperty(f, 'list') is List, isTrue);
|
||||
expect(js_util.getProperty(f, 'objectProperty') is Object, isTrue);
|
||||
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 literal = new ExampleTypedLiteral(a: 'x', b: 42);
|
||||
expect(js_util.getProperty(literal, 'a'), equals('x'));
|
||||
expect(js_util.getProperty(literal, 'b'), equals(42));
|
||||
expect(js_util.getProperty(literal, 'anything'), isNull);
|
||||
});
|
||||
|
||||
test('complex getProperty calls', () {
|
||||
var f = new Foo(42);
|
||||
|
||||
// Accessing a method property.
|
||||
expect(js_util.getProperty(f, 'bar') is Function, isTrue);
|
||||
expect(js_util.callMethod(f, 'bar', []), equals(42));
|
||||
|
||||
// Accessing list properties.
|
||||
expect(js_util.getProperty(f, 'list')[0], equals(2));
|
||||
expect(js_util.getProperty(f, 'fnList')[0] is Function, isTrue);
|
||||
expect(
|
||||
js_util.callMethod(
|
||||
js_util.getProperty(f, 'fnList')[0], 'apply', [f, []]),
|
||||
equals(42));
|
||||
|
||||
// Accessing nested object properites.
|
||||
var objectProperty = js_util.getProperty(f, 'objectProperty');
|
||||
expect(js_util.getProperty(objectProperty, 'c'), equals(1));
|
||||
expect(js_util.getProperty(objectProperty, 'list') is List, isTrue);
|
||||
expect(js_util.getProperty(objectProperty, 'list')[1], equals(20));
|
||||
expect(
|
||||
js_util.getProperty(objectProperty, 'functionProperty') is Function,
|
||||
isTrue);
|
||||
|
||||
// Using a variable for the property name.
|
||||
String propertyName = 'a';
|
||||
expect(js_util.getProperty(f, propertyName), equals(42));
|
||||
String bar = _getBarWithSideEffect();
|
||||
expect(js_util.getProperty(f, bar) is Function, isTrue);
|
||||
expect(js_util.callMethod(f, bar, []), equals(42));
|
||||
});
|
||||
});
|
||||
|
||||
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));
|
||||
|
||||
expect(js_util.getProperty(f, 'list') is List, isTrue);
|
||||
js_util.setProperty(f, 'list', [8]);
|
||||
expect(js_util.getProperty(f, 'list') is List, isTrue);
|
||||
expect(js_util.getProperty(f, 'list')[0], equals(8));
|
||||
|
||||
js_util.setProperty(f, 'newProperty', 'new');
|
||||
expect(js_util.getProperty(f, 'newProperty'), equals('new'));
|
||||
});
|
||||
|
||||
test('typed literal', () {
|
||||
var literal = new ExampleTypedLiteral();
|
||||
js_util.setProperty(literal, 'a', 'foo');
|
||||
expect(js_util.getProperty(literal, 'a'), equals('foo'));
|
||||
expect(literal.a, equals('foo'));
|
||||
js_util.setProperty(literal, 'a', literal);
|
||||
expect(identical(literal.a, literal), isTrue);
|
||||
var list = ['arr'];
|
||||
js_util.setProperty(literal, 'a', list);
|
||||
expect(identical(literal.a, list), isTrue);
|
||||
});
|
||||
|
||||
test('complex setProperty calls', () {
|
||||
var f = new Foo(42);
|
||||
|
||||
// Set function property to a num.
|
||||
expect(js_util.getProperty(f, 'bar') is Function, isTrue);
|
||||
js_util.setProperty(f, 'bar', 5);
|
||||
expect(js_util.getProperty(f, 'bar') is Function, isFalse);
|
||||
expect(js_util.getProperty(f, 'bar'), equals(5));
|
||||
|
||||
// Set property to a Dart function.
|
||||
js_util.setProperty(f, 'bar', allowInterop(dartFunction));
|
||||
expect(js_util.getProperty(f, 'bar') is Function, isTrue);
|
||||
expect(js_util.callMethod(f, 'bar', []), equals('Dart Function'));
|
||||
js_util.setProperty(f, 'bar', allowInterop(() {
|
||||
return 'Inline';
|
||||
}));
|
||||
expect(js_util.callMethod(f, 'bar', []), equals('Inline'));
|
||||
|
||||
// Set property to a JS function.
|
||||
js_util.setProperty(f, 'bar', allowInterop(jsFunction));
|
||||
expect(js_util.getProperty(f, 'bar') is Function, isTrue);
|
||||
expect(js_util.callMethod(f, 'bar', []), equals('JS Function'));
|
||||
|
||||
// Set property with nested object properties.
|
||||
js_util.setProperty(f.objectProperty, 'c', 'new val');
|
||||
expect(js_util.getProperty(f.objectProperty, 'c'), equals('new val'));
|
||||
js_util.setProperty(f.objectProperty, 'list', [1, 2, 3]);
|
||||
expect(js_util.getProperty(f.objectProperty, 'list')[1], equals(2));
|
||||
|
||||
// Using a variable for the property name.
|
||||
String propertyName = 'bar';
|
||||
js_util.setProperty(f, propertyName, 'foo');
|
||||
expect(js_util.getProperty(f, 'bar'), equals('foo'));
|
||||
String bar = _getBarWithSideEffect();
|
||||
js_util.setProperty(f, bar, 'baz');
|
||||
expect(js_util.getProperty(f, bar), equals('baz'));
|
||||
});
|
||||
});
|
||||
|
||||
group('callMethod', () {
|
||||
test('typed object', () {
|
||||
var f = new Foo(42);
|
||||
expect(js_util.callMethod(f, 'bar', []), equals(42));
|
||||
});
|
||||
|
||||
test('complex callMethod calls', () {
|
||||
var f = new Foo(42);
|
||||
|
||||
// Call a method that returns an unbound function.
|
||||
expect(js_util.callMethod(f, 'nestedFunction', []) is Function, isTrue);
|
||||
expect(js_util.callMethod(f, 'nestedFunction', [])(),
|
||||
equals('Nested Function'));
|
||||
|
||||
// Call method on a nested function property.
|
||||
expect(js_util.callMethod(f.objectProperty, 'functionProperty', []),
|
||||
equals('Function Property'));
|
||||
|
||||
// Call method with different args.
|
||||
expect(
|
||||
js_util.callMethod(f, 'getFirstEl', [
|
||||
[25, 50]
|
||||
]),
|
||||
equals(25));
|
||||
expect(js_util.callMethod(f, 'sumFn', [2, 3]), equals(5));
|
||||
expect(js_util.callMethod(f, 'getA', [f]), equals(42));
|
||||
expect(js_util.callMethod(f, 'callFn', [allowInterop(jsFunction)]),
|
||||
equals("JS Function"));
|
||||
expect(js_util.callMethod(f, 'callFn', [allowInterop(dartFunction)]),
|
||||
equals("Dart Function"));
|
||||
expect(
|
||||
js_util.callMethod(f, 'callFn', [
|
||||
allowInterop(() {
|
||||
return "inline";
|
||||
})
|
||||
]),
|
||||
equals("inline"));
|
||||
|
||||
// Using a variable for the method name.
|
||||
String methodName = 'bar';
|
||||
expect(js_util.callMethod(f, methodName, []), equals(42));
|
||||
String bar = _getBarWithSideEffect();
|
||||
expect(js_util.callMethod(f, bar, []), equals(42));
|
||||
});
|
||||
});
|
||||
|
||||
group('instanceof', () {
|
||||
test('typed object', () {
|
||||
var f = new Foo(42);
|
||||
expect(js_util.instanceof(f, JSFooType), isTrue);
|
||||
expect(js_util.instanceof(f, JSArrayBufferType), isFalse);
|
||||
});
|
||||
|
||||
test('typed literal', () {
|
||||
var literal = new ExampleTypedLiteral();
|
||||
expect(js_util.instanceof(literal, JSFooType), isFalse);
|
||||
});
|
||||
});
|
||||
|
||||
group('callConstructor', () {
|
||||
test('typed object', () {
|
||||
Foo f = js_util.callConstructor(JSFooType, [42]);
|
||||
expect(f.a, equals(42));
|
||||
});
|
||||
});
|
||||
}
|
|
@ -37,4 +37,5 @@ html/custom_elements_23127_test: Skip # Issue 29922
|
|||
html/custom_elements_test: Skip # Issue 29922
|
||||
html/notification_permission_test: Skip # Issue 32002
|
||||
isolate/*: SkipByDesign # No support for dart:isolate in dart4web (http://dartbug.com/30538)
|
||||
js/js_util/js_prefix_test: SkipByDesign # JS$ prefix not implemented on ddc.
|
||||
mirrors/*: SkipByDesign # Mirrors not supported on web in Dart 2.0.
|
||||
|
|
Loading…
Reference in a new issue