From 726ce8240211725f14303a6979b8516bafc8aba2 Mon Sep 17 00:00:00 2001 From: Kenzie Schmoll Date: Wed, 19 Jan 2022 18:40:47 +0000 Subject: [PATCH 1/4] Update devtools dep to version 2.9.2+1 Change-Id: I3b0fdc6100874794e874471d3c8e1b269c65d2db Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/228902 Reviewed-by: Ben Konyi --- DEPS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DEPS b/DEPS index b98102b0c95..60bf931b472 100644 --- a/DEPS +++ b/DEPS @@ -108,7 +108,7 @@ vars = { "dart_style_rev": "08b0294d0a500d5c02168ef57dcb8868d0c3cb48", "dartdoc_rev" : "11c4b3c9723bfa7155efcf0fef02329233a6381d", - "devtools_rev" : "85932bb66aa782c4b2c528be7718960bf256ffb7", + "devtools_rev" : "013958fbd45351e5975068756b7b9114465a7f98", "jsshell_tag": "version:88.0", "ffi_rev": "4dd32429880a57b64edaf54c9d5af8a9fa9a4ffb", "fixnum_rev": "16d3890c6dc82ca629659da1934e412292508bba", From 91b75ba69e6d1f94cfb9b016244bd6b9c2b17526 Mon Sep 17 00:00:00 2001 From: Michael Thomsen Date: Thu, 20 Jan 2022 11:46:27 +0000 Subject: [PATCH 2/4] Add deprecation warnings This merely ports the changes already made to the other analyzer binaries: https://dart-review.googlesource.com/c/sdk/+/219702 Change-Id: If848b164eff7d9bf166734aaad437749e44b04a4 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/229143 Reviewed-by: William Hesse Commit-Queue: Michael Thomsen --- sdk/bin/dartanalyzer_sdk | 2 ++ sdk/bin/dartanalyzer_sdk.bat | 2 ++ 2 files changed, 4 insertions(+) diff --git a/sdk/bin/dartanalyzer_sdk b/sdk/bin/dartanalyzer_sdk index 88f4deb0434..bb7b84af85f 100755 --- a/sdk/bin/dartanalyzer_sdk +++ b/sdk/bin/dartanalyzer_sdk @@ -6,6 +6,8 @@ # Run dartanalyzer.dart on the Dart VM. This script assumes the Dart SDK's # directory structure. +echo "Warning: 'dartanalyzer' is deprecated. Please use 'dart analyze'." 1>&2 + function follow_links() { file="$1" while [ -h "$file" ]; do diff --git a/sdk/bin/dartanalyzer_sdk.bat b/sdk/bin/dartanalyzer_sdk.bat index 57dd538db73..7b1e03bfcad 100644 --- a/sdk/bin/dartanalyzer_sdk.bat +++ b/sdk/bin/dartanalyzer_sdk.bat @@ -3,6 +3,8 @@ REM Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file REM for details. All rights reserved. Use of this source code is governed by a REM BSD-style license that can be found in the LICENSE file. +echo Warning: 'dartanalyzer' is deprecated. Please use 'dart analyze'. 1>&2 + setlocal rem Handle the case where dart-sdk/bin has been symlinked to. set DIR_NAME_WITH_SLASH=%~dp0 From 7deca930be8b2996e9851730856796ce69cbd740 Mon Sep 17 00:00:00 2001 From: Srujan Gaddam Date: Fri, 21 Jan 2022 01:04:10 +0000 Subject: [PATCH 3/4] [dart2js] Handle `Object` members of `dart:html` types `dart:html` types have changed to inherit `JavaScriptObject`. Therefore, the dart2js runtime needs to be changed so that interceptors are still created for those types, and they're properly handled in `toString` calculations. Includes tests on `Object` members that are currently inconsistent between both compilers. This test passes on dart2js with and without making the types in `dart:html` extend `JavaScriptObject`. This test fails in DDC for the following reasons: - `toString` of native types calls the native `toString` - `hashCode` for interop objects are random and not 0 - `runtimeType` of interop objects is `LegacyJavaScriptObject` not `JSObject` Change-Id: Ibf80109174615120df9e64995fa13016f7a1677b Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/228741 Reviewed-by: Stephen Adams Commit-Queue: Srujan Gaddam --- .../lib/src/js_emitter/native_emitter.dart | 9 +++ .../jsinterop/internal_annotations_test.dart | 10 ++- pkg/compiler/test/jsinterop/world_test.dart | 10 ++- .../_internal/js_runtime/lib/js_helper.dart | 14 ++-- tests/web/dart2js.status | 4 + tests/web/internal/object_members_test.dart | 80 +++++++++++++++++++ tests/web_2/dart2js_2.status | 4 + tests/web_2/internal/object_members_test.dart | 80 +++++++++++++++++++ 8 files changed, 203 insertions(+), 8 deletions(-) create mode 100644 tests/web/internal/object_members_test.dart create mode 100644 tests/web_2/internal/object_members_test.dart diff --git a/pkg/compiler/lib/src/js_emitter/native_emitter.dart b/pkg/compiler/lib/src/js_emitter/native_emitter.dart index a3137e7930e..857b67bebcd 100644 --- a/pkg/compiler/lib/src/js_emitter/native_emitter.dart +++ b/pkg/compiler/lib/src/js_emitter/native_emitter.dart @@ -94,6 +94,7 @@ class NativeEmitter { Class objectClass = null; Class jsInterceptorClass = null; + Class jsJavaScriptObjectClass = null; void walk(Class cls) { if (cls.element == _commonElements.objectClass) { @@ -104,6 +105,11 @@ class NativeEmitter { jsInterceptorClass = cls; return; } + // Native classes may inherit either `Interceptor` e.g. `JSBool` or + // `JavaScriptObject` e.g. `dart:html` classes. + if (cls.element == _commonElements.jsJavaScriptObjectClass) { + jsJavaScriptObjectClass = cls; + } if (seen.contains(cls)) return; seen.add(cls); walk(cls.superclass); @@ -215,6 +221,9 @@ class NativeEmitter { // by getNativeInterceptor and custom elements. if (_nativeCodegenEnqueuer.hasInstantiatedNativeClasses) { fillNativeInfo(jsInterceptorClass); + if (jsJavaScriptObjectClass != null) { + fillNativeInfo(jsJavaScriptObjectClass); + } for (Class cls in classes) { if (!cls.isNative || neededClasses.contains(cls)) { fillNativeInfo(cls); diff --git a/pkg/compiler/test/jsinterop/internal_annotations_test.dart b/pkg/compiler/test/jsinterop/internal_annotations_test.dart index 4299a38b83c..62deced1da6 100644 --- a/pkg/compiler/test/jsinterop/internal_annotations_test.dart +++ b/pkg/compiler/test/jsinterop/internal_annotations_test.dart @@ -184,7 +184,15 @@ $mainSource "Expected $name to be indirectly instantiated in `${mainSource}`:" "\n${world.classHierarchy.dump(cls)}"); } - if (!isInstantiated && (name != 'Object' && name != 'Interceptor')) { + // Classes that are expected to be instantiated by default. `Object` and + // `Interceptor` are base types for non-native and native types, and + // `JavaScriptObject` is the base type for `dart:html` types. + var insantiatedBaseClasses = [ + 'Object', + 'Interceptor', + 'JavaScriptObject' + ]; + if (!isInstantiated && !insantiatedBaseClasses.contains(name)) { Expect.isFalse( world.classHierarchy.isInstantiated(cls), "Expected $name to be uninstantiated in `${mainSource}`:" diff --git a/pkg/compiler/test/jsinterop/world_test.dart b/pkg/compiler/test/jsinterop/world_test.dart index 6c3253fec08..230873f716c 100644 --- a/pkg/compiler/test/jsinterop/world_test.dart +++ b/pkg/compiler/test/jsinterop/world_test.dart @@ -178,7 +178,15 @@ $mainSource "Expected $name to be indirectly instantiated in `${mainSource}`:" "\n${world.classHierarchy.dump(cls)}"); } - if (!isInstantiated && (name != 'Object' && name != 'Interceptor')) { + // Classes that are expected to be instantiated by default. `Object` and + // `Interceptor` are base types for non-native and native types, and + // `JavaScriptObject` is the base type for `dart:html` types. + var insantiatedBaseClasses = [ + 'Object', + 'Interceptor', + 'JavaScriptObject' + ]; + if (!isInstantiated && !insantiatedBaseClasses.contains(name)) { Expect.isFalse( world.classHierarchy.isInstantiated(cls), "Expected $name to be uninstantiated in `${mainSource}`:" diff --git a/sdk/lib/_internal/js_runtime/lib/js_helper.dart b/sdk/lib/_internal/js_runtime/lib/js_helper.dart index a7f3ca829a8..d41e5114780 100644 --- a/sdk/lib/_internal/js_runtime/lib/js_helper.dart +++ b/sdk/lib/_internal/js_runtime/lib/js_helper.dart @@ -415,19 +415,21 @@ class Primitives { var interceptor = getInterceptor(object); if (identical(interceptor, JS_INTERCEPTOR_CONSTANT(Interceptor)) || + identical(interceptor, JS_INTERCEPTOR_CONSTANT(JavaScriptObject)) || object is UnknownJavaScriptObject) { // Try to do better. If we do not find something better, fallthrough to - // Dart-type based name that leave the name as 'UnknownJavaScriptObject' - // or 'Interceptor' (or the minified versions thereof). + // Dart-type based name that leave the name as 'UnknownJavaScriptObject', + // 'Interceptor', or 'JavaScriptObject' (or their minified versions). // // When we get here via the UnknownJavaScriptObject test (for JavaScript // objects from outside the program), the object's constructor has a // better name that 'UnknownJavaScriptObject'. // - // When we get here the Interceptor test (for Native classes that are - // declared in the Dart program but have been 'folded' into Interceptor), - // the native class's constructor name is better than the generic - // 'Interceptor' (an abstract class). + // When we get here via either the Interceptor or JavaScriptObject test + // (for Native classes that are declared in the Dart program but have been + // 'folded' into one of those interceptors), the native class's + // constructor name is better than the generic 'Interceptor' or + // 'JavaScriptObject'. // Try the [constructorNameFallback]. This gets the constructor name for // any browser (used by [getNativeInterceptor]). diff --git a/tests/web/dart2js.status b/tests/web/dart2js.status index 9faa92ad3de..826b7848f40 100644 --- a/tests/web/dart2js.status +++ b/tests/web/dart2js.status @@ -24,12 +24,16 @@ deferred_split_test: Slow, Pass # Issue 25940 [ $compiler == dart2js && $runtime == chrome && $csp ] deferred/load_in_correct_order_test: SkipByDesign # Purposely uses `eval` +[ $compiler == dart2js && $runtime == d8 ] +internal/object_members_test: SkipByDesign # Browser test + [ $compiler == dart2js && $runtime == ff && $system == windows ] consistent_index_error_string_test: Slow, Pass # Issue 25940 [ $compiler == dart2js && $csp ] deferred_custom_loader_test: SkipByDesign # Issue 25683 deferred_fail_and_retry_test: SkipByDesign # Uses eval to simulate failed loading. +internal/object_members_test: SkipByDesign # Uses eval for interop [ $compiler == dart2js && !$host_checked ] dummy_compiler_test: Slow, Pass # Issue 32439. self-hosting doesn't work with CFE yet. diff --git a/tests/web/internal/object_members_test.dart b/tests/web/internal/object_members_test.dart new file mode 100644 index 00000000000..02092eb1022 --- /dev/null +++ b/tests/web/internal/object_members_test.dart @@ -0,0 +1,80 @@ +// 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/minitest.dart'; + +import 'dart:html'; +import 'dart:_interceptors' show JSObject; + +@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 that do not have an overridden `toString` + // should look up the type through the proto. + expect(window.navigator.toString(), "Instance of 'Navigator'"); + + // Interop type. + var js = JSClass(); + expect(js == js, true); + expect(js == JSClass(), false); + // TODO(srujzs): Modify this once interop has random hash codes. + hashCode = js.hashCode; + 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); + expect(js.runtimeType, JSObject); +} diff --git a/tests/web_2/dart2js_2.status b/tests/web_2/dart2js_2.status index 9faa92ad3de..826b7848f40 100644 --- a/tests/web_2/dart2js_2.status +++ b/tests/web_2/dart2js_2.status @@ -24,12 +24,16 @@ deferred_split_test: Slow, Pass # Issue 25940 [ $compiler == dart2js && $runtime == chrome && $csp ] deferred/load_in_correct_order_test: SkipByDesign # Purposely uses `eval` +[ $compiler == dart2js && $runtime == d8 ] +internal/object_members_test: SkipByDesign # Browser test + [ $compiler == dart2js && $runtime == ff && $system == windows ] consistent_index_error_string_test: Slow, Pass # Issue 25940 [ $compiler == dart2js && $csp ] deferred_custom_loader_test: SkipByDesign # Issue 25683 deferred_fail_and_retry_test: SkipByDesign # Uses eval to simulate failed loading. +internal/object_members_test: SkipByDesign # Uses eval for interop [ $compiler == dart2js && !$host_checked ] dummy_compiler_test: Slow, Pass # Issue 32439. self-hosting doesn't work with CFE yet. diff --git a/tests/web_2/internal/object_members_test.dart b/tests/web_2/internal/object_members_test.dart new file mode 100644 index 00000000000..02092eb1022 --- /dev/null +++ b/tests/web_2/internal/object_members_test.dart @@ -0,0 +1,80 @@ +// 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/minitest.dart'; + +import 'dart:html'; +import 'dart:_interceptors' show JSObject; + +@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 that do not have an overridden `toString` + // should look up the type through the proto. + expect(window.navigator.toString(), "Instance of 'Navigator'"); + + // Interop type. + var js = JSClass(); + expect(js == js, true); + expect(js == JSClass(), false); + // TODO(srujzs): Modify this once interop has random hash codes. + hashCode = js.hashCode; + 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); + expect(js.runtimeType, JSObject); +} From 51a46f783b94a7758401a621791efbc7183a6a6c Mon Sep 17 00:00:00 2001 From: Jonas Termansen Date: Fri, 21 Jan 2022 13:06:00 +0000 Subject: [PATCH 4/4] [infra] Handle DART_EXPERIMENTAL_BUILD in tools/bots/dart-sdk.py. This change uses the DART_EXPERIMENTAL_BUILD environment variable to detect whether the current build happens to be experimental and shouldn't have side effects. Bug: b/215113476 Change-Id: Id5442d80d69309e320077f053d8af75b3aab670a Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/228862 Reviewed-by: Alexander Thomas Commit-Queue: Jonas Termansen --- tools/bots/dart_sdk.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/bots/dart_sdk.py b/tools/bots/dart_sdk.py index d14f3ce1119..934906f52e6 100755 --- a/tools/bots/dart_sdk.py +++ b/tools/bots/dart_sdk.py @@ -79,7 +79,7 @@ def DartArchiveUnstrippedBinaries(arch): def CreateUploadAPIDocs(): dartdoc_dir = BuildRootPath('gen-dartdocs') dartdoc_zip = BuildRootPath('dartdocs-api.zip') - if CHANNEL == bot_utils.Channel.TRY: + if CHANNEL == bot_utils.Channel.TRY or DART_EXPERIMENTAL_BUILD == '1': BuildDartdocAPIDocs(dartdoc_dir) else: UploadApiLatestFile() @@ -222,12 +222,13 @@ if __name__ == '__main__': BUILD_OS = utils.GuessOS() BUILDER_NAME = os.environ.get('BUILDBOT_BUILDERNAME') + DART_EXPERIMENTAL_BUILD = os.environ.get('DART_EXPERIMENTAL_BUILD') CHANNEL = bot_utils.GetChannelFromName(BUILDER_NAME) if command == 'api_docs': if BUILD_OS == 'linux': CreateUploadAPIDocs() - elif CHANNEL != bot_utils.Channel.TRY: + elif CHANNEL != bot_utils.Channel.TRY and DART_EXPERIMENTAL_BUILD != '1': for arch in archs: print('Create and upload sdk zip for ' + arch) sdk_path = BuildRootPath('dart-sdk', arch=arch)