feat(Escaped Identifiers): add ability to use any symbol wrapped in back ticks.

This commit is contained in:
Artem Kobzar
2021-10-29 17:55:59 +00:00
committed by Space
parent ea10b4a781
commit 979e9f94ef
59 changed files with 1260 additions and 159 deletions
@@ -0,0 +1,23 @@
// IGNORE_BACKEND: JS
// !LANGUAGE: +JsAllowInvalidCharsIdentifiersEscaping
package foo
@JsExport()
class A {
class `$invalid inner` {}
}
class B {
class `$invalid inner` {}
}
fun box(): String {
// DCE preventing
val b = B()
assertEquals("function", js("typeof A['\$invalid inner']"))
assertEquals(js("undefined"), js("B['\$invalid inner']"))
return "OK"
}
@@ -0,0 +1,47 @@
// IGNORE_BACKEND: JS
// !LANGUAGE: +JsAllowInvalidCharsIdentifiersEscaping
package foo
@JsExport()
class A {
val `#invalid@char value`: Int = 41
val __invalid_char_value: Int = 23
var `--invalud char@var`: String = "A: before"
}
class B {
val `#invalid@char value`: Int = 42
val __invalid_char_value: Int = 24
var `--invalud char@var`: String = "B: before"
}
fun box(): String {
val a = A()
val b = B()
assertEquals(23, a.__invalid_char_value)
assertEquals(24, b.__invalid_char_value)
assertEquals(41, a.`#invalid@char value`)
assertEquals(42, b.`#invalid@char value`)
assertEquals("A: before", a.`--invalud char@var`)
assertEquals("B: before", b.`--invalud char@var`)
a.`--invalud char@var` = "A: after"
b.`--invalud char@var` = "B: after"
assertEquals("A: after", a.`--invalud char@var`)
assertEquals("B: after", b.`--invalud char@var`)
assertEquals(41, js("a['#invalid@char value']"))
assertEquals(js("undefined"), js("b['#invalid@char value']"))
assertEquals("A: after", js("a['--invalud char@var']"))
assertEquals(js("undefined"), js("b['--invalud char@var']"))
return "OK"
}
@@ -0,0 +1,47 @@
// IGNORE_BACKEND: JS
// !LANGUAGE: +JsAllowInvalidCharsIdentifiersEscaping
package foo
interface IA {
fun `run•invalid@test`(): Int
fun `run@invalid@test`(): Int
fun run_invalid_test(): Int
}
@JsExport()
class A : IA {
override fun `run•invalid@test`(): Int = 41
override fun `run@invalid@test`(): Int = 34
override fun run_invalid_test(): Int = 23
}
class B : IA {
override fun `run•invalid@test`(): Int = 42
override fun `run@invalid@test`(): Int = 35
override fun run_invalid_test(): Int = 24
}
fun box(): String {
val a: IA = A()
val b: IA = B()
assertEquals(23, a.run_invalid_test())
assertEquals(24, b.run_invalid_test())
assertEquals(34, a.`run@invalid@test`())
assertEquals(35, b.`run@invalid@test`())
assertEquals(41, a.`runinvalid@test`())
assertEquals(42, b.`runinvalid@test`())
assertEquals("function", js("typeof a['run•invalid@test']"))
assertEquals(41, js("a['run•invalid@test']()"))
assertEquals(js("undefined"), js("b['run•invalid@test']"))
assertEquals("function", js("typeof a['run@invalid@test']"))
assertEquals(34, js("a['run@invalid@test']()"))
assertEquals(js("undefined"), js("b['run@invalid@test']"))
return "OK"
}
@@ -0,0 +1,11 @@
// IGNORE_BACKEND: JS
// !LANGUAGE: +JsAllowInvalidCharsIdentifiersEscaping
package foo
fun box(): String {
val a: dynamic = js("{ \"--invalid--property@\": 42 }")
assertEquals(42, a.`--invalid--property@`)
return "OK"
}
@@ -0,0 +1,11 @@
define("lib", [], function() {
return {
"@get something-invalid"() {
return "something invalid"
},
"some+value": 42,
"+some+object%:": {
foo: "%%++%%"
}
};
});
@@ -0,0 +1,28 @@
// IGNORE_BACKEND: JS
// MODULE_KIND: COMMON_JS
// !LANGUAGE: +JsAllowInvalidCharsIdentifiersEscaping
// FILE: lib.kt
@file:JsModule("lib")
package lib
external fun `@get something-invalid`(): String = definedExternally
external val `some+value`: Int = definedExternally
external object `+some+object%:` {
val foo: String = definedExternally
}
// FILE: main.kt
import lib.`some+value`
import lib.`@get something-invalid`
import lib.`+some+object%:`
fun box(): String {
assertEquals(42, `some+value`)
assertEquals("%%++%%", `+some+object%:`.foo)
assertEquals("something invalid", `@get something-invalid`())
return "OK"
}
@@ -0,0 +1,15 @@
function A() {
this["@invalid @ val@"] = 23
this["--invalid-var"] = "A: before"
}
A.prototype["get something$weird"] = function() {
return "something weird"
}
A["static val"] = 42
A["static var"] = "Companion: before"
A["get 🦄"] = function() {
return "🦄"
}
@@ -0,0 +1,39 @@
// IGNORE_BACKEND: JS
// !LANGUAGE: +JsAllowInvalidCharsIdentifiersEscaping
package foo
external class A {
val `@invalid @ val@`: Int = definedExternally
var `--invalid-var`: String = definedExternally
fun `get something$weird`(): String = definedExternally
companion object {
val `static val`: Int = definedExternally
var `static var`: String = definedExternally
fun `get 🦄`(): String = definedExternally
}
}
fun box(): String {
val a = A()
assertEquals(23, a.`@invalid @ val@`)
assertEquals("A: before", a.`--invalid-var`)
assertEquals("something weird", a.`get something$weird`())
a.`--invalid-var` = "A: after"
assertEquals("A: after", a.`--invalid-var`)
assertEquals(42, A.Companion.`static val`)
assertEquals("Companion: before", A.Companion.`static var`)
assertEquals("\uD83E\uDD84", A.Companion.`get 🦄`())
A.`static var` = "Companion: after"
assertEquals("Companion: after", A.Companion.`static var`)
return "OK"
}
@@ -0,0 +1,11 @@
$kotlin_test_internal$.beginModule("lib");
module.exports = {
"@get something-invalid"() {
return "something invalid"
},
"some+value": 42,
"+some+object%:": {
foo: "%%++%%"
}
}
$kotlin_test_internal$.endModule("lib");
@@ -0,0 +1,28 @@
// IGNORE_BACKEND: JS
// MODULE_KIND: COMMON_JS
// !LANGUAGE: +JsAllowInvalidCharsIdentifiersEscaping
// FILE: lib.kt
@file:JsModule("lib")
package lib
external fun `@get something-invalid`(): String = definedExternally
external val `some+value`: Int = definedExternally
external object `+some+object%:` {
val foo: String = definedExternally
}
// FILE: main.kt
import lib.`some+value`
import lib.`@get something-invalid`
import lib.`+some+object%:`
fun box(): String {
assertEquals(42, `some+value`)
assertEquals("%%++%%", `+some+object%:`.foo)
assertEquals("something invalid", `@get something-invalid`())
return "OK"
}
@@ -0,0 +1,9 @@
this["@get something-invalid"] = function() {
return "something invalid"
}
this["some+value"] = 42
this["+some+object%:"] = {
foo: "%%++%%"
}
@@ -0,0 +1,23 @@
// IGNORE_BACKEND: JS
// !LANGUAGE: +JsAllowInvalidCharsIdentifiersEscaping
package foo
external fun `@get something-invalid`(): String = definedExternally
external var `some+value`: Int
get() = definedExternally
set(a: Int) = definedExternally
external object `+some+object%:` {
val foo: String = definedExternally
}
fun box(): String {
val a = js("2")
assertEquals(42, `some+value`)
assertEquals("%%++%%", `+some+object%:`.foo)
assertEquals("something invalid", `@get something-invalid`())
return "OK"
}
@@ -0,0 +1,24 @@
// IGNORE_BACKEND: JS
// RUN_PLAIN_BOX_FUNCTION
// INFER_MAIN_MODULE
// !LANGUAGE: +JsAllowInvalidCharsIdentifiersEscaping
// MODULE: export_invalid_name_class
// FILE: lib.kt
@JsExport
class `invalid@class-name `() {
fun foo(): Int = 42
}
// FILE: test.js
function box() {
var InvalidClass = this["export_invalid_name_class"]["invalid@class-name "]
var instance = new InvalidClass()
var value = instance.foo()
if (value !== 42)
return "false: expect exproted class function to return 42 but it equals " + value
return "OK"
}
@@ -0,0 +1,30 @@
// IGNORE_BACKEND: JS
// RUN_PLAIN_BOX_FUNCTION
// INFER_MAIN_MODULE
// !LANGUAGE: +JsAllowInvalidCharsIdentifiersEscaping
// MODULE: export_invalid_name_class
// FILE: lib.kt
@JsExport
class `invalid@class-name `() {
companion object {
val `@invalid val@`: Int = 23
fun `invalid fun`(): Int = 42
}
}
// FILE: test.js
function box() {
var InvalidClass = this["export_invalid_name_class"]["invalid@class-name "]
if (InvalidClass.Companion["@invalid val@"] !== 23)
return "false: expect exproted class static variable '@invalid val@' to be 23 but it equals " + InvalidClass.Companion["@invalud val@"]
var result = InvalidClass.Companion["invalid fun"]()
if (result !== 42)
return "false: expect exproted class static function 'invalid fun' to return 23 but it equals " + result
return "OK"
}
@@ -0,0 +1,20 @@
// IGNORE_BACKEND: JS
// RUN_PLAIN_BOX_FUNCTION
// INFER_MAIN_MODULE
// !LANGUAGE: +JsAllowInvalidCharsIdentifiersEscaping
// MODULE: export_invalid_name_function
// FILE: lib.kt
@JsExport
fun `@do something like-this`(): Int = 42
// FILE: test.js
function box() {
var value = this["export_invalid_name_function"]["@do something like-this"]()
if (value !== 42)
return "false: expect exproted function '@do something like-this' to return 42 but it equals " + value
return "OK"
}
@@ -0,0 +1,20 @@
// IGNORE_BACKEND: JS
// RUN_PLAIN_BOX_FUNCTION
// INFER_MAIN_MODULE
// !LANGUAGE: +JsAllowInvalidCharsIdentifiersEscaping
// MODULE: export_invalid_name_variable
// FILE: lib.kt
@JsExport
val `my@invalid variable` = 42
// FILE: test.js
function box() {
var variableValue = this["export_invalid_name_variable"]["my@invalid variable"]
if (variableValue !== 42)
return "false: expect exproted 'my@invalid variable' to be 42 but it equals " + variableValue
return "OK"
}
@@ -0,0 +1,25 @@
// IGNORE_BACKEND: JS
// !LANGUAGE: +JsAllowInvalidCharsIdentifiersEscaping
package foo
class class_with_invalid_chars {
fun foo(): Int = 23
}
class `class@with$invalid chars` {
fun foo(): Int = 42
}
fun box(): String {
val a = class_with_invalid_chars()
val b = `class@with$invalid chars`()
assertEquals(true, a is class_with_invalid_chars)
assertEquals(true, b is `class@with$invalid chars`)
assertEquals(23, a.foo())
assertEquals(42, b.foo())
return "OK"
}
@@ -0,0 +1,23 @@
// IGNORE_BACKEND: JS
// !LANGUAGE: +JsAllowInvalidCharsIdentifiersEscaping
package foo
class class_with_invalid_chars {
companion object {
fun foo(): Int = 23
}
}
class `class@with$invalid chars` {
companion object {
fun foo(): Int = 42
}
}
fun box(): String {
assertEquals(23, class_with_invalid_chars.foo())
assertEquals(42, `class@with$invalid chars`.foo())
return "OK"
}
@@ -0,0 +1,20 @@
// IGNORE_BACKEND: JS
// !LANGUAGE: +JsAllowInvalidCharsIdentifiersEscaping
package foo
fun _my_fn(a: Int): Int { return a }
fun `my fn`(): Int { return 42 }
fun box(): String {
val fn1 = ::_my_fn
val fn2 = ::`my fn`
assertEquals("_my_fn", fn1.name)
assertEquals("my fn", fn2.name)
assertEquals(23, _my_fn(23))
assertEquals(42, `my fn`())
return "OK"
}
@@ -0,0 +1,13 @@
// !LANGUAGE: +JsAllowInvalidCharsIdentifiersEscaping
package foo
val _my_invalid_variable = 23
val `my@invalid variable` = 42
fun box(): String {
assertEquals(23, _my_invalid_variable)
assertEquals(42, `my@invalid variable`)
return "OK"
}