feat(Escaped Identifiers): add ability to use any symbol wrapped in back ticks.
This commit is contained in:
Generated
+1
-1
@@ -70,7 +70,7 @@
|
||||
<component name="ProjectResources">
|
||||
<default-html-doctype>http://www.w3.org/1999/xhtml</default-html-doctype>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
<component name="PsiViewerSettings">
|
||||
|
||||
+3
@@ -240,6 +240,9 @@ class K2JSCompilerArguments : CommonCompilerArguments() {
|
||||
if (extensionFunctionsInExternals) {
|
||||
this[LanguageFeature.JsEnableExtensionFunctionInExternals] = LanguageFeature.State.ENABLED
|
||||
}
|
||||
if (!isIrBackendEnabled()) {
|
||||
this[LanguageFeature.JsAllowInvalidCharsIdentifiersEscaping] = LanguageFeature.State.DISABLED
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -98,7 +98,7 @@ class ExportModelGenerator(
|
||||
|
||||
private fun exportParameter(parameter: IrValueParameter): ExportedParameter {
|
||||
// Parameter names do not matter in d.ts files. They can be renamed as we like
|
||||
var parameterName = sanitizeName(parameter.name.asString())
|
||||
var parameterName = sanitizeName(parameter.name.asString(), withHash = false)
|
||||
if (parameterName in allReservedWords)
|
||||
parameterName = "_$parameterName"
|
||||
|
||||
|
||||
+6
-5
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.JsAstUtils
|
||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.defineProperty
|
||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.jsAssignment
|
||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.prototypeOf
|
||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.jsElementAccess
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.IrNamer
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.emptyScope
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.getJsNameOrKotlinName
|
||||
@@ -26,19 +27,19 @@ class ExportModelToJsStatements(
|
||||
return module.declarations.flatMap { generateDeclarationExport(it, JsNameRef(internalModuleName)) }
|
||||
}
|
||||
|
||||
fun generateDeclarationExport(declaration: ExportedDeclaration, namespace: JsNameRef?): List<JsStatement> {
|
||||
fun generateDeclarationExport(declaration: ExportedDeclaration, namespace: JsExpression?): List<JsStatement> {
|
||||
return when (declaration) {
|
||||
is ExportedNamespace -> {
|
||||
require(namespace != null) { "Only namespaced namespaces are allowed" }
|
||||
val statements = mutableListOf<JsStatement>()
|
||||
val elements = declaration.name.split(".")
|
||||
var currentNamespace = ""
|
||||
var currentRef: JsNameRef = namespace
|
||||
var currentRef: JsExpression = namespace
|
||||
for (element in elements) {
|
||||
val newNamespace = "$currentNamespace$$element"
|
||||
val newNameSpaceRef = namespaceToRefMap.getOrPut(newNamespace) {
|
||||
val varName = JsName(declareNewNamespace(newNamespace), false)
|
||||
val namespaceRef = JsNameRef(element, currentRef)
|
||||
val namespaceRef = jsElementAccess(element, currentRef)
|
||||
statements += JsVars(
|
||||
JsVars.JsVar(
|
||||
varName,
|
||||
@@ -66,7 +67,7 @@ class ExportModelToJsStatements(
|
||||
} else {
|
||||
listOf(
|
||||
jsAssignment(
|
||||
JsNameRef(declaration.name, namespace),
|
||||
jsElementAccess(declaration.name, namespace),
|
||||
JsNameRef(name)
|
||||
).makeStmt()
|
||||
)
|
||||
@@ -87,7 +88,7 @@ class ExportModelToJsStatements(
|
||||
|
||||
is ExportedClass -> {
|
||||
if (declaration.isInterface) return emptyList()
|
||||
val newNameSpace = JsNameRef(declaration.name, namespace)
|
||||
val newNameSpace = jsElementAccess(declaration.name, namespace)
|
||||
val name = namer.getNameForStaticDeclaration(declaration.ir)
|
||||
val klassExport =
|
||||
if (namespace == null) {
|
||||
|
||||
+19
-6
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.ir.backend.js.utils.getJsNameOrKotlinName
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.sanitizeName
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||
import org.jetbrains.kotlin.js.common.isValidES5Identifier
|
||||
import org.jetbrains.kotlin.serialization.js.ModuleKind
|
||||
|
||||
// TODO: Support module kinds other than plain
|
||||
@@ -22,7 +23,7 @@ fun wrapTypeScript(name: String, moduleKind: ModuleKind, dts: String): String {
|
||||
|
||||
val declarationsDts = types + dts
|
||||
|
||||
val namespaceName = sanitizeName(name)
|
||||
val namespaceName = sanitizeName(name, withHash = false)
|
||||
|
||||
return when (moduleKind) {
|
||||
ModuleKind.PLAIN -> "declare namespace $namespaceName {\n$declarationsDts\n}\n"
|
||||
@@ -73,8 +74,14 @@ fun ExportedDeclaration.toTypeScript(indent: String, prefix: String = ""): Strin
|
||||
""
|
||||
|
||||
val renderedReturnType = returnType.toTypeScript(indent)
|
||||
val containsUnresolvedChar = !name.isValidES5Identifier()
|
||||
|
||||
"${prefix}$visibility$keyword$name$renderedTypeParameters($renderedParameters): $renderedReturnType;"
|
||||
val escapedName = when {
|
||||
isMember && containsUnresolvedChar -> "\"$name\""
|
||||
else -> name
|
||||
}
|
||||
|
||||
if (!isMember && containsUnresolvedChar) "" else "${prefix}$visibility$keyword$escapedName$renderedTypeParameters($renderedParameters): $renderedReturnType;"
|
||||
}
|
||||
|
||||
is ExportedConstructor -> {
|
||||
@@ -95,7 +102,12 @@ fun ExportedDeclaration.toTypeScript(indent: String, prefix: String = ""): Strin
|
||||
else -> if (mutable) "let " else "const "
|
||||
}
|
||||
val possibleStatic = if (isMember && isStatic) "static " else ""
|
||||
"$prefix$visibility$possibleStatic$keyword$name: ${type.toTypeScript(indent)};"
|
||||
val containsUnresolvedChar = !name.isValidES5Identifier()
|
||||
val memberName = when {
|
||||
isMember && containsUnresolvedChar -> "\"$name\""
|
||||
else -> name
|
||||
}
|
||||
if (!isMember && containsUnresolvedChar) "" else "$prefix$visibility$possibleStatic$keyword$memberName: ${type.toTypeScript(indent)};"
|
||||
}
|
||||
|
||||
is ExportedClass -> {
|
||||
@@ -140,7 +152,8 @@ fun ExportedDeclaration.toTypeScript(indent: String, prefix: String = ""): Strin
|
||||
val nestedClasses = nonInnerClasses + innerClasses.map { it.withProtectedConstructors() }
|
||||
val klassExport = "$prefix$modifiers$keyword $name$renderedTypeParameters$superClassClause$superInterfacesClause {\n$bodyString}"
|
||||
val staticsExport = if (nestedClasses.isNotEmpty()) "\n" + ExportedNamespace(name, nestedClasses).toTypeScript(indent, prefix) else ""
|
||||
klassExport + staticsExport
|
||||
|
||||
if (name.isValidES5Identifier()) klassExport + staticsExport else ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,7 +205,7 @@ fun ExportedClass.toReadonlyProperty(): ExportedProperty {
|
||||
}
|
||||
|
||||
fun ExportedParameter.toTypeScript(indent: String): String =
|
||||
"$name: ${type.toTypeScript(indent)}"
|
||||
"${sanitizeName(name, withHash = false)}: ${type.toTypeScript(indent)}"
|
||||
|
||||
fun ExportedType.toTypeScript(indent: String): String = when (this) {
|
||||
is ExportedType.Primitive -> typescript
|
||||
@@ -208,8 +221,8 @@ fun ExportedType.toTypeScript(indent: String): String = when (this) {
|
||||
is ExportedType.TypeOf ->
|
||||
"typeof $name"
|
||||
|
||||
is ExportedType.ErrorType -> "any /*$comment*/"
|
||||
is ExportedType.TypeParameter -> name
|
||||
is ExportedType.ErrorType -> "any /*$comment*/"
|
||||
is ExportedType.Nullable -> "Nullable<" + baseType.toTypeScript(indent) + ">"
|
||||
is ExportedType.InlineInterfaceType -> {
|
||||
members.joinToString(prefix = "{\n", postfix = "$indent}", separator = "") { it.toTypeScript("$indent ") + "\n" }
|
||||
|
||||
+8
-5
@@ -102,7 +102,8 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
|
||||
|
||||
override fun visitGetValue(expression: IrGetValue, context: JsGenerationContext): JsExpression {
|
||||
if (expression.symbol.owner.isThisReceiver()) return JsThisRef().withSource(expression, context)
|
||||
return context.getNameForValueDeclaration(expression.symbol.owner).makeRef().withSource(expression, context)
|
||||
val possibleGlobalVarRef = context.getNameForValueDeclaration(expression.symbol.owner).makeRef().withSource(expression, context)
|
||||
return jsGlobalVarRef(possibleGlobalVarRef)
|
||||
}
|
||||
|
||||
override fun visitGetObjectValue(expression: IrGetObjectValue, context: JsGenerationContext): JsExpression {
|
||||
@@ -110,18 +111,20 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
|
||||
assert(obj.kind == ClassKind.OBJECT)
|
||||
assert(obj.isEffectivelyExternal()) { "Non external IrGetObjectValue must be lowered" }
|
||||
|
||||
return context.getRefForExternalClass(obj).withSource(expression, context)
|
||||
val possibleGlobalVarRef = context.getRefForExternalClass(obj).withSource(expression, context)
|
||||
return jsGlobalVarRef(possibleGlobalVarRef)
|
||||
}
|
||||
|
||||
override fun visitSetField(expression: IrSetField, context: JsGenerationContext): JsExpression {
|
||||
val fieldName = context.getNameForField(expression.symbol.owner)
|
||||
val dest = JsNameRef(fieldName, expression.receiver?.accept(this, context))
|
||||
val dest = jsElementAccess(fieldName.ident, expression.receiver?.accept(this, context))
|
||||
val source = expression.value.accept(this, context)
|
||||
return jsAssignment(dest, source).withSource(expression, context)
|
||||
}
|
||||
|
||||
override fun visitSetValue(expression: IrSetValue, context: JsGenerationContext): JsExpression {
|
||||
val ref = JsNameRef(context.getNameForValueDeclaration(expression.symbol.owner))
|
||||
val possibleGlobalRef = JsNameRef(context.getNameForValueDeclaration(expression.symbol.owner))
|
||||
val ref = jsGlobalVarRef(possibleGlobalRef)
|
||||
val value = expression.value.accept(this, context)
|
||||
return JsBinaryOperation(JsBinaryOperator.ASG, ref, value).withSource(expression, context)
|
||||
}
|
||||
@@ -243,7 +246,7 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
|
||||
}
|
||||
|
||||
override fun visitDynamicMemberExpression(expression: IrDynamicMemberExpression, data: JsGenerationContext): JsExpression =
|
||||
JsNameRef(expression.memberName, expression.receiver.accept(this, data)).withSource(expression, data)
|
||||
jsElementAccess(expression.memberName, expression.receiver.accept(this, data)).withSource(expression, data)
|
||||
|
||||
override fun visitDynamicOperatorExpression(expression: IrDynamicOperatorExpression, data: JsGenerationContext): JsExpression =
|
||||
when (expression.operator) {
|
||||
|
||||
+5
-2
@@ -153,6 +153,7 @@ class IrModuleToJsTransformer(
|
||||
val moduleBody = generateModuleBody(modules, staticContext)
|
||||
|
||||
val internalModuleName = JsName("_", false)
|
||||
val globalThisDeclaration = jsGlobalThisPolyfill();
|
||||
val globalNames = NameTable<String>(namer.globalNames)
|
||||
val exportStatements = ExportModelToJsStatements(nameGenerator) { globalNames.declareFreshName(it, it) }
|
||||
.generateModuleExport(exportedModule, internalModuleName)
|
||||
@@ -163,6 +164,7 @@ class IrModuleToJsTransformer(
|
||||
val program = JsProgram()
|
||||
if (generateScriptModule) {
|
||||
with(program.globalBlock) {
|
||||
statements += globalThisDeclaration
|
||||
statements.addWithComment("block: imports", importStatements + crossModuleImports)
|
||||
statements += moduleBody
|
||||
statements.addWithComment("block: exports", exportStatements + crossModuleExports)
|
||||
@@ -172,6 +174,7 @@ class IrModuleToJsTransformer(
|
||||
parameters += JsParameter(internalModuleName)
|
||||
parameters += (importedJsModules + importedKotlinModules).map { JsParameter(it.internalName) }
|
||||
with(body) {
|
||||
statements += globalThisDeclaration
|
||||
statements.addWithComment("block: imports", importStatements + crossModuleImports)
|
||||
statements += moduleBody
|
||||
statements.addWithComment("block: exports", exportStatements + crossModuleExports)
|
||||
@@ -411,7 +414,7 @@ class IrModuleToJsTransformer(
|
||||
|
||||
assert(jsModule != null || jsQualifier != null)
|
||||
|
||||
val qualifiedReference: JsNameRef
|
||||
val qualifiedReference: JsExpression
|
||||
|
||||
if (jsModule != null) {
|
||||
val internalName = declareFreshGlobal("\$module\$$jsModule")
|
||||
@@ -433,7 +436,7 @@ class IrModuleToJsTransformer(
|
||||
.forEach { declaration ->
|
||||
val declName = getNameForExternalDeclaration(declaration)
|
||||
importStatements.add(
|
||||
JsVars(JsVars.JsVar(declName, JsNameRef(declaration.getJsNameOrKotlinName().identifier, qualifiedReference)))
|
||||
JsVars(JsVars.JsVar(declName, jsElementAccess(declaration.getJsNameOrKotlinName().identifier, qualifiedReference)))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+24
-3
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.ir.types.classifierOrNull
|
||||
import org.jetbrains.kotlin.ir.types.isAny
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.js.backend.ast.*
|
||||
import org.jetbrains.kotlin.js.common.isValidES5Identifier
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
|
||||
class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationContext) {
|
||||
@@ -77,11 +78,13 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
|
||||
properties.addIfNotNull(declaration.correspondingPropertySymbol?.owner)
|
||||
|
||||
if (es6mode) {
|
||||
val (_, function) = generateMemberFunction(declaration)
|
||||
val (memberRef, function) = generateMemberFunction(declaration)
|
||||
function?.let { jsClass.members += it }
|
||||
declaration.generateAssignmentIfMangled(memberRef)
|
||||
} else {
|
||||
val (memberRef, function) = generateMemberFunction(declaration)
|
||||
function?.let { classBlock.statements += jsAssignment(memberRef, it.apply { name = null }).makeStmt() }
|
||||
declaration.generateAssignmentIfMangled(memberRef)
|
||||
}
|
||||
}
|
||||
is IrClass -> {
|
||||
@@ -204,6 +207,24 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
|
||||
return classBlock
|
||||
}
|
||||
|
||||
private fun IrSimpleFunction.generateAssignmentIfMangled(memberRef: JsExpression) {
|
||||
if (
|
||||
irClass.isExported(context.staticContext.backendContext) &&
|
||||
visibility.isPublicAPI && hasMangledName() &&
|
||||
correspondingPropertySymbol == null
|
||||
) {
|
||||
classBlock.statements += jsAssignment(prototypeAccessRef(), memberRef).makeStmt()
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrSimpleFunction.hasMangledName(): Boolean {
|
||||
return getJsName() == null && !name.asString().isValidES5Identifier()
|
||||
}
|
||||
|
||||
private fun IrSimpleFunction.prototypeAccessRef(): JsExpression {
|
||||
return jsElementAccess(name.asString(), classPrototypeRef)
|
||||
}
|
||||
|
||||
private fun IrSimpleFunction.overridesExternal(): Boolean {
|
||||
if (this.isEffectivelyExternal()) return true
|
||||
|
||||
@@ -214,9 +235,9 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
|
||||
return isInterface && !isEffectivelyExternal()
|
||||
}
|
||||
|
||||
private fun generateMemberFunction(declaration: IrSimpleFunction): Pair<JsNameRef, JsFunction?> {
|
||||
private fun generateMemberFunction(declaration: IrSimpleFunction): Pair<JsExpression, JsFunction?> {
|
||||
val memberName = context.getNameForMemberFunction(declaration.realOverrideTarget)
|
||||
val memberRef = JsNameRef(memberName, classPrototypeRef)
|
||||
val memberRef = jsElementAccess(memberName.ident, classPrototypeRef)
|
||||
|
||||
if (declaration.isReal && declaration.body != null) {
|
||||
val translatedFunction: JsFunction = declaration.accept(IrFunctionToJsTransformer(), context)
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
|
||||
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.RESERVED_IDENTIFIERS
|
||||
import org.jetbrains.kotlin.js.backend.ast.*
|
||||
import org.jetbrains.kotlin.js.naming.isValidES5Identifier
|
||||
import org.jetbrains.kotlin.js.common.isValidES5Identifier
|
||||
import org.jetbrains.kotlin.serialization.js.ModuleKind
|
||||
|
||||
object ModuleWrapperTranslation {
|
||||
|
||||
+1
-1
@@ -123,5 +123,5 @@ val IrModuleFragment.safeName: String
|
||||
if (result.startsWith('<')) result = result.substring(1)
|
||||
if (result.endsWith('>')) result = result.substring(0, result.length - 1)
|
||||
|
||||
return sanitizeName("kotlin-$result")
|
||||
return sanitizeName("kotlin_$result")
|
||||
}
|
||||
|
||||
+43
-5
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||
import org.jetbrains.kotlin.js.backend.ast.*
|
||||
import org.jetbrains.kotlin.js.common.isValidES5Identifier
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
|
||||
@@ -43,6 +44,39 @@ fun <T : JsNode> IrWhen.toJsNode(
|
||||
}
|
||||
}
|
||||
|
||||
// https://mathiasbynens.be/notes/globalthis
|
||||
// TODO: add DCE for globalThis polyfill declaration
|
||||
fun jsGlobalThisPolyfill(): List<JsStatement> =
|
||||
parseJsCode(
|
||||
"""
|
||||
(function() {
|
||||
if (typeof globalThis === 'object') return;
|
||||
Object.defineProperty(Object.prototype, '__magic__', {
|
||||
get: function() {
|
||||
return this;
|
||||
},
|
||||
configurable: true
|
||||
});
|
||||
__magic__.globalThis = __magic__;
|
||||
delete Object.prototype.__magic__;
|
||||
}());
|
||||
""".trimIndent()
|
||||
) ?: emptyList()
|
||||
|
||||
fun jsElementAccess(name: String, receiver: JsExpression?): JsExpression =
|
||||
if (receiver == null || name.isValidES5Identifier()) {
|
||||
JsNameRef(JsName(name, false), receiver)
|
||||
} else {
|
||||
JsArrayAccess(receiver, JsStringLiteral(name))
|
||||
}
|
||||
|
||||
fun jsGlobalVarRef(ref: JsNameRef): JsExpression =
|
||||
if (ref.qualifier != null || ref.ident.isValidES5Identifier()) {
|
||||
ref
|
||||
} else {
|
||||
jsElementAccess(ref.ident, JsNameRef("globalThis"))
|
||||
}
|
||||
|
||||
fun jsAssignment(left: JsExpression, right: JsExpression) = JsBinaryOperation(JsBinaryOperator.ASG, left, right)
|
||||
|
||||
fun prototypeOf(classNameRef: JsExpression) = JsNameRef(Namer.PROTOTYPE_NAME, classNameRef)
|
||||
@@ -114,7 +148,11 @@ fun translateCall(
|
||||
if (function.getJsName() == null) {
|
||||
val property = function.correspondingPropertySymbol?.owner
|
||||
if (property != null && property.isEffectivelyExternal()) {
|
||||
val nameRef = JsNameRef(context.getNameForProperty(property), jsDispatchReceiver)
|
||||
val propertyName = context.getNameForProperty(property)
|
||||
val nameRef = when (jsDispatchReceiver) {
|
||||
null -> jsGlobalVarRef(JsNameRef(propertyName))
|
||||
else -> jsElementAccess(propertyName.ident, jsDispatchReceiver)
|
||||
}
|
||||
return when (function) {
|
||||
property.getter -> nameRef
|
||||
property.setter -> jsAssignment(nameRef, arguments.single())
|
||||
@@ -156,8 +194,8 @@ fun translateCall(
|
||||
}
|
||||
|
||||
val ref = when (jsDispatchReceiver) {
|
||||
null -> JsNameRef(symbolName)
|
||||
else -> JsNameRef(symbolName, jsDispatchReceiver)
|
||||
null -> jsGlobalVarRef(JsNameRef(symbolName))
|
||||
else -> jsElementAccess(symbolName.ident, jsDispatchReceiver)
|
||||
}
|
||||
|
||||
return if (isExternalVararg) {
|
||||
@@ -174,7 +212,7 @@ fun translateCall(
|
||||
if (jsDispatchReceiver != null) {
|
||||
if (argumentsAsSingleArray is JsArrayLiteral) {
|
||||
JsInvocation(
|
||||
JsNameRef(symbolName, jsDispatchReceiver),
|
||||
jsElementAccess(symbolName.ident, jsDispatchReceiver),
|
||||
argumentsAsSingleArray.expressions
|
||||
)
|
||||
} else {
|
||||
@@ -188,7 +226,7 @@ fun translateCall(
|
||||
JsVars(JsVars.JsVar(receiverName, jsDispatchReceiver)),
|
||||
JsReturn(
|
||||
JsInvocation(
|
||||
JsNameRef("apply", JsNameRef(symbolName, receiverRef)),
|
||||
JsNameRef("apply", jsElementAccess(symbolName.ident, receiverRef)),
|
||||
listOf(
|
||||
receiverRef,
|
||||
argumentsAsSingleArray
|
||||
|
||||
@@ -20,9 +20,9 @@ import org.jetbrains.kotlin.ir.util.isInterface
|
||||
import org.jetbrains.kotlin.ir.util.render
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
import org.jetbrains.kotlin.js.naming.isES5IdentifierPart
|
||||
import org.jetbrains.kotlin.js.naming.isES5IdentifierStart
|
||||
import org.jetbrains.kotlin.js.naming.isValidES5Identifier
|
||||
import org.jetbrains.kotlin.js.common.isES5IdentifierPart
|
||||
import org.jetbrains.kotlin.js.common.isES5IdentifierStart
|
||||
import org.jetbrains.kotlin.js.common.isValidES5Identifier
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
|
||||
import java.util.*
|
||||
@@ -386,23 +386,30 @@ class LocalNameGenerator(val variableNames: NameTable<IrDeclaration>) : IrElemen
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun sanitizeName(name: String): String {
|
||||
fun sanitizeName(name: String, withHash: Boolean = true): String {
|
||||
if (name.isValidES5Identifier()) return name
|
||||
if (name.isEmpty()) return "_"
|
||||
|
||||
val builder = StringBuilder()
|
||||
|
||||
val first = name.first().let { if (it.isES5IdentifierStart()) it else '_' }
|
||||
builder.append(first)
|
||||
val first = name.first()
|
||||
|
||||
builder.append(first.mangleIfNot(Char::isES5IdentifierStart))
|
||||
|
||||
for (idx in 1..name.lastIndex) {
|
||||
val c = name[idx]
|
||||
builder.append(if (c.isES5IdentifierPart()) c else '_')
|
||||
builder.append(c.mangleIfNot(Char::isES5IdentifierPart))
|
||||
}
|
||||
|
||||
return builder.toString()
|
||||
return if (withHash) {
|
||||
"${builder}_${name.hashCode().toUInt()}"
|
||||
} else {
|
||||
builder.toString()
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun Char.mangleIfNot(predicate: Char.() -> Boolean) =
|
||||
if (predicate()) this else '_'
|
||||
|
||||
private const val SYNTHETIC_LOOP_LABEL = "\$l\$loop"
|
||||
private const val SYNTHETIC_BLOCK_LABEL = "\$l\$block"
|
||||
|
||||
+1
-1
@@ -114,5 +114,5 @@ val RESERVED_IDENTIFIERS = setOf(
|
||||
"Math", "String", "Boolean", "Date", "Array", "RegExp", "JSON", "Map",
|
||||
|
||||
// global identifiers usually declared in know environments (node.js, browser, require.js, WebWorkers, etc)
|
||||
"require", "define", "module", "window", "self"
|
||||
"require", "define", "module", "window", "self", "globalThis"
|
||||
)
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
// IGNORE_BACKEND: WASM
|
||||
// WASM_MUTE_REASON: IGNORED_IN_JS
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// IGNORE_BACKEND: JS_IR_ES6
|
||||
// IGNORE_BACKEND: JS
|
||||
// !LANGUAGE: +JsAllowInvalidCharsIdentifiersEscaping
|
||||
|
||||
// Exclamation marks are not valid in names in the dex file format.
|
||||
// Therefore, do not attempt to dex this file as it will fail.
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
// IGNORE_BACKEND: WASM
|
||||
// WASM_MUTE_REASON: IGNORED_IN_JS
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// IGNORE_BACKEND: JS_IR_ES6
|
||||
// IGNORE_BACKEND: JS
|
||||
// !LANGUAGE: +JsAllowInvalidCharsIdentifiersEscaping
|
||||
|
||||
// Names with spaces are not valid according to the dex specification
|
||||
// before DEX version 040. Therefore, do not attempt to dex the resulting
|
||||
|
||||
+2
-4
@@ -1,8 +1,6 @@
|
||||
// IGNORE_BACKEND: WASM
|
||||
// WASM_MUTE_REASON: IGNORED_IN_JS
|
||||
// !SANITIZE_PARENTHESES
|
||||
// IGNORE_BACKEND: JS, JS_IR
|
||||
// IGNORE_BACKEND: JS_IR_ES6
|
||||
// IGNORE_BACKEND: JS
|
||||
// !LANGUAGE: +JsAllowInvalidCharsIdentifiersEscaping
|
||||
|
||||
// Sanitization is needed here because DxChecker reports ParseException on parentheses in names.
|
||||
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
// SKIP_TXT
|
||||
// IGNORE_BACKEND: JS
|
||||
// !LANGUAGE: +JsAllowInvalidCharsIdentifiersEscaping
|
||||
|
||||
private fun ` .private `(): String = TODO("")
|
||||
|
||||
fun ` .public `(): String = TODO("")
|
||||
|
||||
@JsName(" __ ")
|
||||
fun foo(): String = TODO("")
|
||||
|
||||
@JsName(" ___ ")
|
||||
private fun bar(): String = TODO("")
|
||||
|
||||
@JsName("validName")
|
||||
private fun ` .private with @JsName `(): String = TODO("")
|
||||
|
||||
private class ` .private class ` {
|
||||
val ` .field. ` = ""
|
||||
}
|
||||
|
||||
val x: Int
|
||||
@JsName(".")
|
||||
get() = TODO("")
|
||||
|
||||
fun box(x: dynamic) {
|
||||
x.`foo-bar`()
|
||||
x.`ba-z`
|
||||
}
|
||||
+6
@@ -637,6 +637,12 @@ public class DiagnosticsTestWithJsStdLibGenerated extends AbstractDiagnosticsTes
|
||||
runTest("compiler/testData/diagnostics/testsWithJsStdLib/name/illegalName.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("illegalNameIR.kt")
|
||||
public void testIllegalNameIR() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithJsStdLib/name/illegalNameIR.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("illegalPackageName.kt")
|
||||
public void testIllegalPackageName() throws Exception {
|
||||
|
||||
@@ -262,6 +262,7 @@ enum class LanguageFeature(
|
||||
ProhibitComparisonOfIncompatibleClasses(sinceVersion = null, kind = BUG_FIX, defaultState = State.DISABLED),
|
||||
ExplicitBackingFields(sinceVersion = null, defaultState = State.DISABLED, kind = UNSTABLE_FEATURE),
|
||||
FunctionalTypeWithExtensionAsSupertype(sinceVersion = KOTLIN_1_6, defaultState = State.DISABLED),
|
||||
JsAllowInvalidCharsIdentifiersEscaping(sinceVersion = null, defaultState = State.DISABLED, kind = UNSTABLE_FEATURE)
|
||||
|
||||
;
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import org.jetbrains.kotlin.js.backend.ast.*;
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsDoubleLiteral;
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsIntLiteral;
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsVars.JsVar;
|
||||
import org.jetbrains.kotlin.js.common.IdentifierPolicyKt;
|
||||
import org.jetbrains.kotlin.js.util.TextOutput;
|
||||
import gnu.trove.THashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -895,7 +896,19 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
p.print(((JsNameRef) labelExpr).getIdent());
|
||||
}
|
||||
else if (labelExpr instanceof JsStringLiteral) {
|
||||
p.print(((JsStringLiteral) labelExpr).getValue());
|
||||
JsStringLiteral stringLiteral = (JsStringLiteral) labelExpr;
|
||||
String value = stringLiteral.getValue();
|
||||
boolean isValidIdentifier = IdentifierPolicyKt.isValidES5Identifier(value);
|
||||
|
||||
if (!isValidIdentifier) {
|
||||
p.print('\'');
|
||||
}
|
||||
|
||||
p.print(value);
|
||||
|
||||
if (!isValidIdentifier) {
|
||||
p.print('\'');
|
||||
}
|
||||
}
|
||||
else {
|
||||
accept(labelExpr);
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
package org.jetbrains.kotlin.js.common
|
||||
|
||||
private fun Char.isAllowedLatinLetterOrSpecial(): Boolean {
|
||||
return this in 'a'..'z' || this in 'A'..'Z' || this == '_' || this == '$'
|
||||
}
|
||||
|
||||
private fun Char.isAllowedSimpleDigit() =
|
||||
this in '0'..'9'
|
||||
|
||||
private fun Char.isNotAllowedSimpleCharacter() = when (this) {
|
||||
' ', '<', '>', '-', '?' -> true
|
||||
else -> false
|
||||
}
|
||||
|
||||
fun Char.isES5IdentifierStart(): Boolean {
|
||||
if (isAllowedLatinLetterOrSpecial()) return true
|
||||
if (isNotAllowedSimpleCharacter()) return false
|
||||
|
||||
return isES5IdentifierStartFull()
|
||||
}
|
||||
|
||||
// See ES 5.1 spec: https://www.ecma-international.org/ecma-262/5.1/#sec-7.6
|
||||
private fun Char.isES5IdentifierStartFull() =
|
||||
Character.isLetter(this) || // Lu | Ll | Lt | Lm | Lo
|
||||
// Nl which is missing in Character.isLetter, but present in UnicodeLetter in spec
|
||||
Character.getType(this).toByte() == Character.LETTER_NUMBER
|
||||
|
||||
|
||||
fun Char.isES5IdentifierPart(): Boolean {
|
||||
if (isAllowedLatinLetterOrSpecial()) return true
|
||||
if (isAllowedSimpleDigit()) return true
|
||||
if (isNotAllowedSimpleCharacter()) return false
|
||||
|
||||
return isES5IdentifierStartFull() ||
|
||||
when (Character.getType(this).toByte()) {
|
||||
Character.NON_SPACING_MARK,
|
||||
Character.COMBINING_SPACING_MARK,
|
||||
Character.DECIMAL_DIGIT_NUMBER,
|
||||
Character.CONNECTOR_PUNCTUATION -> true
|
||||
else -> false
|
||||
} ||
|
||||
this == '\u200C' || // Zero-width non-joiner
|
||||
this == '\u200D' // Zero-width joiner
|
||||
}
|
||||
|
||||
fun String.isValidES5Identifier(): Boolean {
|
||||
if (isEmpty() || !this[0].isES5IdentifierStart()) return false
|
||||
for (idx in 1 until length) {
|
||||
if (!get(idx).isES5IdentifierPart()) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
@@ -19,6 +19,8 @@ package org.jetbrains.kotlin.js.naming
|
||||
import org.jetbrains.kotlin.builtins.ReflectionTypes
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
|
||||
import org.jetbrains.kotlin.js.common.isES5IdentifierPart
|
||||
import org.jetbrains.kotlin.js.common.isES5IdentifierStart
|
||||
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils.getNameForAnnotatedObject
|
||||
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils.isNativeObject
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
@@ -358,55 +360,4 @@ class NameSuggestion {
|
||||
return first.toString() + name.drop(1).map { if (it.isES5IdentifierPart()) it else '_' }.joinToString("")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun Char.isAllowedLatinLetterOrSpecial(): Boolean {
|
||||
return this in 'a'..'z' || this in 'A'..'Z' || this == '_' || this == '$'
|
||||
}
|
||||
|
||||
private fun Char.isAllowedSimpleDigit() =
|
||||
this in '0'..'9'
|
||||
|
||||
private fun Char.isNotAllowedSimpleCharacter() = when (this) {
|
||||
' ', '<', '>', '-', '?' -> true
|
||||
else -> false
|
||||
}
|
||||
|
||||
fun Char.isES5IdentifierStart(): Boolean {
|
||||
if (isAllowedLatinLetterOrSpecial()) return true
|
||||
if (isNotAllowedSimpleCharacter()) return false
|
||||
|
||||
return isES5IdentifierStartFull()
|
||||
}
|
||||
|
||||
// See ES 5.1 spec: https://www.ecma-international.org/ecma-262/5.1/#sec-7.6
|
||||
private fun Char.isES5IdentifierStartFull() =
|
||||
Character.isLetter(this) || // Lu | Ll | Lt | Lm | Lo
|
||||
// Nl which is missing in Character.isLetter, but present in UnicodeLetter in spec
|
||||
Character.getType(this).toByte() == Character.LETTER_NUMBER
|
||||
|
||||
|
||||
fun Char.isES5IdentifierPart(): Boolean {
|
||||
if (isAllowedLatinLetterOrSpecial()) return true
|
||||
if (isAllowedSimpleDigit()) return true
|
||||
if (isNotAllowedSimpleCharacter()) return false
|
||||
|
||||
return isES5IdentifierStartFull() ||
|
||||
when (Character.getType(this).toByte()) {
|
||||
Character.NON_SPACING_MARK,
|
||||
Character.COMBINING_SPACING_MARK,
|
||||
Character.DECIMAL_DIGIT_NUMBER,
|
||||
Character.CONNECTOR_PUNCTUATION -> true
|
||||
else -> false
|
||||
} ||
|
||||
this == '\u200C' || // Zero-width non-joiner
|
||||
this == '\u200D' // Zero-width joiner
|
||||
}
|
||||
|
||||
fun String.isValidES5Identifier(): Boolean {
|
||||
if (isEmpty() || !this[0].isES5IdentifierStart()) return false
|
||||
for (idx in 1 ..length-1) {
|
||||
if (!get(idx).isES5IdentifierPart()) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
@@ -17,28 +17,28 @@ import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
|
||||
import org.jetbrains.kotlin.types.DynamicTypesAllowed
|
||||
|
||||
object JsPlatformConfigurator : PlatformConfiguratorBase(
|
||||
DynamicTypesAllowed(),
|
||||
additionalDeclarationCheckers = listOf(
|
||||
NativeInvokeChecker(), NativeGetterChecker(), NativeSetterChecker(),
|
||||
JsNameChecker, JsModuleChecker, JsExternalFileChecker,
|
||||
JsExternalChecker, JsInheritanceChecker, JsMultipleInheritanceChecker,
|
||||
JsRuntimeAnnotationChecker,
|
||||
JsDynamicDeclarationChecker,
|
||||
JsExportAnnotationChecker,
|
||||
JsExportDeclarationChecker
|
||||
),
|
||||
additionalCallCheckers = listOf(
|
||||
JsModuleCallChecker,
|
||||
JsDynamicCallChecker,
|
||||
JsDefinedExternallyCallChecker,
|
||||
),
|
||||
identifierChecker = JsIdentifierChecker
|
||||
DynamicTypesAllowed(),
|
||||
additionalDeclarationCheckers = listOf(
|
||||
NativeInvokeChecker(), NativeGetterChecker(), NativeSetterChecker(),
|
||||
JsNameChecker, JsModuleChecker, JsExternalFileChecker,
|
||||
JsExternalChecker, JsInheritanceChecker, JsMultipleInheritanceChecker,
|
||||
JsRuntimeAnnotationChecker,
|
||||
JsDynamicDeclarationChecker,
|
||||
JsExportAnnotationChecker,
|
||||
JsExportDeclarationChecker
|
||||
),
|
||||
additionalCallCheckers = listOf(
|
||||
JsModuleCallChecker,
|
||||
JsDynamicCallChecker,
|
||||
JsDefinedExternallyCallChecker,
|
||||
),
|
||||
) {
|
||||
override fun configureModuleComponents(container: StorageComponentContainer) {
|
||||
container.useInstance(NameSuggestion())
|
||||
container.useImpl<JsCallChecker>()
|
||||
container.useImpl<JsTypeSpecificityComparator>()
|
||||
container.useImpl<JsNameClashChecker>()
|
||||
container.useImpl<JsIdentifierChecker>()
|
||||
container.useImpl<JsNameCharsChecker>()
|
||||
container.useImpl<JsBuiltinNameClashChecker>()
|
||||
container.useInstance(JsModuleClassLiteralChecker)
|
||||
|
||||
+4
-1
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.js.resolve.diagnostics
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.js.naming.NameSuggestion
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
@@ -82,7 +83,9 @@ object JsDynamicCallChecker : CallChecker {
|
||||
}
|
||||
|
||||
private fun checkIdentifier(name: String?, reportOn: PsiElement, context: CallCheckerContext) {
|
||||
if (name == null) return
|
||||
if (name == null || context.languageVersionSettings.supportsFeature(LanguageFeature.JsAllowInvalidCharsIdentifiersEscaping)) {
|
||||
return
|
||||
}
|
||||
if (NameSuggestion.sanitizeName(name) != name) {
|
||||
context.trace.report(ErrorsJs.NAME_CONTAINS_ILLEGAL_CHARS.on(reportOn))
|
||||
}
|
||||
|
||||
+6
-1
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.jetbrains.kotlin.js.resolve.diagnostics
|
||||
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.js.naming.NameSuggestion
|
||||
@@ -23,8 +25,11 @@ import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
||||
import org.jetbrains.kotlin.resolve.IdentifierChecker
|
||||
|
||||
object JsIdentifierChecker : IdentifierChecker {
|
||||
class JsIdentifierChecker(private val languageVersionSettings: LanguageVersionSettings) : IdentifierChecker {
|
||||
override fun checkIdentifier(simpleNameExpression: KtSimpleNameExpression, diagnosticHolder: DiagnosticSink) {
|
||||
if (languageVersionSettings.supportsFeature(LanguageFeature.JsAllowInvalidCharsIdentifiersEscaping)) {
|
||||
return
|
||||
}
|
||||
val simpleName = simpleNameExpression.getReferencedName()
|
||||
|
||||
val hasIllegalChars = simpleName.split('.').any { NameSuggestion.sanitizeName(it) != it }
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.js.resolve.diagnostics
|
||||
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor
|
||||
@@ -16,6 +17,9 @@ import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
|
||||
|
||||
class JsNameCharsChecker(private val suggestion: NameSuggestion) : DeclarationChecker {
|
||||
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
|
||||
if (context.languageVersionSettings.supportsFeature(LanguageFeature.JsAllowInvalidCharsIdentifiersEscaping)) {
|
||||
return
|
||||
}
|
||||
val bindingContext = context.trace.bindingContext
|
||||
|
||||
if (descriptor is PropertyAccessorDescriptor && AnnotationsUtils.getJsName(descriptor) == null) return
|
||||
|
||||
Generated
+93
@@ -2075,6 +2075,99 @@ public class IrBoxJsES6TestGenerated extends AbstractIrBoxJsES6Test {
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("js/js.translator/testData/box/escapedIdentifiers")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class EscapedIdentifiers extends AbstractIrBoxJsES6Test {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR_ES6, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInEscapedIdentifiers() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/escapedIdentifiers"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS_IR_ES6, true);
|
||||
}
|
||||
|
||||
@TestMetadata("classLikeMemberClassMangling.kt")
|
||||
public void testClassLikeMemberClassMangling() throws Exception {
|
||||
runTest("js/js.translator/testData/box/escapedIdentifiers/classLikeMemberClassMangling.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("classLikeMemberFieldMangling.kt")
|
||||
public void testClassLikeMemberFieldMangling() throws Exception {
|
||||
runTest("js/js.translator/testData/box/escapedIdentifiers/classLikeMemberFieldMangling.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("classLikeMemberFunctionMangling.kt")
|
||||
public void testClassLikeMemberFunctionMangling() throws Exception {
|
||||
runTest("js/js.translator/testData/box/escapedIdentifiers/classLikeMemberFunctionMangling.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("dynamicEscapedField.kt")
|
||||
public void testDynamicEscapedField() throws Exception {
|
||||
runTest("js/js.translator/testData/box/escapedIdentifiers/dynamicEscapedField.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("externalEscapedAMDTopLevel.kt")
|
||||
public void testExternalEscapedAMDTopLevel() throws Exception {
|
||||
runTest("js/js.translator/testData/box/escapedIdentifiers/externalEscapedAMDTopLevel.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("externalEscapedClassFields.kt")
|
||||
public void testExternalEscapedClassFields() throws Exception {
|
||||
runTest("js/js.translator/testData/box/escapedIdentifiers/externalEscapedClassFields.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("externalEscapedCommonJSTopLevel.kt")
|
||||
public void testExternalEscapedCommonJSTopLevel() throws Exception {
|
||||
runTest("js/js.translator/testData/box/escapedIdentifiers/externalEscapedCommonJSTopLevel.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("externalEscapedTopLevel.kt")
|
||||
public void testExternalEscapedTopLevel() throws Exception {
|
||||
runTest("js/js.translator/testData/box/escapedIdentifiers/externalEscapedTopLevel.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("topLevelExportedClass.kt")
|
||||
public void testTopLevelExportedClass() throws Exception {
|
||||
runTest("js/js.translator/testData/box/escapedIdentifiers/topLevelExportedClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("topLevelExportedCompanion.kt")
|
||||
public void testTopLevelExportedCompanion() throws Exception {
|
||||
runTest("js/js.translator/testData/box/escapedIdentifiers/topLevelExportedCompanion.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("topLevelExportedFunction.kt")
|
||||
public void testTopLevelExportedFunction() throws Exception {
|
||||
runTest("js/js.translator/testData/box/escapedIdentifiers/topLevelExportedFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("topLevelExportedVariable.kt")
|
||||
public void testTopLevelExportedVariable() throws Exception {
|
||||
runTest("js/js.translator/testData/box/escapedIdentifiers/topLevelExportedVariable.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("topLevelLocalClassMangling.kt")
|
||||
public void testTopLevelLocalClassMangling() throws Exception {
|
||||
runTest("js/js.translator/testData/box/escapedIdentifiers/topLevelLocalClassMangling.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("topLevelLocalCompanionMangling.kt")
|
||||
public void testTopLevelLocalCompanionMangling() throws Exception {
|
||||
runTest("js/js.translator/testData/box/escapedIdentifiers/topLevelLocalCompanionMangling.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("topLevelLocalFunctionMangling.kt")
|
||||
public void testTopLevelLocalFunctionMangling() throws Exception {
|
||||
runTest("js/js.translator/testData/box/escapedIdentifiers/topLevelLocalFunctionMangling.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("topLevelLocalVariableMangling.kt")
|
||||
public void testTopLevelLocalVariableMangling() throws Exception {
|
||||
runTest("js/js.translator/testData/box/escapedIdentifiers/topLevelLocalVariableMangling.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("js/js.translator/testData/box/examples")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
+18
@@ -84,6 +84,24 @@ public class IrJsTypeScriptExportES6TestGenerated extends AbstractIrJsTypeScript
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("js/js.translator/testData/typescript-export/escapedDeclarations")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class EscapedDeclarations extends AbstractIrJsTypeScriptExportES6Test {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR_ES6, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInEscapedDeclarations() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/typescript-export/escapedDeclarations"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS_IR_ES6, true);
|
||||
}
|
||||
|
||||
@TestMetadata("escapedDeclarations.kt")
|
||||
public void testEscapedDeclarations() throws Exception {
|
||||
runTest("js/js.translator/testData/typescript-export/escapedDeclarations/escapedDeclarations.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("js/js.translator/testData/typescript-export/inheritance")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
+93
@@ -2070,6 +2070,99 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest {
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("js/js.translator/testData/box/escapedIdentifiers")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class EscapedIdentifiers extends AbstractIrBoxJsTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInEscapedIdentifiers() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/escapedIdentifiers"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS_IR, true);
|
||||
}
|
||||
|
||||
@TestMetadata("classLikeMemberClassMangling.kt")
|
||||
public void testClassLikeMemberClassMangling() throws Exception {
|
||||
runTest("js/js.translator/testData/box/escapedIdentifiers/classLikeMemberClassMangling.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("classLikeMemberFieldMangling.kt")
|
||||
public void testClassLikeMemberFieldMangling() throws Exception {
|
||||
runTest("js/js.translator/testData/box/escapedIdentifiers/classLikeMemberFieldMangling.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("classLikeMemberFunctionMangling.kt")
|
||||
public void testClassLikeMemberFunctionMangling() throws Exception {
|
||||
runTest("js/js.translator/testData/box/escapedIdentifiers/classLikeMemberFunctionMangling.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("dynamicEscapedField.kt")
|
||||
public void testDynamicEscapedField() throws Exception {
|
||||
runTest("js/js.translator/testData/box/escapedIdentifiers/dynamicEscapedField.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("externalEscapedAMDTopLevel.kt")
|
||||
public void testExternalEscapedAMDTopLevel() throws Exception {
|
||||
runTest("js/js.translator/testData/box/escapedIdentifiers/externalEscapedAMDTopLevel.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("externalEscapedClassFields.kt")
|
||||
public void testExternalEscapedClassFields() throws Exception {
|
||||
runTest("js/js.translator/testData/box/escapedIdentifiers/externalEscapedClassFields.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("externalEscapedCommonJSTopLevel.kt")
|
||||
public void testExternalEscapedCommonJSTopLevel() throws Exception {
|
||||
runTest("js/js.translator/testData/box/escapedIdentifiers/externalEscapedCommonJSTopLevel.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("externalEscapedTopLevel.kt")
|
||||
public void testExternalEscapedTopLevel() throws Exception {
|
||||
runTest("js/js.translator/testData/box/escapedIdentifiers/externalEscapedTopLevel.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("topLevelExportedClass.kt")
|
||||
public void testTopLevelExportedClass() throws Exception {
|
||||
runTest("js/js.translator/testData/box/escapedIdentifiers/topLevelExportedClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("topLevelExportedCompanion.kt")
|
||||
public void testTopLevelExportedCompanion() throws Exception {
|
||||
runTest("js/js.translator/testData/box/escapedIdentifiers/topLevelExportedCompanion.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("topLevelExportedFunction.kt")
|
||||
public void testTopLevelExportedFunction() throws Exception {
|
||||
runTest("js/js.translator/testData/box/escapedIdentifiers/topLevelExportedFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("topLevelExportedVariable.kt")
|
||||
public void testTopLevelExportedVariable() throws Exception {
|
||||
runTest("js/js.translator/testData/box/escapedIdentifiers/topLevelExportedVariable.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("topLevelLocalClassMangling.kt")
|
||||
public void testTopLevelLocalClassMangling() throws Exception {
|
||||
runTest("js/js.translator/testData/box/escapedIdentifiers/topLevelLocalClassMangling.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("topLevelLocalCompanionMangling.kt")
|
||||
public void testTopLevelLocalCompanionMangling() throws Exception {
|
||||
runTest("js/js.translator/testData/box/escapedIdentifiers/topLevelLocalCompanionMangling.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("topLevelLocalFunctionMangling.kt")
|
||||
public void testTopLevelLocalFunctionMangling() throws Exception {
|
||||
runTest("js/js.translator/testData/box/escapedIdentifiers/topLevelLocalFunctionMangling.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("topLevelLocalVariableMangling.kt")
|
||||
public void testTopLevelLocalVariableMangling() throws Exception {
|
||||
runTest("js/js.translator/testData/box/escapedIdentifiers/topLevelLocalVariableMangling.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("js/js.translator/testData/box/examples")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
+18
@@ -84,6 +84,24 @@ public class IrJsTypeScriptExportTestGenerated extends AbstractIrJsTypeScriptExp
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("js/js.translator/testData/typescript-export/escapedDeclarations")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class EscapedDeclarations extends AbstractIrJsTypeScriptExportTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInEscapedDeclarations() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/typescript-export/escapedDeclarations"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS_IR, true);
|
||||
}
|
||||
|
||||
@TestMetadata("escapedDeclarations.kt")
|
||||
public void testEscapedDeclarations() throws Exception {
|
||||
runTest("js/js.translator/testData/typescript-export/escapedDeclarations/escapedDeclarations.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("js/js.translator/testData/typescript-export/inheritance")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
+106
@@ -1915,6 +1915,112 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("js/js.translator/testData/box/escapedIdentifiers")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class EscapedIdentifiers {
|
||||
@Test
|
||||
public void testAllFilesPresentInEscapedIdentifiers() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/escapedIdentifiers"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("classLikeMemberClassMangling.kt")
|
||||
public void testClassLikeMemberClassMangling() throws Exception {
|
||||
runTest("js/js.translator/testData/box/escapedIdentifiers/classLikeMemberClassMangling.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("classLikeMemberFieldMangling.kt")
|
||||
public void testClassLikeMemberFieldMangling() throws Exception {
|
||||
runTest("js/js.translator/testData/box/escapedIdentifiers/classLikeMemberFieldMangling.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("classLikeMemberFunctionMangling.kt")
|
||||
public void testClassLikeMemberFunctionMangling() throws Exception {
|
||||
runTest("js/js.translator/testData/box/escapedIdentifiers/classLikeMemberFunctionMangling.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("dynamicEscapedField.kt")
|
||||
public void testDynamicEscapedField() throws Exception {
|
||||
runTest("js/js.translator/testData/box/escapedIdentifiers/dynamicEscapedField.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("externalEscapedAMDTopLevel.kt")
|
||||
public void testExternalEscapedAMDTopLevel() throws Exception {
|
||||
runTest("js/js.translator/testData/box/escapedIdentifiers/externalEscapedAMDTopLevel.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("externalEscapedClassFields.kt")
|
||||
public void testExternalEscapedClassFields() throws Exception {
|
||||
runTest("js/js.translator/testData/box/escapedIdentifiers/externalEscapedClassFields.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("externalEscapedCommonJSTopLevel.kt")
|
||||
public void testExternalEscapedCommonJSTopLevel() throws Exception {
|
||||
runTest("js/js.translator/testData/box/escapedIdentifiers/externalEscapedCommonJSTopLevel.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("externalEscapedTopLevel.kt")
|
||||
public void testExternalEscapedTopLevel() throws Exception {
|
||||
runTest("js/js.translator/testData/box/escapedIdentifiers/externalEscapedTopLevel.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("topLevelExportedClass.kt")
|
||||
public void testTopLevelExportedClass() throws Exception {
|
||||
runTest("js/js.translator/testData/box/escapedIdentifiers/topLevelExportedClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("topLevelExportedCompanion.kt")
|
||||
public void testTopLevelExportedCompanion() throws Exception {
|
||||
runTest("js/js.translator/testData/box/escapedIdentifiers/topLevelExportedCompanion.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("topLevelExportedFunction.kt")
|
||||
public void testTopLevelExportedFunction() throws Exception {
|
||||
runTest("js/js.translator/testData/box/escapedIdentifiers/topLevelExportedFunction.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("topLevelExportedVariable.kt")
|
||||
public void testTopLevelExportedVariable() throws Exception {
|
||||
runTest("js/js.translator/testData/box/escapedIdentifiers/topLevelExportedVariable.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("topLevelLocalClassMangling.kt")
|
||||
public void testTopLevelLocalClassMangling() throws Exception {
|
||||
runTest("js/js.translator/testData/box/escapedIdentifiers/topLevelLocalClassMangling.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("topLevelLocalCompanionMangling.kt")
|
||||
public void testTopLevelLocalCompanionMangling() throws Exception {
|
||||
runTest("js/js.translator/testData/box/escapedIdentifiers/topLevelLocalCompanionMangling.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("topLevelLocalFunctionMangling.kt")
|
||||
public void testTopLevelLocalFunctionMangling() throws Exception {
|
||||
runTest("js/js.translator/testData/box/escapedIdentifiers/topLevelLocalFunctionMangling.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("topLevelLocalVariableMangling.kt")
|
||||
public void testTopLevelLocalVariableMangling() throws Exception {
|
||||
runTest("js/js.translator/testData/box/escapedIdentifiers/topLevelLocalVariableMangling.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("js/js.translator/testData/box/examples")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
|
||||
@@ -31,9 +31,9 @@ import org.jetbrains.kotlin.js.backend.ast.*;
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.MetadataProperties;
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.SideEffectKind;
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.SpecialFunction;
|
||||
import org.jetbrains.kotlin.js.common.IdentifierPolicyKt;
|
||||
import org.jetbrains.kotlin.js.config.JsConfig;
|
||||
import org.jetbrains.kotlin.js.naming.NameSuggestion;
|
||||
import org.jetbrains.kotlin.js.naming.NameSuggestionKt;
|
||||
import org.jetbrains.kotlin.js.naming.SuggestedName;
|
||||
import org.jetbrains.kotlin.js.resolve.diagnostics.JsBuiltinNameClashChecker;
|
||||
import org.jetbrains.kotlin.js.sourceMap.SourceFilePathResolver;
|
||||
@@ -843,7 +843,7 @@ public final class StaticContext {
|
||||
JsExpression currentImports = pureFqn(getNameForImportsForInline(), null);
|
||||
|
||||
JsExpression lhsModuleRef;
|
||||
if (NameSuggestionKt.isValidES5Identifier(moduleId)) {
|
||||
if (IdentifierPolicyKt.isValidES5Identifier(moduleId)) {
|
||||
moduleRef = pureFqn(moduleId, importsRef);
|
||||
lhsModuleRef = pureFqn(moduleId, currentImports);
|
||||
}
|
||||
|
||||
+23
@@ -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"
|
||||
}
|
||||
+47
@@ -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"
|
||||
}
|
||||
+47
@@ -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.`run•invalid@test`())
|
||||
assertEquals(42, b.`run•invalid@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"
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
define("lib", [], function() {
|
||||
return {
|
||||
"@get something-invalid"() {
|
||||
return "something invalid"
|
||||
},
|
||||
"some+value": 42,
|
||||
"+some+object%:": {
|
||||
foo: "%%++%%"
|
||||
}
|
||||
};
|
||||
});
|
||||
+28
@@ -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"
|
||||
}
|
||||
+15
@@ -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 "🦄"
|
||||
}
|
||||
+39
@@ -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"
|
||||
}
|
||||
+11
@@ -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");
|
||||
+28
@@ -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"
|
||||
}
|
||||
+30
@@ -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"
|
||||
}
|
||||
+25
@@ -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"
|
||||
}
|
||||
+23
@@ -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"
|
||||
}
|
||||
+20
@@ -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"
|
||||
}
|
||||
+13
@@ -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"
|
||||
}
|
||||
+35
-35
@@ -7,10 +7,10 @@ var a = 0
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: function=get_p1 scope=box TARGET_BACKENDS=JS
|
||||
// CHECK_FUNCTION_EXISTS: set_p1 TARGET_BACKENDS=JS
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: function=set_p1 scope=box TARGET_BACKENDS=JS
|
||||
// CHECK_FUNCTION_EXISTS: _get_p1_ IGNORED_BACKENDS=JS
|
||||
// CHECK_FUNCTION_EXISTS: _get_p1__59117 IGNORED_BACKENDS=JS
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: function=_get_p1_ scope=box IGNORED_BACKENDS=JS
|
||||
// CHECK_FUNCTION_EXISTS: _set_p1_ IGNORED_BACKENDS=JS
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: function=_set_p1_ scope=box IGNORED_BACKENDS=JS
|
||||
// CHECK_FUNCTION_EXISTS: _set_p1__59117 IGNORED_BACKENDS=JS
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: function=_set_p1__59117 scope=box IGNORED_BACKENDS=JS
|
||||
private inline var p1: Int
|
||||
get() = a + 10000
|
||||
set(v) {
|
||||
@@ -20,9 +20,9 @@ private inline var p1: Int
|
||||
// CHECK_FUNCTION_EXISTS: get_p2 TARGET_BACKENDS=JS
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: function=get_p2 scope=box TARGET_BACKENDS=JS
|
||||
// CHECK_CALLED_IN_SCOPE: function=set_p2 scope=box TARGET_BACKENDS=JS
|
||||
// CHECK_FUNCTION_EXISTS: _get_p2_ IGNORED_BACKENDS=JS
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: function=_get_p2_ scope=box IGNORED_BACKENDS=JS
|
||||
// CHECK_CALLED_IN_SCOPE: function=_set_p2_ scope=box IGNORED_BACKENDS=JS
|
||||
// CHECK_FUNCTION_EXISTS: _get_p2__59117 IGNORED_BACKENDS=JS
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: function=_get_p2__59117 scope=box IGNORED_BACKENDS=JS
|
||||
// CHECK_CALLED_IN_SCOPE: function=_set_p2__59117 scope=box IGNORED_BACKENDS=JS
|
||||
private var p2: Int
|
||||
inline get() = a + 20000
|
||||
set(v) {
|
||||
@@ -32,9 +32,9 @@ private var p2: Int
|
||||
// CHECK_CALLED_IN_SCOPE: function=get_p3 scope=box TARGET_BACKENDS=JS
|
||||
// CHECK_FUNCTION_EXISTS: set_p3 TARGET_BACKENDS=JS
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: function=set_p3 scope=box TARGET_BACKENDS=JS
|
||||
// CHECK_CALLED_IN_SCOPE: function=_get_p3_ scope=box IGNORED_BACKENDS=JS
|
||||
// CHECK_FUNCTION_EXISTS: _set_p3_ IGNORED_BACKENDS=JS
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: function=_set_p3_ scope=box IGNORED_BACKENDS=JS
|
||||
// CHECK_CALLED_IN_SCOPE: function=_get_p3__59117 scope=box IGNORED_BACKENDS=JS
|
||||
// CHECK_FUNCTION_EXISTS: _set_p3__59117 IGNORED_BACKENDS=JS
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: function=_set_p3__59117 scope=box IGNORED_BACKENDS=JS
|
||||
var p3: Int
|
||||
get() = a + 30000
|
||||
private inline set(v) {
|
||||
@@ -44,9 +44,9 @@ var p3: Int
|
||||
// CHECK_CALLED_IN_SCOPE: function=get_p4 scope=box TARGET_BACKENDS=JS
|
||||
// CHECK_FUNCTION_EXISTS: set_p4 TARGET_BACKENDS=JS
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: function=set_p4 scope=box TARGET_BACKENDS=JS
|
||||
// CHECK_CALLED_IN_SCOPE: function=_get_p4_ scope=box IGNORED_BACKENDS=JS
|
||||
// CHECK_FUNCTION_EXISTS: _set_p4_ IGNORED_BACKENDS=JS
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: function=_set_p4_ scope=box IGNORED_BACKENDS=JS
|
||||
// CHECK_CALLED_IN_SCOPE: function=_get_p4__59117 scope=box IGNORED_BACKENDS=JS
|
||||
// CHECK_FUNCTION_EXISTS: _set_p4__59117 IGNORED_BACKENDS=JS
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: function=_set_p4__59117 scope=box IGNORED_BACKENDS=JS
|
||||
private var p4: Int
|
||||
get() = a + 40000
|
||||
inline set(v) {
|
||||
@@ -57,10 +57,10 @@ private var p4: Int
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: function=get_p5 scope=box TARGET_BACKENDS=JS
|
||||
// CHECK_FUNCTION_EXISTS: set_p5 TARGET_BACKENDS=JS
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: function=set_p5 scope=box TARGET_BACKENDS=JS
|
||||
// CHECK_FUNCTION_EXISTS: _get_p5_ IGNORED_BACKENDS=JS
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: function=_get_p5_ scope=box IGNORED_BACKENDS=JS
|
||||
// CHECK_FUNCTION_EXISTS: _set_p5_ IGNORED_BACKENDS=JS
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: function=_set_p5_ scope=box IGNORED_BACKENDS=JS
|
||||
// CHECK_FUNCTION_EXISTS: _get_p5__59117 IGNORED_BACKENDS=JS
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: function=_get_p5__59117 scope=box IGNORED_BACKENDS=JS
|
||||
// CHECK_FUNCTION_EXISTS: _set_p5__59117 IGNORED_BACKENDS=JS
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: function=_set_p5__59117 scope=box IGNORED_BACKENDS=JS
|
||||
private inline var Int.p5: Int
|
||||
get() = this * 100 + a + 50000
|
||||
set(v) {
|
||||
@@ -70,9 +70,9 @@ private inline var Int.p5: Int
|
||||
// CHECK_FUNCTION_EXISTS: get_p6 TARGET_BACKENDS=JS
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: function=get_p6 scope=box TARGET_BACKENDS=JS
|
||||
// CHECK_CALLED_IN_SCOPE: function=set_p6 scope=box TARGET_BACKENDS=JS
|
||||
// CHECK_FUNCTION_EXISTS: _get_p6_ IGNORED_BACKENDS=JS
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: function=_get_p6_ scope=box IGNORED_BACKENDS=JS
|
||||
// CHECK_CALLED_IN_SCOPE: function=_set_p6_ scope=box IGNORED_BACKENDS=JS
|
||||
// CHECK_FUNCTION_EXISTS: _get_p6__59117 IGNORED_BACKENDS=JS
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: function=_get_p6__59117 scope=box IGNORED_BACKENDS=JS
|
||||
// CHECK_CALLED_IN_SCOPE: function=_set_p6__59117 scope=box IGNORED_BACKENDS=JS
|
||||
private var Int.p6: Int
|
||||
inline get() = this * 100 + a + 60000
|
||||
set(v) {
|
||||
@@ -82,9 +82,9 @@ private var Int.p6: Int
|
||||
// CHECK_CALLED_IN_SCOPE: function=get_p7 scope=box TARGET_BACKENDS=JS
|
||||
// CHECK_FUNCTION_EXISTS: set_p7 TARGET_BACKENDS=JS
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: function=set_p7 scope=box TARGET_BACKENDS=JS
|
||||
// CHECK_CALLED_IN_SCOPE: function=_get_p7_ scope=box IGNORED_BACKENDS=JS
|
||||
// CHECK_FUNCTION_EXISTS: _set_p7_ IGNORED_BACKENDS=JS
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: function=_set_p7_ scope=box IGNORED_BACKENDS=JS
|
||||
// CHECK_CALLED_IN_SCOPE: function=_get_p7__59117 scope=box IGNORED_BACKENDS=JS
|
||||
// CHECK_FUNCTION_EXISTS: _set_p7__59117 IGNORED_BACKENDS=JS
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: function=_set_p7__59117 scope=box IGNORED_BACKENDS=JS
|
||||
var Int.p7: Int
|
||||
get() = this * 100 + a + 70000
|
||||
private inline set(v) {
|
||||
@@ -94,9 +94,9 @@ var Int.p7: Int
|
||||
// CHECK_CALLED_IN_SCOPE: function=get_p8 scope=box TARGET_BACKENDS=JS
|
||||
// CHECK_FUNCTION_EXISTS: set_p8 TARGET_BACKENDS=JS
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: function=set_p8 scope=box TARGET_BACKENDS=JS
|
||||
// CHECK_CALLED_IN_SCOPE: function=_get_p8_ scope=box IGNORED_BACKENDS=JS
|
||||
// CHECK_FUNCTION_EXISTS: _set_p8_ IGNORED_BACKENDS=JS
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: function=_set_p8_ scope=box IGNORED_BACKENDS=JS
|
||||
// CHECK_CALLED_IN_SCOPE: function=_get_p8__59117 scope=box IGNORED_BACKENDS=JS
|
||||
// CHECK_FUNCTION_EXISTS: _set_p8__59117 IGNORED_BACKENDS=JS
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: function=_set_p8__59117 scope=box IGNORED_BACKENDS=JS
|
||||
private var Int.p8: Int
|
||||
get() = this * 100 + a + 80000
|
||||
inline set(v) {
|
||||
@@ -160,10 +160,10 @@ private class A {
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: function=get_p15 scope=box TARGET_BACKENDS=JS
|
||||
// CHECK_FUNCTION_EXISTS: set_p15 TARGET_BACKENDS=JS
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: function=set_p15 scope=box TARGET_BACKENDS=JS
|
||||
// CHECK_FUNCTION_EXISTS: _get_p15_ IGNORED_BACKENDS=JS
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: function=_get_p15_ scope=box IGNORED_BACKENDS=JS
|
||||
// CHECK_FUNCTION_EXISTS: _set_p15_ IGNORED_BACKENDS=JS
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: function=_set_p15_ scope=box IGNORED_BACKENDS=JS
|
||||
// CHECK_FUNCTION_EXISTS: _get_p15__59117 IGNORED_BACKENDS=JS
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: function=_get_p15__59117 scope=box IGNORED_BACKENDS=JS
|
||||
// CHECK_FUNCTION_EXISTS: _set_p15__59117 IGNORED_BACKENDS=JS
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: function=_set_p15__59117 scope=box IGNORED_BACKENDS=JS
|
||||
private inline var A.p15: Int
|
||||
get() = a + 150000
|
||||
set(v) {
|
||||
@@ -173,9 +173,9 @@ private inline var A.p15: Int
|
||||
// CHECK_FUNCTION_EXISTS: get_p16 TARGET_BACKENDS=JS
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: function=get_p16 scope=box TARGET_BACKENDS=JS
|
||||
// CHECK_CALLED_IN_SCOPE: function=set_p16 scope=box TARGET_BACKENDS=JS
|
||||
// CHECK_FUNCTION_EXISTS: _get_p16_ IGNORED_BACKENDS=JS
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: function=_get_p16_ scope=box IGNORED_BACKENDS=JS
|
||||
// CHECK_CALLED_IN_SCOPE: function=_set_p16_ scope=box IGNORED_BACKENDS=JS
|
||||
// CHECK_FUNCTION_EXISTS: _get_p16__59117 IGNORED_BACKENDS=JS
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: function=_get_p16__59117 scope=box IGNORED_BACKENDS=JS
|
||||
// CHECK_CALLED_IN_SCOPE: function=_set_p16__59117 scope=box IGNORED_BACKENDS=JS
|
||||
private var A.p16: Int
|
||||
inline get() = a + 160000
|
||||
set(v) {
|
||||
@@ -185,9 +185,9 @@ private var A.p16: Int
|
||||
// CHECK_CALLED_IN_SCOPE: function=get_p17 scope=box TARGET_BACKENDS=JS
|
||||
// CHECK_FUNCTION_EXISTS: set_p17 TARGET_BACKENDS=JS
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: function=set_p17 scope=box TARGET_BACKENDS=JS
|
||||
// CHECK_CALLED_IN_SCOPE: function=_get_p17_ scope=box IGNORED_BACKENDS=JS
|
||||
// CHECK_FUNCTION_EXISTS: _set_p17_ IGNORED_BACKENDS=JS
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: function=_set_p17_ scope=box IGNORED_BACKENDS=JS
|
||||
// CHECK_CALLED_IN_SCOPE: function=_get_p17__59117 scope=box IGNORED_BACKENDS=JS
|
||||
// CHECK_FUNCTION_EXISTS: _set_p17__59117 IGNORED_BACKENDS=JS
|
||||
// CHECK_NOT_CALLED_IN_SCOPE: function=_set_p17__59117 scope=box IGNORED_BACKENDS=JS
|
||||
private var A.p17: Int
|
||||
get() = a + 170000
|
||||
inline set(v) {
|
||||
|
||||
+14
@@ -22,6 +22,10 @@ var _valCustomWithField = JS_TESTS.foo._valCustomWithField;
|
||||
var A4 = JS_TESTS.foo.A4;
|
||||
var O = JS_TESTS.foo.O;
|
||||
var takesO = JS_TESTS.foo.takesO;
|
||||
var KT_37829 = JS_TESTS.foo.KT_37829;
|
||||
var TestSealed = JS_TESTS.foo.TestSealed;
|
||||
var TestAbstract = JS_TESTS.foo.TestAbstract;
|
||||
var TestDataClass = JS_TESTS.foo.TestDataClass;
|
||||
function assert(condition) {
|
||||
if (!condition) {
|
||||
throw "Assertion failed";
|
||||
@@ -80,5 +84,15 @@ function box() {
|
||||
assert(O.x === 10);
|
||||
assert(O.foo() === 20);
|
||||
assert(takesO(O) === 30);
|
||||
assert(KT_37829.Companion.x == 10);
|
||||
assert(new TestSealed.AA().name == "AA");
|
||||
assert(new TestSealed.AA().bar() == "bar");
|
||||
assert(new TestSealed.BB().name == "BB");
|
||||
assert(new TestSealed.BB().baz() == "baz");
|
||||
assert(new TestAbstract.AA().name == "AA");
|
||||
assert(new TestAbstract.AA().bar() == "bar");
|
||||
assert(new TestAbstract.BB().name == "BB");
|
||||
assert(new TestAbstract.BB().baz() == "baz");
|
||||
assert(new TestDataClass.Nested().prop == "hello");
|
||||
return "OK";
|
||||
}
|
||||
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
declare namespace JS_TESTS {
|
||||
type Nullable<T> = T | null | undefined
|
||||
namespace foo {
|
||||
|
||||
|
||||
|
||||
function invalid_args_name_sum(first_value: number, second_value: number): number;
|
||||
|
||||
class A1 {
|
||||
constructor(first_value: number, second_value: number);
|
||||
readonly "first value": number;
|
||||
"second.value": number;
|
||||
}
|
||||
class A2 {
|
||||
constructor();
|
||||
"invalid:name": number;
|
||||
}
|
||||
class A3 {
|
||||
constructor();
|
||||
"invalid@name sum"(x: number, y: number): number;
|
||||
invalid_args_name_sum(first_value: number, second_value: number): number;
|
||||
}
|
||||
class A4 {
|
||||
constructor();
|
||||
static readonly Companion: {
|
||||
"@invalid+name@": number;
|
||||
"^)run.something.weird^("(): string;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
// CHECK_TYPESCRIPT_DECLARATIONS
|
||||
// RUN_PLAIN_BOX_FUNCTION
|
||||
// SKIP_MINIFICATION
|
||||
// SKIP_NODE_JS
|
||||
// IGNORE_BACKEND: JS
|
||||
// !LANGUAGE: +JsAllowInvalidCharsIdentifiersEscaping
|
||||
// INFER_MAIN_MODULE
|
||||
// MODULE: JS_TESTS
|
||||
// FILE: escapedDeclarations.kt
|
||||
|
||||
@file:JsExport
|
||||
|
||||
package foo
|
||||
|
||||
fun `invalid@name sum`(x: Int, y: Int): Int =
|
||||
x + y
|
||||
|
||||
fun invalid_args_name_sum(`first value`: Int, `second value`: Int): Int =
|
||||
`first value` + `second value`
|
||||
|
||||
// Properties
|
||||
|
||||
val `invalid name val`: Int = 1
|
||||
var `invalid@name var`: Int = 1
|
||||
|
||||
// Classes
|
||||
|
||||
class `Invalid A`
|
||||
class A1(val `first value`: Int, var `second.value`: Int)
|
||||
class A2 {
|
||||
var `invalid:name`: Int = 42
|
||||
}
|
||||
class A3 {
|
||||
fun `invalid@name sum`(x: Int, y: Int): Int =
|
||||
x + y
|
||||
|
||||
fun invalid_args_name_sum(`first value`: Int, `second value`: Int): Int =
|
||||
`first value` + `second value`
|
||||
}
|
||||
|
||||
class A4 {
|
||||
companion object {
|
||||
var `@invalid+name@` = 23
|
||||
fun `^)run.something.weird^(`(): String = ")_("
|
||||
}
|
||||
}
|
||||
Vendored
+29
@@ -0,0 +1,29 @@
|
||||
"use strict";
|
||||
var foo = JS_TESTS.foo;
|
||||
var A1 = JS_TESTS.foo.A1;
|
||||
var A2 = JS_TESTS.foo.A2;
|
||||
var A3 = JS_TESTS.foo.A3;
|
||||
var A4 = JS_TESTS.foo.A4;
|
||||
function assert(condition) {
|
||||
if (!condition) {
|
||||
throw "Assertion failed";
|
||||
}
|
||||
}
|
||||
function box() {
|
||||
assert(foo.invalid_args_name_sum(10, 20) === 30);
|
||||
assert(foo["invalid@name sum"](10, 20) === 30);
|
||||
assert(foo["invalid name val"] === 1);
|
||||
assert(foo["invalid@name var"] === 1);
|
||||
foo["invalid@name var"] = 4;
|
||||
assert(foo["invalid@name var"] === 4);
|
||||
new foo["Invalid A"]();
|
||||
assert(new A1(10, 20)["first value"] === 10);
|
||||
assert(new A1(10, 20)["second.value"] === 20);
|
||||
assert(new A2()["invalid:name"] === 42);
|
||||
var a3 = new A3();
|
||||
assert(a3.invalid_args_name_sum(10, 20) === 30);
|
||||
assert(a3["invalid@name sum"](10, 20) === 30);
|
||||
assert(A4.Companion["@invalid+name@"] == 23);
|
||||
assert(A4.Companion["^)run.something.weird^("]() === ")_(");
|
||||
return "OK";
|
||||
}
|
||||
Vendored
+37
@@ -0,0 +1,37 @@
|
||||
import foo = JS_TESTS.foo;
|
||||
import A1 = JS_TESTS.foo.A1;
|
||||
import A2 = JS_TESTS.foo.A2;
|
||||
import A3 = JS_TESTS.foo.A3;
|
||||
import A4 = JS_TESTS.foo.A4;
|
||||
|
||||
function assert(condition: boolean) {
|
||||
if (!condition) {
|
||||
throw "Assertion failed";
|
||||
}
|
||||
}
|
||||
|
||||
function box(): string {
|
||||
assert(foo.invalid_args_name_sum(10, 20) === 30);
|
||||
assert((foo as any)["invalid@name sum"](10, 20) === 30);
|
||||
|
||||
assert((foo as any)["invalid name val"] === 1);
|
||||
assert((foo as any)["invalid@name var"] === 1);
|
||||
(foo as any)["invalid@name var"] = 4
|
||||
assert((foo as any)["invalid@name var"] === 4);
|
||||
|
||||
new (foo as any)["Invalid A"]();
|
||||
|
||||
assert(new A1(10, 20)["first value"] === 10);
|
||||
assert(new A1(10, 20)["second.value"] === 20);
|
||||
|
||||
assert(new A2()["invalid:name"] === 42);
|
||||
|
||||
const a3 = new A3()
|
||||
assert(a3.invalid_args_name_sum(10, 20) === 30);
|
||||
assert(a3["invalid@name sum"](10, 20) === 30);
|
||||
|
||||
assert(A4.Companion["@invalid+name@"] == 23);
|
||||
assert(A4.Companion["^)run.something.weird^("]() === ")_(");
|
||||
|
||||
return "OK";
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"include": [ "./*" ],
|
||||
"extends": "../common.tsconfig.json"
|
||||
}
|
||||
Reference in New Issue
Block a user