diff --git a/LibTest/js_interop/JS/js_A03_t01.dart b/LibTest/js_interop/JS/js_A03_t01.dart new file mode 100644 index 0000000000..f46174db84 --- /dev/null +++ b/LibTest/js_interop/JS/js_A03_t01.dart @@ -0,0 +1,71 @@ +// Copyright (c) 2025, 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. + +/// @assertion An annotation on a JavaScript interop declaration. +/// ... +/// Specifying name customizes the JavaScript name to use, which can be used in +/// the following scenarios: +/// - Adding a JavaScript prefix to all the external top-level declarations, +/// static members, and constructors of a library by parameterizing the +/// annotation on the library with `name`. +/// - Specifying the JavaScript class to use for external static members and +/// constructors of an interop extension type by parameterizing the annotation +/// on the interop extension type with `name`. +/// - Renaming external declarations by parameterizing the annotation on the +/// member with `name`. +/// +/// @description Check that specifying `name` customizes the JavaScript `name` +/// to use. Test top-level declarations. +/// @author sgrekhov22@gmail.com + +import 'dart:js_interop'; +import 'dart:js_interop_unsafe'; +import '../../../Utils/expect.dart'; +import '../js_utils.dart'; + +@JS("jsVar1") +external int var1; + +@JS("jsVar2") +external final String var2; + +@JS("jsGetter") +external int get getter; + +@JS("jsF1") +external int f1(); + +@JS("jsF2") +external int f2(int v); + +@JS("jsSetter") +external void set setter(int v); + +main() { + eval(r''' + globalThis.jsVar1 = 42; + globalThis.jsVar2 = "var2 value"; + globalThis.jsGetter = -1; + globalThis.jsF1 = function() {return 1;}; + globalThis.jsF2 = function(v) {return v;}; + globalThis.jsSetter = 0; + + globalThis.var1 = -42; + globalThis.var2 = "Wrong var2 value"; + globalThis.getter = -100; + globalThis.f1 = function() {return 100;}; + globalThis.f2 = function(v) {return 100 + v;}; + globalThis.setter = 100; + '''); + Expect.equals(42, var1); + Expect.equals("var2 value", var2); + Expect.equals(-1, getter); + Expect.equals(1, f1()); + Expect.equals(2, f2(2)); + setter = 3; + Expect.equals(3, (globalContext["jsSetter"] as JSNumber).toDartInt); + var1 = -1; + eval("globalThis.jsVar1++"); + Expect.equals(0, var1); +} diff --git a/LibTest/js_interop/JS/js_A03_t02.dart b/LibTest/js_interop/JS/js_A03_t02.dart new file mode 100644 index 0000000000..689d995c3d --- /dev/null +++ b/LibTest/js_interop/JS/js_A03_t02.dart @@ -0,0 +1,51 @@ +// Copyright (c) 2025, 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. + +/// @assertion An annotation on a JavaScript interop declaration. +/// ... +/// Specifying name customizes the JavaScript name to use, which can be used in +/// the following scenarios: +/// - Adding a JavaScript prefix to all the external top-level declarations, +/// static members, and constructors of a library by parameterizing the +/// annotation on the library with `name`. +/// - Specifying the JavaScript class to use for external static members and +/// constructors of an interop extension type by parameterizing the annotation +/// on the interop extension type with `name`. +/// - Renaming external declarations by parameterizing the annotation on the +/// member with `name`. +/// +/// @description Check that specifying `name` customizes the JavaScript `name` +/// to use. Test extension type declaration. +/// @author sgrekhov22@gmail.com + +import 'dart:js_interop'; +import 'dart:js_interop_unsafe'; +import '../../../Utils/expect.dart'; +import '../js_utils.dart'; + +@JS("JSEt") +extension type ET(JSObject _) implements JSObject { + external String foo(); + external static String bar(); +} + +main() { + eval(r''' + class JSEt { + foo() { + return "foo() from JSEt"; + } + + static bar() { + return "bar() from JSEt"; + } + } + globalThis.JSEt = JSEt; + globalThis.et = new JSEt(); + '''); + + ET et = ET(globalContext["et"] as JSObject); + Expect.equals("foo() from JSEt", et.foo()); + Expect.equals("bar() from JSEt", ET.bar()); +} diff --git a/LibTest/js_interop/JS/js_A03_t03.dart b/LibTest/js_interop/JS/js_A03_t03.dart new file mode 100644 index 0000000000..6e4c273ccc --- /dev/null +++ b/LibTest/js_interop/JS/js_A03_t03.dart @@ -0,0 +1,83 @@ +// Copyright (c) 2025, 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. + +/// @assertion An annotation on a JavaScript interop declaration. +/// ... +/// Specifying name customizes the JavaScript name to use, which can be used in +/// the following scenarios: +/// - Adding a JavaScript prefix to all the external top-level declarations, +/// static members, and constructors of a library by parameterizing the +/// annotation on the library with `name`. +/// - Specifying the JavaScript class to use for external static members and +/// constructors of an interop extension type by parameterizing the annotation +/// on the interop extension type with `name`. +/// - Renaming external declarations by parameterizing the annotation on the +/// member with `name`. +/// +/// @description Check that specifying `name` customizes the JavaScript `name` +/// to use. Test members of an extension type. +/// @author sgrekhov22@gmail.com + +import 'dart:js_interop'; +import 'dart:js_interop_unsafe'; +import '../../../Utils/expect.dart'; +import '../js_utils.dart'; + +extension type ET(JSObject _) implements JSObject { + @JS("jsVar1") + external int var1; + + @JS("jsVar2") + external final String var2; + + @JS("jsX") + external int get x; + + @JS("jsX") + external void set x(int v); + + @JS("jsF1") + external int f1(); + + @JS("jsF2") + external int f2(int v); +} + +main() { + eval(r''' + class ET { + constructor(v1, v2) { + this.jsVar1 = v1; + this.jsVar2 = v2; + this._x = 0; + } + + get jsX() { + return this._x; + } + + set jsX(v) { + this._x = v; + } + + jsF1() { + return this.jsVar1; + } + + jsF2(v) { + return v; + } + } + globalThis.et = new ET(1, "two"); + '''); + + ET et = ET(globalContext["et"] as JSObject); + Expect.equals(1, et.var1); + Expect.equals("two", et.var2); + Expect.equals(0, et.x); + Expect.equals(1, et.f1()); + Expect.equals(2, et.f2(2)); + et.x = 3; + Expect.equals(3, et.x); +} diff --git a/LibTest/js_interop/JS/js_A03_t04.dart b/LibTest/js_interop/JS/js_A03_t04.dart new file mode 100644 index 0000000000..e36a4c9a75 --- /dev/null +++ b/LibTest/js_interop/JS/js_A03_t04.dart @@ -0,0 +1,79 @@ +// Copyright (c) 2025, 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. + +/// @assertion An annotation on a JavaScript interop declaration. +/// ... +/// Specifying name customizes the JavaScript name to use, which can be used in +/// the following scenarios: +/// - Adding a JavaScript prefix to all the external top-level declarations, +/// static members, and constructors of a library by parameterizing the +/// annotation on the library with `name`. +/// - Specifying the JavaScript class to use for external static members and +/// constructors of an interop extension type by parameterizing the annotation +/// on the interop extension type with `name`. +/// - Renaming external declarations by parameterizing the annotation on the +/// member with `name`. +/// +/// @description Check that specifying `name` customizes the JavaScript `name` +/// to use. Test static members of an extension type. +/// @author sgrekhov22@gmail.com + +import 'dart:js_interop'; +import 'dart:js_interop_unsafe'; +import '../../../Utils/expect.dart'; +import '../js_utils.dart'; + +extension type ET(JSObject _) implements JSObject { + @JS("jsVar1") + external static int var1; + + @JS("jsVar2") + external static final String var2; + + @JS("jsX") + external static int get x; + + @JS("jsX") + external static void set x(int v); + + @JS("jsF1") + external static int f1(); + + @JS("jsF2") + external static int f2(int v); +} + +main() { + eval(r''' + class ET { + static jsVar1 = 1; + static jsVar2 = "two"; + static _x = 0; + + static get jsX() { + return ET._x; + } + + static set jsX(v) { + ET._x = v; + } + + static jsF1() { + return ET.jsVar1; + } + + static jsF2(v) { + return v; + } + } + globalThis.ET = ET; + '''); + Expect.equals(1, ET.var1); + Expect.equals("two", ET.var2); + Expect.equals(0, ET.x); + Expect.equals(1, ET.f1()); + Expect.equals(2, ET.f2(2)); + ET.x = 3; + Expect.equals(3, ET.x); +} diff --git a/LibTest/js_interop/JS/js_A03_t05.dart b/LibTest/js_interop/JS/js_A03_t05.dart new file mode 100644 index 0000000000..0d62367a71 --- /dev/null +++ b/LibTest/js_interop/JS/js_A03_t05.dart @@ -0,0 +1,47 @@ +// Copyright (c) 2025, 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. + +/// @assertion An annotation on a JavaScript interop declaration. +/// +/// This annotation defines a given library, top-level external declaration, or +/// extension type as a JavaScript interop declaration. +/// +/// @description Check that a library directive can be annotated with a `@JS()` +/// annotation. +/// @author sgrekhov22@gmail.com + +@JS("lib1") +library; + +import 'dart:async'; +import 'dart:js_interop'; +import 'dart:js_interop_unsafe'; +import '../../../Utils/expect.dart'; +import '../js_utils.dart'; + +@JS() +external int answer(); + +final completer = Completer(); + +void complete(String value) { + completer.complete(value); +} + +main() { + globalContext["complete"] = complete.toJS; + eval(r''' + var lib1; + (async () => { + lib1 = await import('/root_dart/tests/co19/src/LibTest/js_interop/module.js'); + })().then(function(v) { + globalThis.complete(""); + }); + '''); + asyncStart(); + completer.future.then((_) { + Expect.equals(42, answer()); // calls lib1.answer() + asyncEnd(); + }); +} diff --git a/LibTest/js_interop/JSAnyUtilityExtension/instanceOfString_A04_t01.dart b/LibTest/js_interop/JSAnyUtilityExtension/instanceOfString_A04_t01.dart index a274ddd93c..8786c6adfd 100644 --- a/LibTest/js_interop/JSAnyUtilityExtension/instanceOfString_A04_t01.dart +++ b/LibTest/js_interop/JSAnyUtilityExtension/instanceOfString_A04_t01.dart @@ -20,7 +20,6 @@ /// `constructorName`. Test the case when `constructorName` contains '.'. /// @author sgrekhov22@gmail.com -// OtherResources=module.js import 'dart:async'; import 'dart:js_interop'; import 'dart:js_interop_unsafe'; @@ -39,7 +38,7 @@ main() { var lib1; (async () => { // This is path to the module on tryjobs. May not work locally. - lib1 = await import('/root_dart/tests/co19/src/LibTest/js_interop/JSAnyUtilityExtension/module.js'); + lib1 = await import('/root_dart/tests/co19/src/LibTest/js_interop/module.js'); globalThis.objA = new lib1.A(42, "A form JS"); globalThis.objB = new lib1.B(); })().then(function(v) { diff --git a/LibTest/js_interop/JSAnyUtilityExtension/instanceOfString_A04_t02.dart b/LibTest/js_interop/JSAnyUtilityExtension/instanceOfString_A04_t02.dart index 4285d869ec..78d5200afe 100644 --- a/LibTest/js_interop/JSAnyUtilityExtension/instanceOfString_A04_t02.dart +++ b/LibTest/js_interop/JSAnyUtilityExtension/instanceOfString_A04_t02.dart @@ -20,7 +20,6 @@ /// `constructorName`. Test the case when `constructorName` contains '.'. /// @author sgrekhov22@gmail.com -// OtherResources=module.js import 'dart:async'; import 'dart:js_interop'; import 'dart:js_interop_unsafe'; @@ -48,7 +47,7 @@ main() { var lib1; (async () => { // This is path to the module on tryjobs. May not work locally. - lib1 = await import('/root_dart/tests/co19/src/LibTest/js_interop/JSAnyUtilityExtension/module.js'); + lib1 = await import('/root_dart/tests/co19/src/LibTest/js_interop/module.js'); globalThis.objA = new lib1.A(42, "A form JS"); globalThis.objB = new lib1.B(); })().then(function(v) { diff --git a/LibTest/js_interop/JSAnyUtilityExtension/module.js b/LibTest/js_interop/module.js similarity index 68% rename from LibTest/js_interop/JSAnyUtilityExtension/module.js rename to LibTest/js_interop/module.js index 8488df28e2..9629b6097d 100644 --- a/LibTest/js_interop/JSAnyUtilityExtension/module.js +++ b/LibTest/js_interop/module.js @@ -4,3 +4,7 @@ export function A(id, name) { } export function B() {} + +export function answer() { + return 42; +}