Skip to content

Commit

Permalink
Add native_testing library to mock @Native classes
Browse files Browse the repository at this point in the history
Convert 114 tests to use native_testing.dart library.

Review URL: https://codereview.chromium.org/2379173002 .
  • Loading branch information
rakudrama committed Sep 30, 2016
1 parent 1a802d3 commit ddfc70f
Show file tree
Hide file tree
Showing 116 changed files with 894 additions and 490 deletions.
18 changes: 17 additions & 1 deletion sdk/lib/_internal/js_runtime/lib/interceptors.dart
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,16 @@ getNativeInterceptor(object) {
}
}

var interceptor = lookupAndCacheInterceptor(object);
// Check for cached UnknownJavaScriptObject. This avoids doing the slow
// dispatch-record based lookup for repeated js-interop classes.
var constructor = JS('', '#.constructor', object);
var interceptor = JS('', '#.get(#)', constructorToInterceptor, constructor);
if (interceptor != null) return interceptor;

// This takes care of dispatch-record based caching, but not constructor based
// caching of [UnknownJavaScriptObject]s.
interceptor = lookupAndCacheInterceptor(object);

if (interceptor == null) {
// JavaScript Objects created via object literals and `Object.create(null)`
// are 'plain' Objects. This test could be simplified and the dispatch path
Expand All @@ -180,6 +189,10 @@ getNativeInterceptor(object) {
var proto = JS('', 'Object.getPrototypeOf(#)', object);
if (JS('bool', '# == null || # === Object.prototype', proto, proto)) {
return JS_INTERCEPTOR_CONSTANT(PlainJavaScriptObject);
} else if (JS('bool', 'typeof # == "function"', constructor)) {
interceptor = JS_INTERCEPTOR_CONSTANT(UnknownJavaScriptObject);
JS('', '#.set(#, #)', constructorToInterceptor, constructor, interceptor);
return interceptor;
} else {
return JS_INTERCEPTOR_CONSTANT(UnknownJavaScriptObject);
}
Expand All @@ -188,6 +201,9 @@ getNativeInterceptor(object) {
return interceptor;
}

var constructorToInterceptor =
JS('', 'typeof(self.WeakMap) == "undefined" ? new Map() : new WeakMap()');

/**
* Data structure used to map a [Type] to the [Interceptor] and constructors for
* that type. It is JavaScript array of 3N entries of adjacent slots containing
Expand Down
14 changes: 5 additions & 9 deletions sdk/lib/_internal/js_runtime/lib/native_helper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -449,21 +449,17 @@ applyHooksTransformer(transformer, hooks) {

const _baseHooks = const JS_CONST(r'''
function() {
function typeNameInChrome(o) {
var constructor = o.constructor;
if (constructor) {
var name = constructor.name;
if (name) return name;
}
var s = Object.prototype.toString.call(o);
var toStringFunction = Object.prototype.toString;
function getTag(o) {
var s = toStringFunction.call(o);
return s.substring(8, s.length - 1);
}
function getUnknownTag(object, tag) {
// This code really belongs in [getUnknownTagGenericBrowser] but having it
// here allows [getUnknownTag] to be tested on d8.
if (/^HTML[A-Z].*Element$/.test(tag)) {
// Check that it is not a simple JavaScript object.
var name = Object.prototype.toString.call(object);
var name = toStringFunction.call(object);
if (name == "[object Object]") return null;
return "HTMLElement";
}
Expand All @@ -484,7 +480,7 @@ function() {
var isBrowser = typeof navigator == "object";
return {
getTag: typeNameInChrome,
getTag: getTag,
getUnknownTag: isBrowser ? getUnknownTagGenericBrowser : getUnknownTag,
prototypeForTag: prototypeForTag,
discriminator: discriminator };
Expand Down
11 changes: 5 additions & 6 deletions tests/compiler/dart2js_native/abstract_class_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
// 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 "dart:_js_helper";
import "package:expect/expect.dart";
import "native_testing.dart";

// Native classes can have subclasses that are not declared to the program. The
// subclasses are indistinguishable from the base class. This means that
Expand All @@ -29,17 +28,17 @@ function B(){}
B.prototype.foo = function() { return 'B.foo'; };
makeA = function(){return new A};
makeB = function(){return new B};
self.nativeConstructor(A);
self.nativeConstructor(B);
""";

var inscrutable;
main() {
nativeTesting();
setup();
inscrutable = (x) => x;
inscrutable = inscrutable(inscrutable);

var a = makeA();
var b = makeB();
var c = inscrutable(new C());
var c = confuse(new C());

Expect.isTrue(a is A);
Expect.isFalse(b is A);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// Test calling convention of property extraction closures (super edition).
library bound_closure_super_test;

import "package:expect/expect.dart";
import 'package:expect/expect.dart';

import 'bound_closure_test.dart' as bound_closure_test;

Expand Down
7 changes: 5 additions & 2 deletions tests/compiler/dart2js_native/bound_closure_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
// 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 "dart:_js_helper";
import "package:expect/expect.dart";
import 'native_testing.dart';

// Test calling convention of property extraction closures.

Expand Down Expand Up @@ -42,9 +41,13 @@ CC.prototype.foo = function(u, v) {
makeBB = function(){return new BB;};
makeCC = function(){return new CC;};
inscrutable = function(a){return a;};
self.nativeConstructor(BB);
self.nativeConstructor(CC);
""";

main() {
nativeTesting();
setup();
var a = inscrutable(new AA());
var b = inscrutable(makeBB());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@
// 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 "dart:_js_helper";
import "package:expect/expect.dart";
//import 'dart:_foreign_helper' show JS;
//import 'dart:_js_helper' show Creates, setNativeSubclassDispatchRecord;
import "native_testing.dart";

// Test for dartNativeDispatchHooksTransformer, getTag hook.

Expand Down Expand Up @@ -42,6 +39,10 @@ makeT1A = function(){return new T1A;};
makeT1B = function(){return new T1CrazyB;};
makeT1C = function(){return new T1fakeA;};
self.nativeConstructor(T1A);
self.nativeConstructor(T1CrazyB);
self.nativeConstructor(T1fakeA);
var getTagCount = 0;
getTagCallCount = function() { return getTagCount; }
Expand Down Expand Up @@ -69,11 +70,9 @@ function transformer1(hooks) {
dartNativeDispatchHooksTransformer = [transformer1];
''';

var inscrutable;

main() {
nativeTesting();
setup();
inscrutable = (x) => x;

var t1a = makeT1A();
var t1b = makeT1B();
Expand All @@ -85,9 +84,9 @@ main() {

Expect.equals(2, getTagCallCount());

Expect.equals(true, inscrutable(t1a) is T1A, '$t1a is T1A');
Expect.equals(true, inscrutable(t1b) is T1B, '$t1b is T1B');
Expect.equals(true, inscrutable(t1c) is T1C, '$t1c is T1C');
Expect.equals(true, confuse(t1a) is T1A, '$t1a is T1A');
Expect.equals(true, confuse(t1b) is T1B, '$t1b is T1B');
Expect.equals(true, confuse(t1c) is T1C, '$t1c is T1C');

Expect.equals(2, getTagCallCount());
}
19 changes: 9 additions & 10 deletions tests/compiler/dart2js_native/browser_compat_1_unpatched_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@
// 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 "dart:_js_helper";
import "package:expect/expect.dart";
//import 'dart:_foreign_helper' show JS;
//import 'dart:_js_helper' show Creates, setNativeSubclassDispatchRecord;
import "native_testing.dart";

// Test for dartNativeDispatchHooksTransformer, getTag hook.
// Same as browser_compat_1_prepatched_test but with prepatching disabled.
Expand Down Expand Up @@ -43,6 +40,10 @@ makeT1A = function(){return new T1A;};
makeT1B = function(){return new T1CrazyB;};
makeT1C = function(){return new T1fakeA;};
self.nativeConstructor(T1A);
self.nativeConstructor(T1CrazyB);
self.nativeConstructor(T1fakeA);
var getTagCount = 0;
getTagCallCount = function() { return getTagCount; }
Expand Down Expand Up @@ -72,11 +73,9 @@ function transformer1(hooks) {
dartNativeDispatchHooksTransformer = [transformer1];
''';

var inscrutable;

main() {
nativeTesting();
setup();
inscrutable = (x) => x;

var t1a = makeT1A();
var t1b = makeT1B();
Expand All @@ -88,9 +87,9 @@ main() {

Expect.equals(3, getTagCallCount());

Expect.equals(true, inscrutable(t1a) is T1A, '$t1a is T1A');
Expect.equals(true, inscrutable(t1b) is T1B, '$t1b is T1B');
Expect.equals(true, inscrutable(t1c) is T1C, '$t1c is T1C');
Expect.equals(true, confuse(t1a) is T1A, '$t1a is T1A');
Expect.equals(true, confuse(t1b) is T1B, '$t1b is T1B');
Expect.equals(true, confuse(t1c) is T1C, '$t1c is T1C');

Expect.equals(3, getTagCallCount());
}
44 changes: 23 additions & 21 deletions tests/compiler/dart2js_native/browser_compat_2_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
// 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 "dart:_js_helper";
import "package:expect/expect.dart";
import "native_testing.dart";

// Test for dartNativeDispatchHooksTransformer
// - uncached, instance, leaf and interior caching modes.
Expand Down Expand Up @@ -63,6 +62,11 @@ makeT1B = function(){return new T1B;};
makeT1C = function(){return new T1C;};
makeT1D = function(){return new T1D;};
self.nativeConstructor(T1A);
self.nativeConstructor(T1B);
self.nativeConstructor(T1C);
self.nativeConstructor(T1D);
var getTagCount = 0;
getTagCallCount = function() { return getTagCount; }
clearTagCallCount = function() { getTagCount = 0; }
Expand Down Expand Up @@ -99,29 +103,27 @@ function transformer2(hooks) {
dartNativeDispatchHooksTransformer = [transformer1, transformer2];
''';

var inscrutable;

main() {
nativeTesting();
setup();
inscrutable = (x) => x;

var t1a = makeT1A();
var t1b = makeT1B();
var t1c = makeT1C();
var t1d = makeT1D();

clearTagCallCount();
Expect.equals("aA", inscrutable(t1a).foo(), 't1a is T1A');
Expect.equals("bB", inscrutable(t1b).foo(), 't1b is T1B');
Expect.equals("cC", inscrutable(t1c).foo(), 't1c is T1C');
Expect.equals("dD", inscrutable(t1d).foo(), 't1d is T1D');
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", inscrutable(t1a).foo(), 't1a is T1A');
Expect.equals("bB", inscrutable(t1b).foo(), 't1b is T1B');
Expect.equals("cC", inscrutable(t1c).foo(), 't1c is T1C');
Expect.equals("dD", inscrutable(t1d).foo(), 't1d is T1D');
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();
Expand All @@ -130,18 +132,18 @@ main() {
t1d = makeT1D();

clearTagCallCount();
Expect.equals("aA", inscrutable(t1a).foo(), 't1a is T1A');
Expect.equals("bB", inscrutable(t1b).foo(), 't1b is T1B');
Expect.equals("cC", inscrutable(t1c).foo(), 't1c is T1C');
Expect.equals("dD", inscrutable(t1d).foo(), 't1d is T1D');
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", inscrutable(t1a).foo(), 't1a is T1A');
Expect.equals("bB", inscrutable(t1b).foo(), 't1b is T1B');
Expect.equals("cC", inscrutable(t1c).foo(), 't1c is T1C');
Expect.equals("dD", inscrutable(t1d).foo(), 't1d is T1D');
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');
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
// 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 'dart:_foreign_helper' show JS;
import "package:expect/expect.dart";
import 'native_testing.dart';

// Try throwing a javascript null, and getting a stack-trace from it.

Expand Down
13 changes: 8 additions & 5 deletions tests/compiler/dart2js_native/core_type_check_native_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@
// 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 "dart:_js_helper";
import "package:expect/expect.dart";

var inscrutable = (int x) => x == 0 ? 0 : x | inscrutable(x & (x - 1));
import "native_testing.dart";

@Native("A")
class A {}
Expand Down Expand Up @@ -33,6 +30,11 @@ function C() {};
makeC = function() { return new C; }
function D() {};
makeD = function() { return new D; }
self.nativeConstructor(A);
self.nativeConstructor(B);
self.nativeConstructor(C);
self.nativeConstructor(D);
""";

checkTest(value, expectComparable, expectPattern) {
Expand Down Expand Up @@ -65,7 +67,7 @@ checkAll(check) {
makeC(),
makeD()
];
value(i) => things[inscrutable(i)];
value(i) => confuse(things[i]);

check(value(0), false, false); // List
check(value(1), true, false); // int
Expand All @@ -79,6 +81,7 @@ checkAll(check) {
}

main() {
nativeTesting();
setup();

checkAll(checkTest);
Expand Down
8 changes: 0 additions & 8 deletions tests/compiler/dart2js_native/dart2js_native.status
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,3 @@ optimization_hints_test: Fail, OK # Test relies on unminified names.

[ $compiler == dart2js && $runtime == d8 && $system == windows ]
compute_this_script_test: Skip # Issue 17458

[ $compiler == dart2js && $cps_ir ]
foreign_test: RuntimeError # Expect.equals(expected: <1234567891011>, actual: <1234567891011>) fails.
native_exception_test: RuntimeError # Issue 24421
optimization_hints_test: RuntimeError # Please triage this failure.

[ $compiler == dart2js && $cps_ir && $checked ]
*: Skip # `assert` not implemented, 75% of the tests fail.
Loading

0 comments on commit ddfc70f

Please sign in to comment.