ba40d9bece
Change-Id: I73edeeaf4934899b71d6335dcb4b4b54dce46bae Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/426340 Auto-Submit: Bob Nystrom <rnystrom@google.com> Reviewed-by: Nate Biggs <natebiggs@google.com> Commit-Queue: Nate Biggs <natebiggs@google.com>
160 lines
4.4 KiB
Dart
160 lines
4.4 KiB
Dart
// 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";
|
|
|
|
// Test for dartNativeDispatchHooksTransformer
|
|
// - uncached, instance, leaf and interior caching modes.
|
|
// - composition of getTag.
|
|
|
|
@Native("T1A")
|
|
class T1A {
|
|
foo() native;
|
|
}
|
|
|
|
@Native("T1B")
|
|
class T1B {
|
|
foo() native;
|
|
}
|
|
|
|
@Native("T1C")
|
|
class T1C {
|
|
foo() native;
|
|
}
|
|
|
|
@Native("T1D")
|
|
class T1D {
|
|
foo() native;
|
|
}
|
|
|
|
makeT1A() native;
|
|
makeT1B() native;
|
|
makeT1C() native;
|
|
makeT1D() native;
|
|
|
|
int getTagCallCount() native;
|
|
void clearTagCallCount() native;
|
|
|
|
void setup() {
|
|
JS('', r'''
|
|
(function(){
|
|
function T1A() { this.v = "a"; }
|
|
function T1B() { this.v = "b"; }
|
|
function T1C() { this.v = "c"; }
|
|
function T1D() { this.v = "d"; }
|
|
|
|
// T1B, T1C and T1D extend T1A in the implementation but not the declared types.
|
|
// T1A must not be leaf-cached otherwise we will pick up the interceptor for T1A
|
|
// when looking for the dispatch record for an uncached or not-yet-cached T1B,
|
|
// T1C or T1D.
|
|
Object.setPrototypeOf(T1B.prototype, T1A.prototype);
|
|
Object.setPrototypeOf(T1C.prototype, T1A.prototype);
|
|
Object.setPrototypeOf(T1D.prototype, T1A.prototype);
|
|
|
|
// All classes share one implementation of native method 'foo'.
|
|
T1A.prototype.foo = function() { return this.v + this.name(); };
|
|
T1A.prototype.name = function() { return "A"; };
|
|
T1B.prototype.name = function() { return "B"; };
|
|
T1C.prototype.name = function() { return "C"; };
|
|
T1D.prototype.name = function() { return "D"; };
|
|
|
|
self.makeT1A = function(){return new T1A()};
|
|
self.makeT1B = function(){return new T1B()};
|
|
self.makeT1C = function(){return new T1C()};
|
|
self.makeT1D = function(){return new T1D()};
|
|
|
|
self.nativeConstructor(T1A, undefined, true);
|
|
self.nativeConstructor(T1B, undefined, true);
|
|
self.nativeConstructor(T1C, undefined, true);
|
|
self.nativeConstructor(T1D, undefined, true);
|
|
|
|
var getTagCount = 0;
|
|
self.getTagCallCount = function() { return getTagCount; };
|
|
self.clearTagCallCount = function() { getTagCount = 0; };
|
|
|
|
function transformer1(hooks) {
|
|
var getTag = hooks.getTag;
|
|
|
|
function getTagNew(obj) {
|
|
var tag = getTag(obj);
|
|
// Dependency to test composition, rename T1D -> Dep -> -T1D.
|
|
if (tag == "T1D") return "Dep";
|
|
return tag;
|
|
}
|
|
|
|
hooks.getTag = getTagNew;
|
|
}
|
|
|
|
function transformer2(hooks) {
|
|
var getTag = hooks.getTag;
|
|
|
|
function getTagNew(obj) {
|
|
++getTagCount;
|
|
var tag = getTag(obj);
|
|
if (tag == "T1A") return "+T1A"; // Interior cached on prototype
|
|
if (tag == "T1B") return "~T1B"; // Uncached
|
|
if (tag == "T1C") return "!T1C"; // Instance cached
|
|
if (tag == "Dep") return "-T1D"; // Leaf cached on prototype
|
|
return tag;
|
|
}
|
|
|
|
hooks.getTag = getTagNew;
|
|
}
|
|
|
|
self.dartNativeDispatchHooksTransformer = [transformer1, transformer2];
|
|
})()''');
|
|
applyTestExtensions(['T1A', 'T1B', 'T1C', 'T1D']);
|
|
}
|
|
|
|
main() {
|
|
nativeTesting();
|
|
setup();
|
|
|
|
var t1a = makeT1A();
|
|
var t1b = makeT1B();
|
|
var t1c = makeT1C();
|
|
var t1d = makeT1D();
|
|
|
|
clearTagCallCount();
|
|
Expect.equals("aA", confuse(t1a).foo(), 't1a is T1A');
|
|
Expect.equals("bB", confuse(t1b).foo(), 't1b is T1B');
|
|
Expect.equals("cC", confuse(t1c).foo(), 't1c is T1C');
|
|
Expect.equals("dD", confuse(t1d).foo(), 't1d is T1D');
|
|
Expect.equals(4, getTagCallCount(), '4 fresh instances / types');
|
|
|
|
clearTagCallCount();
|
|
Expect.equals("aA", confuse(t1a).foo(), 't1a is T1A');
|
|
Expect.equals("bB", confuse(t1b).foo(), 't1b is T1B');
|
|
Expect.equals("cC", confuse(t1c).foo(), 't1c is T1C');
|
|
Expect.equals("dD", confuse(t1d).foo(), 't1d is T1D');
|
|
Expect.equals(1, getTagCallCount(), '1 = 1 uncached + (3 cached)');
|
|
|
|
t1a = makeT1A();
|
|
t1b = makeT1B();
|
|
t1c = makeT1C();
|
|
t1d = makeT1D();
|
|
|
|
clearTagCallCount();
|
|
Expect.equals("aA", confuse(t1a).foo(), 't1a is T1A');
|
|
Expect.equals("bB", confuse(t1b).foo(), 't1b is T1B');
|
|
Expect.equals("cC", confuse(t1c).foo(), 't1c is T1C');
|
|
Expect.equals("dD", confuse(t1d).foo(), 't1d is T1D');
|
|
Expect.equals(
|
|
2,
|
|
getTagCallCount(),
|
|
'2 = 1 fresh instance + 1 uncached (+ 2 proto cached)',
|
|
);
|
|
|
|
clearTagCallCount();
|
|
Expect.equals("aA", confuse(t1a).foo(), 't1a is T1A');
|
|
Expect.equals("bB", confuse(t1b).foo(), 't1b is T1B');
|
|
Expect.equals("cC", confuse(t1c).foo(), 't1c is T1C');
|
|
Expect.equals("dD", confuse(t1d).foo(), 't1d is T1D');
|
|
Expect.equals(
|
|
1,
|
|
getTagCallCount(),
|
|
'1 = 2 proto cached + 1 instance cached + 1 uncached',
|
|
);
|
|
}
|