[K/JS] Move ES modules logic to a new transformer with IC
This commit is contained in:
@@ -1329,31 +1329,47 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
|
||||
@Override
|
||||
public void visitImport(@NotNull JsImport jsImport) {
|
||||
p.print("import {");
|
||||
boolean isMultiline = jsImport.getElements().size() > 1;
|
||||
p.indentIn();
|
||||
if (isMultiline)
|
||||
newlineOpt();
|
||||
else
|
||||
space();
|
||||
JsImport.Target target = jsImport.getTarget();
|
||||
|
||||
for (JsImport.Element element : jsImport.getElements()) {
|
||||
nameDef(element.getName());
|
||||
JsName alias = element.getAlias();
|
||||
if (alias != null) {
|
||||
p.print(" as ");
|
||||
nameDef(alias);
|
||||
}
|
||||
p.print("import ");
|
||||
|
||||
if (isMultiline) {
|
||||
p.print(',');
|
||||
if (target instanceof JsImport.Target.Default) {
|
||||
nameDef(((JsImport.Target.Default) target).getName());
|
||||
} else if (target instanceof JsImport.Target.All) {
|
||||
p.print("* as ");
|
||||
nameDef(((JsImport.Target.All) target).getAlias());
|
||||
} else if (target instanceof JsImport.Target.Elements) {
|
||||
List<JsImport.Element> elements = ((JsImport.Target.Elements) target).getElements();
|
||||
|
||||
p.print("{");
|
||||
boolean isMultiline = elements.size() > 1;
|
||||
p.indentIn();
|
||||
if (isMultiline)
|
||||
newlineOpt();
|
||||
} else {
|
||||
else
|
||||
space();
|
||||
|
||||
for (JsImport.Element element : elements) {
|
||||
nameDef(element.getName());
|
||||
JsName alias = element.getAlias();
|
||||
if (alias != null) {
|
||||
p.print(" as ");
|
||||
nameDef(alias);
|
||||
}
|
||||
|
||||
if (isMultiline) {
|
||||
p.print(',');
|
||||
newlineOpt();
|
||||
}
|
||||
else {
|
||||
space();
|
||||
}
|
||||
}
|
||||
p.indentOut();
|
||||
p.print("}");
|
||||
}
|
||||
p.indentOut();
|
||||
p.print("} from ");
|
||||
|
||||
p.print(" from ");
|
||||
p.print(javaScriptString(jsImport.getModule()));
|
||||
}
|
||||
|
||||
|
||||
@@ -7,8 +7,23 @@ package org.jetbrains.kotlin.js.backend.ast
|
||||
|
||||
class JsImport(
|
||||
val module: String,
|
||||
val elements: MutableList<Element> = mutableListOf(),
|
||||
val target: Target,
|
||||
) : SourceInfoAwareJsNode(), JsStatement {
|
||||
constructor(module: String, elements: MutableList<Element> = mutableListOf()) : this(module, Target.Elements(elements))
|
||||
|
||||
val elements: MutableList<Element>
|
||||
get() = (target as Target.Elements).elements
|
||||
|
||||
sealed class Target {
|
||||
class Elements(val elements: MutableList<Element>) : Target()
|
||||
class Default(val name: JsName) : Target() {
|
||||
constructor(name: String) : this(JsName(name, false))
|
||||
}
|
||||
|
||||
class All(val alias: JsName) : Target() {
|
||||
constructor(alias: String) : this(JsName(alias, false))
|
||||
}
|
||||
}
|
||||
|
||||
class Element(
|
||||
val name: JsName,
|
||||
@@ -25,7 +40,7 @@ class JsImport(
|
||||
}
|
||||
|
||||
override fun deepCopy(): JsStatement =
|
||||
JsImport(module, elements.map { it }.toMutableList())
|
||||
JsImport(module, target)
|
||||
|
||||
override fun traverse(v: JsVisitorWithContext, ctx: JsContext<*>) {
|
||||
v.visit(this, ctx)
|
||||
|
||||
@@ -9,6 +9,7 @@ import com.intellij.openapi.util.text.StringUtil
|
||||
|
||||
private val LINE_SEPARATOR = System.getProperty("line.separator")!!
|
||||
private val END_MARKER = "<END>$LINE_SEPARATOR"
|
||||
private val ESM_EXTENSION = ".mjs"
|
||||
|
||||
abstract class ProcessBasedScriptEngine(
|
||||
private val executablePath: String
|
||||
@@ -58,6 +59,7 @@ abstract class ProcessBasedScriptEngine(
|
||||
}
|
||||
|
||||
override fun loadFile(path: String) {
|
||||
if (path.endsWith(ESM_EXTENSION)) return
|
||||
eval("load('${path.replace('\\', '/')}');")
|
||||
}
|
||||
|
||||
|
||||
@@ -75,27 +75,31 @@ function restoreGlobalState() {
|
||||
resetRealm();
|
||||
|
||||
// noinspection InfiniteLoopJS
|
||||
while (true) {
|
||||
let code = readline().replace(/\\n/g, '\n');
|
||||
async function loop() {
|
||||
while (true) {
|
||||
let code = readline().replace(/\\n/g, '\n');
|
||||
|
||||
try {
|
||||
switch (code) {
|
||||
case "!reset":
|
||||
resetRealm()
|
||||
break;
|
||||
case "!saveGlobalState":
|
||||
saveGlobalState();
|
||||
break;
|
||||
case "!restoreGlobalState":
|
||||
restoreGlobalState();
|
||||
break;
|
||||
default:
|
||||
print(Realm.eval(currentRealmIndex, code));
|
||||
try {
|
||||
switch (code) {
|
||||
case "!reset":
|
||||
resetRealm()
|
||||
break;
|
||||
case "!saveGlobalState":
|
||||
saveGlobalState();
|
||||
break;
|
||||
case "!restoreGlobalState":
|
||||
restoreGlobalState();
|
||||
break;
|
||||
default:
|
||||
print(await Realm.eval(currentRealmIndex, code));
|
||||
}
|
||||
} catch(e) {
|
||||
printErr(e.stack != null ? e.stack : e.toString());
|
||||
printErr('\nCODE:\n' + code);
|
||||
}
|
||||
} catch(e) {
|
||||
printErr(e.stack != null ? e.stack : e.toString());
|
||||
printErr('\nCODE:\n' + code);
|
||||
}
|
||||
|
||||
print('<END>');
|
||||
print('<END>');
|
||||
}
|
||||
}
|
||||
|
||||
loop()
|
||||
@@ -23,4 +23,7 @@ object JavaScript {
|
||||
|
||||
const val EXTENSION = "js"
|
||||
const val DOT_EXTENSION = "." + EXTENSION
|
||||
|
||||
const val MODULE_EXTENSION = "mjs"
|
||||
const val DOT_MODULE_EXTENSION = "." + MODULE_EXTENSION
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ public class AntTaskJsTest extends AbstractAntTaskTest {
|
||||
|
||||
List<String> filePaths = CollectionsKt.map(fileNames, s -> getOutputFileByName(s).getAbsolutePath());
|
||||
|
||||
(useNashorn ? NashornJsTestChecker.INSTANCE : V8JsTestChecker.INSTANCE).check(filePaths, "out", "foo", "box", "OK", withModuleSystem);
|
||||
(useNashorn ? NashornJsTestChecker.INSTANCE : V8JsTestChecker.INSTANCE).check(filePaths, "out", "foo", "box", "OK", withModuleSystem, null);
|
||||
}
|
||||
|
||||
private void doJsAntTestForPostfixPrefix(@Nullable String prefix, @Nullable String postfix) throws Exception {
|
||||
|
||||
@@ -51,9 +51,7 @@ class ClassicJsBackendFacade(
|
||||
"$KOTLIN_TEST_INTERNAL.setModuleId(\"$escapedModuleId\"); }\n" +
|
||||
"$content\n"
|
||||
|
||||
ModuleKind.PLAIN -> content
|
||||
|
||||
ModuleKind.ES -> error("Module emulation markers are not supported for ES modules")
|
||||
ModuleKind.PLAIN, ModuleKind.ES -> content
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,36 +12,29 @@ import org.jetbrains.kotlin.backend.common.serialization.signature.IdSignatureDe
|
||||
import org.jetbrains.kotlin.cli.common.isWindows
|
||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.config.languageVersionSettings
|
||||
import org.jetbrains.kotlin.ir.backend.js.*
|
||||
import org.jetbrains.kotlin.ir.backend.js.codegen.CompilerOutputSink
|
||||
import org.jetbrains.kotlin.ir.backend.js.codegen.JsGenerationGranularity
|
||||
import org.jetbrains.kotlin.ir.backend.js.codegen.JsGenerationOptions
|
||||
import org.jetbrains.kotlin.ir.backend.js.codegen.generateEsModules
|
||||
import org.jetbrains.kotlin.ir.backend.js.dce.eliminateDeadDeclarations
|
||||
import org.jetbrains.kotlin.ir.backend.js.ic.JsExecutableProducer
|
||||
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsManglerDesc
|
||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.IrModuleToJsTransformer
|
||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.IrModuleToJsTransformerTmp
|
||||
import org.jetbrains.kotlin.ir.backend.js.SourceMapsInfo
|
||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.TranslationMode
|
||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImplForJsIC
|
||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||
import org.jetbrains.kotlin.ir.util.irMessageLogger
|
||||
import org.jetbrains.kotlin.js.config.ErrorTolerancePolicy
|
||||
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
||||
import org.jetbrains.kotlin.js.test.handlers.JsBoxRunner.Companion.TEST_FUNCTION
|
||||
import org.jetbrains.kotlin.js.test.utils.esModulesSubDir
|
||||
import org.jetbrains.kotlin.js.test.utils.extractTestPackage
|
||||
import org.jetbrains.kotlin.js.test.utils.jsIrIncrementalDataProvider
|
||||
import org.jetbrains.kotlin.library.uniqueName
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi2ir.Psi2IrConfiguration
|
||||
import org.jetbrains.kotlin.psi2ir.Psi2IrTranslator
|
||||
import org.jetbrains.kotlin.serialization.js.ModuleKind
|
||||
import org.jetbrains.kotlin.test.DebugMode
|
||||
import org.jetbrains.kotlin.test.directives.JsEnvironmentConfigurationDirectives
|
||||
import org.jetbrains.kotlin.test.frontend.classic.ClassicFrontendOutputArtifact
|
||||
import org.jetbrains.kotlin.test.directives.model.RegisteredDirectives
|
||||
import org.jetbrains.kotlin.test.frontend.classic.moduleDescriptorProvider
|
||||
import org.jetbrains.kotlin.test.model.*
|
||||
import org.jetbrains.kotlin.test.services.*
|
||||
@@ -49,6 +42,9 @@ import org.jetbrains.kotlin.test.services.configuration.JsEnvironmentConfigurato
|
||||
import org.jetbrains.kotlin.utils.fileUtils.withReplacedExtensionOrNull
|
||||
import java.io.File
|
||||
|
||||
const val REGULAR_EXTENSION = ".js"
|
||||
const val ESM_EXTENSION = ".mjs"
|
||||
|
||||
class JsIrBackendFacade(
|
||||
val testServices: TestServices,
|
||||
private val firstTimeCompilation: Boolean
|
||||
@@ -91,16 +87,16 @@ class JsIrBackendFacade(
|
||||
else -> JsGenerationGranularity.WHOLE_PROGRAM
|
||||
}
|
||||
|
||||
val testPackage = extractTestPackage(testServices)
|
||||
val testPackage = extractTestPackage(testServices, ignoreEsModules = false)
|
||||
val skipRegularMode = JsEnvironmentConfigurationDirectives.SKIP_REGULAR_MODE in module.directives
|
||||
|
||||
if (skipRegularMode) return null
|
||||
|
||||
if (JsEnvironmentConfigurator.incrementalEnabled(testServices)) {
|
||||
val outputFile = if (firstTimeCompilation) {
|
||||
File(JsEnvironmentConfigurator.getJsModuleArtifactPath(testServices, module.name) + ".js")
|
||||
File(JsEnvironmentConfigurator.getJsModuleArtifactPath(testServices, module.name) + module.kind.extension)
|
||||
} else {
|
||||
File(JsEnvironmentConfigurator.getRecompiledJsModuleArtifactPath(testServices, module.name) + ".js")
|
||||
File(JsEnvironmentConfigurator.getRecompiledJsModuleArtifactPath(testServices, module.name) + module.kind.extension)
|
||||
}
|
||||
|
||||
val compiledModule = CompilerResult(
|
||||
@@ -136,11 +132,12 @@ class JsIrBackendFacade(
|
||||
PhaseConfig(jsPhases)
|
||||
}
|
||||
|
||||
|
||||
val loweredIr = compileIr(
|
||||
irModuleFragment,
|
||||
irModuleFragment.apply { resolveTestPathes() },
|
||||
MainModule.Klib(inputArtifact.outputFile.absolutePath),
|
||||
configuration,
|
||||
dependencyModules,
|
||||
dependencyModules.apply { forEach { it.resolveTestPathes() } },
|
||||
emptyMap(),
|
||||
irModuleFragment.irBuiltins,
|
||||
symbolTable,
|
||||
@@ -164,22 +161,27 @@ class JsIrBackendFacade(
|
||||
module: TestModule,
|
||||
loweredIr: LoweredIr,
|
||||
granularity: JsGenerationGranularity,
|
||||
): BinaryArtifacts.Js? {
|
||||
val generateDts = JsEnvironmentConfigurationDirectives.GENERATE_DTS in module.directives
|
||||
): BinaryArtifacts.Js {
|
||||
val mainArguments = JsEnvironmentConfigurator.getMainCallParametersForModule(module)
|
||||
.run { if (shouldBeGenerated()) arguments() else null }
|
||||
val runIrDce = JsEnvironmentConfigurationDirectives.RUN_IR_DCE in module.directives
|
||||
val onlyIrDce = JsEnvironmentConfigurationDirectives.ONLY_IR_DCE in module.directives
|
||||
val esModules = JsEnvironmentConfigurationDirectives.ES_MODULES in module.directives
|
||||
val runNewIr2Js = JsEnvironmentConfigurationDirectives.RUN_NEW_IR_2_JS in module.directives
|
||||
val perModuleOnly = JsEnvironmentConfigurationDirectives.SPLIT_PER_MODULE in module.directives
|
||||
val isEsModules = JsEnvironmentConfigurationDirectives.ES_MODULES in module.directives ||
|
||||
module.directives[JsEnvironmentConfigurationDirectives.MODULE_KIND].contains(ModuleKind.ES)
|
||||
|
||||
val outputFile = File(JsEnvironmentConfigurator.getJsModuleArtifactPath(testServices, module.name, TranslationMode.FULL) + ".js")
|
||||
val dceOutputFile = File(JsEnvironmentConfigurator.getJsModuleArtifactPath(testServices, module.name, TranslationMode.FULL_DCE_MINIMIZED_NAMES) + ".js")
|
||||
if (!esModules) {
|
||||
if (runNewIr2Js) {
|
||||
val transformer = IrModuleToJsTransformerTmp(loweredIr.context, mainArguments)
|
||||
val outputFile = File(JsEnvironmentConfigurator.getJsModuleArtifactPath(testServices, module.name, TranslationMode.FULL) + module.kind.extension)
|
||||
|
||||
if (runNewIr2Js) {
|
||||
val transformer = IrModuleToJsTransformerTmp(
|
||||
loweredIr.context,
|
||||
mainArguments,
|
||||
moduleToName = JsIrModuleToPath(
|
||||
testServices,
|
||||
isEsModules && granularity != JsGenerationGranularity.WHOLE_PROGRAM
|
||||
)
|
||||
)
|
||||
// If runIrDce then include DCE results
|
||||
// If perModuleOnly then skip whole program
|
||||
// (it.dce => runIrDce) && (perModuleOnly => it.perModule)
|
||||
@@ -199,19 +201,14 @@ class JsIrBackendFacade(
|
||||
relativeRequirePath = false
|
||||
)
|
||||
|
||||
return BinaryArtifacts.Js.JsIrArtifact(outputFile, transformer.generateModule(loweredIr.allModules)).dump(module)
|
||||
}
|
||||
return BinaryArtifacts.Js.JsIrArtifact(outputFile, transformer.generateModule(loweredIr.allModules)).dump(module)
|
||||
}
|
||||
}
|
||||
|
||||
val options = JsGenerationOptions(generatePackageJson = true, generateTypeScriptDefinitions = generateDts)
|
||||
generateEsModules(loweredIr, jsOutputSink(outputFile.parentFile.esModulesSubDir), mainArguments, granularity, options)
|
||||
|
||||
if (runIrDce) {
|
||||
eliminateDeadDeclarations(loweredIr.allModules, loweredIr.context)
|
||||
generateEsModules(loweredIr, jsOutputSink(dceOutputFile.parentFile.esModulesSubDir), mainArguments, granularity, options)
|
||||
return BinaryArtifacts.Js.JsEsArtifact(outputFile, dceOutputFile).dump(module)
|
||||
private fun IrModuleFragment.resolveTestPathes() {
|
||||
JsIrPathReplacer(testServices).let {
|
||||
files.forEach(it::lower)
|
||||
}
|
||||
return BinaryArtifacts.Js.JsEsArtifact(outputFile, null).dump(module)
|
||||
}
|
||||
|
||||
private fun loadIrFromKlib(module: TestModule, configuration: CompilerConfiguration): IrModuleInfo {
|
||||
@@ -238,55 +235,10 @@ class JsIrBackendFacade(
|
||||
) { if (it == mainModuleLib) moduleDescriptor else testServices.jsLibraryProvider.getDescriptorByCompiledLibrary(it) }
|
||||
}
|
||||
|
||||
private fun loadIrFromSources(
|
||||
private fun BinaryArtifacts.Js.JsIrArtifact.dump(
|
||||
module: TestModule,
|
||||
configuration: CompilerConfiguration,
|
||||
inputArtifact: ClassicFrontendOutputArtifact
|
||||
): IrModuleInfo {
|
||||
val errorPolicy = configuration.get(JSConfigurationKeys.ERROR_TOLERANCE_POLICY) ?: ErrorTolerancePolicy.DEFAULT
|
||||
val messageLogger = configuration.irMessageLogger
|
||||
val symbolTable = SymbolTable(IdSignatureDescriptor(JsManglerDesc), IrFactoryImplForJsIC(WholeWorldStageController()),)
|
||||
val verifySignatures = JsEnvironmentConfigurationDirectives.SKIP_MANGLE_VERIFICATION !in module.directives
|
||||
|
||||
val psi2Ir = Psi2IrTranslator(
|
||||
configuration.languageVersionSettings,
|
||||
Psi2IrConfiguration(errorPolicy.allowErrors),
|
||||
messageLogger::checkNoUnboundSymbols
|
||||
)
|
||||
val psi2IrContext = psi2Ir.createGeneratorContext(
|
||||
inputArtifact.analysisResult.moduleDescriptor,
|
||||
inputArtifact.analysisResult.bindingContext,
|
||||
symbolTable
|
||||
)
|
||||
|
||||
return getIrModuleInfoForSourceFiles(
|
||||
psi2IrContext,
|
||||
inputArtifact.project,
|
||||
configuration,
|
||||
inputArtifact.allKtFiles.values.toList(),
|
||||
sortDependencies(JsEnvironmentConfigurator.getAllRecursiveLibrariesFor(module, testServices)),
|
||||
emptyMap(),
|
||||
symbolTable,
|
||||
messageLogger,
|
||||
loadFunctionInterfacesIntoStdlib = true,
|
||||
verifySignatures,
|
||||
) { testServices.jsLibraryProvider.getDescriptorByCompiledLibrary(it) }
|
||||
}
|
||||
|
||||
private fun jsOutputSink(perFileOutputDir: File): CompilerOutputSink {
|
||||
perFileOutputDir.deleteRecursively()
|
||||
perFileOutputDir.mkdirs()
|
||||
|
||||
return object : CompilerOutputSink {
|
||||
override fun write(module: String, path: String, content: String) {
|
||||
val file = File(File(perFileOutputDir, module), path)
|
||||
file.parentFile.mkdirs()
|
||||
file.writeText(content)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun BinaryArtifacts.Js.JsIrArtifact.dump(module: TestModule, firstTimeCompilation: Boolean = true): BinaryArtifacts.Js.JsIrArtifact {
|
||||
firstTimeCompilation: Boolean = true
|
||||
): BinaryArtifacts.Js.JsIrArtifact {
|
||||
val configuration = testServices.compilerConfigurationProvider.getCompilerConfiguration(module)
|
||||
val moduleId = configuration.getNotNull(CommonConfigurationKeys.MODULE_NAME)
|
||||
val moduleKind = configuration.get(JSConfigurationKeys.MODULE_KIND, ModuleKind.PLAIN)
|
||||
@@ -297,9 +249,15 @@ class JsIrBackendFacade(
|
||||
if (dontSkipRegularMode) {
|
||||
for ((mode, output) in compilerResult.outputs.entries) {
|
||||
val outputFile = if (firstTimeCompilation) {
|
||||
File(JsEnvironmentConfigurator.getJsModuleArtifactPath(testServices, module.name, mode) + ".js")
|
||||
File(JsEnvironmentConfigurator.getJsModuleArtifactPath(testServices, module.name, mode) + moduleKind.extension)
|
||||
} else {
|
||||
File(JsEnvironmentConfigurator.getRecompiledJsModuleArtifactPath(testServices, module.name, mode) + ".js")
|
||||
File(
|
||||
JsEnvironmentConfigurator.getRecompiledJsModuleArtifactPath(
|
||||
testServices,
|
||||
module.name,
|
||||
mode
|
||||
) + moduleKind.extension
|
||||
)
|
||||
}
|
||||
output.writeTo(outputFile, moduleId, moduleKind)
|
||||
}
|
||||
@@ -307,24 +265,13 @@ class JsIrBackendFacade(
|
||||
|
||||
if (generateDts) {
|
||||
outputFile
|
||||
.withReplacedExtensionOrNull("_v5.js", ".d.ts")!!
|
||||
.withReplacedExtensionOrNull("_v5${moduleKind.extension}", ".d.ts")!!
|
||||
.write(compilerResult.tsDefinitions ?: error("No ts definitions"))
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
private fun BinaryArtifacts.Js.JsEsArtifact.dump(module: TestModule): BinaryArtifacts.Js.JsEsArtifact {
|
||||
val configuration = testServices.compilerConfigurationProvider.getCompilerConfiguration(module)
|
||||
val moduleName = configuration.getNotNull(CommonConfigurationKeys.MODULE_NAME)
|
||||
val esmTestFile = outputFile.parentFile.esModulesSubDir.resolve("test.mjs")
|
||||
createEsTestFile(esmTestFile, moduleName)
|
||||
|
||||
val dceEsmTestFile = outputDceFile?.parentFile?.esModulesSubDir?.resolve("test.mjs") ?: return this
|
||||
createEsTestFile(dceEsmTestFile, moduleName)
|
||||
return this
|
||||
}
|
||||
|
||||
private fun CompilationOutputs.writeTo(outputFile: File, moduleId: String, moduleKind: ModuleKind) {
|
||||
val wrappedCode = ClassicJsBackendFacade.wrapWithModuleEmulationMarkers(jsCode, moduleId = moduleId, moduleKind = moduleKind)
|
||||
outputFile.write(wrappedCode)
|
||||
@@ -344,32 +291,37 @@ class JsIrBackendFacade(
|
||||
writeText(text)
|
||||
}
|
||||
|
||||
private fun createEsTestFile(file: File, moduleName: String) {
|
||||
val customTestModule = testServices.moduleStructure.modules
|
||||
.flatMap { it.files }
|
||||
.singleOrNull { JsEnvironmentConfigurationDirectives.ENTRY_ES_MODULE in it.directives }
|
||||
val customTestModuleText = customTestModule?.let { testServices.sourceFileProvider.getContentOfSourceFile(it) }
|
||||
|
||||
val defaultTestModule =
|
||||
"""
|
||||
import { box } from './${moduleName}/index.js';
|
||||
let res = box();
|
||||
if (res !== "OK") {
|
||||
throw "Wrong result: " + String(res);
|
||||
}
|
||||
""".trimIndent()
|
||||
file.writeText(customTestModuleText ?: defaultTestModule)
|
||||
}
|
||||
|
||||
override fun shouldRunAnalysis(module: TestModule): Boolean {
|
||||
return JsEnvironmentConfigurator.isMainModule(module, testServices)
|
||||
}
|
||||
}
|
||||
|
||||
val ModuleKind.extension: String
|
||||
get() = when (this) {
|
||||
ModuleKind.ES -> ESM_EXTENSION
|
||||
else -> REGULAR_EXTENSION
|
||||
}
|
||||
|
||||
val RegisteredDirectives.moduleKind: ModuleKind
|
||||
get() = get(JsEnvironmentConfigurationDirectives.MODULE_KIND).singleOrNull()
|
||||
?: if (contains(JsEnvironmentConfigurationDirectives.ES_MODULES)) ModuleKind.ES else ModuleKind.PLAIN
|
||||
|
||||
val TestModule.kind: ModuleKind
|
||||
get() = directives.moduleKind
|
||||
|
||||
fun String.augmentWithModuleName(moduleName: String): String {
|
||||
check(endsWith("_v5.js"))
|
||||
val normalizedName = moduleName.run { if (isWindows) minify() else this }
|
||||
return removeSuffix("_v5.js") + "-${normalizedName}_v5.js"
|
||||
return if (moduleName.isPath()) {
|
||||
replaceAfterLast(File.separator, moduleName.replace("./", ""))
|
||||
} else {
|
||||
val suffix = when {
|
||||
endsWith(ESM_EXTENSION) -> ESM_EXTENSION
|
||||
endsWith(REGULAR_EXTENSION) -> REGULAR_EXTENSION
|
||||
else -> error("Unexpected file '$this' extension")
|
||||
}
|
||||
val normalizedName = moduleName.run { if (isWindows) minify() else this }
|
||||
|
||||
return removeSuffix("_v5$suffix") + "-${normalizedName}_v5$suffix"
|
||||
}
|
||||
}
|
||||
|
||||
// D8 ignores Windows settings related to extending of maximum path symbols count
|
||||
@@ -380,4 +332,6 @@ fun String.minify(): String {
|
||||
.replace("_minimal_for_test", "_min")
|
||||
}
|
||||
|
||||
private fun String.isPath(): Boolean = contains("/")
|
||||
|
||||
fun File.augmentWithModuleName(moduleName: String): File = File(absolutePath.augmentWithModuleName(moduleName))
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.js.test.converters
|
||||
|
||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.safeName
|
||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||
import org.jetbrains.kotlin.test.services.TestServices
|
||||
import org.jetbrains.kotlin.test.services.configuration.JsEnvironmentConfigurator.Companion.getJsArtifactSimpleName
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.runIf
|
||||
|
||||
private typealias K = IrModuleFragment
|
||||
private typealias V = String
|
||||
|
||||
class JsIrModuleToPath(val testServices: TestServices, shouldProvidePaths: Boolean) : Map<K, V> {
|
||||
override val size = if (!shouldProvidePaths) 0 else 1
|
||||
override val entries = emptySet<Map.Entry<K, V>>()
|
||||
override val keys = emptySet<K>()
|
||||
override val values = emptyList<V>()
|
||||
|
||||
override fun isEmpty() = size == 0
|
||||
override fun containsKey(key: K): Boolean = !isEmpty()
|
||||
override fun containsValue(value: V): Boolean = !isEmpty()
|
||||
|
||||
override operator fun get(key: K): V? {
|
||||
return runIf(!isEmpty()) {
|
||||
"./${getJsArtifactSimpleName(testServices, key.safeName)}_v5.mjs"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.js.test.converters
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.DeclarationTransformer
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.JsAnnotations
|
||||
import org.jetbrains.kotlin.ir.declarations.IrAnnotationContainer
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.expressions.IrConst
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||
import org.jetbrains.kotlin.ir.util.getAnnotation
|
||||
import org.jetbrains.kotlin.js.test.utils.*
|
||||
import org.jetbrains.kotlin.test.services.TestServices
|
||||
import org.jetbrains.kotlin.test.services.isJsFile
|
||||
import org.jetbrains.kotlin.test.services.isMjsFile
|
||||
import org.jetbrains.kotlin.test.services.moduleStructure
|
||||
|
||||
class JsIrPathReplacer(testServices: TestServices) : DeclarationTransformer {
|
||||
private val replacements = testServices.collectReplacementsMap()
|
||||
|
||||
override fun lower(irFile: IrFile) {
|
||||
super.lower(irFile)
|
||||
irFile.replaceJsModulePath()
|
||||
}
|
||||
|
||||
override fun transformFlat(declaration: IrDeclaration): List<IrDeclaration>? {
|
||||
return null.also {
|
||||
declaration.replaceJsModulePath()
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrAnnotationContainer.replaceJsModulePath() {
|
||||
val jsModuleAnnotation = getAnnotation(JsAnnotations.jsModuleFqn) ?: return
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val stringLiteral = jsModuleAnnotation.getValueArgument(0) as IrConst<String>
|
||||
val pathReplacement = stringLiteral.getReplacement() ?: return
|
||||
|
||||
jsModuleAnnotation.putValueArgument(0, pathReplacement)
|
||||
}
|
||||
|
||||
private fun IrConst<String>.getReplacement(): IrConst<String>? {
|
||||
val replacement = replacements[value] ?: replacements[value.replace("./", "")] ?: return null
|
||||
return IrConstImpl.string(startOffset, endOffset, type, "./" + replacement.replace("./", ""))
|
||||
}
|
||||
|
||||
private fun TestServices.collectReplacementsMap(): Map<String, String> {
|
||||
return moduleStructure.modules.asSequence()
|
||||
.map { module -> module to module.files.filter { it.isJsFile || it.isMjsFile } }
|
||||
.filter { (_, files) -> files.isNotEmpty() }
|
||||
.flatMap { (module, files) -> files.map { it.relativePath to module.getNameFor(it, this) } }
|
||||
.plus(getAdditionalFiles(this).map { it.name to it.name })
|
||||
.plus(getAdditionalMainFiles(this).map { it.name to it.name })
|
||||
.toMap()
|
||||
}
|
||||
}
|
||||
@@ -5,25 +5,15 @@
|
||||
|
||||
package org.jetbrains.kotlin.js.test.handlers
|
||||
|
||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.TranslationMode
|
||||
import org.jetbrains.kotlin.js.testOld.engines.ExternalTool
|
||||
import org.jetbrains.kotlin.js.test.utils.*
|
||||
import org.jetbrains.kotlin.test.directives.JsEnvironmentConfigurationDirectives
|
||||
import org.jetbrains.kotlin.test.services.TestServices
|
||||
import org.jetbrains.kotlin.test.services.configuration.JsEnvironmentConfigurator
|
||||
import org.jetbrains.kotlin.test.services.defaultsProvider
|
||||
import org.jetbrains.kotlin.test.services.moduleStructure
|
||||
import java.io.File
|
||||
|
||||
private val v8tool by lazy { ExternalTool(System.getProperty("javascript.engine.path.V8")) }
|
||||
|
||||
class JsBoxRunner(testServices: TestServices) : AbstractJsArtifactsCollector(testServices) {
|
||||
override fun processAfterAllModules(someAssertionWasFailed: Boolean) {
|
||||
if (someAssertionWasFailed) return
|
||||
|
||||
if (JsEnvironmentConfigurationDirectives.ES_MODULES in testServices.moduleStructure.allDirectives) {
|
||||
runEsCode()
|
||||
} else {
|
||||
if (!someAssertionWasFailed) {
|
||||
runJsCode()
|
||||
}
|
||||
}
|
||||
@@ -43,37 +33,30 @@ class JsBoxRunner(testServices: TestServices) : AbstractJsArtifactsCollector(tes
|
||||
|
||||
val dontSkipRegularMode = JsEnvironmentConfigurationDirectives.SKIP_REGULAR_MODE !in globalDirectives
|
||||
if (dontSkipRegularMode) {
|
||||
for (jsFiles in allJsFiles.values) {
|
||||
runGeneratedCode(jsFiles, testModuleName, testPackage, withModuleSystem)
|
||||
for ((mode, jsFiles) in allJsFiles) {
|
||||
val entryModulePath = extractEntryModulePath(mode, testServices)
|
||||
runGeneratedCode(entryModulePath, jsFiles, testModuleName, testPackage, withModuleSystem)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun runEsCode() {
|
||||
val globalDirectives = testServices.moduleStructure.allDirectives
|
||||
|
||||
val esmOutputDir = JsEnvironmentConfigurator.getJsArtifactsOutputDir(testServices).esModulesSubDir
|
||||
val esmDceOutputDir = JsEnvironmentConfigurator.getJsArtifactsOutputDir(testServices, TranslationMode.FULL_DCE_MINIMIZED_NAMES).esModulesSubDir
|
||||
|
||||
val dontSkipRegularMode = JsEnvironmentConfigurationDirectives.SKIP_REGULAR_MODE !in globalDirectives
|
||||
val runIrDce = JsEnvironmentConfigurationDirectives.RUN_IR_DCE in globalDirectives
|
||||
if (dontSkipRegularMode) {
|
||||
singleRunEsCode(esmOutputDir)
|
||||
if (runIrDce) {
|
||||
singleRunEsCode(esmDceOutputDir)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun singleRunEsCode(esmOutputDir: File) {
|
||||
val perFileEsModuleFile = "$esmOutputDir/test.mjs"
|
||||
val (allNonEsModuleFiles, inputJsFilesAfter) = extractAllFilesForEsRunner(testServices, esmOutputDir)
|
||||
v8tool.run(*allNonEsModuleFiles.toTypedArray(), perFileEsModuleFile, *inputJsFilesAfter.toTypedArray())
|
||||
}
|
||||
|
||||
private fun runGeneratedCode(jsFiles: List<String>, testModuleName: String?, testPackage: String?, withModuleSystem: Boolean) {
|
||||
private fun runGeneratedCode(
|
||||
entryModulePath: String?,
|
||||
jsFiles: List<String>,
|
||||
testModuleName: String?,
|
||||
testPackage: String?,
|
||||
withModuleSystem: Boolean
|
||||
) {
|
||||
getTestChecker(testServices)
|
||||
.check(jsFiles, testModuleName, testPackage, TEST_FUNCTION, DEFAULT_EXPECTED_RESULT, withModuleSystem)
|
||||
.check(
|
||||
jsFiles,
|
||||
testModuleName,
|
||||
testPackage,
|
||||
TEST_FUNCTION,
|
||||
DEFAULT_EXPECTED_RESULT,
|
||||
withModuleSystem,
|
||||
entryModulePath,
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -24,6 +24,7 @@ class JsDtsHandler(testServices: TestServices) : JsBinaryArtifactHandler(testSer
|
||||
val referenceDtsFile = module.files.first().originalFile.withReplacedExtensionOrNull(".kt", ".d.ts")
|
||||
?: error("Can't find reference .d.ts file")
|
||||
val generatedDtsFile = info.outputFile.withReplacedExtensionOrNull("_v5.js", ".d.ts")
|
||||
?: info.outputFile.withReplacedExtensionOrNull("_v5.mjs", ".d.ts")
|
||||
?: error("Can't find generated .d.ts file")
|
||||
|
||||
val generatedDts = generatedDtsFile.readText()
|
||||
|
||||
@@ -10,9 +10,10 @@ import org.jetbrains.kotlin.js.JavaScript
|
||||
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
||||
import org.jetbrains.kotlin.js.test.JsAdditionalSourceProvider
|
||||
import org.jetbrains.kotlin.js.test.converters.augmentWithModuleName
|
||||
import org.jetbrains.kotlin.js.test.converters.extension
|
||||
import org.jetbrains.kotlin.js.test.converters.kind
|
||||
import org.jetbrains.kotlin.js.test.handlers.JsBoxRunner.Companion.TEST_FUNCTION
|
||||
import org.jetbrains.kotlin.js.testOld.*
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||
import org.jetbrains.kotlin.serialization.js.ModuleKind
|
||||
import org.jetbrains.kotlin.test.TargetBackend
|
||||
@@ -30,14 +31,23 @@ import java.io.File
|
||||
|
||||
private const val MODULE_EMULATION_FILE = "${JsEnvironmentConfigurator.TEST_DATA_DIR_PATH}/moduleEmulation.js"
|
||||
|
||||
val File.esModulesSubDir: File
|
||||
get() = File(absolutePath + "_esm")
|
||||
fun TestModule.getNameFor(filePath: String, testServices: TestServices): String {
|
||||
return JsEnvironmentConfigurator.getJsArtifactSimpleName(testServices, name) + "-js-" + filePath
|
||||
}
|
||||
|
||||
private fun extractJsFiles(testServices: TestServices, modules: List<TestModule>): Pair<List<String>, List<String>> {
|
||||
val outputDir = JsEnvironmentConfigurator.getJsArtifactsOutputDir(testServices)
|
||||
fun TestModule.getNameFor(file: TestFile, testServices: TestServices): String {
|
||||
return getNameFor(file.name, testServices)
|
||||
}
|
||||
|
||||
private fun extractJsFiles(
|
||||
testServices: TestServices,
|
||||
modules: List<TestModule>,
|
||||
mode: TranslationMode = TranslationMode.FULL,
|
||||
): Pair<List<String>, List<String>> {
|
||||
val outputDir = JsEnvironmentConfigurator.getJsArtifactsOutputDir(testServices, mode)
|
||||
|
||||
fun copyInputJsFile(module: TestModule, inputJsFile: TestFile): String {
|
||||
val newName = JsEnvironmentConfigurator.getJsArtifactSimpleName(testServices, module.name) + "-js-" + inputJsFile.name
|
||||
val newName = module.getNameFor(inputJsFile, testServices)
|
||||
val targetFile = File(outputDir, newName)
|
||||
targetFile.writeText(inputJsFile.originalContent)
|
||||
return targetFile.absolutePath
|
||||
@@ -45,49 +55,74 @@ private fun extractJsFiles(testServices: TestServices, modules: List<TestModule>
|
||||
|
||||
val inputJsFiles = modules
|
||||
.flatMap { module -> module.files.map { module to it } }
|
||||
.filter { it.second.isJsFile }
|
||||
|
||||
.filter { it.second.isJsFile || it.second.isMjsFile }
|
||||
|
||||
val after = inputJsFiles
|
||||
.filter { (_, inputJsFile) -> inputJsFile.name.endsWith("__after.js") }
|
||||
.filter { (module, inputJsFile) -> inputJsFile.name.endsWith("__after${module.kind.extension}") }
|
||||
.map { (module, inputJsFile) -> copyInputJsFile(module, inputJsFile) }
|
||||
val before = inputJsFiles
|
||||
.filterNot { (_, inputJsFile) -> inputJsFile.name.endsWith("__after.js") }
|
||||
.filterNot { (module, inputJsFile) -> inputJsFile.name.endsWith("__after${module.kind.extension}") }
|
||||
.map { (module, inputJsFile) -> copyInputJsFile(module, inputJsFile) }
|
||||
|
||||
return before to after
|
||||
}
|
||||
|
||||
private fun getAdditionalFiles(testServices: TestServices): List<String> {
|
||||
fun getAdditionalFilePathes(testServices: TestServices, mode: TranslationMode = TranslationMode.FULL): List<String> {
|
||||
return getAdditionalFiles(testServices, mode, true).map { it.absolutePath }
|
||||
}
|
||||
|
||||
fun getAdditionalFiles(
|
||||
testServices: TestServices,
|
||||
mode: TranslationMode = TranslationMode.FULL,
|
||||
shouldCopyFiles: Boolean = false
|
||||
): List<File> {
|
||||
val originalFile = testServices.moduleStructure.originalTestDataFiles.first()
|
||||
|
||||
val withModuleSystem = testWithModuleSystem(testServices)
|
||||
|
||||
val additionalFiles = mutableListOf<String>()
|
||||
if (withModuleSystem) additionalFiles += File(MODULE_EMULATION_FILE).absolutePath
|
||||
val additionalFiles = mutableListOf<File>()
|
||||
if (withModuleSystem) additionalFiles += File(MODULE_EMULATION_FILE)
|
||||
|
||||
originalFile.parentFile.resolve(originalFile.nameWithoutExtension + JavaScript.DOT_EXTENSION)
|
||||
.takeIf { it.exists() }
|
||||
?.let { additionalFiles += it.absolutePath }
|
||||
?.let { additionalFiles += it }
|
||||
|
||||
originalFile.parentFile.resolve(originalFile.nameWithoutExtension + JavaScript.DOT_MODULE_EXTENSION)
|
||||
.takeIf { it.exists() }
|
||||
?.let {
|
||||
File(JsEnvironmentConfigurator.getJsArtifactsOutputDir(testServices, mode), it.name).apply {
|
||||
if (shouldCopyFiles) it.copyTo(this, true)
|
||||
}
|
||||
}
|
||||
?.let { additionalFiles += it }
|
||||
|
||||
return additionalFiles
|
||||
}
|
||||
|
||||
private fun getAdditionalMjsFiles(testServices: TestServices): List<String> {
|
||||
val originalFile = testServices.moduleStructure.originalTestDataFiles.first()
|
||||
|
||||
return originalFile.parentFile.resolve(originalFile.nameWithoutExtension + ".mjs")
|
||||
.takeIf { it.exists() }
|
||||
?.let { listOf(it.absolutePath) } ?: emptyList()
|
||||
fun getAdditionalMainFilePathes(testServices: TestServices, mode: TranslationMode = TranslationMode.FULL): List<String> {
|
||||
return getAdditionalMainFiles(testServices, mode, shouldCopyFiles = true).map { it.absolutePath }
|
||||
}
|
||||
|
||||
private fun getAdditionalMainFiles(testServices: TestServices): List<String> {
|
||||
fun getAdditionalMainFiles(
|
||||
testServices: TestServices,
|
||||
mode: TranslationMode = TranslationMode.FULL,
|
||||
shouldCopyFiles: Boolean = false
|
||||
): List<File> {
|
||||
val originalFile = testServices.moduleStructure.originalTestDataFiles.first()
|
||||
val additionalFiles = mutableListOf<String>()
|
||||
val additionalFiles = mutableListOf<File>()
|
||||
|
||||
originalFile.parentFile.resolve(originalFile.nameWithoutExtension + "__main.js")
|
||||
.takeIf { it.exists() }
|
||||
?.let { additionalFiles += it.absolutePath }
|
||||
?.let { additionalFiles += it }
|
||||
|
||||
originalFile.parentFile.resolve(originalFile.nameWithoutExtension + "__main.mjs")
|
||||
.takeIf { it.exists() }
|
||||
?.let {
|
||||
File(JsEnvironmentConfigurator.getJsArtifactsOutputDir(testServices, mode), it.name).apply {
|
||||
if (shouldCopyFiles) it.copyTo(this, true)
|
||||
}
|
||||
}
|
||||
?.let { additionalFiles += it }
|
||||
|
||||
return additionalFiles
|
||||
}
|
||||
@@ -99,26 +134,31 @@ fun testWithModuleSystem(testServices: TestServices): Boolean {
|
||||
return mainModuleKind != ModuleKind.PLAIN && NO_JS_MODULE_SYSTEM !in globalDirectives
|
||||
}
|
||||
|
||||
fun getModeOutputFilePath(testServices: TestServices, module: TestModule, mode: TranslationMode): String {
|
||||
return JsEnvironmentConfigurator.getJsModuleArtifactPath(testServices, module.name, mode) + module.kind.extension
|
||||
}
|
||||
|
||||
fun getAllFilesForRunner(
|
||||
testServices: TestServices, modulesToArtifact: Map<TestModule, BinaryArtifacts.Js>
|
||||
): Map<TranslationMode, List<String>> {
|
||||
val originalFile = testServices.moduleStructure.originalTestDataFiles.first()
|
||||
|
||||
val commonFiles = JsAdditionalSourceProvider.getAdditionalJsFiles(originalFile.parent).map { it.absolutePath }
|
||||
val (inputJsFilesBefore, inputJsFilesAfter) = extractJsFiles(testServices, testServices.moduleStructure.modules)
|
||||
val additionalFiles = getAdditionalFiles(testServices)
|
||||
val additionalMainFiles = getAdditionalMainFiles(testServices)
|
||||
|
||||
if (modulesToArtifact.values.any { it is BinaryArtifacts.Js.JsIrArtifact }) {
|
||||
// JS IR
|
||||
val (module, compilerResult) = modulesToArtifact.entries.mapNotNull { (m, c) -> (c as? BinaryArtifacts.Js.JsIrArtifact)?.let { m to c.compilerResult } }.single()
|
||||
|
||||
val (module, compilerResult) = modulesToArtifact.entries.mapNotNull { (m, c) -> (c as? BinaryArtifacts.Js.JsIrArtifact)?.let { m to c.compilerResult } }
|
||||
.single()
|
||||
val result = mutableMapOf<TranslationMode, List<String>>()
|
||||
|
||||
compilerResult.outputs.entries.forEach { (mode, outputs) ->
|
||||
val paths = mutableListOf<String>()
|
||||
|
||||
val outputFile = JsEnvironmentConfigurator.getJsModuleArtifactPath(testServices, module.name, mode) + ".js"
|
||||
val outputFile = getModeOutputFilePath(testServices, module, mode)
|
||||
val (inputJsFilesBefore, inputJsFilesAfter) = extractJsFiles(testServices, testServices.moduleStructure.modules, mode)
|
||||
val additionalFiles = getAdditionalFilePathes(testServices, mode)
|
||||
val additionalMainFiles = getAdditionalMainFilePathes(testServices, mode)
|
||||
|
||||
outputs.dependencies.forEach { (moduleId, _) ->
|
||||
paths += outputFile.augmentWithModuleName(moduleId)
|
||||
}
|
||||
@@ -129,12 +169,15 @@ fun getAllFilesForRunner(
|
||||
|
||||
return result
|
||||
} else {
|
||||
// Old BE and ES modules
|
||||
val (inputJsFilesBefore, inputJsFilesAfter) = extractJsFiles(testServices, testServices.moduleStructure.modules)
|
||||
val additionalFiles = getAdditionalFilePathes(testServices)
|
||||
val additionalMainFiles = getAdditionalMainFilePathes(testServices)
|
||||
// Old BE
|
||||
val outputDir = JsEnvironmentConfigurator.getJsArtifactsOutputDir(testServices)
|
||||
val dceOutputDir = JsEnvironmentConfigurator.getJsArtifactsOutputDir(testServices, TranslationMode.FULL_DCE_MINIMIZED_NAMES)
|
||||
|
||||
val artifactsPaths = modulesToArtifact.values.map { it.outputFile.absolutePath }.filter { !File(it).isDirectory }
|
||||
val allJsFiles = additionalFiles + inputJsFilesBefore +artifactsPaths + commonFiles + additionalMainFiles + inputJsFilesAfter
|
||||
val allJsFiles = additionalFiles + inputJsFilesBefore + artifactsPaths + commonFiles + additionalMainFiles + inputJsFilesAfter
|
||||
|
||||
val result = mutableMapOf<TranslationMode, List<String>>()
|
||||
|
||||
@@ -154,38 +197,6 @@ fun getAllFilesForRunner(
|
||||
}
|
||||
}
|
||||
|
||||
fun extractAllFilesForEsRunner(testServices: TestServices, esmOutputDir: File): Pair<List<String>, List<String>> {
|
||||
val modules = testServices.moduleStructure.modules
|
||||
val originalFile = testServices.moduleStructure.originalTestDataFiles.first()
|
||||
|
||||
val commonFiles = JsAdditionalSourceProvider.getAdditionalJsFiles(originalFile.parent).map { it.absolutePath }
|
||||
val (inputJsFilesBefore, inputJsFilesAfter) = extractJsFiles(testServices, modules)
|
||||
val additionalFiles = getAdditionalFiles(testServices)
|
||||
val additionalMjsFiles = getAdditionalMjsFiles(testServices)
|
||||
val additionalMainFiles = getAdditionalMainFiles(testServices)
|
||||
|
||||
val allNonEsModuleFiles = additionalFiles + inputJsFilesBefore + commonFiles
|
||||
|
||||
// Copy __main file if present
|
||||
if (additionalMainFiles.isNotEmpty()) {
|
||||
val newFileName = File(esmOutputDir, "test.mjs")
|
||||
newFileName.delete()
|
||||
File(additionalMainFiles.first()).copyTo(newFileName)
|
||||
}
|
||||
|
||||
// Copy all .mjs files into generated directory
|
||||
modules.flatMap { it.files }
|
||||
.filter { it.isMjsFile }
|
||||
.map { File(esmOutputDir, it.name).writeText(it.originalContent) }
|
||||
|
||||
additionalMjsFiles.forEach { mjsFile ->
|
||||
val outFile = File(esmOutputDir, File(mjsFile).name)
|
||||
File(mjsFile).copyTo(outFile, overwrite = true)
|
||||
}
|
||||
|
||||
return Pair(allNonEsModuleFiles, inputJsFilesAfter)
|
||||
}
|
||||
|
||||
fun getOnlyJsFilesForRunner(testServices: TestServices, modulesToArtifact: Map<TestModule, BinaryArtifacts.Js>): List<String> {
|
||||
return getAllFilesForRunner(testServices, modulesToArtifact).let {
|
||||
it[TranslationMode.FULL] ?: it[TranslationMode.PER_MODULE]!!
|
||||
@@ -215,8 +226,49 @@ fun getBoxFunction(testServices: TestServices): KtNamedFunction? {
|
||||
}.singleOrNull()
|
||||
}
|
||||
|
||||
fun extractTestPackage(testServices: TestServices): String? =
|
||||
getBoxFunction(testServices)?.containingKtFile?.packageFqName?.asString()?.takeIf { it.isNotEmpty() }
|
||||
fun extractTestPackage(testServices: TestServices, ignoreEsModules: Boolean = true): String? {
|
||||
val runPlainBoxFunction = RUN_PLAIN_BOX_FUNCTION in testServices.moduleStructure.allDirectives
|
||||
if (runPlainBoxFunction) return null
|
||||
|
||||
val ktFiles = testServices.moduleStructure.modules.flatMap { module ->
|
||||
module.files
|
||||
.filter { it.isKtFile }
|
||||
.map {
|
||||
val project = testServices.compilerConfigurationProvider.getProject(module)
|
||||
module to testServices.sourceFileProvider.getKtFileForSourceFile(it, project)
|
||||
}
|
||||
}
|
||||
|
||||
val fileWithBoxFunction = ktFiles.find { (module, ktFile) ->
|
||||
(!ignoreEsModules || module.kind != ModuleKind.ES) &&
|
||||
ktFile.declarations.find { it is KtNamedFunction && it.name == TEST_FUNCTION } != null
|
||||
} ?: return null
|
||||
|
||||
return fileWithBoxFunction.second.packageFqName.asString().takeIf { it.isNotEmpty() }
|
||||
}
|
||||
|
||||
fun extractEntryModulePath(
|
||||
mode: TranslationMode,
|
||||
testServices: TestServices,
|
||||
): String? =
|
||||
if (getBoxFunction(testServices) == null) {
|
||||
testServices.moduleStructure.modules
|
||||
.find { JsEnvironmentConfigurator.isMainModule(it, testServices) }
|
||||
?.run {
|
||||
files
|
||||
.find { it.isMjsFile && JsEnvironmentConfigurationDirectives.ENTRY_ES_MODULE in it.directives }
|
||||
?.let {
|
||||
JsEnvironmentConfigurator.getJsArtifactsOutputDir(testServices, mode).absolutePath +
|
||||
File.separator + getNameFor(it, testServices)
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
testServices.moduleStructure.modules
|
||||
.find { JsEnvironmentConfigurator.isMainModule(it, testServices) }
|
||||
?.let { getModeOutputFilePath(testServices, it, mode) }
|
||||
}
|
||||
|
||||
|
||||
fun getTestChecker(testServices: TestServices): AbstractJsTestChecker {
|
||||
val runTestInNashorn = java.lang.Boolean.getBoolean("kotlin.js.useNashorn")
|
||||
|
||||
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.js.engine.loadFiles
|
||||
import org.junit.Assert
|
||||
|
||||
private const val DIST_DIR_JS_PATH = "dist/js/"
|
||||
private const val ESM_EXTENSION = ".mjs"
|
||||
|
||||
fun createScriptEngine(): ScriptEngine {
|
||||
return if (java.lang.Boolean.getBoolean("kotlin.js.useNashorn")) ScriptEngineNashorn() else ScriptEngineV8()
|
||||
@@ -22,14 +23,26 @@ fun ScriptEngine.overrideAsserter() {
|
||||
eval("this['kotlin-test'].kotlin.test.overrideAsserter_wbnzx$(this['kotlin-test'].kotlin.test.DefaultAsserter);")
|
||||
}
|
||||
|
||||
private fun String.escapePath(): String {
|
||||
return replace("\\", "/")
|
||||
}
|
||||
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
fun ScriptEngine.runTestFunction(
|
||||
testModuleName: String?,
|
||||
testPackageName: String?,
|
||||
testFunctionName: String,
|
||||
withModuleSystem: Boolean,
|
||||
testFunctionArgs: String = "",
|
||||
entryModulePath: String? = null,
|
||||
): String {
|
||||
if (withModuleSystem && testModuleName == null && entryModulePath == null) {
|
||||
error("Entry point was not found. Please specify ENTRY_ES_MODULE directive near js file, if this is ES Modules test.")
|
||||
}
|
||||
var script = when {
|
||||
entryModulePath != null && entryModulePath.endsWith(ESM_EXTENSION) -> "globalThis".also {
|
||||
eval("import('${entryModulePath.escapePath()}').then(module => Object.assign(globalThis, module)).catch(console.error)")
|
||||
}
|
||||
withModuleSystem -> "\$kotlin_test_internal\$.require('" + testModuleName!! + "')"
|
||||
testModuleName === null -> "this"
|
||||
else -> testModuleName
|
||||
@@ -51,9 +64,10 @@ abstract class AbstractJsTestChecker {
|
||||
testPackageName: String?,
|
||||
testFunctionName: String,
|
||||
expectedResult: String,
|
||||
withModuleSystem: Boolean
|
||||
withModuleSystem: Boolean,
|
||||
entryModulePath: String? = null,
|
||||
) {
|
||||
val actualResult = run(files, testModuleName, testPackageName, testFunctionName, "", withModuleSystem)
|
||||
val actualResult = run(files, testModuleName, testPackageName, testFunctionName, "", withModuleSystem, entryModulePath)
|
||||
Assert.assertEquals(expectedResult, actualResult.normalize())
|
||||
}
|
||||
|
||||
@@ -76,9 +90,10 @@ abstract class AbstractJsTestChecker {
|
||||
testPackageName: String?,
|
||||
testFunctionName: String,
|
||||
testFunctionArgs: String,
|
||||
withModuleSystem: Boolean
|
||||
withModuleSystem: Boolean,
|
||||
entryModulePath: String? = null,
|
||||
) = run(files) {
|
||||
runTestFunction(testModuleName, testPackageName, testFunctionName, withModuleSystem, testFunctionArgs)
|
||||
runTestFunction(testModuleName, testPackageName, testFunctionName, withModuleSystem, testFunctionArgs, entryModulePath)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1906,18 +1906,6 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
|
||||
public void testAllFilesPresentInExport() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules/export"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("overriddenExternalMethodWithSameStableNameMethod.kt")
|
||||
public void testOverriddenExternalMethodWithSameStableNameMethod() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/overriddenExternalMethodWithSameStableNameMethod.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("reservedModuleName.kt")
|
||||
public void testReservedModuleName() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/reservedModuleName.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
|
||||
+138
@@ -2217,35 +2217,173 @@ public class FirJsTestGenerated extends AbstractFirJsTest {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules/export"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS_IR, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("bridgeSavingAfterExport.kt")
|
||||
public void testBridgeSavingAfterExport() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/bridgeSavingAfterExport.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("bridgeSavingAfterExportInExportedFile.kt")
|
||||
public void testBridgeSavingAfterExportInExportedFile() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/bridgeSavingAfterExportInExportedFile.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("defaultInlineClassConstructorParam.kt")
|
||||
public void testDefaultInlineClassConstructorParam() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/defaultInlineClassConstructorParam.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("defaultInlineClassConstructorParamInExportedFile.kt")
|
||||
public void testDefaultInlineClassConstructorParamInExportedFile() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/defaultInlineClassConstructorParamInExportedFile.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exportAllFile.kt")
|
||||
public void testExportAllFile() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/exportAllFile.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exportEnumClass.kt")
|
||||
public void testExportEnumClass() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/exportEnumClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exportFileWithEnumClass.kt")
|
||||
public void testExportFileWithEnumClass() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/exportFileWithEnumClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exportFileWithInterface.kt")
|
||||
public void testExportFileWithInterface() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/exportFileWithInterface.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exportFileWithNestedClass.kt")
|
||||
public void testExportFileWithNestedClass() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/exportFileWithNestedClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exportFileWithNestedObject.kt")
|
||||
public void testExportFileWithNestedObject() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/exportFileWithNestedObject.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exportFileWithProtectedMembers.kt")
|
||||
public void testExportFileWithProtectedMembers() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/exportFileWithProtectedMembers.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exportFileWithTopLevelProperty.kt")
|
||||
public void testExportFileWithTopLevelProperty() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/exportFileWithTopLevelProperty.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exportInnerClass.kt")
|
||||
public void testExportInnerClass() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/exportInnerClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exportInterface.kt")
|
||||
public void testExportInterface() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/exportInterface.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exportNestedClass.kt")
|
||||
public void testExportNestedClass() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/exportNestedClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exportNestedObject.kt")
|
||||
public void testExportNestedObject() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/exportNestedObject.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exportProtectedMembers.kt")
|
||||
public void testExportProtectedMembers() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/exportProtectedMembers.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exportTopLevelProperty.kt")
|
||||
public void testExportTopLevelProperty() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/exportTopLevelProperty.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nonIndetifierModuleName.kt")
|
||||
public void testNonIndetifierModuleName() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/nonIndetifierModuleName.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nonIndetifierModuleNameInExportedFile.kt")
|
||||
public void testNonIndetifierModuleNameInExportedFile() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/nonIndetifierModuleNameInExportedFile.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("overriddenChainNonExportIntermediate.kt")
|
||||
public void testOverriddenChainNonExportIntermediate() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/overriddenChainNonExportIntermediate.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("overriddenChainNonExportIntermediateInExportedFile.kt")
|
||||
public void testOverriddenChainNonExportIntermediateInExportedFile() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/overriddenChainNonExportIntermediateInExportedFile.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("overriddenExternalMethodWithSameNameMethod.kt")
|
||||
public void testOverriddenExternalMethodWithSameNameMethod() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/overriddenExternalMethodWithSameNameMethod.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("overriddenExternalMethodWithSameStableNameMethod.kt")
|
||||
public void testOverriddenExternalMethodWithSameStableNameMethod() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/overriddenExternalMethodWithSameStableNameMethod.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("overriddenExternalMethodWithSameStableNameMethodInExportedFile.kt")
|
||||
public void testOverriddenExternalMethodWithSameStableNameMethodInExportedFile() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/overriddenExternalMethodWithSameStableNameMethodInExportedFile.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("reservedModuleName.kt")
|
||||
public void testReservedModuleName() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/reservedModuleName.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("reservedModuleNameInExportedFile.kt")
|
||||
public void testReservedModuleNameInExportedFile() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/reservedModuleNameInExportedFile.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("vararg.kt")
|
||||
public void testVararg() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/vararg.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
|
||||
+138
@@ -2217,35 +2217,173 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules/export"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS_IR, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("bridgeSavingAfterExport.kt")
|
||||
public void testBridgeSavingAfterExport() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/bridgeSavingAfterExport.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("bridgeSavingAfterExportInExportedFile.kt")
|
||||
public void testBridgeSavingAfterExportInExportedFile() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/bridgeSavingAfterExportInExportedFile.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("defaultInlineClassConstructorParam.kt")
|
||||
public void testDefaultInlineClassConstructorParam() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/defaultInlineClassConstructorParam.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("defaultInlineClassConstructorParamInExportedFile.kt")
|
||||
public void testDefaultInlineClassConstructorParamInExportedFile() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/defaultInlineClassConstructorParamInExportedFile.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exportAllFile.kt")
|
||||
public void testExportAllFile() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/exportAllFile.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exportEnumClass.kt")
|
||||
public void testExportEnumClass() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/exportEnumClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exportFileWithEnumClass.kt")
|
||||
public void testExportFileWithEnumClass() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/exportFileWithEnumClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exportFileWithInterface.kt")
|
||||
public void testExportFileWithInterface() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/exportFileWithInterface.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exportFileWithNestedClass.kt")
|
||||
public void testExportFileWithNestedClass() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/exportFileWithNestedClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exportFileWithNestedObject.kt")
|
||||
public void testExportFileWithNestedObject() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/exportFileWithNestedObject.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exportFileWithProtectedMembers.kt")
|
||||
public void testExportFileWithProtectedMembers() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/exportFileWithProtectedMembers.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exportFileWithTopLevelProperty.kt")
|
||||
public void testExportFileWithTopLevelProperty() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/exportFileWithTopLevelProperty.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exportInnerClass.kt")
|
||||
public void testExportInnerClass() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/exportInnerClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exportInterface.kt")
|
||||
public void testExportInterface() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/exportInterface.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exportNestedClass.kt")
|
||||
public void testExportNestedClass() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/exportNestedClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exportNestedObject.kt")
|
||||
public void testExportNestedObject() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/exportNestedObject.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exportProtectedMembers.kt")
|
||||
public void testExportProtectedMembers() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/exportProtectedMembers.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exportTopLevelProperty.kt")
|
||||
public void testExportTopLevelProperty() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/exportTopLevelProperty.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nonIndetifierModuleName.kt")
|
||||
public void testNonIndetifierModuleName() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/nonIndetifierModuleName.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nonIndetifierModuleNameInExportedFile.kt")
|
||||
public void testNonIndetifierModuleNameInExportedFile() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/nonIndetifierModuleNameInExportedFile.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("overriddenChainNonExportIntermediate.kt")
|
||||
public void testOverriddenChainNonExportIntermediate() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/overriddenChainNonExportIntermediate.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("overriddenChainNonExportIntermediateInExportedFile.kt")
|
||||
public void testOverriddenChainNonExportIntermediateInExportedFile() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/overriddenChainNonExportIntermediateInExportedFile.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("overriddenExternalMethodWithSameNameMethod.kt")
|
||||
public void testOverriddenExternalMethodWithSameNameMethod() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/overriddenExternalMethodWithSameNameMethod.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("overriddenExternalMethodWithSameStableNameMethod.kt")
|
||||
public void testOverriddenExternalMethodWithSameStableNameMethod() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/overriddenExternalMethodWithSameStableNameMethod.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("overriddenExternalMethodWithSameStableNameMethodInExportedFile.kt")
|
||||
public void testOverriddenExternalMethodWithSameStableNameMethodInExportedFile() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/overriddenExternalMethodWithSameStableNameMethodInExportedFile.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("reservedModuleName.kt")
|
||||
public void testReservedModuleName() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/reservedModuleName.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("reservedModuleNameInExportedFile.kt")
|
||||
public void testReservedModuleNameInExportedFile() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/reservedModuleNameInExportedFile.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("vararg.kt")
|
||||
public void testVararg() throws Exception {
|
||||
runTest("js/js.translator/testData/box/esModules/export/vararg.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
|
||||
Generated
+12
@@ -456,6 +456,12 @@ public class IrJsTypeScriptExportTestGenerated extends AbstractIrJsTypeScriptExp
|
||||
runTest("js/js.translator/testData/typescript-export/module-systems/commonjs.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("esm.kt")
|
||||
public void testEsm() throws Exception {
|
||||
runTest("js/js.translator/testData/typescript-export/module-systems/esm.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("plain.kt")
|
||||
public void testPlain() throws Exception {
|
||||
@@ -484,6 +490,12 @@ public class IrJsTypeScriptExportTestGenerated extends AbstractIrJsTypeScriptExp
|
||||
runTest("js/js.translator/testData/typescript-export/module-systems-in-exported-file/commonjs.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("esm.kt")
|
||||
public void testEsm() throws Exception {
|
||||
runTest("js/js.translator/testData/typescript-export/module-systems-in-exported-file/esm.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("plain.kt")
|
||||
public void testPlain() throws Exception {
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
// DONT_TARGET_EXACT_BACKEND: JS
|
||||
// ES_MODULES
|
||||
|
||||
// MODULE: bridge_saving_after_export
|
||||
// FILE: lib.kt
|
||||
|
||||
@JsExport
|
||||
open class A<T> {
|
||||
open fun foo(value: T): T = value
|
||||
}
|
||||
|
||||
@JsExport
|
||||
class B: A<String>() {
|
||||
override fun foo(value: String): String = value
|
||||
}
|
||||
|
||||
// FILE: entry.mjs
|
||||
// ENTRY_ES_MODULE
|
||||
import { A, B } from "./bridgeSavingAfterExport-bridge_saving_after_export_v5.mjs";
|
||||
|
||||
export function box() {
|
||||
var a = new A()
|
||||
var aFoo = a.foo("ok")
|
||||
if (aFoo != "ok") return "fail 1"
|
||||
|
||||
var b = new B()
|
||||
var bFoo = b.foo("ok")
|
||||
if (bFoo != "ok") return "fail 2"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
// DONT_TARGET_EXACT_BACKEND: JS
|
||||
// ES_MODULES
|
||||
|
||||
// MODULE: bridge_saving_after_export
|
||||
// FILE: lib.kt
|
||||
@file:JsExport
|
||||
|
||||
open class A<T> {
|
||||
open fun foo(value: T): T = value
|
||||
}
|
||||
|
||||
class B: A<String>() {
|
||||
override fun foo(value: String): String = value
|
||||
}
|
||||
|
||||
// FILE: entry.mjs
|
||||
// ENTRY_ES_MODULE
|
||||
import { A, B } from "./bridgeSavingAfterExportInExportedFile-bridge_saving_after_export_v5.mjs";
|
||||
|
||||
export function box() {
|
||||
var a = new A()
|
||||
var aFoo = a.foo("ok")
|
||||
if (aFoo != "ok") return "fail 1"
|
||||
|
||||
var b = new B()
|
||||
var bFoo = b.foo("ok")
|
||||
if (bFoo != "ok") return "fail 2"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
// IGNORE_FIR
|
||||
// KT-49225
|
||||
// DONT_TARGET_EXACT_BACKEND: JS
|
||||
// ES_MODULES
|
||||
// SPLIT_PER_MODULE
|
||||
|
||||
// MODULE: lib
|
||||
// FILE: lib.kt
|
||||
value class Koo(val koo: String = "OK")
|
||||
|
||||
@JsExport
|
||||
class Bar(val koo: Koo = Koo())
|
||||
|
||||
// MODULE: main(lib)
|
||||
// FILE: entry.mjs
|
||||
// ENTRY_ES_MODULE
|
||||
|
||||
import { Bar } from "./defaultInlineClassConstructorParam-kotlin_lib_v5.mjs";
|
||||
|
||||
export function box() {
|
||||
return new Bar().koo;
|
||||
}
|
||||
Vendored
+24
@@ -0,0 +1,24 @@
|
||||
// IGNORE_FIR
|
||||
// KT-49225
|
||||
// ES_MODULES
|
||||
// DONT_TARGET_EXACT_BACKEND: JS
|
||||
// SPLIT_PER_MODULE
|
||||
|
||||
// MODULE: lib
|
||||
// FILE: koo.kt
|
||||
value class Koo(val koo: String = "OK")
|
||||
|
||||
// FILE: bar.kt
|
||||
@file:JsExport
|
||||
|
||||
class Bar(val koo: Koo = Koo())
|
||||
|
||||
// MODULE: main(lib)
|
||||
// FILE: entry.mjs
|
||||
// ENTRY_ES_MODULE
|
||||
|
||||
import { Bar } from "./defaultInlineClassConstructorParamInExportedFile-kotlin_lib_v5.mjs";
|
||||
|
||||
export function box() {
|
||||
return new Bar().koo;
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
// DONT_TARGET_EXACT_BACKEND: JS
|
||||
// EXPECTED_REACHABLE_NODES: 1252
|
||||
// INFER_MAIN_MODULE
|
||||
// ES_MODULES
|
||||
|
||||
// MODULE: export_all_file
|
||||
@@ -19,5 +18,9 @@ class B : A() {
|
||||
|
||||
// FILE: entry.mjs
|
||||
// ENTRY_ES_MODULE
|
||||
import { B } from "./export_all_file/index.js";
|
||||
console.assert(new B().foo("K") == "OK");
|
||||
|
||||
import { B } from "./exportAllFile-export_all_file_v5.mjs";
|
||||
|
||||
export function box() {
|
||||
return new B().foo("K")
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
// DONT_TARGET_EXACT_BACKEND: JS
|
||||
// ES_MODULES
|
||||
|
||||
// MODULE: export_enum_class
|
||||
// FILE: lib.kt
|
||||
|
||||
@JsExport
|
||||
enum class Foo(val constructorParameter: String) {
|
||||
A("aConstructorParameter"),
|
||||
B("bConstructorParameter");
|
||||
|
||||
val foo = ordinal
|
||||
|
||||
fun bar(value: String) = value
|
||||
|
||||
fun bay() = name
|
||||
|
||||
companion object {
|
||||
val baz = "baz"
|
||||
}
|
||||
}
|
||||
|
||||
@JsExport
|
||||
enum class Bar {
|
||||
A,
|
||||
B {
|
||||
var d = "d"
|
||||
init {
|
||||
d = "d2"
|
||||
}
|
||||
fun huh() = "huh"
|
||||
};
|
||||
|
||||
val foo = ordinal
|
||||
|
||||
fun bar(value: String) = value
|
||||
|
||||
fun bay() = name
|
||||
}
|
||||
|
||||
@JsExport
|
||||
class OuterClass {
|
||||
enum class NestedEnum {
|
||||
A,
|
||||
B;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// FILE: main.mjs
|
||||
// ENTRY_ES_MODULE
|
||||
import { Foo, Bar, OuterClass } from "./exportEnumClass-export_enum_class_v5.mjs"
|
||||
|
||||
export function box() {
|
||||
if (Foo.A !== Foo.A) return "fail1"
|
||||
if (Foo.B !== Foo.B) return "fail2"
|
||||
|
||||
if (Foo.Companion.baz !== "baz") return "fail3"
|
||||
|
||||
if (Foo.A.foo !== 0) return "fail4"
|
||||
if (Foo.B.foo !== 1) return "fail5"
|
||||
|
||||
if (Foo.A.bar("A") !== "A") return "fail6"
|
||||
if (Foo.B.bar("B") !== "B") return "fail7"
|
||||
|
||||
if (Foo.A.bay() !== "A") return "fail8"
|
||||
if (Foo.B.bay() !== "B") return "fail9"
|
||||
|
||||
if (Foo.A.constructorParameter !== "aConstructorParameter") return "fail10"
|
||||
if (Foo.B.constructorParameter !== "bConstructorParameter") return "fail11"
|
||||
|
||||
if (Bar.A.foo !== 0) return "fail12"
|
||||
if (Bar.B.foo !== 1) return "fail13"
|
||||
|
||||
if (Bar.A.bar("A") !== "A") return "fail14"
|
||||
if (Bar.B.bar("B") !== "B") return "fail15"
|
||||
|
||||
if (Bar.A.bay() !== "A") return "fail15"
|
||||
if (Bar.B.bay() !== "B") return "fail16"
|
||||
|
||||
if (Bar.B.constructor.prototype.hasOwnProperty('d')) return "fail17"
|
||||
if (Bar.B.constructor.prototype.hasOwnProperty('huh')) return "fail18"
|
||||
|
||||
if (Foo.valueOf("A") !== Foo.A) return "fail19"
|
||||
if (Foo.valueOf("B") !== Foo.B) return "fail20"
|
||||
|
||||
if (Foo.values().indexOf(Foo.A) === -1) return "fail21"
|
||||
if (Foo.values().indexOf(Foo.B) === -1) return "fail22"
|
||||
|
||||
if (Foo.A.name !== "A") return "fail23"
|
||||
if (Foo.B.name !== "B") return "fail24"
|
||||
|
||||
if (Foo.A.ordinal !== 0) return "fail25"
|
||||
if (Foo.B.ordinal !== 1) return "fail26"
|
||||
|
||||
if (OuterClass.NestedEnum.A.name !== "A") return "fail27"
|
||||
if (OuterClass.NestedEnum.B.name !== "B") return "fail28"
|
||||
|
||||
if (OuterClass.NestedEnum.A.ordinal !== 0) return "fail29"
|
||||
if (OuterClass.NestedEnum.B.ordinal !== 1) return "fail30"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
// DONT_TARGET_EXACT_BACKEND: JS
|
||||
// ES_MODULES
|
||||
|
||||
// MODULE: export_enum_class
|
||||
// FILE: lib.kt
|
||||
@file:JsExport
|
||||
|
||||
enum class Foo(val constructorParameter: String) {
|
||||
A("aConstructorParameter"),
|
||||
B("bConstructorParameter");
|
||||
|
||||
val foo = ordinal
|
||||
|
||||
fun bar(value: String) = value
|
||||
|
||||
fun bay() = name
|
||||
|
||||
companion object {
|
||||
val baz = "baz"
|
||||
}
|
||||
}
|
||||
|
||||
enum class Bar {
|
||||
A,
|
||||
B {
|
||||
var d = "d"
|
||||
init {
|
||||
d = "d2"
|
||||
}
|
||||
fun huh() = "huh"
|
||||
};
|
||||
|
||||
val foo = ordinal
|
||||
|
||||
fun bar(value: String) = value
|
||||
|
||||
fun bay() = name
|
||||
}
|
||||
|
||||
class OuterClass {
|
||||
enum class NestedEnum {
|
||||
A,
|
||||
B;
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: main.mjs
|
||||
// ENTRY_ES_MODULE
|
||||
import { Foo, Bar, OuterClass } from "./exportFileWithEnumClass-export_enum_class_v5.mjs"
|
||||
|
||||
export function box() {
|
||||
if (Foo.A !== Foo.A) return "fail1"
|
||||
if (Foo.B !== Foo.B) return "fail2"
|
||||
|
||||
if (Foo.Companion.baz !== "baz") return "fail3"
|
||||
|
||||
if (Foo.A.foo !== 0) return "fail4"
|
||||
if (Foo.B.foo !== 1) return "fail5"
|
||||
|
||||
if (Foo.A.bar("A") !== "A") return "fail6"
|
||||
if (Foo.B.bar("B") !== "B") return "fail7"
|
||||
|
||||
if (Foo.A.bay() !== "A") return "fail8"
|
||||
if (Foo.B.bay() !== "B") return "fail9"
|
||||
|
||||
if (Foo.A.constructorParameter !== "aConstructorParameter") return "fail10"
|
||||
if (Foo.B.constructorParameter !== "bConstructorParameter") return "fail11"
|
||||
|
||||
if (Bar.A.foo !== 0) return "fail12"
|
||||
if (Bar.B.foo !== 1) return "fail13"
|
||||
|
||||
if (Bar.A.bar("A") !== "A") return "fail14"
|
||||
if (Bar.B.bar("B") !== "B") return "fail15"
|
||||
|
||||
if (Bar.A.bay() !== "A") return "fail15"
|
||||
if (Bar.B.bay() !== "B") return "fail16"
|
||||
|
||||
if (Bar.B.constructor.prototype.hasOwnProperty('d')) return "fail17"
|
||||
if (Bar.B.constructor.prototype.hasOwnProperty('huh')) return "fail18"
|
||||
|
||||
if (Foo.valueOf("A") !== Foo.A) return "fail19"
|
||||
if (Foo.valueOf("B") !== Foo.B) return "fail20"
|
||||
|
||||
if (Foo.values().indexOf(Foo.A) === -1) return "fail21"
|
||||
if (Foo.values().indexOf(Foo.B) === -1) return "fail22"
|
||||
|
||||
if (Foo.A.name !== "A") return "fail23"
|
||||
if (Foo.B.name !== "B") return "fail24"
|
||||
|
||||
if (Foo.A.ordinal !== 0) return "fail25"
|
||||
if (Foo.B.ordinal !== 1) return "fail26"
|
||||
|
||||
if (OuterClass.NestedEnum.A.name !== "A") return "fail27"
|
||||
if (OuterClass.NestedEnum.B.name !== "B") return "fail28"
|
||||
|
||||
if (OuterClass.NestedEnum.A.ordinal !== 0) return "fail29"
|
||||
if (OuterClass.NestedEnum.B.ordinal !== 1) return "fail30"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
// DONT_TARGET_EXACT_BACKEND: JS
|
||||
// ES_MODULES
|
||||
|
||||
// MODULE: export_interface
|
||||
// FILE: not_exported.kt
|
||||
|
||||
interface ParentI {
|
||||
val str: String
|
||||
}
|
||||
|
||||
interface ExtendedI: I {
|
||||
fun bar(): Int
|
||||
}
|
||||
|
||||
open class NotExportedClass(override var value: Int) : ExtendedI {
|
||||
override var variable: Int = value
|
||||
override open fun foo(): String = "Not Exported"
|
||||
override val str: String = "test 1"
|
||||
override open fun bar(): Int = 42
|
||||
}
|
||||
|
||||
|
||||
// FILE: exportes.kt
|
||||
@file:JsExport
|
||||
|
||||
interface I : ParentI {
|
||||
val value: Int
|
||||
var variable: Int
|
||||
fun foo(): String
|
||||
}
|
||||
|
||||
class ExportedClass(override val value: Int) : ExtendedI {
|
||||
override var variable: Int = value
|
||||
override fun foo(): String = "Exported"
|
||||
override val str: String = "test 2"
|
||||
override open fun bar(): Int = 43
|
||||
}
|
||||
|
||||
class AnotherOne : NotExportedClass(42) {
|
||||
override fun foo(): String = "Another One Exported"
|
||||
}
|
||||
|
||||
fun generateNotExported(value: Int): NotExportedClass {
|
||||
return NotExportedClass(value)
|
||||
}
|
||||
|
||||
fun consume(i: I): String {
|
||||
return "Value is ${i.value}, variable is ${i.variable} and result is '${i.foo()}'"
|
||||
}
|
||||
|
||||
// FILE: main.mjs
|
||||
// ENTRY_ES_MODULE
|
||||
import * as pkg from "./exportFileWithInterface-export_interface_v5.mjs"
|
||||
|
||||
export function box() {
|
||||
const { I, ExportedClass, AnotherOne, generateNotExported, consume } = pkg
|
||||
if (I !== undefined) return "Fail: module should not export interface in runtime"
|
||||
|
||||
const exported = new ExportedClass(1)
|
||||
const another = new AnotherOne()
|
||||
const notExported = generateNotExported (3)
|
||||
|
||||
if (exported.foo() !== "Exported") return "Fail: foo function was not generated for ExportedClass"
|
||||
if (another.foo() !== "Another One Exported") return "Fail: foo function was not generated for AnotherOne"
|
||||
if (notExported.foo() !== "Not Exported") return "Fail: foo function was not generated for NotExportedClass"
|
||||
|
||||
if (exported.value !== 1) return "Fail: value getter was not generated for ExportedClass"
|
||||
if (another.value !== 42) return "Fail: value getter was not generated for AnotherOne"
|
||||
if (notExported.value !== 3) return "Fail: value getter was not generated for NotExportedClass"
|
||||
|
||||
if (exported.variable !== 1) return "Fail: variable getter was not generated for ExportedClass"
|
||||
if (another.variable !== 42) return "Fail: variable getter was not generated for AnotherOne"
|
||||
if (notExported.variable !== 3) return "Fail: variable getter was not generated for NotExportedClass"
|
||||
|
||||
exported.variable = 101
|
||||
another.variable = 102
|
||||
notExported.variable = 103
|
||||
|
||||
if (exported.variable !== 101) return "Fail: variable setter was not generated for ExportedClass"
|
||||
if (another.variable !== 102) return "Fail: variable setter was not generated for AnotherOne"
|
||||
if (notExported.variable !== 103) return "Fail: variable setter was not generated for NotExportedClass"
|
||||
|
||||
try {
|
||||
notExported.value = 42
|
||||
} catch(e) {}
|
||||
if (notExported.value !== 3) return "Fail: value setter was generated for NotExportedClass, but it shouldn't"
|
||||
|
||||
if (consume(exported) !== "Value is 1, variable is 101 and result is 'Exported'") return "Fail: methods or fields of ExportedClass was mangled"
|
||||
if (consume(another) !== "Value is 42, variable is 102 and result is 'Another One Exported'") return "Fail: methods or fields of AnotherOne was mangled"
|
||||
if (consume(notExported) !== "Value is 3, variable is 103 and result is 'Not Exported'") return "Fail: methods or fields of NotExported was mangled"
|
||||
|
||||
if (notExported.str !== undefined) return "Fail: str should not exist inside NotExportedClass"
|
||||
if (exported.str !== undefined) return "Fail: str should not exist inside ExportedClass"
|
||||
|
||||
if (notExported.bar !== undefined) return "Fail: bar should not exist inside NotExportedClass"
|
||||
if (exported.bar !== undefined) return "Fail: bar should not exist inside ExportedClass"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
// EXPECTED_REACHABLE_NODES: 1252
|
||||
// DONT_TARGET_EXACT_BACKEND: JS
|
||||
// ES_MODULES
|
||||
// SKIP_DCE_DRIVEN
|
||||
|
||||
// MODULE: export_nested_class
|
||||
// FILE: lib.kt
|
||||
@file:JsExport
|
||||
|
||||
abstract class A {
|
||||
abstract fun foo(k: String): String
|
||||
}
|
||||
|
||||
class B {
|
||||
class Foo : A() {
|
||||
override fun foo(k: String): String {
|
||||
return "O" + k
|
||||
}
|
||||
|
||||
fun bar(k: String): String {
|
||||
return foo(k)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object MyObject {
|
||||
class A {
|
||||
fun valueA() = "OK"
|
||||
}
|
||||
class B {
|
||||
fun valueB() = "OK"
|
||||
}
|
||||
class C {
|
||||
fun valueC() = "OK"
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: test.mjs
|
||||
// ENTRY_ES_MODULE
|
||||
import { B, MyObject } from "./exportFileWithNestedClass-export_nested_class_v5.mjs"
|
||||
|
||||
export function box() {
|
||||
if (new B.Foo().bar("K") != "OK") return "fail 1";
|
||||
|
||||
const myObject = MyObject.getInstance()
|
||||
if (new myObject.A().valueA() != "OK") return "fail 2";
|
||||
if (new myObject.B().valueB() != "OK") return "fail 3";
|
||||
if (new myObject.C().valueC() != "OK") return "fail 4";
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
// EXPECTED_REACHABLE_NODES: 1265
|
||||
// ES_MODULES
|
||||
// DONT_TARGET_EXACT_BACKEND: JS
|
||||
// SKIP_MINIFICATION
|
||||
// SKIP_DCE_DRIVEN
|
||||
// SKIP_NODE_JS
|
||||
|
||||
// See KT-43783
|
||||
|
||||
// MODULE: nestedObjectExport
|
||||
// FILE: lib.kt
|
||||
@file:JsExport
|
||||
|
||||
class Abc {
|
||||
companion object AbcCompanion {
|
||||
fun xyz(): String = "Companion object method OK"
|
||||
|
||||
val prop: String
|
||||
get() = "Companion object property OK"
|
||||
}
|
||||
}
|
||||
|
||||
class Foo {
|
||||
companion object {
|
||||
fun xyz(): String = "Companion object method OK"
|
||||
|
||||
val prop: String
|
||||
get() = "Companion object property OK"
|
||||
}
|
||||
}
|
||||
|
||||
sealed class MyEnum(val name: String) {
|
||||
object A: MyEnum("A")
|
||||
object B: MyEnum("B")
|
||||
object C: MyEnum("C")
|
||||
}
|
||||
|
||||
object MyObject {
|
||||
object A {
|
||||
fun valueA() = "OK"
|
||||
}
|
||||
object B {
|
||||
fun valueB() = "OK"
|
||||
}
|
||||
object C {
|
||||
fun valueC() = "OK"
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: main.mjs
|
||||
// ENTRY_ES_MODULE
|
||||
import { Foo, Abc, MyEnum, MyObject } from "./exportFileWithNestedObject-nestedObjectExport_v5.mjs"
|
||||
|
||||
export function box() {
|
||||
if (Abc.AbcCompanion.xyz() != 'Companion object method OK') return 'companion object function failure';
|
||||
if (Abc.AbcCompanion.prop != 'Companion object property OK') return 'companion object property failure';
|
||||
|
||||
if (Foo.Companion.xyz() != 'Companion object method OK') return 'companion object function failure';
|
||||
if (Foo.Companion.prop != 'Companion object property OK') return 'companion object property failure';
|
||||
|
||||
if (MyEnum.A.name != 'A') return 'MyEnum.A failure';
|
||||
if (MyEnum.B.name != 'B') return 'MyEnum.B failure';
|
||||
if (MyEnum.C.name != 'C') return 'MyEnum.C failure';
|
||||
|
||||
if (MyObject.getInstance().A.valueA() != "OK") return 'MyObject.A failure';
|
||||
if (MyObject.getInstance().B.valueB() != "OK") return 'MyObject.B failure';
|
||||
if (MyObject.getInstance().C.valueC() != "OK") return 'MyObject.C failure';
|
||||
|
||||
return 'OK';
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
// EXPECTED_REACHABLE_NODES: 1265
|
||||
// ES_MODULES
|
||||
// DONT_TARGET_EXACT_BACKEND: JS
|
||||
// SKIP_MINIFICATION
|
||||
// SKIP_NODE_JS
|
||||
// SKIP_DCE_DRIVEN
|
||||
|
||||
// MODULE: exportProtectedMembers
|
||||
// FILE: lib.kt
|
||||
@file:JsExport
|
||||
|
||||
open class Foo protected constructor() {
|
||||
protected fun bar(): String = "protected method"
|
||||
|
||||
private var _baz: String = "baz"
|
||||
|
||||
protected var baz: String
|
||||
get() = _baz
|
||||
set(value) {
|
||||
_baz = value
|
||||
}
|
||||
|
||||
protected val bazReadOnly: String
|
||||
get() = _baz
|
||||
|
||||
protected val quux: String = "quux"
|
||||
|
||||
protected var quuz: String = "quuz"
|
||||
|
||||
protected class NestedClass {
|
||||
val prop: String = "nested class property"
|
||||
}
|
||||
protected object NestedObject {
|
||||
val prop: String = "nested object property"
|
||||
}
|
||||
|
||||
protected companion object {
|
||||
val prop: String = "companion object property"
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: main.mjs
|
||||
// ENTRY_ES_MODULE
|
||||
import { Foo } from "./exportFileWithProtectedMembers-exportProtectedMembers_v5.mjs"
|
||||
|
||||
export function box() {
|
||||
var foo = new Foo();
|
||||
|
||||
if (foo.bar() != 'protected method') return 'failed to call protected method';
|
||||
if (foo.baz != 'baz') return 'failed to read `baz`';
|
||||
if (foo.bazReadOnly != 'baz') return 'failed to read `bazReadOnly`';
|
||||
foo.baz = 'beer';
|
||||
if (foo.baz != 'beer') return 'failed to write protected var';
|
||||
if (foo.bazReadOnly != 'beer') return 'unexpected value of `bazReadOnly` after modifying `baz`';
|
||||
if (foo.quux != 'quux') return 'failed to read `quux`';
|
||||
if (foo.quuz != 'quuz') return 'failed to read `quuz`';
|
||||
foo.quuz = 'ale';
|
||||
if (foo.quuz != 'ale') return 'failed to write `quuz`';
|
||||
|
||||
var nestedClass = new Foo.NestedClass()
|
||||
if (nestedClass.prop != 'nested class property')
|
||||
return 'failed to read protected class property'
|
||||
if (Foo.NestedObject.prop != 'nested object property')
|
||||
return 'failed to read protected nested object property'
|
||||
if (Foo.Companion.prop != 'companion object property')
|
||||
return 'failed to read protected companion object property'
|
||||
|
||||
return 'OK';
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
// DONT_TARGET_EXACT_BACKEND: JS
|
||||
// EXPECTED_REACHABLE_NODES: 1252
|
||||
// INFER_MAIN_MODULE
|
||||
// ES_MODULES
|
||||
|
||||
// MODULE: exported_properites
|
||||
// FILE: lib.kt
|
||||
@file:JsExport
|
||||
|
||||
val regularValueProperty: String = "regularValueProperty"
|
||||
|
||||
val regularPropertyGetter: String
|
||||
get() = "regularPropertyGetter"
|
||||
|
||||
var regularVariableProperty: String = "regularVariableProperty"
|
||||
|
||||
var regularVariableGetterWithSetter: String = "regularVariableGetterWithSetter"
|
||||
get() = "$field by custom getter"
|
||||
set(value) { field = "$value set by custom setter" }
|
||||
|
||||
// FILE: entry.mjs
|
||||
// ENTRY_ES_MODULE
|
||||
|
||||
import {
|
||||
regularValueProperty,
|
||||
regularPropertyGetter,
|
||||
regularVariableProperty,
|
||||
regularVariableGetterWithSetter
|
||||
} from "./exportFileWithTopLevelProperty-exported_properites_v5.mjs";
|
||||
|
||||
export function box() {
|
||||
if (typeof regularValueProperty.get !== "function" || regularValueProperty.get() !== "regularValueProperty") {
|
||||
return "Fail: wrongly exported getter for regular `val` property"
|
||||
}
|
||||
if (typeof regularValueProperty.set !== "undefined") {
|
||||
return "Fail: wrongly exported setter for regular `val` property"
|
||||
}
|
||||
if (typeof regularPropertyGetter.get !== "function" || regularPropertyGetter.get() !== "regularPropertyGetter") {
|
||||
return "Fail: wrongly exported getter for a `val` property with custom getter"
|
||||
}
|
||||
if (typeof regularPropertyGetter.set !== "undefined") {
|
||||
return "Fail: wrongly exported setter for a `val` property with custom getter"
|
||||
}
|
||||
if (typeof regularVariableProperty.get !== "function" || regularVariableProperty.get() !== "regularVariableProperty") {
|
||||
return "Fail: wrongly exported getter for regular `var` property"
|
||||
}
|
||||
if (typeof regularVariableProperty.set !== "function" || (regularVariableProperty.set("test1"), regularVariableProperty.get()) !== "test1") {
|
||||
return "Fail: wrongly exported setter for regular `var` property"
|
||||
}
|
||||
if (typeof regularVariableGetterWithSetter.get !== "function" || regularVariableGetterWithSetter.get() !== "regularVariableGetterWithSetter by custom getter") {
|
||||
return "Fail: wrongly exported getter for a `var` property with custom getter and setter"
|
||||
}
|
||||
if (typeof regularVariableGetterWithSetter.set !== "function" || (regularVariableGetterWithSetter.set("test1"), regularVariableGetterWithSetter.get()) !== "test1 set by custom setter by custom getter") {
|
||||
return "Fail: wrongly exported setter for a `var` property with custom getter and setter"
|
||||
}
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
// EXPECTED_REACHABLE_NODES: 1252
|
||||
// IGNORE_BACKEND: JS
|
||||
// ES_MODULES
|
||||
// DONT_TARGET_EXACT_BACKEND: JS
|
||||
|
||||
// MODULE: export_inner_class
|
||||
// FILE: lib.kt
|
||||
|
||||
@JsExport
|
||||
class RegularParent(val value: String) {
|
||||
inner class RegularInner(val message: String, val anotherValue: Int) {
|
||||
fun getResult() = value + message
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@JsExport
|
||||
class ParentForSecondary {
|
||||
inner class InnerWithSecondaryConstructor(val value: String) {
|
||||
@JsName("innerSuccess")
|
||||
constructor(): this("OK")
|
||||
}
|
||||
}
|
||||
|
||||
@JsExport
|
||||
class ParentWithSecondary(val value: String) {
|
||||
@JsName("createO")
|
||||
constructor(): this("O")
|
||||
|
||||
inner class InnerWithSecondaryConstructor(val anotherValue: String) {
|
||||
@JsName("createK")
|
||||
constructor(): this("K")
|
||||
|
||||
fun getResult() = value + anotherValue
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// FILE: main.mjs
|
||||
// ENTRY_ES_MODULE
|
||||
import { RegularParent, ParentForSecondary, ParentWithSecondary } from "./exportInnerClass-export_inner_class_v5.mjs"
|
||||
|
||||
export function box() {
|
||||
var regularParent = new RegularParent("O")
|
||||
var regularInner = new regularParent.RegularInner("K", 42)
|
||||
|
||||
if (regularInner.anotherValue !== 42) return "Fail: second parameter of the RegularInner primary constructor was ignored"
|
||||
if (regularInner.getResult() !== "OK") return "Fail: something is going wrong with the outer this capturing logic"
|
||||
|
||||
var parentForSecondary = new ParentForSecondary()
|
||||
var innerWithSecondary = new parentForSecondary.InnerWithSecondaryConstructor("OK")
|
||||
|
||||
if (innerWithSecondary.value !== "OK") return "Fail: something is going wrong with primary constructor when a secondary one exists"
|
||||
|
||||
var fromSecondary = parentForSecondary.InnerWithSecondaryConstructor.innerSuccess()
|
||||
|
||||
if (fromSecondary.value !== "OK") return "Fail: something is going wrong with secondary constructor inside the inner class"
|
||||
|
||||
var parentFromSecondary = ParentWithSecondary.createO()
|
||||
var innerFromSecondary = parentFromSecondary.InnerWithSecondaryConstructor.createK()
|
||||
|
||||
if (innerFromSecondary.getResult() !== "OK") return "Fail: there is a problem when both parent and inner class have secondary constructors"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
// IGNORE_BACKEND: JS
|
||||
// RUN_PLAIN_BOX_FUNCTION
|
||||
// DONT_TARGET_EXACT_BACKEND: JS
|
||||
// ES_MODULES
|
||||
|
||||
// MODULE: export_interface
|
||||
// FILE: lib.kt
|
||||
|
||||
interface ParentI {
|
||||
val str: String
|
||||
}
|
||||
|
||||
@JsExport
|
||||
interface I : ParentI {
|
||||
val value: Int
|
||||
var variable: Int
|
||||
fun foo(): String
|
||||
}
|
||||
|
||||
interface ExtendedI: I {
|
||||
fun bar(): Int
|
||||
}
|
||||
|
||||
open class NotExportedClass(override var value: Int) : ExtendedI {
|
||||
override var variable: Int = value
|
||||
override open fun foo(): String = "Not Exported"
|
||||
override val str: String = "test 1"
|
||||
override open fun bar(): Int = 42
|
||||
}
|
||||
|
||||
@JsExport
|
||||
class ExportedClass(override val value: Int) : ExtendedI {
|
||||
override var variable: Int = value
|
||||
override fun foo(): String = "Exported"
|
||||
override val str: String = "test 2"
|
||||
override open fun bar(): Int = 43
|
||||
}
|
||||
|
||||
@JsExport
|
||||
class AnotherOne : NotExportedClass(42) {
|
||||
override fun foo(): String = "Another One Exported"
|
||||
}
|
||||
|
||||
@JsExport
|
||||
fun generateNotExported(value: Int): NotExportedClass {
|
||||
return NotExportedClass(value)
|
||||
}
|
||||
|
||||
@JsExport
|
||||
fun consume(i: I): String {
|
||||
return "Value is ${i.value}, variable is ${i.variable} and result is '${i.foo()}'"
|
||||
}
|
||||
|
||||
// FILE: main.mjs
|
||||
// ENTRY_ES_MODULE
|
||||
|
||||
import * as pkg from "./exportInterface-export_interface_v5.mjs"
|
||||
|
||||
export function box() {
|
||||
const { I, ExportedClass, AnotherOne, generateNotExported, consume } = pkg
|
||||
|
||||
if (I !== undefined) return "Fail: module should not export interface in runtime"
|
||||
|
||||
const exported = new ExportedClass(1)
|
||||
const another = new AnotherOne()
|
||||
const notExported = generateNotExported (3)
|
||||
|
||||
if (exported.foo() !== "Exported") return "Fail: foo function was not generated for ExportedClass"
|
||||
if (another.foo() !== "Another One Exported") return "Fail: foo function was not generated for AnotherOne"
|
||||
if (notExported.foo() !== "Not Exported") return "Fail: foo function was not generated for NotExportedClass"
|
||||
|
||||
if (exported.value !== 1) return "Fail: value getter was not generated for ExportedClass"
|
||||
if (another.value !== 42) return "Fail: value getter was not generated for AnotherOne"
|
||||
if (notExported.value !== 3) return "Fail: value getter was not generated for NotExportedClass"
|
||||
|
||||
if (exported.variable !== 1) return "Fail: variable getter was not generated for ExportedClass"
|
||||
if (another.variable !== 42) return "Fail: variable getter was not generated for AnotherOne"
|
||||
if (notExported.variable !== 3) return "Fail: variable getter was not generated for NotExportedClass"
|
||||
|
||||
exported.variable = 101
|
||||
another.variable = 102
|
||||
notExported.variable = 103
|
||||
|
||||
if (exported.variable !== 101) return "Fail: variable setter was not generated for ExportedClass"
|
||||
if (another.variable !== 102) return "Fail: variable setter was not generated for AnotherOne"
|
||||
if (notExported.variable !== 103) return "Fail: variable setter was not generated for NotExportedClass"
|
||||
|
||||
try {
|
||||
notExported.value = 42
|
||||
} catch(e) {}
|
||||
|
||||
if (notExported.value !== 3) return "Fail: value setter was generated for NotExportedClass, but it shouldn't"
|
||||
|
||||
if (consume(exported) !== "Value is 1, variable is 101 and result is 'Exported'") return "Fail: methods or fields of ExportedClass was mangled"
|
||||
if (consume(another) !== "Value is 42, variable is 102 and result is 'Another One Exported'") return "Fail: methods or fields of AnotherOne was mangled"
|
||||
if (consume(notExported) !== "Value is 3, variable is 103 and result is 'Not Exported'") return "Fail: methods or fields of NotExported was mangled"
|
||||
|
||||
if (notExported.str !== undefined) return "Fail: str should not exist inside NotExportedClass"
|
||||
if (exported.str !== undefined) return "Fail: str should not exist inside ExportedClass"
|
||||
|
||||
if (notExported.bar !== undefined) return "Fail: bar should not exist inside NotExportedClass"
|
||||
if (exported.bar !== undefined) return "Fail: bar should not exist inside ExportedClass"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
// EXPECTED_REACHABLE_NODES: 1252
|
||||
// IGNORE_BACKEND: JS
|
||||
// ES_MODULES
|
||||
// DONT_TARGET_EXACT_BACKEND: JS
|
||||
// SKIP_DCE_DRIVEN
|
||||
|
||||
// MODULE: export_nested_class
|
||||
// FILE: lib.kt
|
||||
|
||||
abstract class A {
|
||||
abstract fun foo(k: String): String
|
||||
}
|
||||
|
||||
@JsExport
|
||||
class B {
|
||||
class Foo : A() {
|
||||
override fun foo(k: String): String {
|
||||
return "O" + k
|
||||
}
|
||||
|
||||
fun bar(k: String): String {
|
||||
return foo(k)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@JsExport
|
||||
object MyObject {
|
||||
class A {
|
||||
fun valueA() = "OK"
|
||||
}
|
||||
class B {
|
||||
fun valueB() = "OK"
|
||||
}
|
||||
class C {
|
||||
fun valueC() = "OK"
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: main.mjs
|
||||
// ENTRY_ES_MODULE
|
||||
import { B, MyObject } from "./exportNestedClass-export_nested_class_v5.mjs"
|
||||
|
||||
export function box() {
|
||||
if (new B.Foo().bar("K") != "OK") return "fail 1";
|
||||
const myObject = MyObject.getInstance()
|
||||
if (new myObject.A().valueA() != "OK") return "fail 2";
|
||||
if (new myObject.B().valueB() != "OK") return "fail 3";
|
||||
if (new myObject.C().valueC() != "OK") return "fail 4";
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
// EXPECTED_REACHABLE_NODES: 1265
|
||||
// ES_MODULES
|
||||
// DONT_TARGET_EXACT_BACKEND: JS
|
||||
// SKIP_MINIFICATION
|
||||
// SKIP_DCE_DRIVEN
|
||||
// SKIP_NODE_JS
|
||||
|
||||
// See KT-43783
|
||||
|
||||
// MODULE: nestedObjectExport
|
||||
// FILE: lib.kt
|
||||
|
||||
@JsExport
|
||||
class Abc {
|
||||
companion object AbcCompanion {
|
||||
fun xyz(): String = "Companion object method OK"
|
||||
|
||||
val prop: String
|
||||
get() = "Companion object property OK"
|
||||
}
|
||||
}
|
||||
|
||||
@JsExport
|
||||
class Foo {
|
||||
companion object {
|
||||
fun xyz(): String = "Companion object method OK"
|
||||
|
||||
val prop: String
|
||||
get() = "Companion object property OK"
|
||||
}
|
||||
}
|
||||
|
||||
@JsExport
|
||||
sealed class MyEnum(val name: String) {
|
||||
object A: MyEnum("A")
|
||||
object B: MyEnum("B")
|
||||
object C: MyEnum("C")
|
||||
}
|
||||
|
||||
@JsExport
|
||||
object MyObject {
|
||||
object A {
|
||||
fun valueA() = "OK"
|
||||
}
|
||||
object B {
|
||||
fun valueB() = "OK"
|
||||
}
|
||||
object C {
|
||||
fun valueC() = "OK"
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: main.mjs
|
||||
// ENTRY_ES_MODULE
|
||||
import { Abc, Foo, MyEnum, MyObject } from "./exportNestedObject-nestedObjectExport_v5.mjs"
|
||||
|
||||
export function box() {
|
||||
if (Abc.AbcCompanion.xyz() != 'Companion object method OK') return 'companion object function failure';
|
||||
if (Abc.AbcCompanion.prop != 'Companion object property OK') return 'companion object property failure';
|
||||
|
||||
if (Foo.Companion.xyz() != 'Companion object method OK') return 'companion object function failure';
|
||||
if (Foo.Companion.prop != 'Companion object property OK') return 'companion object property failure';
|
||||
|
||||
if (MyEnum.A.name != 'A') return 'MyEnum.A failure';
|
||||
if (MyEnum.B.name != 'B') return 'MyEnum.B failure';
|
||||
if (MyEnum.C.name != 'C') return 'MyEnum.C failure';
|
||||
|
||||
if (MyObject.getInstance().A.valueA() != "OK") return 'MyObject.A failure';
|
||||
if (MyObject.getInstance().B.valueB() != "OK") return 'MyObject.B failure';
|
||||
if (MyObject.getInstance().C.valueC() != "OK") return 'MyObject.C failure';
|
||||
|
||||
return 'OK';
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
// EXPECTED_REACHABLE_NODES: 1265
|
||||
// ES_MODULES
|
||||
// DONT_TARGET_EXACT_BACKEND: JS
|
||||
// SKIP_MINIFICATION
|
||||
// SKIP_NODE_JS
|
||||
// SKIP_DCE_DRIVEN
|
||||
|
||||
// MODULE: exportProtectedMembers
|
||||
// FILE: lib.kt
|
||||
|
||||
@JsExport
|
||||
open class Foo protected constructor() {
|
||||
protected fun bar(): String = "protected method"
|
||||
|
||||
private var _baz: String = "baz"
|
||||
|
||||
protected var baz: String
|
||||
get() = _baz
|
||||
set(value) {
|
||||
_baz = value
|
||||
}
|
||||
|
||||
protected val bazReadOnly: String
|
||||
get() = _baz
|
||||
|
||||
protected val quux: String = "quux"
|
||||
|
||||
protected var quuz: String = "quuz"
|
||||
|
||||
protected class NestedClass {
|
||||
val prop: String = "nested class property"
|
||||
}
|
||||
protected object NestedObject {
|
||||
val prop: String = "nested object property"
|
||||
}
|
||||
|
||||
protected companion object {
|
||||
val prop: String = "companion object property"
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: main.mjs
|
||||
// ENTRY_ES_MODULE
|
||||
import { Foo } from "./exportProtectedMembers-exportProtectedMembers_v5.mjs"
|
||||
|
||||
export function box() {
|
||||
var foo = new Foo();
|
||||
|
||||
if (foo.bar() != 'protected method') return 'failed to call protected method';
|
||||
if (foo.baz != 'baz') return 'failed to read `baz`';
|
||||
if (foo.bazReadOnly != 'baz') return 'failed to read `bazReadOnly`';
|
||||
foo.baz = 'beer';
|
||||
if (foo.baz != 'beer') return 'failed to write protected var';
|
||||
if (foo.bazReadOnly != 'beer') return 'unexpected value of `bazReadOnly` after modifying `baz`';
|
||||
if (foo.quux != 'quux') return 'failed to read `quux`';
|
||||
if (foo.quuz != 'quuz') return 'failed to read `quuz`';
|
||||
foo.quuz = 'ale';
|
||||
if (foo.quuz != 'ale') return 'failed to write `quuz`';
|
||||
|
||||
var nestedClass = new Foo.NestedClass()
|
||||
if (nestedClass.prop != 'nested class property')
|
||||
return 'failed to read protected class property'
|
||||
if (Foo.NestedObject.prop != 'nested object property')
|
||||
return 'failed to read protected nested object property'
|
||||
if (Foo.Companion.prop != 'companion object property')
|
||||
return 'failed to read protected companion object property'
|
||||
|
||||
return 'OK';
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
// DONT_TARGET_EXACT_BACKEND: JS
|
||||
// EXPECTED_REACHABLE_NODES: 1252
|
||||
// ES_MODULES
|
||||
|
||||
// MODULE: exported_properites
|
||||
// FILE: lib.kt
|
||||
|
||||
@JsExport
|
||||
val regularValueProperty: String = "regularValueProperty"
|
||||
|
||||
@JsExport
|
||||
val regularPropertyGetter: String
|
||||
get() = "regularPropertyGetter"
|
||||
|
||||
@JsExport
|
||||
var regularVariableProperty: String = "regularVariableProperty"
|
||||
|
||||
@JsExport
|
||||
var regularVariableGetterWithSetter: String = "regularVariableGetterWithSetter"
|
||||
get() = "$field by custom getter"
|
||||
set(value) { field = "$value set by custom setter" }
|
||||
|
||||
// FILE: entry.mjs
|
||||
// ENTRY_ES_MODULE
|
||||
|
||||
import {
|
||||
regularValueProperty,
|
||||
regularPropertyGetter,
|
||||
regularVariableProperty,
|
||||
regularVariableGetterWithSetter
|
||||
} from "./exportTopLevelProperty-exported_properites_v5.mjs";
|
||||
|
||||
export function box() {
|
||||
if (typeof regularValueProperty.get !== "function" || regularValueProperty.get() !== "regularValueProperty") {
|
||||
return "Fail: wrongly exported getter for regular `val` property"
|
||||
}
|
||||
if (typeof regularValueProperty.set !== "undefined") {
|
||||
return "Fail: wrongly exported setter for regular `val` property"
|
||||
}
|
||||
if (typeof regularPropertyGetter.get !== "function" || regularPropertyGetter.get() !== "regularPropertyGetter") {
|
||||
return "Fail: wrongly exported getter for a `val` property with custom getter"
|
||||
}
|
||||
if (typeof regularPropertyGetter.set !== "undefined") {
|
||||
return "Fail: wrongly exported setter for a `val` property with custom getter"
|
||||
}
|
||||
if (typeof regularVariableProperty.get !== "function" || regularVariableProperty.get() !== "regularVariableProperty") {
|
||||
return "Fail: wrongly exported getter for regular `var` property"
|
||||
}
|
||||
if (typeof regularVariableProperty.set !== "function" || (regularVariableProperty.set("test1"), regularVariableProperty.get()) !== "test1") {
|
||||
return "Fail: wrongly exported setter for regular `var` property"
|
||||
}
|
||||
if (typeof regularVariableGetterWithSetter.get !== "function" || regularVariableGetterWithSetter.get() !== "regularVariableGetterWithSetter by custom getter") {
|
||||
return "Fail: wrongly exported getter for a `var` property with custom getter and setter"
|
||||
}
|
||||
if (typeof regularVariableGetterWithSetter.set !== "function" || (regularVariableGetterWithSetter.set("test1"), regularVariableGetterWithSetter.get()) !== "test1 set by custom setter by custom getter") {
|
||||
return "Fail: wrongly exported setter for a `var` property with custom getter and setter"
|
||||
}
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -1,10 +1,9 @@
|
||||
// DONT_TARGET_EXACT_BACKEND: JS
|
||||
// SKIP_MINIFICATION
|
||||
// INFER_MAIN_MODULE
|
||||
// SKIP_NODE_JS
|
||||
// ES_MODULES
|
||||
|
||||
// MODULE: non_identifier_module_name
|
||||
// MODULE: lib
|
||||
// FILE: lib.kt
|
||||
@JsName("foo")
|
||||
@JsExport
|
||||
@@ -12,5 +11,8 @@ public fun foo(k: String): String = "O$k"
|
||||
|
||||
// FILE: entry.mjs
|
||||
// ENTRY_ES_MODULE
|
||||
import { foo } from "./non_identifier_module_name/index.js";
|
||||
console.assert(foo("K") == "OK");
|
||||
import { foo } from "./nonIndetifierModuleName-lib_v5.mjs";
|
||||
|
||||
export function box() {
|
||||
return foo("K")
|
||||
}
|
||||
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
// EXPECTED_REACHABLE_NODES: 1270
|
||||
// DONT_TARGET_EXACT_BACKEND: JS
|
||||
// ES_MODULES
|
||||
// SKIP_MINIFICATION
|
||||
// SKIP_NODE_JS
|
||||
|
||||
// MODULE: lib
|
||||
// FILE: lib.kt
|
||||
@file:JsExport
|
||||
|
||||
@JsName("foo")
|
||||
public fun foo(k: String): String = "O$k"
|
||||
|
||||
// FILE: enty.mjs
|
||||
// ENTRY_ES_MODULE
|
||||
|
||||
import { foo } from "./nonIndetifierModuleNameInExportedFile-lib_v5.mjs";
|
||||
|
||||
export function box() {
|
||||
return foo("K")
|
||||
}
|
||||
+13
-7
@@ -1,6 +1,5 @@
|
||||
// DONT_TARGET_EXACT_BACKEND: JS
|
||||
// EXPECTED_REACHABLE_NODES: 1252
|
||||
// INFER_MAIN_MODULE
|
||||
|
||||
// ES_MODULES
|
||||
// MODULE: overriden_chain_non_export_intermediate
|
||||
@@ -28,12 +27,19 @@ class C : B() {
|
||||
|
||||
// FILE: entry.mjs
|
||||
// ENTRY_ES_MODULE
|
||||
import { C } from "./overriden_chain_non_export_intermediate/index.js";
|
||||
import { C } from "./overriddenChainNonExportIntermediate-overriden_chain_non_export_intermediate_v5.mjs";
|
||||
|
||||
function test(c) {
|
||||
if (c.foo() === "foo" && c.bar() === "bar" && c.bay() == "bay") return "OK"
|
||||
export function box() {
|
||||
const c = new C()
|
||||
|
||||
return "fail"
|
||||
}
|
||||
const foo = c.foo()
|
||||
if (foo !== "foo") return `Fail: expect c.foo() to return 'foo' but it returns ${foo}`
|
||||
|
||||
console.assert(test(new C()) == "OK");
|
||||
const bar = c.bar()
|
||||
if (bar !== "bar") return `Fail: expect c.bar() to return 'bar' but it returns ${bar}`
|
||||
|
||||
const bay = c.bay()
|
||||
if (bay !== "bay") return `Fail: expect c.bay() to return 'bay' but it returns ${bay}`
|
||||
|
||||
return "OK"
|
||||
}
|
||||
js/js.translator/testData/box/esModules/export/overriddenChainNonExportIntermediateInExportedFile.kt
Vendored
+39
@@ -0,0 +1,39 @@
|
||||
// EXPECTED_REACHABLE_NODES: 1252
|
||||
// DONT_TARGET_EXACT_BACKEND: JS
|
||||
// ES_MODULES
|
||||
|
||||
// MODULE: overriden_chain_non_export_intermediate
|
||||
// FILE: not_exported.kt
|
||||
abstract class B : A() {
|
||||
abstract fun baz(): String
|
||||
|
||||
override fun foo(): String = "foo"
|
||||
}
|
||||
|
||||
|
||||
// FILE: exported.kt
|
||||
@file:JsExport
|
||||
|
||||
abstract class A {
|
||||
abstract fun foo(): String
|
||||
|
||||
abstract fun bar(): String
|
||||
}
|
||||
|
||||
class C : B() {
|
||||
override fun bar(): String = "bar"
|
||||
override fun baz(): String = "baz"
|
||||
|
||||
fun bay(): String = "bay"
|
||||
}
|
||||
|
||||
// FILE: main.mjs
|
||||
// ENTRY_ES_MODULE
|
||||
import { C } from "./overriddenChainNonExportIntermediateInExportedFile-overriden_chain_non_export_intermediate_v5.mjs"
|
||||
|
||||
export function box() {
|
||||
var c = new C();
|
||||
if (c.foo() === "foo" && c.bar() === "bar" && c.bay() == "bay") return "OK"
|
||||
|
||||
return "fail"
|
||||
}
|
||||
Vendored
+5
-7
@@ -1,9 +1,8 @@
|
||||
// EXPECTED_REACHABLE_NODES: 1252
|
||||
// INFER_MAIN_MODULE
|
||||
// DONT_TARGET_EXACT_BACKEND: JS
|
||||
// ES_MODULES
|
||||
|
||||
// MODULE: overriden_external_method_with_same_name_method
|
||||
// MODULE: lib
|
||||
// FILE: lib.kt
|
||||
external abstract class Foo {
|
||||
abstract fun o(): String
|
||||
@@ -32,10 +31,9 @@ Foo.prototype.k = function() {
|
||||
|
||||
// FILE: entry.mjs
|
||||
// ENTRY_ES_MODULE
|
||||
import { Baz } from "./overriden_external_method_with_same_name_method/index.js";
|
||||
import { Baz } from "./overriddenExternalMethodWithSameNameMethod-lib_v5.mjs";
|
||||
|
||||
function test(foo) {
|
||||
export function box() {
|
||||
const foo = new Baz()
|
||||
return foo.o() + foo.k()
|
||||
}
|
||||
|
||||
console.assert(test(new Baz()) == "OK");
|
||||
}
|
||||
Vendored
+6
-11
@@ -1,12 +1,8 @@
|
||||
// EXPECTED_REACHABLE_NODES: 1252
|
||||
// IGNORE_BACKEND: JS
|
||||
// INFER_MAIN_MODULE
|
||||
// DONT_TARGET_EXACT_BACKEND: JS
|
||||
// ES_MODULES
|
||||
|
||||
// TODO: Fix tests on Windows
|
||||
// DONT_TARGET_EXACT_BACKEND: JS_IR
|
||||
|
||||
// MODULE: overriden_external_method_with_same_stable_name_method
|
||||
// MODULE: lib
|
||||
// FILE: lib.kt
|
||||
external abstract class Foo {
|
||||
abstract fun o(): String
|
||||
@@ -36,12 +32,11 @@ Foo.prototype.k = function() {
|
||||
|
||||
// FILE: entry.mjs
|
||||
// ENTRY_ES_MODULE
|
||||
import { Baz } from "./overriden-external-method-with-same-stable-name-method/index.js";
|
||||
import { Baz } from "./overriddenExternalMethodWithSameStableNameMethod-lib_v5.mjs";
|
||||
|
||||
function test(foo) {
|
||||
export function box() {
|
||||
const foo = new Baz()
|
||||
const oStable = foo.oStable("OK")
|
||||
if (oStable !== "OK") return "false: " + oStable
|
||||
return foo.o() + foo.k()
|
||||
}
|
||||
|
||||
console.assert(test(new Baz()) == "OK");
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
// EXPECTED_REACHABLE_NODES: 1252
|
||||
// DONT_TARGET_EXACT_BACKEND: JS
|
||||
// ES_MODULES
|
||||
|
||||
// MODULE: lib
|
||||
// FILE: not_exported.kt
|
||||
|
||||
external abstract class Foo {
|
||||
abstract fun o(): String
|
||||
}
|
||||
|
||||
abstract class Bar : Foo() {
|
||||
@JsName("oStable")
|
||||
abstract fun String.o(): String
|
||||
|
||||
override fun o(): String {
|
||||
return "O".o()
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: exported.kt
|
||||
@file:JsExport
|
||||
|
||||
class Baz : Bar() {
|
||||
override fun String.o(): String {
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: foo.js
|
||||
function Foo() {}
|
||||
Foo.prototype.k = function() {
|
||||
return "K"
|
||||
}
|
||||
|
||||
|
||||
// FILE: main.mjs
|
||||
// ENTRY_ES_MODULE
|
||||
import { Baz } from "./overriddenExternalMethodWithSameStableNameMethodInExportedFile-lib_v5.mjs"
|
||||
|
||||
export function box() {
|
||||
return test(new Baz());
|
||||
}
|
||||
|
||||
function test(foo) {
|
||||
const oStable = foo.oStable("OK")
|
||||
if (oStable !== "OK") return "false: " + oStable
|
||||
return foo.o() + foo.k()
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
// IGNORE_BACKEND: JS
|
||||
// DONT_TARGET_EXACT_BACKEND: JS
|
||||
// EXPECTED_REACHABLE_NODES: 1270
|
||||
// SKIP_MINIFICATION
|
||||
// INFER_MAIN_MODULE
|
||||
// ES_MODULES
|
||||
|
||||
// MODULE: if
|
||||
@@ -12,6 +11,8 @@ public fun foo(k: String): String = "O$k"
|
||||
|
||||
// FILE: entry.mjs
|
||||
// ENTRY_ES_MODULE
|
||||
import { foo } from "./if/index.js";
|
||||
import { foo } from "./reservedModuleName-if_v5.mjs";
|
||||
|
||||
console.assert(foo("K") == "OK");
|
||||
export function box() {
|
||||
return foo("K")
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
// DONT_TARGET_EXACT_BACKEND: JS
|
||||
// EXPECTED_REACHABLE_NODES: 1270
|
||||
// SKIP_MINIFICATION
|
||||
// ES_MODULES
|
||||
|
||||
// MODULE: if
|
||||
// FILE: lib.kt
|
||||
@file:JsExport
|
||||
|
||||
@JsName("foo")
|
||||
public fun foo(k: String): String = "O$k"
|
||||
|
||||
// FILE: entry.mjs
|
||||
// ENTRY_ES_MODULE
|
||||
import { foo } from "./reservedModuleNameInExportedFile-if_v5.mjs";
|
||||
|
||||
export function box() {
|
||||
return foo("K")
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// DONT_TARGET_EXACT_BACKEND: JS
|
||||
// EXPECTED_REACHABLE_NODES: 1270
|
||||
// SKIP_MINIFICATION
|
||||
// ES_MODULES
|
||||
|
||||
// MODULE: vararg
|
||||
// FILE: lib.kt
|
||||
@JsExport
|
||||
fun uintVararg(vararg uints: UInt): String {
|
||||
for (u in uints) {
|
||||
if (u == 0u) return "Failed"
|
||||
}
|
||||
|
||||
return "OK"
|
||||
}
|
||||
|
||||
@JsExport
|
||||
fun uint(a: Int): UInt {
|
||||
return a.toUInt()
|
||||
}
|
||||
|
||||
// FILE: main.mjs
|
||||
// ENTRY_ES_MODULE
|
||||
import { uint, uintVararg } from "./vararg-vararg_v5.mjs"
|
||||
|
||||
export function box() {
|
||||
return uintVararg([uint(1), uint(2), uint(3)])
|
||||
}
|
||||
+4
-2
@@ -30,6 +30,8 @@ fun testOk(ok: Any): String {
|
||||
|
||||
// FILE: entry.mjs
|
||||
// ENTRY_ES_MODULE
|
||||
import { convolutedOk, testOk } from "./main/index.js";
|
||||
import { convolutedOk, testOk } from "./inlinedObjectLiteralIsCheck_v5.mjs";
|
||||
|
||||
console.assert(testOk(convolutedOk()) == "OK");
|
||||
export function box() {
|
||||
return testOk(convolutedOk())
|
||||
}
|
||||
|
||||
@@ -48,8 +48,5 @@ fun box(): String {
|
||||
return "Fail6: ${res.component2}"
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Point } from "./main/index.js";
|
||||
import { Point } from "./dataClass_v5.mjs";
|
||||
|
||||
export default function() {
|
||||
var p = new Point(3, 7);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as api from "./main/index.js";
|
||||
import * as api from "./exportedDefaultStub_v5.mjs";
|
||||
|
||||
export default function() {
|
||||
var ping = api.ping;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { A, B } from "./main/index.js";
|
||||
import { A, B } from "./jsExportInClass_v5.mjs";
|
||||
|
||||
export default function() {
|
||||
return {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ping, Something } from "./main/index.js"
|
||||
import { ping, Something } from "./recursiveExport_v5.mjs"
|
||||
|
||||
export default function() {
|
||||
return {
|
||||
|
||||
@@ -24,7 +24,7 @@ open class B {
|
||||
// FILE: entry.mjs
|
||||
// ENTRY_ES_MODULE
|
||||
|
||||
import { A, B } from "./main/index.js";
|
||||
import { A, B } from "./inheritanceInNativeClass_v5.mjs";
|
||||
|
||||
function createA() {
|
||||
function ADerived() {
|
||||
@@ -46,7 +46,7 @@ function createB() {
|
||||
return new BDerived();
|
||||
}
|
||||
|
||||
function box() {
|
||||
export function box() {
|
||||
let a = createA();
|
||||
if (a.bar(0) != 124) return "fail1";
|
||||
|
||||
@@ -54,6 +54,4 @@ function box() {
|
||||
if (b.bar(0) != 42) return "fail2";
|
||||
|
||||
return "OK";
|
||||
}
|
||||
|
||||
console.assert(box() == "OK");
|
||||
}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
type Nullable<T> = T | null | undefined
|
||||
export namespace foo {
|
||||
export declare namespace foo {
|
||||
const prop: number;
|
||||
class C {
|
||||
constructor(x: number);
|
||||
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
type Nullable<T> = T | null | undefined
|
||||
export declare const value: { get(): number; };
|
||||
export declare const variable: { get(): number; set(value: number): void; };
|
||||
export declare class C {
|
||||
constructor(x: number);
|
||||
get x(): number;
|
||||
doubleX(): number;
|
||||
}
|
||||
export declare const O: {
|
||||
getInstance(): {
|
||||
get value(): number;
|
||||
};
|
||||
};
|
||||
export declare const Parent: {
|
||||
getInstance(): typeof __NonExistentParent;
|
||||
};
|
||||
declare abstract class __NonExistentParent extends _objects_.foo$Parent {
|
||||
private constructor();
|
||||
}
|
||||
declare namespace __NonExistentParent {
|
||||
class Nested {
|
||||
constructor();
|
||||
get value(): number;
|
||||
}
|
||||
}
|
||||
export declare function box(): string;
|
||||
declare namespace _objects_ {
|
||||
const foo$Parent: {
|
||||
get value(): number;
|
||||
} & {
|
||||
new(): any;
|
||||
};
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/** This file is generated by {@link :js:js.test:generateJsExportOnFileTestFilesForTS} task. DO NOT MODIFY MANUALLY */
|
||||
|
||||
// CHECK_TYPESCRIPT_DECLARATIONS
|
||||
// SKIP_MINIFICATION
|
||||
// SKIP_NODE_JS
|
||||
// INFER_MAIN_MODULE
|
||||
// MODULE: JS_TESTS
|
||||
// MODULE_KIND: ES
|
||||
// FILE: esm.kt
|
||||
|
||||
@file:JsExport
|
||||
|
||||
package foo
|
||||
|
||||
|
||||
val value = 10
|
||||
|
||||
|
||||
var variable = 10
|
||||
|
||||
|
||||
class C(val x: Int) {
|
||||
fun doubleX() = x * 2
|
||||
}
|
||||
|
||||
|
||||
object O {
|
||||
val value = 10
|
||||
}
|
||||
|
||||
|
||||
object Parent {
|
||||
val value = 10
|
||||
class Nested {
|
||||
val value = 10
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun box(): String = "OK"
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
type Nullable<T> = T | null | undefined
|
||||
export namespace foo {
|
||||
export declare namespace foo {
|
||||
const prop: number;
|
||||
class C {
|
||||
constructor(x: number);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
type Nullable<T> = T | null | undefined
|
||||
export namespace foo {
|
||||
export declare namespace foo {
|
||||
const prop: number;
|
||||
class C {
|
||||
constructor(x: number);
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
type Nullable<T> = T | null | undefined
|
||||
export declare const value: { get(): number; };
|
||||
export declare const variable: { get(): number; set(value: number): void; };
|
||||
export declare class C {
|
||||
constructor(x: number);
|
||||
get x(): number;
|
||||
doubleX(): number;
|
||||
}
|
||||
export declare const O: {
|
||||
getInstance(): {
|
||||
get value(): number;
|
||||
};
|
||||
};
|
||||
export declare const Parent: {
|
||||
getInstance(): typeof __NonExistentParent;
|
||||
};
|
||||
declare abstract class __NonExistentParent extends _objects_.foo$Parent {
|
||||
private constructor();
|
||||
}
|
||||
declare namespace __NonExistentParent {
|
||||
class Nested {
|
||||
constructor();
|
||||
get value(): number;
|
||||
}
|
||||
}
|
||||
export declare function box(): string;
|
||||
declare namespace _objects_ {
|
||||
const foo$Parent: {
|
||||
get value(): number;
|
||||
} & {
|
||||
new(): any;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// CHECK_TYPESCRIPT_DECLARATIONS
|
||||
// SKIP_MINIFICATION
|
||||
// SKIP_NODE_JS
|
||||
// INFER_MAIN_MODULE
|
||||
// MODULE: JS_TESTS
|
||||
// MODULE_KIND: ES
|
||||
// FILE: esm.kt
|
||||
|
||||
package foo
|
||||
|
||||
@JsExport
|
||||
val value = 10
|
||||
|
||||
@JsExport
|
||||
var variable = 10
|
||||
|
||||
@JsExport
|
||||
class C(val x: Int) {
|
||||
fun doubleX() = x * 2
|
||||
}
|
||||
|
||||
@JsExport
|
||||
object O {
|
||||
val value = 10
|
||||
}
|
||||
|
||||
@JsExport
|
||||
object Parent {
|
||||
val value = 10
|
||||
class Nested {
|
||||
val value = 10
|
||||
}
|
||||
}
|
||||
|
||||
@JsExport
|
||||
fun box(): String = "OK"
|
||||
@@ -1,5 +1,5 @@
|
||||
type Nullable<T> = T | null | undefined
|
||||
export namespace foo {
|
||||
export declare namespace foo {
|
||||
const prop: number;
|
||||
class C {
|
||||
constructor(x: number);
|
||||
|
||||
+6
@@ -8,6 +8,12 @@ declare namespace JS_TESTS {
|
||||
foo(): number;
|
||||
};
|
||||
function takesO(o: typeof foo.O): number;
|
||||
const WithSimpleObjectInside: {
|
||||
get value(): string;
|
||||
get SimpleObject(): {
|
||||
get value(): string;
|
||||
};
|
||||
};
|
||||
abstract class Parent {
|
||||
private constructor();
|
||||
}
|
||||
|
||||
+8
@@ -26,6 +26,14 @@ fun takesO(o: O): Int =
|
||||
O.x + O.foo()
|
||||
|
||||
|
||||
object WithSimpleObjectInside {
|
||||
val value: String = "WithSimpleObjectInside"
|
||||
object SimpleObject {
|
||||
val value: String = "SimpleObject"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
object Parent {
|
||||
object Nested1 {
|
||||
val value: String = "Nested1"
|
||||
|
||||
+3
@@ -7,6 +7,7 @@ var getParent = JS_TESTS.foo.getParent;
|
||||
var createNested1 = JS_TESTS.foo.createNested1;
|
||||
var createNested2 = JS_TESTS.foo.createNested2;
|
||||
var createNested3 = JS_TESTS.foo.createNested3;
|
||||
var WithSimpleObjectInside = JS_TESTS.foo.WithSimpleObjectInside;
|
||||
function assert(condition) {
|
||||
if (!condition) {
|
||||
throw "Assertion failed";
|
||||
@@ -27,5 +28,7 @@ function box() {
|
||||
assert(createNested1() === nested1);
|
||||
assert(createNested2() !== nested2 && createNested2() instanceof Parent.Nested1.Nested2);
|
||||
assert(createNested3() !== nested3 && createNested3() instanceof Parent.Nested1.Nested2.Companion.Nested3);
|
||||
assert(WithSimpleObjectInside.value === "WithSimpleObjectInside");
|
||||
assert(WithSimpleObjectInside.SimpleObject.value === "SimpleObject");
|
||||
return "OK";
|
||||
}
|
||||
|
||||
+4
@@ -6,6 +6,7 @@ import getParent = JS_TESTS.foo.getParent;
|
||||
import createNested1 = JS_TESTS.foo.createNested1;
|
||||
import createNested2 = JS_TESTS.foo.createNested2;
|
||||
import createNested3 = JS_TESTS.foo.createNested3;
|
||||
import WithSimpleObjectInside = JS_TESTS.foo.WithSimpleObjectInside;
|
||||
|
||||
function assert(condition: boolean) {
|
||||
if (!condition) {
|
||||
@@ -30,5 +31,8 @@ function box(): string {
|
||||
assert(createNested1() === nested1)
|
||||
assert(createNested2() !== nested2 && createNested2() instanceof Parent.Nested1.Nested2)
|
||||
assert(createNested3() !== nested3 && createNested3() instanceof Parent.Nested1.Nested2.Companion.Nested3)
|
||||
|
||||
assert(WithSimpleObjectInside.value === "WithSimpleObjectInside");
|
||||
assert(WithSimpleObjectInside.SimpleObject.value === "SimpleObject");
|
||||
return "OK";
|
||||
}
|
||||
@@ -8,6 +8,12 @@ declare namespace JS_TESTS {
|
||||
foo(): number;
|
||||
};
|
||||
function takesO(o: typeof foo.O): number;
|
||||
const WithSimpleObjectInside: {
|
||||
get value(): string;
|
||||
get SimpleObject(): {
|
||||
get value(): string;
|
||||
};
|
||||
};
|
||||
abstract class Parent {
|
||||
private constructor();
|
||||
}
|
||||
|
||||
@@ -21,6 +21,14 @@ object O {
|
||||
fun takesO(o: O): Int =
|
||||
O.x + O.foo()
|
||||
|
||||
@JsExport
|
||||
object WithSimpleObjectInside {
|
||||
val value: String = "WithSimpleObjectInside"
|
||||
object SimpleObject {
|
||||
val value: String = "SimpleObject"
|
||||
}
|
||||
}
|
||||
|
||||
@JsExport
|
||||
object Parent {
|
||||
object Nested1 {
|
||||
|
||||
@@ -7,6 +7,7 @@ var getParent = JS_TESTS.foo.getParent;
|
||||
var createNested1 = JS_TESTS.foo.createNested1;
|
||||
var createNested2 = JS_TESTS.foo.createNested2;
|
||||
var createNested3 = JS_TESTS.foo.createNested3;
|
||||
var WithSimpleObjectInside = JS_TESTS.foo.WithSimpleObjectInside;
|
||||
function assert(condition) {
|
||||
if (!condition) {
|
||||
throw "Assertion failed";
|
||||
@@ -27,5 +28,7 @@ function box() {
|
||||
assert(createNested1() === nested1);
|
||||
assert(createNested2() !== nested2 && createNested2() instanceof Parent.Nested1.Nested2);
|
||||
assert(createNested3() !== nested3 && createNested3() instanceof Parent.Nested1.Nested2.Companion.Nested3);
|
||||
assert(WithSimpleObjectInside.value === "WithSimpleObjectInside");
|
||||
assert(WithSimpleObjectInside.SimpleObject.value === "SimpleObject");
|
||||
return "OK";
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import getParent = JS_TESTS.foo.getParent;
|
||||
import createNested1 = JS_TESTS.foo.createNested1;
|
||||
import createNested2 = JS_TESTS.foo.createNested2;
|
||||
import createNested3 = JS_TESTS.foo.createNested3;
|
||||
import WithSimpleObjectInside = JS_TESTS.foo.WithSimpleObjectInside;
|
||||
|
||||
function assert(condition: boolean) {
|
||||
if (!condition) {
|
||||
@@ -30,5 +31,8 @@ function box(): string {
|
||||
assert(createNested1() === nested1)
|
||||
assert(createNested2() !== nested2 && createNested2() instanceof Parent.Nested1.Nested2)
|
||||
assert(createNested3() !== nested3 && createNested3() instanceof Parent.Nested1.Nested2.Companion.Nested3)
|
||||
|
||||
assert(WithSimpleObjectInside.value === "WithSimpleObjectInside");
|
||||
assert(WithSimpleObjectInside.SimpleObject.value === "SimpleObject");
|
||||
return "OK";
|
||||
}
|
||||
Reference in New Issue
Block a user