[JS IR] Support per-file mode and ES modules

This commit is contained in:
Svyatoslav Kuzmich
2021-02-23 15:44:06 +03:00
parent f479ac5c3a
commit 3f8dce4b53
140 changed files with 5136 additions and 609 deletions
@@ -0,0 +1,33 @@
// EXPECTED_REACHABLE_NODES: 1284
// ES_MODULES
// DONT_TARGET_EXACT_BACKEND: JS
package foo
@JsModule("./externalClass.mjs")
external class A(x: Int = definedExternally) {
val x: Int
fun foo(y: Int): Int = definedExternally
fun bar(vararg arg: String): String = definedExternally
}
class C {
val e = arrayOf("e")
val f = arrayOf("f")
val a = A(1)
fun qux() = a.bar(*e, *f)
}
fun box(): String {
val a = A(23)
assertEquals(23, a.x)
assertEquals(65, a.foo(42))
assertEquals(C().qux(), "(ef)")
return "OK"
}
@@ -0,0 +1,11 @@
export default function A(x) {
this.x = x;
}
A.prototype.foo = function (y) {
return this.x + y;
};
A.prototype.bar = function() {
return "(" + Array.prototype.join.call(arguments, "") + ")";
};
@@ -0,0 +1,62 @@
// DONT_TARGET_EXACT_BACKEND: JS
// ES_MODULES
// FILE: a.kt
@file:JsModule("./a.mjs")
package a
external class A {
fun foo(): String
}
external fun bar(): Int
external val prop: Int
// FILE: b.kt
@file:JsModule("./b.mjs")
package b
external class A {
fun foo(): String
}
external fun bar(): Int
external var prop: Int
// FILE: main.kt
import a.A as O
import b.A as K
fun box(): String {
if (a.bar() != 1) return "fail 1"
if (a.prop != 10) return "fail 2"
if (b.bar() != 2) return "fail 3"
if (b.prop != 20) return "fail 4"
return O().foo() + K().foo()
}
// FILE: a.mjs
export function A() {}
A.prototype.foo = function () {
return "O";
};
export function bar() { return 1; }
export let prop = 10
// FILE: b.mjs
export function A() {}
A.prototype.foo = function () {
return "K";
};
export function bar() { return 2; }
export let prop = 20;
@@ -0,0 +1,46 @@
// EXPECTED_REACHABLE_NODES: 1284
// ES_MODULES
// DONT_TARGET_EXACT_BACKEND: JS
package foo
@JsModule("./externalClassWithDefaults.mjs")
external open class A(ss: String = definedExternally) {
val s: String
fun foo(y: String = definedExternally): String = definedExternally
fun bar(y: String = definedExternally): String = definedExternally
}
class C: A {
constructor(ss: String) : super(ss) {}
constructor() : super() {}
fun qux(s: String = "O") = s
}
fun box(): String {
val a = A()
val c = C()
val r1 = a.foo("O") + c.foo()
if (r1 != "OK") return "Fail1: $r1"
val r2 = a.bar() + c.bar("K")
if (r2 != "OK") return "Fail2: $r2"
val r3 = c.qux() + c.qux("K")
if (r3 != "OK") return "Fail3: $r3"
if (a.s != "A") return "Fail4: ${a.s}"
if (c.s != "A") return "Fail5: ${c.s}"
val a2 = A("A2")
val c2 = C("C2")
val r6 = a2.s + c2.s
if (r6 != "A2C2") return "Fail6: $r6"
return "OK"
}
@@ -0,0 +1,9 @@
export default function A(ss) {
this.s = ss || "A"
}
A.prototype.foo = function (y) {
return y || "K";
};
A.prototype.bar = function (y) {
return y || "O";
};
@@ -0,0 +1,26 @@
// EXPECTED_REACHABLE_NODES: 1334
// ES_MODULES
// DONT_TARGET_EXACT_BACKEND: JS
package foo
@JsModule("./externalConstructor.mjs")
open external class A(data: String) {
constructor(data: Int)
constructor(data: Boolean)
val data: Any
}
class B(data: String) : A(data)
class C(data: Int) : A(data)
class D(data: Boolean) : A(data)
fun box(): String {
assertEquals("13", B("13").data)
assertEquals(42, C(42).data)
assertEquals(true, D(true).data)
return "OK"
}
@@ -0,0 +1,3 @@
export default function (data) {
this.data = data
}
@@ -0,0 +1,11 @@
// DONT_TARGET_EXACT_BACKEND: JS
// ES_MODULES
package foo
@JsModule("./externalFunction.mjs")
external fun foo(y: Int): Int = definedExternally
fun box(): String {
assertEquals(65, foo(42))
return "OK"
}
@@ -0,0 +1,3 @@
export default function(y) {
return 23 + y;
}
@@ -0,0 +1,14 @@
// DONT_TARGET_EXACT_BACKEND: JS
// ES_MODULES
package foo
@JsModule("./externalFunctionNameClash.mjs")
external fun foo(y: Int): Int = definedExternally
fun foo(y: String): String = y + "K"
fun box(): String {
val foo10 = foo(10)
if (foo10 != 33) return "Fail: $foo10"
return "OK"
}
@@ -0,0 +1,3 @@
export default function(y) {
return 23 + y;
}
@@ -0,0 +1,16 @@
// DONT_TARGET_EXACT_BACKEND: JS
// ES_MODULES
package foo
@JsModule("./externalObject.mjs")
external object A {
val x: Int = definedExternally
fun foo(y: Int): Int = definedExternally
}
fun box(): String {
assertEquals(23, A.x)
assertEquals(65, A.foo(42))
return "OK"
}
@@ -0,0 +1,6 @@
export default {
x: 23,
foo: function(y) {
return this.x + y;
}
};
@@ -0,0 +1,45 @@
// DONT_TARGET_EXACT_BACKEND: JS
// ES_MODULES
// FILE: a.kt
@file:JsModule("./externalPackage.mjs")
package foo
external class A(x: Int) {
val x: Int
fun foo(y: Int): Int = definedExternally
class Nested {
val y: Int
}
}
external object B {
val x: Int = definedExternally
fun foo(y: Int): Int = definedExternally
}
external fun foo(y: Int): Int = definedExternally
external val bar: Int = definedExternally
// FILE: b.kt
package foo
fun box(): String {
val a = A(23)
assertEquals(23, a.x)
assertEquals(65, a.foo(42))
val nested = A.Nested()
assertEquals(55, nested.y)
assertEquals(123, B.x)
assertEquals(265, B.foo(142))
assertEquals(365, foo(42))
assertEquals(423, bar)
return "OK"
}
@@ -0,0 +1,24 @@
export function A(x) {
this.x = x;
}
A.prototype.foo = function (y) {
return this.x + y;
};
function Nested() {
this.y = 55;
}
A.Nested = Nested;
export var B = {
x: 123,
foo: function(y) {
return this.x + y;
}
};
export function foo(y) {
return 323 + y;
}
export var bar = 423;
@@ -0,0 +1,5 @@
C = {
f: function() {
return 12345;
}
};
@@ -0,0 +1,47 @@
// DONT_TARGET_EXACT_BACKEND: JS
// ES_MODULES
// FILE: lib.kt
@file:JsModule("./externalPackageInDifferentFile.mjs")
package foo
external class A(x: Int = definedExternally) {
val x: Int
fun foo(y: Int): Int = definedExternally
}
external object B {
val x: Int = definedExternally
fun foo(y: Int): Int = definedExternally
}
external fun foo(y: Int): Int = definedExternally
external val bar: Int = definedExternally
// FILE: lib2.kt
package foo
external object C {
fun f(): Int = definedExternally
}
// FILE: main.kt
package foo
fun box(): String {
val a = A(23)
assertEquals(23, a.x)
assertEquals(65, a.foo(42))
assertEquals(123, B.x)
assertEquals(265, B.foo(142))
assertEquals(365, foo(42))
assertEquals(423, bar)
assertEquals(12345, C.f())
return "OK"
}
@@ -0,0 +1,21 @@
function A(x) {
this.x = x;
}
A.prototype.foo = function (y) {
return this.x + y;
};
var B = {
x: 123,
foo: function(y) {
return this.x + y;
}
};
function foo(y) {
return 323 + y;
}
var bar = 423;
export { A, B, foo, bar };
@@ -0,0 +1,11 @@
// DONT_TARGET_EXACT_BACKEND: JS
// ES_MODULES
package foo
@JsModule("./externalProperty.mjs")
external val foo: Int = definedExternally
fun box(): String {
assertEquals(23, foo)
return "OK"
}
@@ -0,0 +1 @@
export default 23;
@@ -0,0 +1,33 @@
// DONT_TARGET_EXACT_BACKEND: JS
// ES_MODULES
// FILE: bar.kt
@file:JsModule("./interfaces.mjs")
@file:JsQualifier("foo")
package foo
external interface Bar {
fun ping(): String
}
// FILE: baz.kt
@file:JsModule("./interfaces.mjs")
package boo
external interface Baz {
fun pong(): Int
}
// FILE: root.kt
@file:JsModule("./interfaces.mjs")
import foo.Bar
import boo.Baz
external val bar: Bar
external val baz: Baz
// FILE: test.kt
fun box(): String {
if (bar.ping() != "ping" || baz.pong() != 194) return "Fail"
return "OK"
}
@@ -0,0 +1,12 @@
export var bar = {
ping() {
return "ping"
}
};
export var baz = {
pong() {
return 194
}
};
@@ -0,0 +1,15 @@
// DONT_TARGET_EXACT_BACKEND: JS
// ES_MODULES
@JsModule("./topLevelVarargFun.mjs")
external fun foo(vararg arg: String): String
fun box(): String {
val x = arrayOf("a", "b")
var r = foo(*x)
if (r != "(ab)") return "fail1: $r"
r = foo("c", "d")
if (r != "(cd)") return "fail2: $r"
return "OK"
}
@@ -0,0 +1,3 @@
export default function() {
return "(" + Array.prototype.join.call(arguments, "") + ")";
};