blob: 2116dd43387c792901bcc540349e1d0a2cdbce46 [file] [log] [blame]
// Copyright (c) 2022, 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.
// Make sure `Object` methods work as expected with `dart:html` and interop
// types. The expectations here aren't guarantees that they should work a
// particular way, but rather a way to monitor regressions/changes.
@JS()
library object_members_test;
import 'package:js/js.dart';
import 'package:expect/legacy/minitest.dart'; // ignore: deprecated_member_use_from_same_package
import 'dart:html';
import 'dart:_interceptors' show JSObject, LegacyJavaScriptObject;
const isDart2JS = const bool.fromEnvironment('dart.library._dart2js_only');
@JS()
external void eval(String code);
@JS()
class JSClass {
external JSClass();
}
void main() {
eval(r'''
function JSClass() {}
''');
// `dart:html` type.
var div = document.createElement('div');
expect(div == div, true);
expect(div == DomPointReadOnly(), false);
// Ensure that we get a random hash for each new instance. It should be
// improbable for this to fail across many runs if the hash is
// non-deterministic.
var hashCode = div.hashCode;
var attempts = 0;
var maxAttempts = 1000;
while (div.hashCode == hashCode && attempts < maxAttempts) {
div = document.createElement('div');
attempts++;
}
expect(attempts > 0 && attempts != maxAttempts, isTrue);
expect(div.toString, isNotNull);
expect(div.toString(), 'div');
expect(div.noSuchMethod, isNotNull);
var noSuchMethodErrorThrown = true;
try {
(div as dynamic).triggerNoSuchMethod();
noSuchMethodErrorThrown = false;
} catch (_) {}
expect(noSuchMethodErrorThrown, isTrue);
expect(div.runtimeType, DivElement);
// `toString` for `dart:html` types depend on the implementation. dart2js
// provides a more readable string, whereas DDC just uses the underlying
// `toString`.
final navigatorToString = window.navigator.toString();
if (isDart2JS) {
expect(navigatorToString, "Instance of 'Navigator'");
} else {
expect(navigatorToString, "[object Navigator]");
}
// Interop type.
var js = JSClass();
expect(js == js, true);
expect(js == JSClass(), false);
hashCode = js.hashCode;
if (isDart2JS) {
// DDC adds a random hash code to the object (should use a weak map), but
// dart2js returns 0 for all `LegacyJavaScriptObject`s.
// TODO(srujzs): Modify this once interop has random hash codes.
expect(hashCode, 0);
}
expect(hashCode, js.hashCode);
expect(js.toString, isNotNull);
// Should forward to underlying `toString` call.
expect(js.toString(), '[object Object]');
expect(js.noSuchMethod, isNotNull);
noSuchMethodErrorThrown = true;
try {
(js as dynamic).triggerNoSuchMethod();
noSuchMethodErrorThrown = false;
} catch (_) {}
expect(noSuchMethodErrorThrown, isTrue);
final runtimeType = js.runtimeType;
if (isDart2JS) {
// dart2js explicitly returns `JSObject` as the `runtimeType` for all
// `LegacyJavaScriptObject`s.
expect(runtimeType, JSObject);
} else {
expect(runtimeType, LegacyJavaScriptObject);
}
}