OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. |
| 4 |
| 5 @JS() |
| 6 library js_native_test; |
| 7 |
| 8 import 'dart:async'; |
| 9 import 'dart:html'; |
| 10 import 'dart:typed_data' show ByteBuffer, Int32List; |
| 11 import 'dart:indexed_db' show IdbFactory, KeyRange; |
| 12 |
| 13 import 'package:js/js.dart'; |
| 14 import 'package:unittest/unittest.dart'; |
| 15 import 'package:unittest/html_individual_config.dart'; |
| 16 |
| 17 _injectJs() { |
| 18 final script = new ScriptElement(); |
| 19 script.type = 'text/javascript'; |
| 20 script.innerHtml = r""" |
| 21 var x = 42; |
| 22 |
| 23 var _x = 123; |
| 24 |
| 25 var myArray = ["value1"]; |
| 26 |
| 27 function returnThis() { |
| 28 return this; |
| 29 } |
| 30 |
| 31 function getTypeOf(o) { |
| 32 return typeof(o); |
| 33 } |
| 34 |
| 35 function Foo(a) { |
| 36 this.a = a; |
| 37 } |
| 38 |
| 39 Foo.b = 38; |
| 40 |
| 41 Foo.prototype.bar = function() { |
| 42 return this.a; |
| 43 } |
| 44 Foo.prototype.toString = function() { |
| 45 return "I'm a Foo a=" + this.a; |
| 46 } |
| 47 |
| 48 var container = new Object(); |
| 49 container.Foo = Foo; |
| 50 |
| 51 function checkMap(m, key, value) { |
| 52 if (m.hasOwnProperty(key)) |
| 53 return m[key] == value; |
| 54 else |
| 55 return false; |
| 56 } |
| 57 |
| 58 """; |
| 59 document.body.append(script); |
| 60 } |
| 61 |
| 62 @JS() |
| 63 external bool checkMap(m, String, value); |
| 64 |
| 65 @JS('JSON.stringify') |
| 66 external String stringify(o); |
| 67 |
| 68 @JS('Node') |
| 69 external Function get JSNodeType; |
| 70 |
| 71 @JS('Element') |
| 72 external Function get JSElementType; |
| 73 |
| 74 @JS('Text') |
| 75 external Function get JSTextType; |
| 76 |
| 77 @JS('HTMLCanvasElement') |
| 78 external Function get JSHtmlCanvasElementType; |
| 79 |
| 80 @JS() |
| 81 class Foo { |
| 82 external Foo(num a); |
| 83 |
| 84 external num get a; |
| 85 external num bar(); |
| 86 } |
| 87 |
| 88 @JS('Foo') |
| 89 external Function get JSFooType; |
| 90 |
| 91 @JS() |
| 92 @anonymous |
| 93 class ExampleTypedLiteral { |
| 94 external factory ExampleTypedLiteral({a, b, JS$_c, JS$class}); |
| 95 |
| 96 external get a; |
| 97 external get b; |
| 98 external get JS$_c; |
| 99 external set JS$_c(v); |
| 100 // Identical to JS$_c but only accessible within the library. |
| 101 external get _c; |
| 102 external get JS$class; |
| 103 external set JS$class(v); |
| 104 } |
| 105 |
| 106 @JS("Object.prototype.hasOwnProperty") |
| 107 external Function get _hasOwnProperty; |
| 108 |
| 109 bool hasOwnProperty(o, String name) { |
| 110 return JSNative.callMethod(_hasOwnProperty, 'call', [o, name]); |
| 111 } |
| 112 |
| 113 main() { |
| 114 _injectJs(); |
| 115 useHtmlIndividualConfiguration(); |
| 116 |
| 117 group('JSNative.jsify()', () { |
| 118 test('convert a List', () { |
| 119 final list = [1, 2, 3, 4, 5, 6, 7, 8]; |
| 120 var array = JSNative.jsify(list); |
| 121 expect(array is List, isTrue); |
| 122 expect(identical(array, list), isFalse); |
| 123 expect(array.length, equals(list.length)); |
| 124 for (var i = 0; i < list.length; i++) { |
| 125 expect(array[i], equals(list[i])); |
| 126 } |
| 127 }); |
| 128 |
| 129 test('convert an Iterable', () { |
| 130 final set = new Set.from([1, 2, 3, 4, 5, 6, 7, 8]); |
| 131 var array = JSNative.jsify(set); |
| 132 expect(array is List, isTrue); |
| 133 expect(array.length, equals(set.length)); |
| 134 for (var i = 0; i < array.length; i++) { |
| 135 expect(set.contains(array[i]), isTrue); |
| 136 } |
| 137 }); |
| 138 |
| 139 test('convert a Map', () { |
| 140 var map = {'a': 1, 'b': 2, 'c': 3}; |
| 141 var jsMap = JSNative.jsify(map); |
| 142 expect(jsMap is! List, isTrue); |
| 143 for (var key in map.keys) { |
| 144 expect(checkMap(jsMap, key, map[key]), isTrue); |
| 145 } |
| 146 }); |
| 147 |
| 148 test('deep convert a complex object', () { |
| 149 final object = { |
| 150 'a': [ |
| 151 1, |
| 152 [2, 3] |
| 153 ], |
| 154 'b': {'c': 3, 'd': new Foo(42)}, |
| 155 'e': null |
| 156 }; |
| 157 var jsObject = JSNative.jsify(object); |
| 158 expect(JSNative.getProperty(jsObject, 'a')[0], equals(object['a'][0])); |
| 159 expect( |
| 160 JSNative.getProperty(jsObject, 'a')[1][0], equals(object['a'][1][0])); |
| 161 expect( |
| 162 JSNative.getProperty(jsObject, 'a')[1][1], equals(object['a'][1][1])); |
| 163 expect(JSNative.getProperty(JSNative.getProperty(jsObject, 'b'), 'c'), |
| 164 equals(object['b']['c'])); |
| 165 expect(JSNative.getProperty(JSNative.getProperty(jsObject, 'b'), 'd'), |
| 166 equals(object['b']['d'])); |
| 167 expect( |
| 168 JSNative.callMethod( |
| 169 JSNative.getProperty(JSNative.getProperty(jsObject, 'b'), 'd'), |
| 170 'bar', []), |
| 171 equals(42)); |
| 172 expect(JSNative.getProperty(jsObject, 'e'), isNull); |
| 173 }); |
| 174 |
| 175 test('throws if object is not a Map or Iterable', () { |
| 176 expect(() => JSNative.jsify('a'), |
| 177 throwsA(new isInstanceOf<ArgumentError>())); |
| 178 }); |
| 179 }); |
| 180 |
| 181 group('JSNative.newObject', () { |
| 182 test('create', () { |
| 183 expect(identical(JSNative.newObject(), JSNative.newObject()), isFalse); |
| 184 }); |
| 185 |
| 186 test('callMethod', () { |
| 187 var o = JSNative.newObject(); |
| 188 expect(JSNative.callMethod(o, 'toString', []), equals('[object Object]')); |
| 189 expect(stringify(o), equals('{}')); |
| 190 }); |
| 191 |
| 192 test('properties', () { |
| 193 var o = JSNative.newObject(); |
| 194 expect(JSNative.hasProperty(o, 'foo bar'), isFalse); |
| 195 expect(JSNative.hasProperty(o, 'toString'), isTrue); |
| 196 expect(hasOwnProperty(o, 'toString'), isFalse); |
| 197 expect(hasOwnProperty(o, 'foo bar'), isFalse); |
| 198 JSNative.setProperty(o, 'foo bar', 42); |
| 199 expect(hasOwnProperty(o, 'foo bar'), isTrue); |
| 200 expect(JSNative.getProperty(o, 'foo bar'), equals(42)); |
| 201 expect(JSNative.hasProperty(o, 'foo bar'), isTrue); |
| 202 expect(stringify(o), equals('{"foo bar":42}')); |
| 203 }); |
| 204 }); |
| 205 |
| 206 group('hasProperty', () { |
| 207 test('typed object', () { |
| 208 var f = new Foo(42); |
| 209 expect(JSNative.hasProperty(f, 'a'), isTrue); |
| 210 expect(JSNative.hasProperty(f, 'toString'), isTrue); |
| 211 JSNative.setProperty(f, '__proto__', null); |
| 212 expect(JSNative.hasProperty(f, 'toString'), isFalse); |
| 213 }); |
| 214 test('typed literal', () { |
| 215 var l = |
| 216 new ExampleTypedLiteral(a: 'x', b: 42, JS$_c: null, JS$class: true); |
| 217 expect(JSNative.hasProperty(l, 'a'), isTrue); |
| 218 expect(JSNative.hasProperty(l, 'b'), isTrue); |
| 219 expect(JSNative.hasProperty(l, '_c'), isTrue); |
| 220 expect(l.JS$_c, isNull); |
| 221 expect(JSNative.hasProperty(l, 'class'), isTrue); |
| 222 // JS$_c escapes to _c so the property JS$_c will not exist on the object. |
| 223 expect(JSNative.hasProperty(l, r'JS$_c'), isFalse); |
| 224 expect(JSNative.hasProperty(l, r'JS$class'), isFalse); |
| 225 expect(l.JS$class, isTrue); |
| 226 |
| 227 l = new ExampleTypedLiteral(a: null); |
| 228 expect(JSNative.hasProperty(l, 'a'), isTrue); |
| 229 expect(JSNative.hasProperty(l, 'b'), isFalse); |
| 230 expect(JSNative.hasProperty(l, '_c'), isFalse); |
| 231 expect(JSNative.hasProperty(l, 'class'), isFalse); |
| 232 |
| 233 l = new ExampleTypedLiteral(JS$_c: 74); |
| 234 expect(JSNative.hasProperty(l, '_c'), isTrue); |
| 235 expect(l.JS$_c, equals(74)); |
| 236 }); |
| 237 }); |
| 238 |
| 239 group('getProperty', () { |
| 240 test('typed object', () { |
| 241 var f = new Foo(42); |
| 242 expect(JSNative.getProperty(f, 'a'), equals(42)); |
| 243 expect(JSNative.getProperty(f, 'toString') is Function, isTrue); |
| 244 JSNative.setProperty(f, '__proto__', null); |
| 245 expect(JSNative.getProperty(f, 'toString'), isNull); |
| 246 }); |
| 247 |
| 248 test('typed literal', () { |
| 249 var l = new ExampleTypedLiteral(a: 'x', b: 42, JS$_c: 7, JS$class: true); |
| 250 expect(JSNative.getProperty(l, 'a'), equals('x')); |
| 251 expect(JSNative.getProperty(l, 'b'), equals(42)); |
| 252 expect(JSNative.getProperty(l, '_c'), equals(7)); |
| 253 expect(l.JS$_c, equals(7)); |
| 254 expect(JSNative.getProperty(l, 'class'), isTrue); |
| 255 expect(JSNative.getProperty(l, r'JS$_c'), isNull); |
| 256 expect(JSNative.getProperty(l, r'JS$class'), isNull); |
| 257 }); |
| 258 }); |
| 259 |
| 260 group('setProperty', () { |
| 261 test('typed object', () { |
| 262 var f = new Foo(42); |
| 263 expect(JSNative.getProperty(f, 'a'), equals(42)); |
| 264 JSNative.setProperty(f, 'a', 100); |
| 265 expect(f.a, equals(100)); |
| 266 expect(JSNative.getProperty(f, 'a'), equals(100)); |
| 267 }); |
| 268 |
| 269 test('typed literal', () { |
| 270 var l = new ExampleTypedLiteral(); |
| 271 JSNative.setProperty(l, 'a', 'foo'); |
| 272 expect(JSNative.getProperty(l, 'a'), equals('foo')); |
| 273 expect(l.a, equals('foo')); |
| 274 JSNative.setProperty(l, 'a', l); |
| 275 expect(identical(l.a, l), isTrue); |
| 276 var list = ['arr']; |
| 277 JSNative.setProperty(l, 'a', list); |
| 278 expect(identical(l.a, list), isTrue); |
| 279 l.JS$class = 42; |
| 280 expect(l.JS$class, equals(42)); |
| 281 JSNative.setProperty(l, 'class', 100); |
| 282 expect(l.JS$class, equals(100)); |
| 283 }); |
| 284 }); |
| 285 |
| 286 group('callMethod', () { |
| 287 test('html object', () { |
| 288 var canvas = new Element.tag('canvas'); |
| 289 expect( |
| 290 identical(canvas.getContext('2d'), |
| 291 JSNative.callMethod(canvas, 'getContext', ['2d'])), |
| 292 isTrue); |
| 293 }); |
| 294 |
| 295 test('typed object', () { |
| 296 var f = new Foo(42); |
| 297 expect(JSNative.callMethod(f, 'bar', []), equals(42)); |
| 298 }); |
| 299 }); |
| 300 |
| 301 group('instanceof', () { |
| 302 test('html object', () { |
| 303 var canvas = new Element.tag('canvas'); |
| 304 expect(JSNative.instanceof(canvas, JSNodeType), isTrue); |
| 305 expect(JSNative.instanceof(canvas, JSTextType), isFalse); |
| 306 expect(JSNative.instanceof(canvas, JSElementType), isTrue); |
| 307 expect(JSNative.instanceof(canvas, JSHtmlCanvasElementType), isTrue); |
| 308 var div = new Element.tag('div'); |
| 309 expect(JSNative.instanceof(div, JSNodeType), isTrue); |
| 310 expect(JSNative.instanceof(div, JSTextType), isFalse); |
| 311 expect(JSNative.instanceof(div, JSElementType), isTrue); |
| 312 expect(JSNative.instanceof(div, JSHtmlCanvasElementType), isFalse); |
| 313 |
| 314 var text = new Text('foo'); |
| 315 expect(JSNative.instanceof(text, JSNodeType), isTrue); |
| 316 expect(JSNative.instanceof(text, JSTextType), isTrue); |
| 317 expect(JSNative.instanceof(text, JSElementType), isFalse); |
| 318 }); |
| 319 |
| 320 test('typed object', () { |
| 321 var f = new Foo(42); |
| 322 expect(JSNative.instanceof(f, JSFooType), isTrue); |
| 323 expect(JSNative.instanceof(f, JSNodeType), isFalse); |
| 324 }); |
| 325 |
| 326 test('typed literal', () { |
| 327 var l = new ExampleTypedLiteral(); |
| 328 expect(JSNative.instanceof(l, JSFooType), isFalse); |
| 329 }); |
| 330 }); |
| 331 |
| 332 group('callConstructor', () { |
| 333 test('html object', () { |
| 334 var textNode = JSNative.callConstructor(JSTextType, ['foo']); |
| 335 expect(JSNative.instanceof(textNode, JSTextType), isTrue); |
| 336 expect(textNode is Text, isTrue); |
| 337 expect(textNode.text, equals('foo')); |
| 338 }); |
| 339 |
| 340 test('typed object', () { |
| 341 Foo f = JSNative.callConstructor(JSFooType, [42]); |
| 342 expect(f.a, equals(42)); |
| 343 }); |
| 344 }); |
| 345 } |
OLD | NEW |