| // 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 for super access from classes that extend native classes. |
| |
| @Native("N1") |
| class N1 {} |
| |
| @Native("N2") |
| class N2 extends N1 { |
| N2.init(); |
| void set text(String unused) native; |
| String get text native; |
| foo() native; |
| } |
| |
| class AA extends N2 { |
| AA.init() : super.init(); |
| String? afield; |
| afun() => 'afun:$afield'; |
| } |
| |
| class BB extends AA { |
| BB.init() : super.init(); |
| |
| get text => super.text; |
| set text(value) => super.text = value; |
| foo() => super.foo(); |
| |
| get afield => super.afield; |
| set afield(value) => super.afield = value; |
| afun() => super.afun(); |
| } |
| |
| BB makeBB() native; |
| |
| @Creates('=Object') |
| getBBPrototype() native; |
| |
| void setup() { |
| JS('', r""" |
| (function(){ |
| function N2() {} |
| N2.prototype.foo = function() { return "foo:" + this.text; }; |
| function BB() {} |
| BB.prototype.__proto__ = N2.prototype; |
| self.makeBB = function(){return new BB()}; |
| |
| self.getBBPrototype = function(){return BB.prototype;}; |
| })()"""); |
| } |
| |
| testSuperOnNative() { |
| BB b1 = makeBB(); |
| BB b2 = makeBB(); |
| |
| var constructor = findConstructorForNativeSubclassType(BB, 'init'); |
| Expect.isNotNull(constructor); |
| JS('', '#(#)', constructor, b1); |
| JS('', '#(#)', constructor, b2); |
| |
| b1.text = confuse('one'); |
| b2.text = confuse('two'); |
| |
| print('b1.text ${confuse(b1).text}'); |
| print('b2.text ${confuse(b2).text}'); |
| |
| print('b1.foo() ${confuse(b1).foo()}'); |
| print('b2.foo() ${confuse(b2).foo()}'); |
| |
| Expect.equals('one', b1.text); |
| Expect.equals('two', b2.text); |
| |
| Expect.equals('foo:one', b1.foo()); |
| Expect.equals('foo:two', b2.foo()); |
| |
| confuse(b1).text = confuse('three'); |
| confuse(b2).text = confuse('four'); |
| |
| Expect.equals('three', confuse(b1).text); |
| Expect.equals('four', confuse(b2).text); |
| |
| Expect.equals('foo:three', confuse(b1).foo()); |
| Expect.equals('foo:four', confuse(b2).foo()); |
| } |
| |
| testSuperOnSubclassOfNative() { |
| BB b1 = makeBB(); |
| BB b2 = makeBB(); |
| |
| var constructor = findConstructorForNativeSubclassType(BB, 'init'); |
| Expect.isNotNull(constructor); |
| JS('', '#(#)', constructor, b1); |
| JS('', '#(#)', constructor, b2); |
| |
| b1.afield = confuse('one'); |
| b2.afield = confuse('two'); |
| |
| print('b1.afield ${confuse(b1).afield}'); |
| print('b2.afield ${confuse(b2).afield}'); |
| |
| print('b1.afun() ${confuse(b1).afun()}'); |
| print('b2.afun() ${confuse(b2).afun()}'); |
| |
| Expect.equals('one', b1.afield); |
| Expect.equals('two', b2.afield); |
| |
| Expect.equals('afun:one', b1.afun()); |
| Expect.equals('afun:two', b2.afun()); |
| |
| confuse(b1).afield = confuse('three'); |
| confuse(b2).afield = confuse('four'); |
| |
| Expect.equals('three', confuse(b1).afield); |
| Expect.equals('four', confuse(b2).afield); |
| |
| Expect.equals('afun:three', confuse(b1).afun()); |
| Expect.equals('afun:four', confuse(b2).afun()); |
| } |
| |
| main() { |
| nativeTesting(); |
| setup(); |
| |
| setNativeSubclassDispatchRecord(getBBPrototype(), findInterceptorForType(BB)); |
| |
| testSuperOnNative(); |
| testSuperOnSubclassOfNative(); |
| } |