| // 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. | |
| import "native_testing.dart"; | |
| import 'dart:_js_helper' show setNativeSubclassDispatchRecord; | |
| import 'dart:_interceptors' | |
| show findInterceptorForType, findConstructorForNativeSubclassType; | |
| // Test that subclasses of native classes can be initialized by calling the | |
| // 'upgrade' constructor. | |
| var trace = []; | |
| var log; | |
| @Native("A") | |
| class A { | |
| final a1 = log(101); // Only initialized IF named constructor called. | |
| get a2 native; // Initialized by native constructor. | |
| var a3; // Initialized only by A.two. | |
| var a4 = log(104); | |
| A.one(); | |
| A.two() : a3 = log(103) { | |
| log('body(A.two)'); | |
| log(a4 += increment); | |
| } | |
| A.three(x, this.a4) { | |
| log('body(A.three)'); | |
| log(a4 = '($a4, $x)'); | |
| } | |
| get increment => 10; | |
| } | |
| class B extends A { | |
| var b1; | |
| final b2 = log(202); | |
| var b3; | |
| B.one() : super.one(); | |
| B.two() : b1 = log(201), b3 = log(203), super.two() { | |
| log('body(B.two)'); | |
| } | |
| B.three([x]) : super.three(205, x); | |
| get increment => 20; | |
| } | |
| makeB() native; | |
| @Creates('=Object') | |
| getBPrototype() native; | |
| void setup() { | |
| JS('', r""" | |
| (function(){ | |
| function B() { this.a2 = 102; } | |
| self.makeB = function(){return new B()}; | |
| self.getBPrototype = function(){return B.prototype;}; | |
| })()"""); | |
| } | |
| test_one() { | |
| trace = []; | |
| var constructor = findConstructorForNativeSubclassType(B, 'one'); | |
| Expect.isNotNull(constructor); | |
| Expect.isNull(findConstructorForNativeSubclassType(B, 'Missing')); | |
| var b = makeB(); | |
| Expect.isTrue(b is B); | |
| // Call constructor to initialize native object. | |
| var b2 = JS('', '#(#)', constructor, b); | |
| Expect.identical(b, b2); | |
| Expect.isTrue(b is B); | |
| Expect.equals(101, b.a1); | |
| Expect.equals(102, b.a2); | |
| Expect.equals(null, b.a3); | |
| Expect.equals(104, b.a4); | |
| Expect.equals(null, b.b1); | |
| Expect.equals(202, b.b2); | |
| Expect.equals(null, b.b3); | |
| Expect.equals('[202, 101, 104]', '$trace'); | |
| } | |
| test_two() { | |
| trace = []; | |
| var constructor = findConstructorForNativeSubclassType(B, 'two'); | |
| Expect.isNotNull(constructor); | |
| var b = makeB(); | |
| Expect.isTrue(b is B); | |
| // Call constructor to initialize native object. | |
| JS('', '#(#)', constructor, b); | |
| Expect.isTrue(b is B); | |
| Expect.equals(101, b.a1); | |
| Expect.equals(102, b.a2); | |
| Expect.equals(103, b.a3); | |
| Expect.equals(124, b.a4); | |
| Expect.equals(201, b.b1); | |
| Expect.equals(202, b.b2); | |
| Expect.equals(203, b.b3); | |
| Expect.equals( | |
| '[202, 201, 101, 104, 103, 203, body(A.two), 124, body(B.two)]', | |
| '$trace', | |
| ); | |
| } | |
| test_three() { | |
| trace = []; | |
| var constructor = findConstructorForNativeSubclassType(B, 'three'); | |
| Expect.isNotNull(constructor); | |
| var b = makeB(); | |
| Expect.isTrue(b is B); | |
| // Call constructor to initialize native object. | |
| // | |
| // Since the constructor takes some optional arguments that are not passed, it | |
| // is as though the web components runtime explicitly passed `null` for all | |
| // parameters. | |
| // | |
| // TODO(sra): The constructor returned by findConstructorForNativeSubclassType | |
| // should be a function that fills in the default values. | |
| JS('', '#(#)', constructor, b); | |
| Expect.isTrue(b is B); | |
| Expect.equals(101, b.a1); | |
| Expect.equals(102, b.a2); | |
| Expect.equals(null, b.a3); | |
| Expect.equals('(null, 205)', b.a4); | |
| Expect.equals(null, b.b1); | |
| Expect.equals(202, b.b2); | |
| Expect.equals(null, b.b3); | |
| print(trace); | |
| Expect.equals('[202, 101, 104, body(A.three), (null, 205)]', '$trace'); | |
| } | |
| test_new() { | |
| trace = []; | |
| checkThrows(action, description) { | |
| Expect.throws(action, (e) => true, "'$description must fail'"); | |
| } | |
| checkThrows(() => new B.one(), 'new B.one()'); | |
| checkThrows(() => new B.two(), 'new B.two()'); | |
| checkThrows(() => new B.three(), 'new B.three()'); | |
| checkThrows(() => new B.three(1), 'new B.three(1)'); | |
| checkThrows(() => new B.three([]), 'new B.three([])'); | |
| } | |
| main() { | |
| nativeTesting(); | |
| setup(); | |
| log = (message) { | |
| trace.add('$message'); | |
| return message; | |
| }; | |
| setNativeSubclassDispatchRecord(getBPrototype(), findInterceptorForType(B)); | |
| test_one(); | |
| test_two(); | |
| test_three(); | |
| test_new(); | |
| } |