From 3f8dce4b53b348a746fa414f62e8e17c53bf1fd5 Mon Sep 17 00:00:00 2001 From: Svyatoslav Kuzmich Date: Tue, 23 Feb 2021 15:44:06 +0300 Subject: [PATCH] [JS IR] Support per-file mode and ES modules --- .../common/arguments/K2JSCompilerArguments.kt | 3 + .../arguments/K2JsArgumentConstants.java | 1 + .../jetbrains/kotlin/cli/js/K2JsIrCompiler.kt | 37 +- .../PropertyAccessorInlineLowering.kt | 16 +- .../ir/backend/js/JsIrBackendContext.kt | 4 +- .../kotlin/ir/backend/js/JsLoweringPhases.kt | 14 +- .../kotlin/ir/backend/js/codegen/IrToJs.kt | 457 ++++++++++++++++ .../kotlin/ir/backend/js/compiler.kt | 53 +- .../backend/js/export/ExportModelGenerator.kt | 14 +- .../js/export/ExportModelToJsStatements.kt | 62 ++- .../js/export/ExportModelToTsDeclarations.kt | 2 +- .../jetbrains/kotlin/ir/backend/js/ic/ic.kt | 26 +- .../lower/JsPropertyAccessorInlineLowering.kt | 40 ++ .../lower/MoveOpenClassesToSeparateFiles.kt | 61 +++ .../irToJs/IrFileToJsTransformer.kt | 1 + .../irToJs/IrFunctionToJsTransformer.kt | 6 +- .../irToJs/IrModuleToJsTransformer.kt | 59 ++- .../transformers/irToJs/JsClassGenerator.kt | 28 +- .../irToJs/ModuleWrapperTranslation.kt | 1 + .../transformers/irToJs/MultiModuleSupport.kt | 88 ---- .../js/transformers/irToJs/jsAstUtils.kt | 39 +- .../ir/backend/js/utils/JsStaticContext.kt | 3 +- .../kotlin/ir/backend/js/utils/NameTables.kt | 17 +- .../kotlin/ir/backend/js/utils/NewNamer.kt | 207 ++++++++ compiler/testData/cli/js/jsExtraHelp.out | 1 + .../testData/codegen/box/enum/kt18731_2.kt | 1 + .../box/properties/lazyInitializationPure.kt | 36 -- .../lazyInitializationThroughTopFun.kt | 5 +- ...InitializationLazilyOnNonPropertiesCall.kt | 3 +- .../codegen/box/regressions/kt10143.kt | 2 + .../backend/JsToStringGenerationVisitor.java | 63 +++ .../kotlin/js/backend/ast/JsExport.kt | 40 ++ .../kotlin/js/backend/ast/JsImport.kt | 34 ++ .../kotlin/js/backend/ast/JsVisitor.kt | 6 + .../js/backend/ast/JsVisitorWithContext.java | 14 + .../js/KotlinJavascriptSerializationUtil.kt | 1 + .../kotlin/serialization/js/ModuleKind.java | 3 +- js/js.tests/build.gradle.kts | 2 + .../generators/tests/GenerateJsTests.kt | 5 - .../jetbrains/kotlin/js/test/BasicBoxTest.kt | 125 ++++- .../kotlin/js/test/BasicIrBoxTest.kt | 160 ++++-- .../kotlin/js/test/engines/SpiderMonkey.kt | 8 +- .../AbstractLegacyJsTypeScriptExportTest.kt | 13 - .../semantics/IrBoxJsES6TestGenerated.java | 498 +++++++++++++++++- .../IrJsCodegenBoxES6TestGenerated.java | 5 - .../ir/semantics/IrBoxJsTestGenerated.java | 498 +++++++++++++++++- .../IrJsCodegenBoxTestGenerated.java | 5 - .../js/test/semantics/BoxJsTestGenerated.java | 153 ++++++ ...LegacyJsTypeScriptExportTestGenerated.java | 181 ------- .../general/ModuleWrapperTranslation.kt | 1 + .../crossModuleRef/callableObjectRef.kt | 27 + .../esModules/crossModuleRef/constructor.kt | 72 +++ .../esModules/crossModuleRef/inheritance.kt | 27 + .../crossModuleRef/inlineJsModule.kt | 20 + .../inlineJsModuleNonIdentifier.kt | 20 + .../crossModuleRef/inlineJsModulePackage.kt | 21 + .../esModules/crossModuleRef/inlineModule.kt | 16 + .../inlineModuleNonIndentifier.kt | 16 + .../box/esModules/crossModuleRef/lambda.kt | 19 + .../box/esModules/crossModuleRef/object.kt | 37 ++ .../crossModuleRef/objectInInlineClosure.kt | 27 + .../crossModuleRef/objectIsObject.kt | 21 + .../crossModuleRef/topLevelExtension.kt | 44 ++ .../crossModuleRef/topLevelFunction.kt | 51 ++ .../crossModuleRef/topLevelMutableProperty.kt | 38 ++ .../crossModuleRef/topLevelProperty.kt | 48 ++ .../callableObjectRef.kt | 29 + .../crossModuleRefPerFile/constructor.kt | 74 +++ .../crossModuleRefPerFile/inheritance.kt | 29 + .../crossModuleRefPerFile/inlineModule.kt | 18 + .../inlineModuleNonIndentifier.kt | 18 + .../esModules/crossModuleRefPerFile/lambda.kt | 21 + .../esModules/crossModuleRefPerFile/object.kt | 39 ++ .../objectInInlineClosure.kt | 29 + .../crossModuleRefPerFile/objectIsObject.kt | 23 + .../topLevelExtension.kt | 46 ++ .../crossModuleRefPerFile/topLevelFunction.kt | 53 ++ .../topLevelMutableProperty.kt | 40 ++ .../crossModuleRefPerFile/topLevelProperty.kt | 50 ++ .../callableObjectRef.kt | 29 + .../crossModuleRefPerModule/constructor.kt | 74 +++ .../crossModuleRefPerModule/inheritance.kt | 29 + .../crossModuleRefPerModule/inlineModule.kt | 18 + .../inlineModuleNonIndentifier.kt | 18 + .../crossModuleRefPerModule/lambda.kt | 21 + .../crossModuleRefPerModule/object.kt | 39 ++ .../objectInInlineClosure.kt | 29 + .../crossModuleRefPerModule/objectIsObject.kt | 23 + .../topLevelExtension.kt | 46 ++ .../topLevelFunction.kt | 53 ++ .../topLevelMutableProperty.kt | 40 ++ .../topLevelProperty.kt | 50 ++ .../box/esModules/export/exportAllFile.kt | 23 + .../export/nonIndetifierModuleName.kt | 16 + .../overriddenChainNonExportIntermediate.kt | 39 ++ ...rriddenExternalMethodWithSameNameMethod.kt | 41 ++ ...nExternalMethodWithSameStableNameMethod.kt | 44 ++ .../esModules/export/reservedModuleName.kt | 17 + .../box/esModules/incremental/jsModule.kt | 41 ++ .../inline/inlinedObjectLiteralIsCheck.kt | 35 ++ .../box/esModules/jsExport/dataClass.kt | 55 ++ .../box/esModules/jsExport/dataClass.mjs | 14 + .../esModules/jsExport/exportedDefaultStub.kt | 118 +++++ .../jsExport/exportedDefaultStub.mjs | 36 ++ .../box/esModules/jsExport/jsExportInClass.kt | 38 ++ .../esModules/jsExport/jsExportInClass.mjs | 7 + .../box/esModules/jsExport/recursiveExport.kt | 28 + .../esModules/jsExport/recursiveExport.mjs | 9 + .../box/esModules/jsModule/externalClass.kt | 33 ++ .../box/esModules/jsModule/externalClass.mjs | 11 + .../jsModule/externalClassNameClash.kt | 62 +++ .../jsModule/externalClassWithDefaults.kt | 46 ++ .../jsModule/externalClassWithDefaults.mjs | 9 + .../esModules/jsModule/externalConstructor.kt | 26 + .../jsModule/externalConstructor.mjs | 3 + .../esModules/jsModule/externalFunction.kt | 11 + .../esModules/jsModule/externalFunction.mjs | 3 + .../jsModule/externalFunctionNameClash.kt | 14 + .../jsModule/externalFunctionNameClash.mjs | 3 + .../box/esModules/jsModule/externalObject.kt | 16 + .../box/esModules/jsModule/externalObject.mjs | 6 + .../box/esModules/jsModule/externalPackage.kt | 45 ++ .../esModules/jsModule/externalPackage.mjs | 24 + .../externalPackageInDifferentFile.js | 5 + .../externalPackageInDifferentFile.kt | 47 ++ .../externalPackageInDifferentFile.mjs | 21 + .../esModules/jsModule/externalProperty.kt | 11 + .../esModules/jsModule/externalProperty.mjs | 1 + .../box/esModules/jsModule/interfaces.kt | 33 ++ .../box/esModules/jsModule/interfaces.mjs | 12 + .../esModules/jsModule/topLevelVarargFun.kt | 15 + .../esModules/jsModule/topLevelVarargFun.mjs | 3 + .../box/esModules/jsName/defaultJsName.kt | 34 ++ .../box/esModules/jsName/jsTopLevelClashes.kt | 32 ++ .../native/inheritanceInNativeClass.kt | 59 +++ ...lingClashWithFunctionsWithoutParameters.kt | 3 + .../expression/function/manglingStability.kt | 3 + js/js.translator/testData/box/native/eval.kt | 7 +- .../constructors/constructors.d.ts | 10 +- .../inheritance/inheritance.d.ts | 32 +- 140 files changed, 5136 insertions(+), 609 deletions(-) create mode 100644 compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/codegen/IrToJs.kt create mode 100644 compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsPropertyAccessorInlineLowering.kt create mode 100644 compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/MoveOpenClassesToSeparateFiles.kt create mode 100644 compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/NewNamer.kt delete mode 100644 compiler/testData/codegen/box/properties/lazyInitializationPure.kt create mode 100644 js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsExport.kt create mode 100644 js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsImport.kt delete mode 100644 js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/AbstractLegacyJsTypeScriptExportTest.kt delete mode 100644 js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/LegacyJsTypeScriptExportTestGenerated.java create mode 100644 js/js.translator/testData/box/esModules/crossModuleRef/callableObjectRef.kt create mode 100644 js/js.translator/testData/box/esModules/crossModuleRef/constructor.kt create mode 100644 js/js.translator/testData/box/esModules/crossModuleRef/inheritance.kt create mode 100644 js/js.translator/testData/box/esModules/crossModuleRef/inlineJsModule.kt create mode 100644 js/js.translator/testData/box/esModules/crossModuleRef/inlineJsModuleNonIdentifier.kt create mode 100644 js/js.translator/testData/box/esModules/crossModuleRef/inlineJsModulePackage.kt create mode 100644 js/js.translator/testData/box/esModules/crossModuleRef/inlineModule.kt create mode 100644 js/js.translator/testData/box/esModules/crossModuleRef/inlineModuleNonIndentifier.kt create mode 100644 js/js.translator/testData/box/esModules/crossModuleRef/lambda.kt create mode 100644 js/js.translator/testData/box/esModules/crossModuleRef/object.kt create mode 100644 js/js.translator/testData/box/esModules/crossModuleRef/objectInInlineClosure.kt create mode 100644 js/js.translator/testData/box/esModules/crossModuleRef/objectIsObject.kt create mode 100644 js/js.translator/testData/box/esModules/crossModuleRef/topLevelExtension.kt create mode 100644 js/js.translator/testData/box/esModules/crossModuleRef/topLevelFunction.kt create mode 100644 js/js.translator/testData/box/esModules/crossModuleRef/topLevelMutableProperty.kt create mode 100644 js/js.translator/testData/box/esModules/crossModuleRef/topLevelProperty.kt create mode 100644 js/js.translator/testData/box/esModules/crossModuleRefPerFile/callableObjectRef.kt create mode 100644 js/js.translator/testData/box/esModules/crossModuleRefPerFile/constructor.kt create mode 100644 js/js.translator/testData/box/esModules/crossModuleRefPerFile/inheritance.kt create mode 100644 js/js.translator/testData/box/esModules/crossModuleRefPerFile/inlineModule.kt create mode 100644 js/js.translator/testData/box/esModules/crossModuleRefPerFile/inlineModuleNonIndentifier.kt create mode 100644 js/js.translator/testData/box/esModules/crossModuleRefPerFile/lambda.kt create mode 100644 js/js.translator/testData/box/esModules/crossModuleRefPerFile/object.kt create mode 100644 js/js.translator/testData/box/esModules/crossModuleRefPerFile/objectInInlineClosure.kt create mode 100644 js/js.translator/testData/box/esModules/crossModuleRefPerFile/objectIsObject.kt create mode 100644 js/js.translator/testData/box/esModules/crossModuleRefPerFile/topLevelExtension.kt create mode 100644 js/js.translator/testData/box/esModules/crossModuleRefPerFile/topLevelFunction.kt create mode 100644 js/js.translator/testData/box/esModules/crossModuleRefPerFile/topLevelMutableProperty.kt create mode 100644 js/js.translator/testData/box/esModules/crossModuleRefPerFile/topLevelProperty.kt create mode 100644 js/js.translator/testData/box/esModules/crossModuleRefPerModule/callableObjectRef.kt create mode 100644 js/js.translator/testData/box/esModules/crossModuleRefPerModule/constructor.kt create mode 100644 js/js.translator/testData/box/esModules/crossModuleRefPerModule/inheritance.kt create mode 100644 js/js.translator/testData/box/esModules/crossModuleRefPerModule/inlineModule.kt create mode 100644 js/js.translator/testData/box/esModules/crossModuleRefPerModule/inlineModuleNonIndentifier.kt create mode 100644 js/js.translator/testData/box/esModules/crossModuleRefPerModule/lambda.kt create mode 100644 js/js.translator/testData/box/esModules/crossModuleRefPerModule/object.kt create mode 100644 js/js.translator/testData/box/esModules/crossModuleRefPerModule/objectInInlineClosure.kt create mode 100644 js/js.translator/testData/box/esModules/crossModuleRefPerModule/objectIsObject.kt create mode 100644 js/js.translator/testData/box/esModules/crossModuleRefPerModule/topLevelExtension.kt create mode 100644 js/js.translator/testData/box/esModules/crossModuleRefPerModule/topLevelFunction.kt create mode 100644 js/js.translator/testData/box/esModules/crossModuleRefPerModule/topLevelMutableProperty.kt create mode 100644 js/js.translator/testData/box/esModules/crossModuleRefPerModule/topLevelProperty.kt create mode 100644 js/js.translator/testData/box/esModules/export/exportAllFile.kt create mode 100644 js/js.translator/testData/box/esModules/export/nonIndetifierModuleName.kt create mode 100644 js/js.translator/testData/box/esModules/export/overriddenChainNonExportIntermediate.kt create mode 100644 js/js.translator/testData/box/esModules/export/overriddenExternalMethodWithSameNameMethod.kt create mode 100644 js/js.translator/testData/box/esModules/export/overriddenExternalMethodWithSameStableNameMethod.kt create mode 100644 js/js.translator/testData/box/esModules/export/reservedModuleName.kt create mode 100644 js/js.translator/testData/box/esModules/incremental/jsModule.kt create mode 100644 js/js.translator/testData/box/esModules/inline/inlinedObjectLiteralIsCheck.kt create mode 100644 js/js.translator/testData/box/esModules/jsExport/dataClass.kt create mode 100644 js/js.translator/testData/box/esModules/jsExport/dataClass.mjs create mode 100644 js/js.translator/testData/box/esModules/jsExport/exportedDefaultStub.kt create mode 100644 js/js.translator/testData/box/esModules/jsExport/exportedDefaultStub.mjs create mode 100644 js/js.translator/testData/box/esModules/jsExport/jsExportInClass.kt create mode 100644 js/js.translator/testData/box/esModules/jsExport/jsExportInClass.mjs create mode 100644 js/js.translator/testData/box/esModules/jsExport/recursiveExport.kt create mode 100644 js/js.translator/testData/box/esModules/jsExport/recursiveExport.mjs create mode 100644 js/js.translator/testData/box/esModules/jsModule/externalClass.kt create mode 100644 js/js.translator/testData/box/esModules/jsModule/externalClass.mjs create mode 100644 js/js.translator/testData/box/esModules/jsModule/externalClassNameClash.kt create mode 100644 js/js.translator/testData/box/esModules/jsModule/externalClassWithDefaults.kt create mode 100644 js/js.translator/testData/box/esModules/jsModule/externalClassWithDefaults.mjs create mode 100644 js/js.translator/testData/box/esModules/jsModule/externalConstructor.kt create mode 100644 js/js.translator/testData/box/esModules/jsModule/externalConstructor.mjs create mode 100644 js/js.translator/testData/box/esModules/jsModule/externalFunction.kt create mode 100644 js/js.translator/testData/box/esModules/jsModule/externalFunction.mjs create mode 100644 js/js.translator/testData/box/esModules/jsModule/externalFunctionNameClash.kt create mode 100644 js/js.translator/testData/box/esModules/jsModule/externalFunctionNameClash.mjs create mode 100644 js/js.translator/testData/box/esModules/jsModule/externalObject.kt create mode 100644 js/js.translator/testData/box/esModules/jsModule/externalObject.mjs create mode 100644 js/js.translator/testData/box/esModules/jsModule/externalPackage.kt create mode 100644 js/js.translator/testData/box/esModules/jsModule/externalPackage.mjs create mode 100644 js/js.translator/testData/box/esModules/jsModule/externalPackageInDifferentFile.js create mode 100644 js/js.translator/testData/box/esModules/jsModule/externalPackageInDifferentFile.kt create mode 100644 js/js.translator/testData/box/esModules/jsModule/externalPackageInDifferentFile.mjs create mode 100644 js/js.translator/testData/box/esModules/jsModule/externalProperty.kt create mode 100644 js/js.translator/testData/box/esModules/jsModule/externalProperty.mjs create mode 100644 js/js.translator/testData/box/esModules/jsModule/interfaces.kt create mode 100644 js/js.translator/testData/box/esModules/jsModule/interfaces.mjs create mode 100644 js/js.translator/testData/box/esModules/jsModule/topLevelVarargFun.kt create mode 100644 js/js.translator/testData/box/esModules/jsModule/topLevelVarargFun.mjs create mode 100644 js/js.translator/testData/box/esModules/jsName/defaultJsName.kt create mode 100644 js/js.translator/testData/box/esModules/jsName/jsTopLevelClashes.kt create mode 100644 js/js.translator/testData/box/esModules/native/inheritanceInNativeClass.kt diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JSCompilerArguments.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JSCompilerArguments.kt index 88ee80ed57e..ce3ed60bb95 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JSCompilerArguments.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JSCompilerArguments.kt @@ -170,6 +170,9 @@ class K2JSCompilerArguments : CommonCompilerArguments() { @Argument(value = "-Xir-per-module-output-name", description = "Adds a custom output name to the splitted js files") var irPerModuleOutputName: String? by NullableStringFreezableVar(null) + @Argument(value = "-Xir-per-file", description = "Splits generated .js per-file") + var irPerFile: Boolean by FreezableVar(false) + @Argument( value = "-Xinclude", valueDescription = "", diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JsArgumentConstants.java b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JsArgumentConstants.java index dcee2ea8b06..bbaae233691 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JsArgumentConstants.java +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JsArgumentConstants.java @@ -24,6 +24,7 @@ public interface K2JsArgumentConstants { String MODULE_AMD = "amd"; String MODULE_COMMONJS = "commonjs"; String MODULE_UMD = "umd"; + String MODULE_ES = "es"; String SOURCE_MAP_SOURCE_CONTENT_ALWAYS = "always"; String SOURCE_MAP_SOURCE_CONTENT_NEVER = "never"; diff --git a/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/K2JsIrCompiler.kt b/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/K2JsIrCompiler.kt index 42c54fdb281..c8c3aec17ec 100644 --- a/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/K2JsIrCompiler.kt +++ b/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/K2JsIrCompiler.kt @@ -44,6 +44,8 @@ import org.jetbrains.kotlin.ir.backend.js.ic.checkCaches import org.jetbrains.kotlin.ir.backend.js.utils.sanitizeName import org.jetbrains.kotlin.ir.backend.js.ic.* import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl +import org.jetbrains.kotlin.ir.backend.js.codegen.JsGenerationGranularity +import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.IrModuleToJsTransformer import org.jetbrains.kotlin.ir.declarations.persistent.PersistentIrFactory import org.jetbrains.kotlin.js.analyzer.JsAnalysisResult import org.jetbrains.kotlin.js.config.* @@ -332,20 +334,21 @@ class K2JsIrCompiler : CLICompiler() { val start = System.currentTimeMillis() - val compiledModule = compile( + val granularity = when { + arguments.irPerModule -> JsGenerationGranularity.PER_MODULE + arguments.irPerFile -> JsGenerationGranularity.PER_FILE + else -> JsGenerationGranularity.WHOLE_PROGRAM + } + + val ir = compile( module, phaseConfig, if (arguments.irDceDriven) PersistentIrFactory() else IrFactoryImpl, - mainArguments = mainCallArguments, - generateFullJs = !arguments.irDce, - generateDceJs = arguments.irDce, dceRuntimeDiagnostic = RuntimeDiagnostic.resolve( arguments.irDceRuntimeDiagnostic, messageCollector ), dceDriven = arguments.irDceDriven, - multiModule = arguments.irPerModule, - relativeRequirePath = true, propertyLazyInitialization = arguments.irPropertyLazyInitialization, baseClassIntoMetadata = arguments.irBaseClassInMetadata, safeExternalBoolean = arguments.irSafeExternalBoolean, @@ -354,11 +357,28 @@ class K2JsIrCompiler : CLICompiler() { messageCollector ), lowerPerModule = icCaches.isNotEmpty(), + granularity = granularity ) + val transformer = IrModuleToJsTransformer( + ir.context, + mainCallArguments, + fullJs = true, + dceJs = arguments.irDce, + multiModule = arguments.irPerModule, + relativeRequirePath = false + ) + val compiledModule: CompilerResult = transformer.generateModule(ir.allModules) + messageCollector.report(INFO, "Executable production duration: ${System.currentTimeMillis() - start}ms") - val outputs = if (arguments.irDce && !arguments.irDceDriven) compiledModule.outputsAfterDce!! else compiledModule.outputs!! + + + val outputs = if (arguments.irDce && !arguments.irDceDriven) + compiledModule.outputsAfterDce!! + else + compiledModule.outputs!! + outputFile.write(outputs) outputs.dependencies.forEach { (name, content) -> outputFile.resolveSibling("$name.js").write(content) @@ -495,7 +515,8 @@ class K2JsIrCompiler : CLICompiler() { K2JsArgumentConstants.MODULE_PLAIN to ModuleKind.PLAIN, K2JsArgumentConstants.MODULE_COMMONJS to ModuleKind.COMMON_JS, K2JsArgumentConstants.MODULE_AMD to ModuleKind.AMD, - K2JsArgumentConstants.MODULE_UMD to ModuleKind.UMD + K2JsArgumentConstants.MODULE_UMD to ModuleKind.UMD, + K2JsArgumentConstants.MODULE_ES to ModuleKind.ES, ) private val sourceMapContentEmbeddingMap = mapOf( K2JsArgumentConstants.SOURCE_MAP_SOURCE_CONTENT_ALWAYS to SourceMapSourceEmbedding.ALWAYS, diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/optimizations/PropertyAccessorInlineLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/optimizations/PropertyAccessorInlineLowering.kt index 37f483a3cb8..c69cec20038 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/optimizations/PropertyAccessorInlineLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/optimizations/PropertyAccessorInlineLowering.kt @@ -25,12 +25,18 @@ import org.jetbrains.kotlin.ir.types.isUnit import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid -class PropertyAccessorInlineLowering(private val context: CommonBackendContext) : BodyLoweringPass { +open class PropertyAccessorInlineLowering( + private val context: CommonBackendContext, +) : BodyLoweringPass { - private val IrProperty.isSafeToInline: Boolean get() = isTopLevel || (modality === Modality.FINAL || visibility == DescriptorVisibilities.PRIVATE) || (parent as IrClass).modality === Modality.FINAL + fun IrProperty.isSafeToInlineInClosedWorld() = + isTopLevel || (modality === Modality.FINAL || visibility == DescriptorVisibilities.PRIVATE) || (parent as IrClass).modality === Modality.FINAL + + open fun IrProperty.isSafeToInline(accessContainer: IrDeclaration): Boolean = + isSafeToInlineInClosedWorld() // TODO: implement general function inlining optimization and replace it with - private inner class AccessorInliner : IrElementTransformerVoid() { + private inner class AccessorInliner(val container: IrDeclaration) : IrElementTransformerVoid() { private val unitType = context.irBuiltIns.unitType @@ -38,7 +44,7 @@ class PropertyAccessorInlineLowering(private val context: CommonBackendContext) val property = callee.correspondingPropertySymbol?.owner ?: return false // Some devirtualization required here - if (!property.isSafeToInline) return false + if (!property.isSafeToInline(container)) return false val parent = property.parent if (parent is IrClass) { @@ -176,6 +182,6 @@ class PropertyAccessorInlineLowering(private val context: CommonBackendContext) } override fun lower(irBody: IrBody, container: IrDeclaration) { - irBody.transformChildrenVoid(AccessorInliner()) + irBody.transformChildrenVoid(AccessorInliner(container)) } } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt index d44ede3db36..20f2d20b20c 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt @@ -17,6 +17,7 @@ import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor import org.jetbrains.kotlin.descriptors.impl.EmptyPackageFragmentDescriptor import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.ir.* +import org.jetbrains.kotlin.ir.backend.js.codegen.JsGenerationGranularity import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder import org.jetbrains.kotlin.ir.backend.js.lower.JsInnerClassesSupport import org.jetbrains.kotlin.ir.backend.js.utils.JsInlineClassesUtils @@ -58,7 +59,8 @@ class JsIrBackendContext( val baseClassIntoMetadata: Boolean = false, val safeExternalBoolean: Boolean = false, val safeExternalBooleanDiagnostic: RuntimeDiagnostic? = null, - override val mapping: JsMapping = JsMapping(symbolTable.irFactory) + override val mapping: JsMapping = JsMapping(symbolTable.irFactory), + val granularity: JsGenerationGranularity = JsGenerationGranularity.WHOLE_PROGRAM, ) : JsCommonBackendContext { val fileToInitializationFuns: MutableMap = mutableMapOf() val fileToInitializerPureness: MutableMap = mutableMapOf() diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt index dcb62961788..a63fa462564 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt @@ -16,6 +16,7 @@ import org.jetbrains.kotlin.backend.common.lower.optimizations.FoldConstantLower import org.jetbrains.kotlin.backend.common.lower.optimizations.PropertyAccessorInlineLowering import org.jetbrains.kotlin.backend.common.phaser.* import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.backend.js.codegen.JsGenerationGranularity import org.jetbrains.kotlin.ir.backend.js.lower.* import org.jetbrains.kotlin.ir.backend.js.lower.calls.CallsLowering import org.jetbrains.kotlin.ir.backend.js.lower.cleanup.CleanupLowering @@ -397,7 +398,7 @@ private val removeInitializersForLazyProperties = makeDeclarationTransformerPhas ) private val propertyAccessorInlinerLoweringPhase = makeBodyLoweringPhase( - ::PropertyAccessorInlineLowering, + ::JsPropertyAccessorInlineLowering, name = "PropertyAccessorInlineLowering", description = "[Optimization] Inline property accessors" ) @@ -775,6 +776,14 @@ private val cleanupLoweringPhase = makeBodyLoweringPhase( name = "CleanupLowering", description = "Clean up IR before codegen" ) +private val moveOpenClassesToSeparatePlaceLowering = makeCustomJsModulePhase( + { context, module -> + if (context.granularity == JsGenerationGranularity.PER_FILE) + moveOpenClassesToSeparateFiles(module) + }, + name = "MoveOpenClassesToSeparateFiles", + description = "Move open classes to separate files" +).toModuleLowering() private val jsSuspendArityStorePhase = makeDeclarationTransformerPhase( ::JsSuspendArityStoreLowering, @@ -880,6 +889,9 @@ private val loweringList = listOf( captureStackTraceInThrowablesPhase, callsLoweringPhase, cleanupLoweringPhase, + // Currently broken due to static members lowering making single-open-class + // files non-recognizable as single-class files + // moveOpenClassesToSeparatePlaceLowering, validateIrAfterLowering, ) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/codegen/IrToJs.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/codegen/IrToJs.kt new file mode 100644 index 00000000000..6f74dcb9a57 --- /dev/null +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/codegen/IrToJs.kt @@ -0,0 +1,457 @@ +/* + * Copyright 2010-2020 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.ir.backend.js.codegen + +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext +import org.jetbrains.kotlin.ir.backend.js.LoweredIr +import org.jetbrains.kotlin.ir.backend.js.codegen.JsGenerationGranularity.* +import org.jetbrains.kotlin.ir.backend.js.export.* +import org.jetbrains.kotlin.ir.backend.js.lower.StaticMembersLowering +import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.IrFileToJsTransformer +import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.processClassModels +import org.jetbrains.kotlin.ir.backend.js.utils.* +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.types.classOrNull +import org.jetbrains.kotlin.ir.util.file +import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable +import org.jetbrains.kotlin.ir.util.hasInterfaceParent +import org.jetbrains.kotlin.ir.util.isInterface +import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid +import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid +import org.jetbrains.kotlin.ir.visitors.acceptVoid +import org.jetbrains.kotlin.js.backend.ast.* +import org.jetbrains.kotlin.serialization.js.ModuleKind +import kotlin.math.abs + +interface CompilerOutputSink { + fun write(module: String, path: String, content: String) +} + +class JsGenerationOptions( + val jsExtension: String = "js", + val generatePackageJson: Boolean = false, + val generateTypeScriptDefinitions: Boolean = false, +) + +class IrToJs( + private val backendContext: JsIrBackendContext, + private val guid: (IrDeclaration) -> String, + private val outputSink: CompilerOutputSink, + private val mainArguments: List?, + private val granularity: JsGenerationGranularity, + private val mainModuleName: String, + private val options: JsGenerationOptions, +) { + val indexFileName = "index.${options.jsExtension}" + + val FileUnit.initFunctionName + get() = "KotlinInit$" + sanitizeName(pathToJsModule(file)) + + sealed class CodegenUnitReference + object ThisUnitReference : CodegenUnitReference() + inner class OtherUnitReference( + module: IrModuleFragment, + ) : CodegenUnitReference() { + // Path to entry point of other module from "top-level", e.g. directory which contains all other modules + val importPath = "./" + module.jsModuleName + "/" + indexFileName + } + + abstract class CodegenUnit { + abstract val packageFragments: Iterable + abstract val externalPackageFragments: Iterable + abstract fun referenceCodegenUnitOfDeclaration(declaration: IrDeclaration): CodegenUnitReference + abstract val pathToKotlinModulesRoot: String + } + + inner class FileUnit(val file: IrFile, val externalFile: IrFile?) : CodegenUnit() { + override val packageFragments = + listOf(file) + + override val externalPackageFragments = + listOfNotNull(externalFile) + + override fun referenceCodegenUnitOfDeclaration(declaration: IrDeclaration): CodegenUnitReference = + when (val declarationFile = declaration.file) { + file -> ThisUnitReference + else -> OtherUnitReference(declarationFile.module) + } + + override val pathToKotlinModulesRoot: String by lazy { + "../".repeat(file.fqName.pathSegments().size + 1) + } + } + + inner class ModuleUnit(val module: IrModuleFragment) : CodegenUnit() { + override val packageFragments: Iterable = + module.files + + override val externalPackageFragments: Iterable = + packageFragments.mapNotNull { backendContext.externalPackageFragment[it.symbol] } + + override fun referenceCodegenUnitOfDeclaration(declaration: IrDeclaration): CodegenUnitReference = + when (val declarationModule = declaration.file.module) { + module -> ThisUnitReference + else -> OtherUnitReference(declarationModule) + } + + override val pathToKotlinModulesRoot: String = "../" + } + + class WholeProgramUnit( + val modules: Iterable, + val externalModules: Iterable + ) : CodegenUnit() { + override val packageFragments: Iterable = + modules.flatMap { it.files } + + override val externalPackageFragments: Iterable + get() = externalModules + + override fun referenceCodegenUnitOfDeclaration(declaration: IrDeclaration): CodegenUnitReference = + ThisUnitReference + + override val pathToKotlinModulesRoot: String + get() = "../" + } + + private fun pathToJsModule(file: IrFile): String = + "${fileJsRootModuleName(file)}/${fileJsSubModulePath(file)}" + + private fun fileJsRootModuleName(file: IrFile): String = + when (granularity) { + WHOLE_PROGRAM -> mainModuleName + PER_MODULE, PER_FILE -> file.module.jsModuleName + } + + private fun fileJsSubModulePath(file: IrFile): String = + when (granularity) { + WHOLE_PROGRAM, PER_MODULE -> indexFileName + + PER_FILE -> { + val maybeSingleOpenClass = (file.declarations.singleOrNull() as? IrClass)?.takeIf { + it.modality == Modality.ABSTRACT || it.modality == Modality.OPEN + } + + val hash = abs((maybeSingleOpenClass?.let { guid(it) } ?: file.path).hashCode()) + val filePrefix = maybeSingleOpenClass?.name?.asString()?.let { sanitizeName(it) + ".class" } ?: file.name + val fileName = "${filePrefix}_$hash.${options.jsExtension}" + val packagePath = file.fqName.pathSegments().joinToString("") { it.identifier + "/" } + "$packagePath$fileName" + } + } + + class GeneratedUnit( + val jsStatements: List, + val exportedDeclarations: List, + ) + + fun generateUnit(unit: CodegenUnit): GeneratedUnit { + val exportedDeclarations: List = + with(ExportModelGenerator(backendContext, generateNamespacesForPackages = false)) { + (unit.externalPackageFragments + unit.packageFragments).flatMap { packageFragment -> + generateExport(packageFragment) + } + } + + val stableNames: Set = collectStableNames(unit) + val nameGenerator = NewNamerImpl(backendContext, unit, guid, stableNames) + + val staticContext = JsStaticContext( + backendContext = backendContext, + irNamer = nameGenerator, + globalNameScope = nameGenerator.staticNames + ) + + val rootContext = JsGenerationContext( + currentFunction = null, + currentFile = null, + staticContext = staticContext, + localNames = LocalNameGenerator(NameTable()) + ) + + + val declarationStatements: List = unit.packageFragments.flatMap { + StaticMembersLowering(backendContext).lower(it as IrFile) + it.accept(IrFileToJsTransformer(), rootContext).statements + } + + val preDeclarationBlock = JsGlobalBlock() + val postDeclarationBlock = JsGlobalBlock() + processClassModels(rootContext.staticContext.classModels, preDeclarationBlock, postDeclarationBlock) + + val statements = mutableListOf() + statements += nameGenerator.internalImports.values + statements += preDeclarationBlock + statements += declarationStatements + statements += postDeclarationBlock + + // Generate module initialization + + val initializerBlock = rootContext.staticContext.initializerBlock + when (unit) { + is WholeProgramUnit, is ModuleUnit -> { + // Run initialization during ES module initialization + statements += initializerBlock + } + + is FileUnit -> { + // Postpone initialization by putting it into a separate function + // Will be called later in proper order after class model is initialized + val initFunction = JsFunction(emptyScope, JsBlock(initializerBlock.statements), "init fun") + initFunction.name = JsName(unit.initFunctionName) + statements += initFunction.makeStmt() + statements += JsExport(initFunction.name) + } + } + + // Generate internal export + + val internalExports = mutableListOf() + fun export(declaration: IrDeclarationWithName) { + internalExports += JsExport.Element(nameGenerator.getNameForStaticDeclaration(declaration), JsName(guid(declaration))) + } + + for (fragment in unit.packageFragments) { + for (declaration in fragment.declarations) { + if (declaration is IrDeclarationWithName) { + export(declaration) + } + + // Default implementations of interface methods are nested under interface declarations in IR at this point, + // but they are effectively used as a static declaration and can be directly referenced by other codegen unit, + // thus requiring internal export + declaration.acceptChildrenVoid(object : IrElementVisitorVoid { + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) + } + + override fun visitSimpleFunction(declaration: IrSimpleFunction) { + if (declaration.hasInterfaceParent() && declaration.body != null) { + export(declaration) + } + super.visitSimpleFunction(declaration) + } + }) + } + } + statements += JsExport(JsExport.Subject.Elements(internalExports), null) + + // Generate external export + + val globalNames = NameTable(nameGenerator.staticNames) + val exporter = ExportModelToJsStatements( + nameGenerator, + declareNewNamespace = { globalNames.declareFreshName(it, it) } + ) + exportedDeclarations.forEach { + statements += exporter.generateDeclarationExport(it, null) + } + + return GeneratedUnit(statements, exportedDeclarations) + } + + private fun collectStableNames(unit: CodegenUnit): Set { + val newStableStaticNamesCollectorVisitor = + NewStableStaticNamesCollectorVisitor(needToCollectReferences = granularity != WHOLE_PROGRAM) + unit.packageFragments.forEach { it.acceptVoid(newStableStaticNamesCollectorVisitor) } + unit.externalPackageFragments.forEach { it.acceptVoid(newStableStaticNamesCollectorVisitor) } + + return newStableStaticNamesCollectorVisitor.collectedStableNames + } + + // Returns import statement and call expression + private fun invokeFunctionFromEntryJsFile( + function: IrFunction, + args: List = emptyList() + ): Pair { + val name = guid(function) + val importPath = if (granularity == WHOLE_PROGRAM) "./$indexFileName" else "../" + pathToJsModule(function.file) + return Pair( + JsImport(importPath, mutableListOf(JsImport.Element(name, null))), + JsInvocation(JsNameRef(name), args) + ) + } + + private fun invokeFunctionFromEntryJsFileAsStatements( + function: IrFunction, + args: List = emptyList() + ): List = + invokeFunctionFromEntryJsFile(function, args) + .let { listOf(it.first, it.second.makeStmt()) } + + fun generateModules( + mainModule: IrModuleFragment, + allModules: List + ) { + when (granularity) { + WHOLE_PROGRAM -> + generateModule(mainModule, allModules) + + PER_MODULE, + PER_FILE -> + allModules.forEach { module -> + generateModule(mainModule = module, allModules = emptyList()) + } + } + } + + fun generateModuleLevelCode(module: IrModuleFragment, statements: MutableList) { + if (mainArguments != null) { + val mainFunction = JsMainFunctionDetector(backendContext).getMainFunctionOrNull(module) + if (mainFunction != null) { + val generateArgv = mainFunction.valueParameters.firstOrNull()?.isStringArrayParameter() ?: false + val generateContinuation = mainFunction.isLoweredSuspendFunction(backendContext) + + val mainArgumentsArray = + if (generateArgv) + JsArrayLiteral(mainArguments.map { JsStringLiteral(it) }) + else + null + + val continuation = + if (generateContinuation) { + val (import, invoke) = invokeFunctionFromEntryJsFile(backendContext.coroutineEmptyContinuation.owner.getter!!) + statements += import + invoke + } else + null + + statements += invokeFunctionFromEntryJsFileAsStatements( + mainFunction, listOfNotNull(mainArgumentsArray, continuation) + ) + } + } + + backendContext.testRoots[module]?.let { testContainer -> + statements += invokeFunctionFromEntryJsFileAsStatements(testContainer) + } + } + + fun generateModule( + mainModule: IrModuleFragment, + allModules: List, + ) { + val moduleName = mainModule.jsModuleName + val indexJsStatements = mutableListOf() + val exportedDeclarations = mutableListOf() + + when (granularity) { + PER_FILE -> { + for (file in mainModule.files.sortedBy(::fileInitOrder)) { + if (file.declarations.isEmpty()) continue + + val pathToSubModule = fileJsSubModulePath(file) + indexJsStatements += JsExport(JsExport.Subject.All, fromModule = "./$pathToSubModule") + + val unit = FileUnit(file, backendContext.externalPackageFragment[file.symbol]) + val generatedUnit = generateUnit(unit) + + val importElements = JsImport.Element(unit.initFunctionName, null) + indexJsStatements += JsImport("./$pathToSubModule", mutableListOf(importElements)) + indexJsStatements += JsInvocation(JsNameRef(JsName(unit.initFunctionName))).makeStmt() + + exportedDeclarations += generatedUnit.exportedDeclarations + + outputSink.write( + file.module.jsModuleName, + pathToSubModule, + "// Kotlin file: ${file.path}\n" + generatedUnit.jsStatements.toJsCodeString() + ) + } + generateModuleLevelCode(mainModule, indexJsStatements) + } + + PER_MODULE -> { + val generatedUnit = generateUnit(ModuleUnit(mainModule)) + indexJsStatements += generatedUnit.jsStatements + generateModuleLevelCode(mainModule, indexJsStatements) + exportedDeclarations += generatedUnit.exportedDeclarations + } + + WHOLE_PROGRAM -> { + val generatedUnit = generateUnit(WholeProgramUnit(allModules, backendContext.externalPackageFragment.values)) + indexJsStatements += generatedUnit.jsStatements + allModules.forEach { + generateModuleLevelCode(it, indexJsStatements) + } + exportedDeclarations += generatedUnit.exportedDeclarations + } + } + + outputSink.write(moduleName, indexFileName, indexJsStatements.toJsCodeString()) + + if (options.generatePackageJson) { + outputSink.write(moduleName, "package.json", """{ "main": "$indexFileName", "type": "module" }""") + } + + if (options.generateTypeScriptDefinitions && exportedDeclarations.isNotEmpty()) { + val dts = ExportedModule(moduleName, moduleKind = ModuleKind.ES, exportedDeclarations).toTypeScript() + outputSink.write(moduleName, "index.d.ts", dts) + } + } + + private fun fileInitOrder(file: IrFile): Int = + when (val singleDeclaration = file.declarations.singleOrNull()) { + // Initialize parent classes before child classes + // TODO: Comment about open classes in separate files + is IrClass -> singleDeclaration.getInheritanceChainLength() + // Initialize regular files after all open classes + else -> Int.MAX_VALUE + } + + private fun IrClass.getInheritanceChainLength(): Int { + if (symbol == backendContext.irBuiltIns.anyClass) + return 0 + + // FIXME: Filter out interfaces + superTypes.forEach { superType -> + val superClass: IrClass? = superType.classOrNull?.owner + if (superClass != null && /* !!! */ !superClass.isInterface) + return superClass.getInheritanceChainLength() + 1 + } + + + return 1 + } +} + +private val IrModuleFragment.jsModuleName: String + get() = name.asString().dropWhile { it == '<' }.dropLastWhile { it == '>' } + +private fun List.toJsCodeString(): String = + JsGlobalBlock().also { it.statements += this }.toString() + +enum class JsGenerationGranularity { + WHOLE_PROGRAM, + PER_MODULE, + PER_FILE +} + +fun generateEsModules( + ir: LoweredIr, + outputSink: CompilerOutputSink, + mainArguments: List?, + granularity: JsGenerationGranularity, + options: JsGenerationOptions, +) { + // Declaration numeration to create temporary GUID + // TODO: Replace with an actual GUID + val numerator = StaticDeclarationNumerator() + ir.allModules.forEach { numerator.add(it) } + + fun guid(declaration: IrDeclaration): String { + val name = sanitizeName((declaration as IrDeclarationWithName).name.toString()) + val number = numerator.numeration[declaration] + ?: error("Can't find number for declaration ${declaration.fqNameWhenAvailable}") + // TODO: Use shorter names in release mode + return "${name}_GUID_${number}" + } + + val ir2js = IrToJs(ir.context, ::guid, outputSink, mainArguments, granularity, ir.mainModule.jsModuleName, options) + ir2js.generateModules(ir.mainModule, ir.allModules) +} diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt index f44a025b493..a99addc008a 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt @@ -8,6 +8,9 @@ package org.jetbrains.kotlin.ir.backend.js import org.jetbrains.kotlin.backend.common.lower import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig import org.jetbrains.kotlin.backend.common.phaser.invokeToplevel +import org.jetbrains.kotlin.config.CompilerConfiguration +import org.jetbrains.kotlin.ir.backend.js.codegen.JsGenerationGranularity +import org.jetbrains.kotlin.ir.backend.js.ic.SerializedIcData import org.jetbrains.kotlin.ir.backend.js.ic.ModuleCache import org.jetbrains.kotlin.ir.backend.js.ic.icCompile import org.jetbrains.kotlin.ir.backend.js.lower.generateTests @@ -37,39 +40,36 @@ class CompilationOutputs( val dependencies: Iterable> = emptyList() ) +class LoweredIr( + val context: JsIrBackendContext, + val mainModule: IrModuleFragment, + val allModules: List +) + fun compile( depsDescriptors: ModulesStructure, phaseConfig: PhaseConfig, irFactory: IrFactory, - mainArguments: List?, exportedDeclarations: Set = emptySet(), - generateFullJs: Boolean = true, - generateDceJs: Boolean = false, dceDriven: Boolean = false, dceRuntimeDiagnostic: RuntimeDiagnostic? = null, es6mode: Boolean = false, - multiModule: Boolean = false, - relativeRequirePath: Boolean = false, propertyLazyInitialization: Boolean, verifySignatures: Boolean = true, baseClassIntoMetadata: Boolean = false, lowerPerModule: Boolean = false, safeExternalBoolean: Boolean = false, safeExternalBooleanDiagnostic: RuntimeDiagnostic? = null, - filesToLower: Set? = null -): CompilerResult { + filesToLower: Set? = null, + granularity: JsGenerationGranularity = JsGenerationGranularity.WHOLE_PROGRAM, +): LoweredIr { if (lowerPerModule) { return icCompile( depsDescriptors, - mainArguments, exportedDeclarations, - generateFullJs, - generateDceJs, dceRuntimeDiagnostic, es6mode, - multiModule, - relativeRequirePath, propertyLazyInitialization, baseClassIntoMetadata, safeExternalBoolean, @@ -77,7 +77,7 @@ fun compile( ) } - val (moduleFragment: IrModuleFragment, dependencyModules, irBuiltIns, symbolTable, deserializer, moduleToName) = + val (moduleFragment: IrModuleFragment, dependencyModules, irBuiltIns, symbolTable, deserializer, _) = loadIr(depsDescriptors, irFactory, verifySignatures, filesToLower, loadFunctionInterfacesIntoStdlib = true) val mainModule = depsDescriptors.mainModule @@ -102,7 +102,8 @@ fun compile( propertyLazyInitialization = propertyLazyInitialization, baseClassIntoMetadata = baseClassIntoMetadata, safeExternalBoolean = safeExternalBoolean, - safeExternalBooleanDiagnostic = safeExternalBooleanDiagnostic + safeExternalBooleanDiagnostic = safeExternalBooleanDiagnostic, + granularity = granularity ) // Load declarations referenced during `context` initialization @@ -130,17 +131,6 @@ fun compile( eliminateDeadDeclarations(allModules, context) irFactory.stageController = StageController(controller.currentStage) - - val transformer = IrModuleToJsTransformer( - context, - mainArguments, - fullJs = true, - dceJs = false, - multiModule = multiModule, - relativeRequirePath = relativeRequirePath, - moduleToName = moduleToName, - ) - return transformer.generateModule(allModules) } else { // TODO is this reachable when lowerPerModule == true? if (lowerPerModule) { @@ -154,18 +144,9 @@ fun compile( } else { jsPhases.invokeToplevel(phaseConfig, context, allModules) } - - val transformer = IrModuleToJsTransformer( - context, - mainArguments, - fullJs = generateFullJs, - dceJs = generateDceJs, - multiModule = multiModule, - relativeRequirePath = relativeRequirePath, - moduleToName = moduleToName, - ) - return transformer.generateModule(allModules) } + + return LoweredIr(context, moduleFragment, allModules) } fun lowerPreservingIcData(module: IrModuleFragment, context: JsIrBackendContext, controller: WholeWorldStageController) { diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModelGenerator.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModelGenerator.kt index e6f71e774dd..50b0360d9e3 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModelGenerator.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModelGenerator.kt @@ -26,24 +26,28 @@ import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.js.config.JSConfigurationKeys +import org.jetbrains.kotlin.serialization.js.ModuleKind import org.jetbrains.kotlin.utils.addIfNotNull -class ExportModelGenerator(val context: JsIrBackendContext) { +class ExportModelGenerator( + val context: JsIrBackendContext, + val generateNamespacesForPackages: Boolean +) { fun generateExport(file: IrPackageFragment): List { val namespaceFqName = file.fqName val exports = file.declarations.flatMap { declaration -> listOfNotNull(exportDeclaration(declaration)) } return when { exports.isEmpty() -> emptyList() - namespaceFqName.isRoot -> exports + !generateNamespacesForPackages || namespaceFqName.isRoot -> exports else -> listOf(ExportedNamespace(namespaceFqName.toString(), exports)) } } - fun generateExport(modules: Iterable): ExportedModule = + fun generateExport(modules: Iterable, moduleKind: ModuleKind = ModuleKind.PLAIN): ExportedModule = ExportedModule( context.configuration[CommonConfigurationKeys.MODULE_NAME]!!, - context.configuration[JSConfigurationKeys.MODULE_KIND]!!, + moduleKind, (context.externalPackageFragment.values + modules.flatMap { it.files }).flatMap { generateExport(it) } @@ -296,7 +300,7 @@ class ExportModelGenerator(val context: JsIrBackendContext) { classifier is IrClassSymbol -> { val klass = classifier.owner - val name = klass.fqNameWhenAvailable!!.asString() + val name = if (generateNamespacesForPackages) klass.fqNameWhenAvailable!!.asString() else klass.name.asString() when (klass.kind) { ClassKind.ANNOTATION_CLASS, diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModelToJsStatements.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModelToJsStatements.kt index b0b8e57a549..99bc573219e 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModelToJsStatements.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModelToJsStatements.kt @@ -11,25 +11,24 @@ import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.jsAssignment import org.jetbrains.kotlin.ir.backend.js.utils.IrNamer import org.jetbrains.kotlin.js.backend.ast.* - class ExportModelToJsStatements( - private val internalModuleName: JsName, private val namer: IrNamer, private val declareNewNamespace: (String) -> String ) { private val namespaceToRefMap = mutableMapOf() - fun generateModuleExport(module: ExportedModule): List { + fun generateModuleExport(module: ExportedModule, internalModuleName: JsName): List { return module.declarations.flatMap { generateDeclarationExport(it, JsNameRef(internalModuleName)) } } - private fun generateDeclarationExport(declaration: ExportedDeclaration, namespace: JsNameRef): List { + fun generateDeclarationExport(declaration: ExportedDeclaration, namespace: JsNameRef?): List { return when (declaration) { is ExportedNamespace -> { + require(namespace != null) { "Only namespaced namespaces are allowed" } val statements = mutableListOf() val elements = declaration.name.split(".") var currentNamespace = "" - var currentRef = namespace + var currentRef: JsNameRef = namespace for (element in elements) { val newNamespace = "$currentNamespace$$element" val newNameSpaceRef = namespaceToRefMap.getOrPut(newNamespace) { @@ -37,14 +36,15 @@ class ExportModelToJsStatements( val varRef = JsNameRef(varName) val namespaceRef = JsNameRef(element, currentRef) statements += JsVars( - JsVars.JsVar(JsName(varName), - JsAstUtils.or( - namespaceRef, - jsAssignment( - namespaceRef, - JsObjectLiteral() - ) - ) + JsVars.JsVar( + JsName(varName), + JsAstUtils.or( + namespaceRef, + jsAssignment( + namespaceRef, + JsObjectLiteral() + ) + ) ) ) varRef @@ -56,17 +56,23 @@ class ExportModelToJsStatements( } is ExportedFunction -> { - listOf( - jsAssignment( - JsNameRef(declaration.name, namespace), - JsNameRef(namer.getNameForStaticDeclaration(declaration.ir)) - ).makeStmt() - ) + val name = namer.getNameForStaticDeclaration(declaration.ir) + if (namespace == null) { + listOf(JsExport(name, alias = JsName(declaration.name))) + } else { + listOf( + jsAssignment( + JsNameRef(declaration.name, namespace), + JsNameRef(name) + ).makeStmt() + ) + } } is ExportedConstructor -> emptyList() is ExportedProperty -> { + require(namespace != null) { "Only namespaced properties are allowed" } val getter = declaration.irGetter?.let { JsNameRef(namer.getNameForStaticDeclaration(it)) } val setter = declaration.irSetter?.let { JsNameRef(namer.getNameForStaticDeclaration(it)) } listOf(defineProperty(namespace, declaration.name, getter, setter).makeStmt()) @@ -77,14 +83,16 @@ class ExportModelToJsStatements( is ExportedClass -> { if (declaration.isInterface) return emptyList() val newNameSpace = JsNameRef(declaration.name, namespace) - val klassExport = jsAssignment( - newNameSpace, - JsNameRef( - namer.getNameForStaticDeclaration( - declaration.ir - ) - ) - ).makeStmt() + val name = namer.getNameForStaticDeclaration(declaration.ir) + val klassExport = + if (namespace == null) { + JsExport(name, alias = JsName(declaration.name)) + } else { + jsAssignment( + newNameSpace, + JsNameRef(name) + ).makeStmt() + } // These are only used when exporting secondary constructors annotated with @JsName val staticFunctions = declaration.members.filter { it is ExportedFunction && it.isStatic } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModelToTsDeclarations.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModelToTsDeclarations.kt index 450601ed98a..85b3a2d08d4 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModelToTsDeclarations.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModelToTsDeclarations.kt @@ -26,7 +26,7 @@ fun ExportedModule.toTypeScript(): String { return when (moduleKind) { ModuleKind.PLAIN -> "declare namespace $namespaceName {\n$declarationsDts\n}\n" - ModuleKind.AMD, ModuleKind.COMMON_JS -> declarationsDts + ModuleKind.AMD, ModuleKind.COMMON_JS, ModuleKind.ES -> declarationsDts ModuleKind.UMD -> "$declarationsDts\nexport as namespace $namespaceName;" } } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/ic.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/ic.kt index 25437888a50..09729330041 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/ic.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/ic/ic.kt @@ -123,25 +123,20 @@ private fun dumpIr(module: IrModuleFragment, fileName: String) { fun icCompile( depsDescriptor: ModulesStructure, - mainArguments: List?, exportedDeclarations: Set = emptySet(), - generateFullJs: Boolean = true, - generateDceJs: Boolean = false, dceRuntimeDiagnostic: RuntimeDiagnostic? = null, es6mode: Boolean = false, - multiModule: Boolean = false, - relativeRequirePath: Boolean = false, propertyLazyInitialization: Boolean, baseClassIntoMetadata: Boolean = false, safeExternalBoolean: Boolean = false, safeExternalBooleanDiagnostic: RuntimeDiagnostic? = null, -): CompilerResult { +): LoweredIr { val irFactory = PersistentIrFactory() val controller = WholeWorldStageController() irFactory.stageController = controller - val (context, _, allModules, moduleToName, loweredIrLoaded) = prepareIr( + val (context, _, allModules, _, loweredIrLoaded) = prepareIr( depsDescriptor, exportedDeclarations, dceRuntimeDiagnostic, @@ -155,8 +150,6 @@ fun icCompile( val modulesToLower = allModules.filter { it !in loweredIrLoaded } - - if (!modulesToLower.isEmpty()) { // This won't work incrementally modulesToLower.forEach { module -> @@ -172,20 +165,7 @@ fun icCompile( // dumpIr(allModules.first(), "simple-dump${if (useStdlibCache) "-actual" else ""}") - val transformer = IrModuleToJsTransformer( - context, - mainArguments, - fullJs = generateFullJs, - dceJs = generateDceJs, - multiModule = multiModule, - relativeRequirePath = relativeRequirePath, - moduleToName = moduleToName, - removeUnusedAssociatedObjects = false, - ) - - irFactory.stageController = object : StageController(999) {} - - return transformer.generateModule(allModules) + return LoweredIr(context, allModules.last(), allModules) } fun lowerPreservingIcData(module: IrModuleFragment, context: JsIrBackendContext, controller: WholeWorldStageController) { diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsPropertyAccessorInlineLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsPropertyAccessorInlineLowering.kt new file mode 100644 index 00000000000..acc48c4e325 --- /dev/null +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsPropertyAccessorInlineLowering.kt @@ -0,0 +1,40 @@ +/* + * Copyright 2010-2021 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.ir.backend.js.lower + +import org.jetbrains.kotlin.backend.common.lower.optimizations.PropertyAccessorInlineLowering +import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext +import org.jetbrains.kotlin.ir.backend.js.codegen.JsGenerationGranularity +import org.jetbrains.kotlin.ir.declarations.IrDeclaration +import org.jetbrains.kotlin.ir.declarations.IrProperty +import org.jetbrains.kotlin.ir.util.fileOrNull + +class JsPropertyAccessorInlineLowering( + val context: JsIrBackendContext +) : PropertyAccessorInlineLowering(context) { + override fun IrProperty.isSafeToInline(accessContainer: IrDeclaration): Boolean { + if (!isSafeToInlineInClosedWorld()) + return false + + if (isConst) + return true + + return when (context.granularity) { + JsGenerationGranularity.WHOLE_PROGRAM -> + true + JsGenerationGranularity.PER_MODULE -> { + val accessModule = accessContainer.fileOrNull?.module ?: return false + val module = fileOrNull?.module ?: return false + accessModule == module + } + JsGenerationGranularity.PER_FILE -> + // Not inlining because + // 1. we need a way to distinguish per-file generation units + // 2. per-file mode intended for debug builds only at the moment + false + } + } +} \ No newline at end of file diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/MoveOpenClassesToSeparateFiles.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/MoveOpenClassesToSeparateFiles.kt new file mode 100644 index 00000000000..44ebc808a24 --- /dev/null +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/MoveOpenClassesToSeparateFiles.kt @@ -0,0 +1,61 @@ +/* + * Copyright 2010-2019 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.ir.backend.js.lower + +import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.descriptors.DescriptorVisibilities +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrDeclarationContainer +import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.declarations.IrModuleFragment +import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrFileSymbolImpl +import org.jetbrains.kotlin.ir.util.transformDeclarationsFlat +import org.jetbrains.kotlin.ir.util.transformFlat + +fun moveOpenClassesToSeparateFiles(moduleFragment: IrModuleFragment) { + fun createFile(file: IrFile, klass: IrClass): IrFile = + IrFileImpl(fileEntry = file.fileEntry, fqName = file.fqName, symbol = IrFileSymbolImpl(), module = file.module).also { + it.annotations += file.annotations + it.declarations += klass + klass.parent = it + } + + moduleFragment.files.transformFlat { file -> + // We don't have to split declarations with a single class + if (file.declarations.size <= 1) + return@transformFlat null + + val openClasses = mutableListOf() + fun removeAndCollectOpenClasses(container: IrDeclarationContainer) { + container.transformDeclarationsFlat { declaration -> + if (declaration is IrDeclarationContainer) { + removeAndCollectOpenClasses(declaration) + } + if ( + declaration is IrClass && + (declaration.modality == Modality.OPEN || declaration.modality == Modality.ABSTRACT) && + declaration.kind == ClassKind.CLASS && + declaration.visibility != DescriptorVisibilities.PRIVATE && + declaration.visibility != DescriptorVisibilities.LOCAL + ) { + openClasses += declaration + emptyList() + } else { + null + } + } + } + removeAndCollectOpenClasses(file) + + return@transformFlat if (openClasses.isEmpty()) + null + else + listOf(file) + openClasses.map { createFile(file, it) } + } +} + diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrFileToJsTransformer.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrFileToJsTransformer.kt index fbeaecdebca..11b9bb6f0fd 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrFileToJsTransformer.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrFileToJsTransformer.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs import org.jetbrains.kotlin.ir.backend.js.utils.JsGenerationContext import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.declarations.IrPackageFragment import org.jetbrains.kotlin.js.backend.ast.JsBlock import org.jetbrains.kotlin.js.backend.ast.JsGlobalBlock diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrFunctionToJsTransformer.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrFunctionToJsTransformer.kt index 2a7b77b6a41..9a8ce82b641 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrFunctionToJsTransformer.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrFunctionToJsTransformer.kt @@ -6,15 +6,19 @@ package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs import org.jetbrains.kotlin.ir.backend.js.utils.JsGenerationContext +import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrConstructor import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction +import org.jetbrains.kotlin.ir.util.isInterface import org.jetbrains.kotlin.js.backend.ast.JsFunction @Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE") class IrFunctionToJsTransformer : BaseIrElementToJsNodeTransformer { override fun visitSimpleFunction(declaration: IrSimpleFunction, context: JsGenerationContext): JsFunction { - val funcName = if (declaration.dispatchReceiverParameter == null) { + val parentClass = declaration.parent as? IrClass + val isInterfaceDefaultImpl = parentClass?.isInterface ?: false + val funcName = if (declaration.dispatchReceiverParameter == null || isInterfaceDefaultImpl) { if (declaration.parent is IrFunction) { context.getNameForValueDeclaration(declaration) } else { diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrModuleToJsTransformer.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrModuleToJsTransformer.kt index 1fe77739ed2..a3c4f5be95a 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrModuleToJsTransformer.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrModuleToJsTransformer.kt @@ -23,6 +23,7 @@ import org.jetbrains.kotlin.js.backend.JsToStringGenerationVisitor import org.jetbrains.kotlin.js.backend.NoOpSourceLocationConsumer import org.jetbrains.kotlin.js.backend.ast.* import org.jetbrains.kotlin.js.config.JSConfigurationKeys +import org.jetbrains.kotlin.serialization.js.ModuleKind import org.jetbrains.kotlin.js.config.SourceMapSourceEmbedding import org.jetbrains.kotlin.js.sourceMap.SourceFilePathResolver import org.jetbrains.kotlin.js.sourceMap.SourceMap3Builder @@ -52,17 +53,14 @@ class IrModuleToJsTransformer( ) + packageLevelJsModules } - val exportedModule = ExportModelGenerator(backendContext).generateExport(modules) + val moduleKind: ModuleKind = backendContext.configuration[JSConfigurationKeys.MODULE_KIND]!! + val exportedModule = ExportModelGenerator(backendContext, generateNamespacesForPackages = true).generateExport(modules, moduleKind = moduleKind) val dts = exportedModule.toTypeScript() modules.forEach { module -> module.files.forEach { StaticMembersLowering(backendContext).lower(it) } } - if (multiModule) { - breakCrossModuleFieldAccess(backendContext, modules) - } - modules.forEach { module -> namer.merge(module.files, additionalPackages) } @@ -103,7 +101,7 @@ class IrModuleToJsTransformer( val dependencies = others.mapIndexed { index, module -> val moduleName = module.externalModuleName() - val exportedDeclarations = ExportModelGenerator(backendContext).let { module.files.flatMap { file -> it.generateExport(file) } } + val exportedDeclarations = ExportModelGenerator(backendContext, generateNamespacesForPackages = true).let { module.files.flatMap { file -> it.generateExport(file) } } moduleName to generateWrappedModuleBody2( listOf(module), @@ -149,7 +147,7 @@ class IrModuleToJsTransformer( currentFile = null, currentFunction = null, staticContext = staticContext, - localNames = LocalNameGenerator(NameScope.EmptyScope) + localNames = LocalNameGenerator(NameTable()) ) val (importStatements, importedJsModules) = @@ -162,7 +160,8 @@ class IrModuleToJsTransformer( val internalModuleName = JsName("_") val globalNames = NameTable(namer.globalNames) - val exportStatements = ExportModelToJsStatements(internalModuleName, nameGenerator, { globalNames.declareFreshName(it, it)}).generateModuleExport(exportedModule) + val exportStatements = ExportModelToJsStatements(nameGenerator) { globalNames.declareFreshName(it, it) } + .generateModuleExport(exportedModule, internalModuleName) val (crossModuleImports, importedKotlinModules) = generateCrossModuleImports(nameGenerator, modules, dependencies, { JsName(sanitizeName(it)) }) val crossModuleExports = generateCrossModuleExports(modules, refInfo, internalModuleName) @@ -431,27 +430,6 @@ class IrModuleToJsTransformer( return Pair(importStatements, importedJsModules) } - private fun processClassModels( - classModelMap: Map, - preDeclarationBlock: JsBlock, - postDeclarationBlock: JsBlock - ) { - val declarationHandler = object : DFS.AbstractNodeHandler() { - override fun result() {} - override fun afterChildren(current: IrClassSymbol) { - classModelMap[current]?.let { - preDeclarationBlock.statements += it.preDeclarationBlock.statements - postDeclarationBlock.statements += it.postDeclarationBlock.statements - } - } - } - - DFS.dfs( - classModelMap.keys, - { klass -> classModelMap[klass]?.superClasses ?: emptyList() }, - declarationHandler - ) - } private fun MutableList.startRegion(description: String = "") { if (generateRegionComments) { @@ -479,3 +457,26 @@ class IrModuleToJsTransformer( endRegion() } } + +fun processClassModels( + classModelMap: Map, + preDeclarationBlock: JsBlock, + postDeclarationBlock: JsBlock +) { + val declarationHandler = object : DFS.AbstractNodeHandler() { + override fun result() {} + override fun afterChildren(current: IrClassSymbol) { + classModelMap[current]?.let { + preDeclarationBlock.statements += it.preDeclarationBlock.statements + postDeclarationBlock.statements += it.postDeclarationBlock.statements + } + } + } + + DFS.dfs( + classModelMap.keys, + { klass -> classModelMap[klass]?.superClasses ?: emptyList() }, + declarationHandler + ) +} + diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsClassGenerator.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsClassGenerator.kt index f2ab9298e39..ff8b777461e 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsClassGenerator.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsClassGenerator.kt @@ -85,7 +85,7 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo } } is IrClass -> { - classBlock.statements += JsClassGenerator(declaration, context).generate() +// classBlock.statements += JsClassGenerator(declaration, context).generate() } is IrField -> { } @@ -208,9 +208,14 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo val memberRef = JsNameRef(memberName, classPrototypeRef) if (declaration.isReal && declaration.body != null) { - val translatedFunction = declaration.accept(IrFunctionToJsTransformer(), context) + val translatedFunction: JsFunction = declaration.accept(IrFunctionToJsTransformer(), context) assert(!declaration.isStaticMethodOfClass) + if (irClass.isInterface) { + classModel.preDeclarationBlock.statements += translatedFunction.makeStmt() + return Pair(memberRef, null) + } + return Pair(memberRef, translatedFunction) } @@ -224,14 +229,19 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo ?.let { val implClassDeclaration = it.parent as IrClass - if (implClassDeclaration.shouldCopyFrom()) { - val implMethodName = context.getNameForMemberFunction(it) - val implClassName = context.getNameForClass(implClassDeclaration) + if (implClassDeclaration.shouldCopyFrom() && it.body != null) { + val reference = context.getNameForStaticDeclaration(it).makeRef() + classModel.postDeclarationBlock.statements += jsAssignment(memberRef, reference).makeStmt() + } + } + declaration.collectRealOverrides() + .find { it.modality != Modality.ABSTRACT } + ?.let { + val implClassDeclaration = it.parent as IrClass - val implClassPrototype = prototypeOf(implClassName.makeRef()) - val implMemberRef = JsNameRef(implMethodName, implClassPrototype) - - classModel.postDeclarationBlock.statements += jsAssignment(memberRef, implMemberRef).makeStmt() + if (implClassDeclaration.shouldCopyFrom() && it.body != null) { + val reference = context.getNameForStaticDeclaration(it).makeRef() + classModel.postDeclarationBlock.statements += jsAssignment(memberRef, reference).makeStmt() } } } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/ModuleWrapperTranslation.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/ModuleWrapperTranslation.kt index 5289c69c2a7..a135b324d36 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/ModuleWrapperTranslation.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/ModuleWrapperTranslation.kt @@ -25,6 +25,7 @@ object ModuleWrapperTranslation { ModuleKind.COMMON_JS -> wrapCommonJs(function, importedModules, program) ModuleKind.UMD -> wrapUmd(moduleId, function, importedModules, program) ModuleKind.PLAIN -> wrapPlain(moduleId, function, importedModules, program) + ModuleKind.ES -> error("ES modules are not supported in legacy wrapper") } } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/MultiModuleSupport.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/MultiModuleSupport.kt index b5cdf4f6c35..9d239909e40 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/MultiModuleSupport.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/MultiModuleSupport.kt @@ -116,94 +116,6 @@ fun buildCrossModuleReferenceInfo(modules: Iterable): CrossMod return CrossModuleReferenceInfoImpl(map) } -fun breakCrossModuleFieldAccess( - context: JsIrBackendContext, - modules: Iterable -) { - val fieldToGetter = mutableMapOf() - - fun IrField.getter(): IrSimpleFunction { - return fieldToGetter.getOrPut(this) { - val fieldName = name - val getter = context.irFactory.buildFun { - name = Name.identifier("get-$fieldName") - returnType = type - } - getter.body = factory.createBlockBody( - UNDEFINED_OFFSET, UNDEFINED_OFFSET, listOf( - IrReturnImpl( - UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, getter.symbol, - IrGetFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, symbol, type) - ) - ) - ) - getter.parent = parent - (parent as IrDeclarationContainer).declarations += getter - - getter - } - } - - val fieldToSetter = mutableMapOf() - - fun IrField.setter(): IrSimpleFunction { - return fieldToSetter.getOrPut(this) { - val fieldName = name - val setter = context.irFactory.buildFun { - name = Name.identifier("set-$fieldName") - returnType = context.irBuiltIns.unitType - } - - val param = setter.addValueParameter("value", type) - - setter.body = factory.createBlockBody( - UNDEFINED_OFFSET, UNDEFINED_OFFSET, listOf( - IrSetFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, symbol, type).apply { - value = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, param.symbol) - } - ) - ) - setter.parent = parent - (parent as IrDeclarationContainer).declarations += setter - - setter - } - } - - modules.reversed().forEach { module -> - - val moduleFields = module.files.flatMap { it.declarations.filterIsInstance() }.toSet() - - fun IrField.transformAccess(fn: IrField.() -> IrCall): IrCall? { - if (parent !is IrPackageFragment || isEffectivelyExternal() || this in moduleFields) return null - return fn() - } - - module.transformChildrenVoid(object : IrElementTransformerVoid() { - - override fun visitGetField(expression: IrGetField): IrExpression { - expression.transformChildrenVoid(this) - - return expression.symbol.owner.transformAccess { - val getter = getter() - IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, getter.returnType, getter.symbol, getter.typeParameters.size, getter.valueParameters.size) - } ?: expression - } - - override fun visitSetField(expression: IrSetField): IrExpression { - expression.transformChildrenVoid(this) - - return expression.symbol.owner.transformAccess { - val setter = setter() - IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, setter.returnType, setter.symbol, setter.typeParameters.size, setter.valueParameters.size).apply { - putValueArgument(0, expression.value) - } - } ?: expression - } - }) - } -} - val IrModuleFragment.safeName: String get() { var result = name.asString() diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/jsAstUtils.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/jsAstUtils.kt index c186a5cd3bf..f94d692325c 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/jsAstUtils.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/jsAstUtils.kt @@ -11,6 +11,7 @@ import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.backend.js.JsStatementOrigins import org.jetbrains.kotlin.ir.backend.js.utils.* +import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.expressions.* @@ -127,17 +128,22 @@ fun translateCall( } expression.superQualifierSymbol?.let { superQualifier -> - val (target, klass) = if (superQualifier.owner.isInterface) { + val (target: IrSimpleFunction, klass: IrClass) = if (superQualifier.owner.isInterface) { val impl = function.resolveFakeOverride()!! Pair(impl, impl.parentAsClass) } else { Pair(function, superQualifier.owner) } - val qualifierName = context.getNameForClass(klass).makeRef() - val targetName = context.getNameForMemberFunction(target) - val qPrototype = JsNameRef(targetName, prototypeOf(qualifierName)) - val callRef = JsNameRef(Namer.CALL_FUNCTION, qPrototype) + val callRef = if (klass.isInterface && target.body != null) { + JsNameRef(Namer.CALL_FUNCTION, JsNameRef(context.getNameForStaticDeclaration(target))) + } else { + val qualifierName = context.getNameForClass(klass).makeRef() + val targetName = context.getNameForMemberFunction(target) + val qPrototype = JsNameRef(targetName, prototypeOf(qualifierName)) + JsNameRef(Namer.CALL_FUNCTION, qPrototype) + } + return JsInvocation(callRef, jsDispatchReceiver?.let { receiver -> listOf(receiver) + arguments } ?: arguments) } @@ -193,20 +199,15 @@ fun translateCall( "VarargIIFE" ) - val iifeFunHasContext = (jsDispatchReceiver as? JsNameRef)?.qualifier is JsThisRef - if (iifeFunHasContext) { - JsInvocation( - // Create scope for temporary variable holding dispatch receiver - // It is used both during method reference and passing `this` value to `apply` function. - JsNameRef( - "call", - iifeFun - ), - JsThisRef() - ) - } else { - JsInvocation(iifeFun) - } + JsInvocation( + // Create scope for temporary variable holding dispatch receiver + // It is used both during method reference and passing `this` value to `apply` function. + JsNameRef( + "call", + iifeFun + ), + JsThisRef() + ) } } else { if (argumentsAsSingleArray is JsArrayLiteral) { diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/JsStaticContext.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/JsStaticContext.kt index e854a10efcf..325f7bc319f 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/JsStaticContext.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/JsStaticContext.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.ir.backend.js.utils import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.JsIntrinsicTransformers import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.JsIrClassModel +import org.jetbrains.kotlin.ir.declarations.IrDeclaration import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.js.backend.ast.JsGlobalBlock import org.jetbrains.kotlin.js.config.JSConfigurationKeys @@ -16,7 +17,7 @@ import org.jetbrains.kotlin.js.config.JSConfigurationKeys class JsStaticContext( val backendContext: JsIrBackendContext, private val irNamer: IrNamer, - val globalNameScope: NameScope, + val globalNameScope: NameTable, ) : IrNamer by irNamer { val intrinsics = JsIntrinsicTransformers(backendContext) val classModels = mutableMapOf() diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/NameTables.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/NameTables.kt index 3af60e3a1cd..9c5690c7916 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/NameTables.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/NameTables.kt @@ -16,6 +16,7 @@ import org.jetbrains.kotlin.ir.types.isUnit import org.jetbrains.kotlin.ir.util.file import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable import org.jetbrains.kotlin.ir.util.isEffectivelyExternal +import org.jetbrains.kotlin.ir.util.isInterface import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid @@ -32,7 +33,12 @@ import kotlin.math.abs private fun mapToKey(declaration: T): String { return with(JsManglerIr) { if (declaration is IrDeclaration) { - declaration.hashedMangle(compatibleMode = false).toString() + try { + declaration.hashedMangle(compatibleMode = false).toString() + } catch (e: Throwable) { + // FIXME: We can't mangle some local declarations. But + "wrong_key" + } } else if (declaration is String) { declaration.hashMangle.toString() } else { @@ -118,6 +124,7 @@ fun jsFunctionSignature(declaration: IrFunction, context: JsIrBackendContext?): } val nameBuilder = StringBuilder() + nameBuilder.append(declarationName) // TODO should we skip type parameters and use upper bound of type parameter when print type of value parameters? declaration.typeParameters.ifNotEmpty { @@ -202,6 +209,11 @@ class NameTables( when (memberDecl) { is IrField -> generateNameForMemberField(memberDecl) + is IrSimpleFunction -> { + if (declaration.isInterface && memberDecl.body != null) { + globalNames.declareFreshName(memberDecl, memberDecl.name.asString()) + } + } } } } @@ -299,8 +311,7 @@ class NameTables( } -class LocalNameGenerator(parentScope: NameScope) : IrElementVisitorVoid { - val variableNames = NameTable(parentScope) +class LocalNameGenerator(val variableNames: NameTable) : IrElementVisitorVoid { val localLoopNames = NameTable() val localReturnableBlockNames = NameTable() diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/NewNamer.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/NewNamer.kt new file mode 100644 index 00000000000..c0e06186a52 --- /dev/null +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/NewNamer.kt @@ -0,0 +1,207 @@ +/* + * Copyright 2010-2020 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.ir.backend.js.utils + +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext +import org.jetbrains.kotlin.ir.backend.js.codegen.IrToJs +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.expressions.IrDeclarationReference +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid +import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid +import org.jetbrains.kotlin.js.backend.ast.JsImport +import org.jetbrains.kotlin.js.backend.ast.JsName + +class StaticDeclarationNumerator { + var currentNumber = 0 + val numeration = mutableMapOf() + + fun add(moduleFragment: IrModuleFragment) { + moduleFragment.files.forEach { add(it) } + } + + fun add(declaration: IrDeclaration) { + // TODO: We should not visit declarations multiple times. + // Investigate enum tests in dce-driven mode. + if (declaration !in numeration) { + numeration[declaration] = currentNumber + currentNumber++ + } + } + + fun add(packageFragment: IrPackageFragment) { + packageFragment.acceptChildrenVoid(object : IrElementVisitorVoid { + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) + } + + override fun visitDeclaration(declaration: IrDeclarationBase) { + if (declaration !is IrVariable) { + add(declaration) + } + super.visitDeclaration(declaration) + } + }) + } +} + +class NewStableStaticNamesCollectorVisitor(val needToCollectReferences: Boolean) : IrElementVisitorVoid { + val collectedStableNames = mutableSetOf() + + init { + collectedStableNames.addAll(RESERVED_IDENTIFIERS) + collectedStableNames.add(Namer.IMPLICIT_RECEIVER_NAME) + } + + private fun IrDeclaration.collectStableName() { + collectedStableNames += stableNameForExternalDeclaration(this) ?: return + } + + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) + } + + override fun visitDeclaration(declaration: IrDeclarationBase) { + super.visitDeclaration(declaration) + declaration.collectStableName() + } + + override fun visitDeclarationReference(expression: IrDeclarationReference) { + super.visitDeclarationReference(expression) + if (needToCollectReferences) { + val declaration = expression.symbol.owner as? IrDeclaration + declaration?.collectStableName() + } + } +} + +class NewNamerImpl( + val context: JsIrBackendContext, + val unit: IrToJs.CodegenUnit, + val exportId: (IrDeclarationWithName) -> String, + val stableNames: Set, +) : IrNamerBase() { + val staticNames = NameTable( + reserved = stableNames.toMutableSet() + ) + val internalImports = mutableMapOf() + + override fun getNameForMemberFunction(function: IrSimpleFunction): JsName { + require(function.dispatchReceiverParameter != null) + val name = jsFunctionSignature(function, context) + return name.toJsName() + } + + override fun getNameForMemberField(field: IrField): JsName { + val fieldName = sanitizeName( + try { + exportId(field) + } catch (e: IllegalStateException) { + // TODO: Fix DCE with inline classes and remove this hack + field.name.asString() + "_LIKELY_ELIMINATED_BY_DCE" + } + ) + // TODO: Webpack not minimize member names, it is long name, which is not minimized, so it affects final JS bundle size + // Use shorter names + return JsName("f_$fieldName") + } + + override fun getNameForStaticDeclaration(declaration: IrDeclarationWithName): JsName { + staticNames.names[declaration]?.let { return JsName(it) } + + fun registerImport(moduleId: String, importedName: String) { + val fullModuleId = if (moduleId.startsWith(".")) { + unit.pathToKotlinModulesRoot + moduleId + } else { + // TODO: Do we cover this path in tests? + moduleId + } + + val import = internalImports.getOrPut(fullModuleId) { + JsImport(fullModuleId) + } + import.elements += JsImport.Element(importedName, staticNames.names[declaration]!!) + } + + if (declaration.isEffectivelyExternal()) { + val jsModule: String? = declaration.getJsModule() + val maybeParentFile: IrFile? = declaration.parent as? IrFile + val fileJsModule: String? = maybeParentFile?.getJsModule() + val jsQualifier: String? = maybeParentFile?.getJsQualifier() + + when { + jsModule != null -> { + // TODO: Support jsQualifier + staticNames.declareFreshName(declaration, declaration.name.asString()) + registerImport(jsModule, "default") + } + + fileJsModule != null -> { + // TODO: Support jsQualifier + staticNames.declareFreshName(declaration, declaration.name.asString()) + registerImport(fileJsModule, declaration.getJsNameOrKotlinName().identifier) + } + + else -> { + var name = declaration.getJsNameOrKotlinName().identifier + if (jsQualifier != null) + name = "$jsQualifier.$name" + + staticNames.declareStableName(declaration, name) + } + } + + + } else { // Non-external declaration + staticNames.declareFreshName(declaration, declaration.name.asString()) + val unitReference = unit.referenceCodegenUnitOfDeclaration(declaration) + if (unitReference is IrToJs.OtherUnitReference) { + registerImport(unitReference.importPath, exportId(declaration)) + } + } + + return JsName(staticNames.names[declaration]!!) + } +} + +// TODO: Cache? +private fun stableNameForExternalDeclaration(declaration: IrDeclaration): String? { + if (declaration !is IrDeclarationWithName || + !declaration.hasStaticDispatch() || + !declaration.isEffectivelyExternal() || + declaration.isPropertyAccessor || + declaration.isPropertyField + ) { + return null + } + + if (declaration is IrConstructor) { + return stableNameForExternalDeclaration(declaration.parentAsClass) + } + + val importedFromModuleOnly = + declaration.getJsModule() != null && !declaration.isJsNonModule() + + val jsName = declaration.getJsName() + + val jsQualifier = declaration.fileOrNull?.getJsQualifier() + + return when { + importedFromModuleOnly -> + null + + jsQualifier != null -> + jsQualifier.split('1')[0] + + jsName != null -> + jsName + + else -> + declaration.name.identifier + } +} + diff --git a/compiler/testData/cli/js/jsExtraHelp.out b/compiler/testData/cli/js/jsExtraHelp.out index 8650b354f09..f22fff300a3 100644 --- a/compiler/testData/cli/js/jsExtraHelp.out +++ b/compiler/testData/cli/js/jsExtraHelp.out @@ -20,6 +20,7 @@ where advanced options include: Enable runtime diagnostics when performing DCE instead of removing declarations -Xir-module-name= Specify a compilation module name for IR backend -Xir-only Disables pre-IR backend + -Xir-per-file Splits generated .js per-file -Xir-per-module Splits generated .js per-module -Xir-per-module-output-name Adds a custom output name to the splitted js files -Xir-produce-js Generates JS file using IR backend. Also disables pre-IR backend diff --git a/compiler/testData/codegen/box/enum/kt18731_2.kt b/compiler/testData/codegen/box/enum/kt18731_2.kt index e986919f9e1..cbba381aa00 100644 --- a/compiler/testData/codegen/box/enum/kt18731_2.kt +++ b/compiler/testData/codegen/box/enum/kt18731_2.kt @@ -1,3 +1,4 @@ +// SKIP_DCE_DRIVEN enum class Bar { ONE { diff --git a/compiler/testData/codegen/box/properties/lazyInitializationPure.kt b/compiler/testData/codegen/box/properties/lazyInitializationPure.kt deleted file mode 100644 index 2600f4e6483..00000000000 --- a/compiler/testData/codegen/box/properties/lazyInitializationPure.kt +++ /dev/null @@ -1,36 +0,0 @@ -// TARGET_BACKEND: JS_IR -// PROPERTY_LAZY_INITIALIZATION - -// FILE: A.kt - -val a = "A" - -// FILE: B.kt -val b = "B".let { - it + "B" -} - -val c = b - -// FILE: C.kt -val d = "D".let { - it + "D" -} - -val e = d - -// FILE: main.kt - -fun box(): String { - // Get only e to initialize all properties in file - e - return if ( - js("a") === "A" && - js("typeof b") == "undefined" && - js("typeof c") == "undefined" && - js("d") === "DD" && - js("e") === "DD" - ) - "OK" - else "a = ${js("a")}; typeof b = ${js("typeof b")}; typeof c = ${js("typeof c")}; d = ${js("d")}; e = ${js("e")}" -} \ No newline at end of file diff --git a/compiler/testData/codegen/box/properties/lazyInitializationThroughTopFun.kt b/compiler/testData/codegen/box/properties/lazyInitializationThroughTopFun.kt index 82f6742257c..9d2ec4bda9c 100644 --- a/compiler/testData/codegen/box/properties/lazyInitializationThroughTopFun.kt +++ b/compiler/testData/codegen/box/properties/lazyInitializationThroughTopFun.kt @@ -3,7 +3,10 @@ // PROPERTY_LAZY_INITIALIZATION // FILE: A.kt +var result: String? = null + val a = "a".let { + result = "OK" it + "a" } @@ -13,5 +16,5 @@ fun foo() = // FILE: main.kt fun box(): String { val foo = foo() - return if (js("typeof a") == "string" && js("a") == "aa") "OK" else "fail" + return result!! } \ No newline at end of file diff --git a/compiler/testData/codegen/box/properties/noInitializationLazilyOnNonPropertiesCall.kt b/compiler/testData/codegen/box/properties/noInitializationLazilyOnNonPropertiesCall.kt index 61109c20fa1..8faf467d239 100644 --- a/compiler/testData/codegen/box/properties/noInitializationLazilyOnNonPropertiesCall.kt +++ b/compiler/testData/codegen/box/properties/noInitializationLazilyOnNonPropertiesCall.kt @@ -5,6 +5,7 @@ // FILE: A.kt val a1 = "a".let { + throw Error() it + "a" } @@ -39,5 +40,5 @@ fun box(): String { C.values() C.valueOf("OK") val baz = b - return if (js("typeof a1") == "undefined") "OK" else "fail" + return "OK" } \ No newline at end of file diff --git a/compiler/testData/codegen/box/regressions/kt10143.kt b/compiler/testData/codegen/box/regressions/kt10143.kt index 33a0cbbce16..6fca5e5f2d8 100644 --- a/compiler/testData/codegen/box/regressions/kt10143.kt +++ b/compiler/testData/codegen/box/regressions/kt10143.kt @@ -1,3 +1,5 @@ +// TODO: Investigate ES modules issue + // FILE: Outer.kt package another diff --git a/js/js.ast/src/org/jetbrains/kotlin/js/backend/JsToStringGenerationVisitor.java b/js/js.ast/src/org/jetbrains/kotlin/js/backend/JsToStringGenerationVisitor.java index dce38741b54..ac41ade5fe1 100644 --- a/js/js.ast/src/org/jetbrains/kotlin/js/backend/JsToStringGenerationVisitor.java +++ b/js/js.ast/src/org/jetbrains/kotlin/js/backend/JsToStringGenerationVisitor.java @@ -1173,6 +1173,69 @@ public class JsToStringGenerationVisitor extends JsVisitor { } } + @Override + public void visitExport(@NotNull JsExport export) { + p.print("export"); + space(); + JsExport.Subject subject = export.getSubject(); + + if (subject instanceof JsExport.Subject.All) { + p.print("*"); + } else if (subject instanceof JsExport.Subject.Elements) { + blockOpen(); + List elements = ((JsExport.Subject.Elements) subject).getElements(); + for (JsExport.Element element : elements) { + nameDef(element.getName()); + JsName alias = element.getAlias(); + if (alias != null) { + p.print(" as "); + nameDef(alias); + } + p.print(','); + p.newline(); + } + p.indentOut(); + p.print('}'); + } + + if (export.getFromModule() != null) { + p.print(" from "); + p.print(javaScriptString(export.getFromModule())); + } + needSemi = true; + } + + @Override + public void visitImport(@NotNull JsImport jsImport) { + p.print("import {"); + boolean isMultiline = jsImport.getElements().size() > 1; + p.indentIn(); + if (isMultiline) + newlineOpt(); + else + space(); + + for (JsImport.Element element : jsImport.getElements()) { + 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("} from "); + p.print(javaScriptString(jsImport.getModule())); + } + + private void newline() { p.newline(); sourceLocationConsumer.newLine(); diff --git a/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsExport.kt b/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsExport.kt new file mode 100644 index 00000000000..a7d5efbaea3 --- /dev/null +++ b/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsExport.kt @@ -0,0 +1,40 @@ +/* + * Copyright 2010-2020 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.backend.ast + +class JsExport( + val subject: Subject, + val fromModule: String? = null, +) : SourceInfoAwareJsNode(), JsStatement { + + constructor(element: Element) : this(Subject.Elements(listOf(element))) + constructor(name: JsName, alias: JsName? = null) : this(Element(name, alias)) + + sealed class Subject { + class Elements(val elements: List) : Subject() + object All : Subject() + } + + class Element( + val name: JsName, + val alias: JsName? + ) + + override fun accept(visitor: JsVisitor) { + visitor.visitExport(this) + } + + override fun acceptChildren(visitor: JsVisitor) { + } + + override fun deepCopy(): JsStatement = + JsExport(subject, fromModule) + + override fun traverse(v: JsVisitorWithContext, ctx: JsContext<*>) { + v.visit(this, ctx) + v.endVisit(this, ctx) + } +} \ No newline at end of file diff --git a/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsImport.kt b/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsImport.kt new file mode 100644 index 00000000000..6484552c412 --- /dev/null +++ b/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsImport.kt @@ -0,0 +1,34 @@ +/* + * Copyright 2010-2020 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.backend.ast + +class JsImport( + val module: String, + val elements: MutableList = mutableListOf(), +) : SourceInfoAwareJsNode(), JsStatement { + + class Element( + val name: JsName, + val alias: JsName? + ) { + constructor(name: String, alias: String?) : this(JsName(name), alias?.let { JsName(it) }) + } + + override fun accept(visitor: JsVisitor) { + visitor.visitImport(this) + } + + override fun acceptChildren(visitor: JsVisitor) { + } + + override fun deepCopy(): JsStatement = + JsImport(module, elements.map { it }.toMutableList()) + + override fun traverse(v: JsVisitorWithContext, ctx: JsContext<*>) { + v.visit(this, ctx) + v.endVisit(this, ctx) + } +} \ No newline at end of file diff --git a/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsVisitor.kt b/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsVisitor.kt index d9a1c022303..856175537fb 100644 --- a/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsVisitor.kt +++ b/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsVisitor.kt @@ -165,6 +165,12 @@ abstract class JsVisitor { open fun visitSingleLineComment(comment: JsSingleLineComment): Unit = visitElement(comment) + open fun visitExport(export: JsExport): Unit = + visitElement(export) + + open fun visitImport(import: JsImport): Unit = + visitElement(import) + protected open fun visitElement(node: JsNode) { } } \ No newline at end of file diff --git a/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsVisitorWithContext.java b/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsVisitorWithContext.java index ba922290e38..955c38e86fd 100644 --- a/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsVisitorWithContext.java +++ b/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsVisitorWithContext.java @@ -214,6 +214,12 @@ public abstract class JsVisitorWithContext { public void endVisit(@NotNull JsSingleLineComment x, @NotNull JsContext ctx) { } + public void endVisit(@NotNull JsExport x, @NotNull JsContext ctx) { + } + + public void endVisit(@NotNull JsImport x, @NotNull JsContext ctx) { + } + public void endVisit(@NotNull JsWhile x, @NotNull JsContext ctx) { endVisit((JsLoop) x, ctx); } @@ -398,6 +404,14 @@ public abstract class JsVisitorWithContext { return true; } + public boolean visit(@NotNull JsExport x, @NotNull JsContext ctx) { + return true; + } + + public boolean visit(@NotNull JsImport x, @NotNull JsContext ctx) { + return true; + } + protected abstract T doAccept(T node); protected abstract JsExpression doAcceptLvalue(JsExpression expr); diff --git a/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/KotlinJavascriptSerializationUtil.kt b/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/KotlinJavascriptSerializationUtil.kt index 199d31a286e..55a8a3a8e4b 100644 --- a/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/KotlinJavascriptSerializationUtil.kt +++ b/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/KotlinJavascriptSerializationUtil.kt @@ -124,6 +124,7 @@ object KotlinJavascriptSerializationUtil { ModuleKind.AMD -> JsProtoBuf.Library.Kind.AMD ModuleKind.COMMON_JS -> JsProtoBuf.Library.Kind.COMMON_JS ModuleKind.UMD -> JsProtoBuf.Library.Kind.UMD + ModuleKind.ES -> error("Es modules serialization") } if (builder.kind != moduleProtoKind) { builder.kind = moduleProtoKind diff --git a/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/ModuleKind.java b/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/ModuleKind.java index fcdb3a0eb94..96e7bac578d 100644 --- a/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/ModuleKind.java +++ b/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/ModuleKind.java @@ -22,5 +22,6 @@ public enum ModuleKind { PLAIN, AMD, COMMON_JS, - UMD + UMD, + ES } diff --git a/js/js.tests/build.gradle.kts b/js/js.tests/build.gradle.kts index e120a057a8d..53e57202138 100644 --- a/js/js.tests/build.gradle.kts +++ b/js/js.tests/build.gradle.kts @@ -257,6 +257,8 @@ projectTest(parallel = true) { } projectTest("jsTest", true) { + // PIR temporary disabled + systemProperty("kotlin.js.ir.pir", "false") setUpJsBoxTests(jsEnabled = true, jsIrEnabled = false) } diff --git a/js/js.tests/test/org/jetbrains/kotlin/generators/tests/GenerateJsTests.kt b/js/js.tests/test/org/jetbrains/kotlin/generators/tests/GenerateJsTests.kt index d76d26efc6e..6e6c9f1e18d 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/generators/tests/GenerateJsTests.kt +++ b/js/js.tests/test/org/jetbrains/kotlin/generators/tests/GenerateJsTests.kt @@ -47,11 +47,6 @@ fun main(args: Array) { model("typescript-export/", pattern = "^([^_](.+))\\.kt$", targetBackend = TargetBackend.JS_IR_ES6) } - testClass { - model("typescript-export/", pattern = "^([^_](.+))\\.kt$", targetBackend = TargetBackend.JS) - } - - testClass { model("sourcemap/", pattern = "^([^_](.+))\\.kt$", targetBackend = TargetBackend.JS) } diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicBoxTest.kt b/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicBoxTest.kt index 547866f8830..d83bd7eaaec 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicBoxTest.kt +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicBoxTest.kt @@ -26,6 +26,7 @@ import org.jetbrains.kotlin.idea.KotlinFileType import org.jetbrains.kotlin.incremental.js.IncrementalDataProviderImpl import org.jetbrains.kotlin.incremental.js.IncrementalResultsConsumerImpl import org.jetbrains.kotlin.incremental.js.TranslationResultValue +import org.jetbrains.kotlin.ir.backend.js.codegen.JsGenerationGranularity import org.jetbrains.kotlin.ir.backend.js.ic.ICCache import org.jetbrains.kotlin.js.JavaScript import org.jetbrains.kotlin.js.backend.JsToStringGenerationVisitor @@ -46,6 +47,7 @@ import org.jetbrains.kotlin.js.parser.sourcemaps.SourceMapParser import org.jetbrains.kotlin.js.parser.sourcemaps.SourceMapSuccess import org.jetbrains.kotlin.js.sourceMap.SourceFilePathResolver import org.jetbrains.kotlin.js.sourceMap.SourceMap3Builder +import org.jetbrains.kotlin.js.test.engines.ExternalTool import org.jetbrains.kotlin.js.sourceMap.SourceMapBuilderConsumer import org.jetbrains.kotlin.js.test.utils.* import org.jetbrains.kotlin.js.util.TextOutputImpl @@ -153,7 +155,17 @@ abstract class BasicBoxTest( if (errorPolicyMatcher.find()) ErrorTolerancePolicy.resolvePolicy(errorPolicyMatcher.group(1)) else ErrorTolerancePolicy.DEFAULT val skipDceDriven = SKIP_DCE_DRIVEN.matcher(fileContent).find() + val esModules = ES_MODULES.matcher(fileContent).find() + val splitPerModule = SPLIT_PER_MODULE.matcher(fileContent).find() + val splitPerFile = SPLIT_PER_FILE.matcher(fileContent).find() + + val granularity = when { + splitPerModule -> JsGenerationGranularity.PER_MODULE + splitPerFile -> JsGenerationGranularity.PER_FILE + else -> JsGenerationGranularity.WHOLE_PROGRAM + } + val skipMangleVerification = SKIP_MANGLE_VERIFICATION.matcher(fileContent).find() val safeExternalBoolean = SAFE_EXTERNAL_BOOLEAN.matcher(fileContent).find() @@ -196,6 +208,12 @@ abstract class BasicBoxTest( val mainModule = modules[mainModuleName] ?: error("No module with name \"$mainModuleName\"") val icCache = mutableMapOf() + if (esModules) { + modules.forEach { _, m -> m.moduleKind = ModuleKind.ES } + } + + val customTestModule: String? = inputFiles.find { it.testEntryEsModule }?.let { File(it.fileName).readText() } + val generatedJsFiles = orderedModules.asReversed().mapNotNull { module -> val dependencies = module.dependenciesSymbols.map { modules[it]?.outputFileName(outputDir) + ".meta.js" } val allDependencies = module.allTransitiveDependencies().map { modules[it]?.outputFileName(outputDir) + ".meta.js" } @@ -229,7 +247,8 @@ abstract class BasicBoxTest( isMainModule, expectActualLinker, skipDceDriven, - splitPerModule, + esModules, + granularity, errorPolicy, propertyLazyInitialization = true, safeExternalBoolean, @@ -237,7 +256,8 @@ abstract class BasicBoxTest( skipMangleVerification, abiVersion, checkIC, - icCache + icCache, + customTestModule, ) when { @@ -279,6 +299,7 @@ abstract class BasicBoxTest( } val additionalFiles = mutableListOf() + val moduleEmulationFiles = mutableListOf() val moduleKindMatcher = MODULE_KIND_PATTERN.matcher(fileContent) val moduleKind = if (moduleKindMatcher.find()) ModuleKind.valueOf(moduleKindMatcher.group(1)) else ModuleKind.PLAIN @@ -286,7 +307,7 @@ abstract class BasicBoxTest( val withModuleSystem = moduleKind != ModuleKind.PLAIN && !NO_MODULE_SYSTEM_PATTERN.matcher(fileContent).find() if (withModuleSystem) { - additionalFiles += MODULE_EMULATION_FILE + moduleEmulationFiles += MODULE_EMULATION_FILE } val additionalJsFile = filePath.removeSuffix("." + KotlinFileType.EXTENSION) + JavaScript.DOT_EXTENSION @@ -294,6 +315,63 @@ abstract class BasicBoxTest( additionalFiles += additionalJsFile } + if (esModules) { + val additionalMainJsFile = + (filePath.removeSuffix("." + KotlinFileType.EXTENSION) + "__main.js").takeIf { File(it).exists() } + + val maybeAdditionalMjsFile: String? = + (filePath.removeSuffix("." + KotlinFileType.EXTENSION) + ".mjs") + .takeIf { File(it).exists() } + + val allMjsFiles: List = + inputFiles.filter { it.fileName.endsWith(".mjs") }.map { it.fileName } + listOfNotNull(maybeAdditionalMjsFile) + + val allNonEsModuleFiles: List = + additionalFiles + inputJsFilesBefore + globalCommonFiles + localCommonFiles + additionalCommonFiles + + fun runIrEsmTests(testOutputDir: File) { + val esmOutputDir = testOutputDir.esModulesSubDir + + // Copy __main file if present + if (additionalMainJsFile != null) { + val newFileName = File(esmOutputDir, "test.mjs") + newFileName.delete() + File(additionalMainJsFile).copyTo(newFileName) + } + + // Copy all .mjs files into generated directory + allMjsFiles.forEach { mjsFile -> + val outFile = File(esmOutputDir, File(mjsFile).name) + File(mjsFile).copyTo(outFile) + } + + val perFileEsModuleFile = "$esmOutputDir/test.mjs" + v8tool.run(*allNonEsModuleFiles.toTypedArray(), perFileEsModuleFile, *inputJsFilesAfter.toTypedArray()) + } + + fun File.getTestDir(): File = + File(generatedJsFiles.single().first.replace(outputDir.absolutePath, this.absolutePath)) + + if (!skipRegularMode) { + runIrEsmTests(outputDir.getTestDir()) + + if (runIrDce) { + runIrEsmTests(dceOutputDir.getTestDir()) + } + } + + if (runIrPir && !skipDceDriven) { + runIrEsmTests(pirOutputDir.getTestDir()) + } + } + + if (esModules) + return + + // Old systems tests + + additionalFiles.addAll(0, moduleEmulationFiles) + val additionalMainFiles = mutableListOf() val additionalMainJsFile = filePath.removeSuffix("." + KotlinFileType.EXTENSION) + "__main.js" if (File(additionalMainJsFile).exists()) { @@ -318,7 +396,6 @@ abstract class BasicBoxTest( } + globalCommonFiles + localCommonFiles + additionalCommonFiles + additionalMainFiles + inputJsFilesAfter - val dontRunGeneratedCode = InTextDirectivesUtils.dontRunGeneratedCode(targetBackend, file) @@ -501,7 +578,8 @@ abstract class BasicBoxTest( isMainModule: Boolean, expectActualLinker: Boolean, skipDceDriven: Boolean, - splitPerModule: Boolean, + esModules: Boolean, + granularity: JsGenerationGranularity, errorIgnorancePolicy: ErrorTolerancePolicy, propertyLazyInitialization: Boolean, safeExternalBoolean: Boolean, @@ -509,7 +587,8 @@ abstract class BasicBoxTest( skipMangleVerification: Boolean, abiVersion: KotlinAbiVersion, checkIC: Boolean, - icCache: MutableMap + icCache: MutableMap, + customTestModule: String?, ) { val kotlinFiles = module.files.filter { it.fileName.endsWith(".kt") } val testFiles = kotlinFiles.map { it.fileName } @@ -558,7 +637,8 @@ abstract class BasicBoxTest( needsFullIrRuntime, isMainModule, skipDceDriven, - splitPerModule, + esModules, + granularity, propertyLazyInitialization, safeExternalBoolean, safeExternalBooleanDiagnostic, @@ -566,7 +646,8 @@ abstract class BasicBoxTest( abiVersion, checkIC, recompile = false, - icCache + icCache, + customTestModule, ) if (incrementalCompilationChecksEnabled && module.hasFilesToRecompile) { @@ -661,7 +742,8 @@ abstract class BasicBoxTest( needsFullIrRuntime, isMainModule = false, skipDceDriven = true, - splitPerModule = false, + esModules = false, + granularity = JsGenerationGranularity.WHOLE_PROGRAM, propertyLazyInitialization = true, safeExternalBoolean = false, safeExternalBooleanDiagnostic = null, @@ -669,7 +751,8 @@ abstract class BasicBoxTest( abiVersion = KotlinAbiVersion.CURRENT, incrementalCompilation = true, recompile = true, - mutableMapOf() + mutableMapOf(), + customTestModule = null, ) val originalOutput = FileUtil.loadFile(outputFile) @@ -747,7 +830,8 @@ abstract class BasicBoxTest( needsFullIrRuntime: Boolean, isMainModule: Boolean, skipDceDriven: Boolean, - splitPerModule: Boolean, + esModules: Boolean, + granularity: JsGenerationGranularity, propertyLazyInitialization: Boolean, safeExternalBoolean: Boolean, safeExternalBooleanDiagnostic: RuntimeDiagnostic?, @@ -755,7 +839,8 @@ abstract class BasicBoxTest( abiVersion: KotlinAbiVersion, incrementalCompilation: Boolean, recompile: Boolean, - icCache: MutableMap + icCache: MutableMap, + customTestModule: String?, ) { val translator = K2JSTranslator(config, false) val translationResult = translator.translateUnits(ExceptionThrowingReporter, units, mainCallParameters) @@ -813,6 +898,8 @@ abstract class BasicBoxTest( "$content\n" ModuleKind.PLAIN -> content + + ModuleKind.ES -> error("Module emulation markers are not supported for ES modules") } } @@ -1082,7 +1169,8 @@ abstract class BasicBoxTest( temporaryFile.absolutePath, currentModule, recompile = RECOMPILE_PATTERN.matcher(text).find(), - packageName = ktFile.packageFqName.asString() + packageName = ktFile.packageFqName.asString(), + testEntryEsModule = ENTRY_ES_MODULE.matcher(text).find(), ) } @@ -1099,7 +1187,7 @@ abstract class BasicBoxTest( } } - protected class TestFile(val fileName: String, val module: TestModule, val recompile: Boolean, val packageName: String) { + protected class TestFile(val fileName: String, val module: TestModule, val recompile: Boolean, val packageName: String, val testEntryEsModule: Boolean) { init { module.files += this } @@ -1149,6 +1237,8 @@ abstract class BasicBoxTest( // Run top level box function private val RUN_PLAIN_BOX_FUNCTION = Pattern.compile("^// *RUN_PLAIN_BOX_FUNCTION", Pattern.MULTILINE) + private val ENTRY_ES_MODULE = Pattern.compile("^// *ENTRY_ES_MODULE", Pattern.MULTILINE) + private val NO_INLINE_PATTERN = Pattern.compile("^// *NO_INLINE *$", Pattern.MULTILINE) private val SKIP_NODE_JS = Pattern.compile("^// *SKIP_NODE_JS *$", Pattern.MULTILINE) private val SKIP_MINIFICATION = Pattern.compile("^// *SKIP_MINIFICATION *$", Pattern.MULTILINE) @@ -1163,7 +1253,10 @@ abstract class BasicBoxTest( private val WITH_STDLIB = Pattern.compile("^// *WITH_STDLIB *\$", Pattern.MULTILINE) private val EXPECT_ACTUAL_LINKER = Pattern.compile("^// EXPECT_ACTUAL_LINKER *$", Pattern.MULTILINE) private val SKIP_DCE_DRIVEN = Pattern.compile("^// *SKIP_DCE_DRIVEN *$", Pattern.MULTILINE) + private val ES_MODULES = Pattern.compile("^// *ES_MODULES *$", Pattern.MULTILINE) + private val SPLIT_PER_MODULE = Pattern.compile("^// *SPLIT_PER_MODULE *$", Pattern.MULTILINE) + private val SPLIT_PER_FILE = Pattern.compile("^// *SPLIT_PER_FILE *$", Pattern.MULTILINE) private val SKIP_MANGLE_VERIFICATION = Pattern.compile("^// *SKIP_MANGLE_VERIFICATION *$", Pattern.MULTILINE) private val ERROR_POLICY_PATTERN = Pattern.compile("^// *ERROR_POLICY: *(.+)$", Pattern.MULTILINE) @@ -1216,4 +1309,6 @@ fun RuntimeDiagnostic.Companion.resolve( else -> { null } -} \ No newline at end of file +} + +val v8tool by lazy { ExternalTool(System.getProperty("javascript.engine.path.V8")) } \ No newline at end of file diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicIrBoxTest.kt b/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicIrBoxTest.kt index 44ae27621c5..ec726208e84 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicIrBoxTest.kt +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicIrBoxTest.kt @@ -10,7 +10,14 @@ import org.jetbrains.kotlin.backend.common.phaser.AnyNamedPhase import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig import org.jetbrains.kotlin.backend.common.phaser.toPhaseMap import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport +import org.jetbrains.kotlin.config.CommonConfigurationKeys 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.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.transformers.irToJs.IrModuleToJsTransformer import org.jetbrains.kotlin.ir.backend.js.ic.* import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl import org.jetbrains.kotlin.ir.declarations.persistent.PersistentIrFactory @@ -205,7 +212,8 @@ abstract class BasicIrBoxTest( needsFullIrRuntime: Boolean, isMainModule: Boolean, skipDceDriven: Boolean, - splitPerModule: Boolean, + esModules: Boolean, + granularity: JsGenerationGranularity, propertyLazyInitialization: Boolean, safeExternalBoolean: Boolean, safeExternalBooleanDiagnostic: RuntimeDiagnostic?, @@ -213,7 +221,8 @@ abstract class BasicIrBoxTest( abiVersion: KotlinAbiVersion, incrementalCompilation: Boolean, recompile: Boolean, - icCache: MutableMap + icCache: MutableMap, + customTestModule: String?, ) { val filesToCompile = units.mapNotNull { (it as? TranslationUnit.SourceFile)?.file } @@ -299,38 +308,73 @@ abstract class BasicIrBoxTest( icCache = emptyMap() ) - if (!skipRegularMode) { -// val dirtyFilesToRecompile = if (recompile) { -// units.map { (it as TranslationUnit.SourceFile).file.virtualFilePath }.toSet() -// } else null - val dirtyFilesToRecompile: Set? = null - val compiledModule = compile( + val mainArguments = mainCallParameters.run { if (shouldBeGenerated()) arguments() else null } + fun compileToLoweredIr( + dceDriven: Boolean, + granularity: JsGenerationGranularity, + dirtyFilesToRecompile: Set? = null + ): LoweredIr = + compile( module, phaseConfig = phaseConfig, irFactory = IrFactoryImpl, - mainArguments = mainCallParameters.run { if (shouldBeGenerated()) arguments() else null }, exportedDeclarations = setOf(FqName.fromSegments(listOfNotNull(testPackage, testFunction))), - generateFullJs = true, - generateDceJs = runIrDce, - dceDriven = false, + dceDriven = dceDriven, es6mode = runEs6Mode, - multiModule = splitPerModule || perModule, propertyLazyInitialization = propertyLazyInitialization, + verifySignatures = !skipMangleVerification, lowerPerModule = lowerPerModule, safeExternalBoolean = safeExternalBoolean, safeExternalBooleanDiagnostic = safeExternalBooleanDiagnostic, - verifySignatures = !skipMangleVerification, + granularity = granularity, filesToLower = dirtyFilesToRecompile ) -// if (incrementalCompilation) { -// // TODO: enable once incremental js generation is done -// generateJsFromAst(klibPath, icCache.map { it.key to it.value.createModuleCache() }.toMap()) -// } + fun generateTestFile(outputDir: File) { + val moduleName = config.configuration[CommonConfigurationKeys.MODULE_NAME] + val esmTestFile = File(outputDir, "test.mjs") + logger.logFile("ES module test file", esmTestFile) + val defaultTestModule = + """ + import { box } from './${moduleName}/index.js'; + let res = box(); + if (res !== "OK") { + throw "Wrong result: " + String(res); + } + """.trimIndent() - val jsOutputFile = if (recompile) File(outputFile.parentFile, outputFile.nameWithoutExtension + "-recompiled.js") - else outputFile + esmTestFile.writeText(customTestModule ?: defaultTestModule) + } + + val options = JsGenerationOptions(generatePackageJson = true, generateTypeScriptDefinitions = generateDts) + + fun generateEsModules(ir: LoweredIr, outputDir: File, granularity: JsGenerationGranularity) { + outputDir.deleteRecursively() + generateEsModules(ir, jsOutputSink(outputDir), mainArguments = mainArguments, granularity = granularity, options = options) + generateTestFile(outputDir) + } + + fun generateOldModuleSystems( + ir: LoweredIr, + outputFile: File, + outputDceFile: File, + granularity: JsGenerationGranularity, + runDce: Boolean, + dirtyFilesToRecompile: Set? = null + ) { + outputFile.deleteRecursively() + + check(granularity != PER_FILE) { "Per file granularity is not supported for old module systems" } + val transformer = IrModuleToJsTransformer( + ir.context, + mainArguments, + fullJs = true, + dceJs = runDce, + multiModule = granularity == PER_MODULE, + relativeRequirePath = false + ) + val compiledModule: CompilerResult = transformer.generateModule(ir.allModules) val compiledOutput = if (dirtyFilesToRecompile != null) CompilationOutputs( """ @@ -343,9 +387,9 @@ abstract class BasicIrBoxTest( ) else compiledModule.outputs!! val compiledDCEOutput = if (dirtyFilesToRecompile != null) null else compiledModule.outputsAfterDce - compiledOutput.writeTo(jsOutputFile, config) + compiledOutput.writeTo(outputFile, config) - compiledDCEOutput?.writeTo(dceOutputFile, config) + compiledDCEOutput?.writeTo(outputDceFile, config) if (generateDts) { val dtsFile = outputFile.withReplacedExtensionOrNull("_v5.js", ".d.ts")!! @@ -356,26 +400,31 @@ abstract class BasicIrBoxTest( compiledOutput.jsProgram?.let { processJsProgram(it, units) } } - if (runIrPir) { - val compiledModule = compile( - module, - phaseConfig = phaseConfig, - irFactory = PersistentIrFactory(), - mainArguments = mainCallParameters.run { if (shouldBeGenerated()) arguments() else null }, - exportedDeclarations = setOf(FqName.fromSegments(listOfNotNull(testPackage, testFunction))), - generateFullJs = true, - generateDceJs = runIrDce, - dceDriven = true, - es6mode = runEs6Mode, - multiModule = splitPerModule || perModule, - propertyLazyInitialization = propertyLazyInitialization, - lowerPerModule = lowerPerModule, - safeExternalBoolean = safeExternalBoolean, - safeExternalBooleanDiagnostic = safeExternalBooleanDiagnostic, - verifySignatures = !skipMangleVerification, - ) - compiledModule.outputs!!.writeTo(pirOutputFile, config) - processJsProgram(compiledModule.outputs!!.jsProgram!!, units) + @Suppress("NAME_SHADOWING") + val granularity = if (perModule) PER_MODULE else granularity + + if (!skipRegularMode) { + val ir = compileToLoweredIr(dceDriven = false, granularity) + if (esModules) { + generateEsModules(ir, outputFile.esModulesSubDir, granularity) + if (runIrDce) { + eliminateDeadDeclarations(ir.allModules, ir.context) + generateEsModules(ir, dceOutputFile.esModulesSubDir, granularity) + } + } else { + val jsOutputFile = if (recompile) File(outputFile.parentFile, outputFile.nameWithoutExtension + "-recompiled.js") + else outputFile + generateOldModuleSystems(ir, jsOutputFile, dceOutputFile, granularity, runIrDce) + } + } + + if (runIrPir && !skipDceDriven) { + val ir = compileToLoweredIr(dceDriven = true, granularity) + if (esModules) { + generateEsModules(ir, pirOutputFile.esModulesSubDir, granularity) + } else { + generateOldModuleSystems(ir, pirOutputFile, pirOutputFile, granularity, false) + } } } } @@ -453,15 +502,19 @@ abstract class BasicIrBoxTest( needsFullIrRuntime, isMainModule, skipDceDriven = true, - splitPerModule = false, // TODO?? + granularity = WHOLE_PROGRAM, // TODO?? propertyLazyInitialization = true, safeExternalBoolean = false, safeExternalBooleanDiagnostic = null, skipMangleVerification = false, - KotlinAbiVersion.CURRENT, + abiVersion = KotlinAbiVersion.CURRENT, incrementalCompilation = true, recompile = true, - icCaches + icCache = icCaches, + + // TODO?? + customTestModule = null, + esModules = false, ) val cacheProvider = icCache.cacheProvider() @@ -481,6 +534,19 @@ abstract class BasicIrBoxTest( } } + 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 createIcCache( path: String, dirtyFiles: Collection?, @@ -561,8 +627,10 @@ abstract class BasicIrBoxTest( } } - private fun File.write(text: String) { parentFile.mkdirs() writeText(text) } + +val File.esModulesSubDir: File + get() = File(absolutePath + "_esm") diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/engines/SpiderMonkey.kt b/js/js.tests/test/org/jetbrains/kotlin/js/test/engines/SpiderMonkey.kt index 2a1db810565..bbfb49c772d 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/engines/SpiderMonkey.kt +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/engines/SpiderMonkey.kt @@ -7,8 +7,12 @@ package org.jetbrains.kotlin.js.test.engines import java.io.BufferedReader import java.io.InputStreamReader +import java.lang.Boolean.getBoolean import kotlin.test.fail + +val toolLogsEnabled: Boolean = getBoolean("kotlin.js.test.verbose") + class ExternalTool(val path: String) { fun run(vararg arguments: String) { val command = arrayOf(path, *arguments) @@ -17,7 +21,9 @@ class ExternalTool(val path: String) { .start() val commandString = command.joinToString(" ") { escapeShellArgument(it) } - println(commandString) + if (toolLogsEnabled) { + println(commandString) + } // Print process output val input = BufferedReader(InputStreamReader(process.inputStream)) diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/AbstractLegacyJsTypeScriptExportTest.kt b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/AbstractLegacyJsTypeScriptExportTest.kt deleted file mode 100644 index c95489f9a08..00000000000 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/AbstractLegacyJsTypeScriptExportTest.kt +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright 2010-2020 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.semantics - -import org.jetbrains.kotlin.js.test.BasicBoxTest - -abstract class AbstractLegacyJsTypeScriptExportTest : BasicBoxTest( - pathToTestDir = TEST_DATA_DIR_PATH + "typescript-export/", - testGroupOutputDirPrefix = "legacy-typescript-export/" -) \ No newline at end of file diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrBoxJsES6TestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrBoxJsES6TestGenerated.java index 021d11d45d3..0a857d33796 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrBoxJsES6TestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrBoxJsES6TestGenerated.java @@ -1587,6 +1587,494 @@ public class IrBoxJsES6TestGenerated extends AbstractIrBoxJsES6Test { } } + @TestMetadata("js/js.translator/testData/box/esModules") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class EsModules extends AbstractIrBoxJsES6Test { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR_ES6, testDataFilePath); + } + + public void testAllFilesPresentInEsModules() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS_IR_ES6, true); + } + + @TestMetadata("js/js.translator/testData/box/esModules/crossModuleRef") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class CrossModuleRef extends AbstractIrBoxJsES6Test { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR_ES6, testDataFilePath); + } + + public void testAllFilesPresentInCrossModuleRef() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules/crossModuleRef"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS_IR_ES6, true); + } + + @TestMetadata("callableObjectRef.kt") + public void testCallableObjectRef() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRef/callableObjectRef.kt"); + } + + @TestMetadata("constructor.kt") + public void testConstructor() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRef/constructor.kt"); + } + + @TestMetadata("inheritance.kt") + public void testInheritance() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRef/inheritance.kt"); + } + + @TestMetadata("inlineJsModule.kt") + public void testInlineJsModule() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRef/inlineJsModule.kt"); + } + + @TestMetadata("inlineJsModuleNonIdentifier.kt") + public void testInlineJsModuleNonIdentifier() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRef/inlineJsModuleNonIdentifier.kt"); + } + + @TestMetadata("inlineJsModulePackage.kt") + public void testInlineJsModulePackage() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRef/inlineJsModulePackage.kt"); + } + + @TestMetadata("inlineModule.kt") + public void testInlineModule() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRef/inlineModule.kt"); + } + + @TestMetadata("inlineModuleNonIndentifier.kt") + public void testInlineModuleNonIndentifier() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRef/inlineModuleNonIndentifier.kt"); + } + + @TestMetadata("lambda.kt") + public void testLambda() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRef/lambda.kt"); + } + + @TestMetadata("object.kt") + public void testObject() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRef/object.kt"); + } + + @TestMetadata("objectInInlineClosure.kt") + public void testObjectInInlineClosure() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRef/objectInInlineClosure.kt"); + } + + @TestMetadata("objectIsObject.kt") + public void testObjectIsObject() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRef/objectIsObject.kt"); + } + + @TestMetadata("topLevelExtension.kt") + public void testTopLevelExtension() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRef/topLevelExtension.kt"); + } + + @TestMetadata("topLevelFunction.kt") + public void testTopLevelFunction() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRef/topLevelFunction.kt"); + } + + @TestMetadata("topLevelMutableProperty.kt") + public void testTopLevelMutableProperty() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRef/topLevelMutableProperty.kt"); + } + + @TestMetadata("topLevelProperty.kt") + public void testTopLevelProperty() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRef/topLevelProperty.kt"); + } + } + + @TestMetadata("js/js.translator/testData/box/esModules/crossModuleRefPerFile") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class CrossModuleRefPerFile extends AbstractIrBoxJsES6Test { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR_ES6, testDataFilePath); + } + + public void testAllFilesPresentInCrossModuleRefPerFile() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules/crossModuleRefPerFile"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS_IR_ES6, true); + } + + @TestMetadata("callableObjectRef.kt") + public void testCallableObjectRef() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerFile/callableObjectRef.kt"); + } + + @TestMetadata("constructor.kt") + public void testConstructor() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerFile/constructor.kt"); + } + + @TestMetadata("inheritance.kt") + public void testInheritance() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerFile/inheritance.kt"); + } + + @TestMetadata("inlineModule.kt") + public void testInlineModule() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerFile/inlineModule.kt"); + } + + @TestMetadata("inlineModuleNonIndentifier.kt") + public void testInlineModuleNonIndentifier() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerFile/inlineModuleNonIndentifier.kt"); + } + + @TestMetadata("lambda.kt") + public void testLambda() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerFile/lambda.kt"); + } + + @TestMetadata("object.kt") + public void testObject() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerFile/object.kt"); + } + + @TestMetadata("objectInInlineClosure.kt") + public void testObjectInInlineClosure() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerFile/objectInInlineClosure.kt"); + } + + @TestMetadata("objectIsObject.kt") + public void testObjectIsObject() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerFile/objectIsObject.kt"); + } + + @TestMetadata("topLevelExtension.kt") + public void testTopLevelExtension() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerFile/topLevelExtension.kt"); + } + + @TestMetadata("topLevelFunction.kt") + public void testTopLevelFunction() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerFile/topLevelFunction.kt"); + } + + @TestMetadata("topLevelMutableProperty.kt") + public void testTopLevelMutableProperty() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerFile/topLevelMutableProperty.kt"); + } + + @TestMetadata("topLevelProperty.kt") + public void testTopLevelProperty() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerFile/topLevelProperty.kt"); + } + } + + @TestMetadata("js/js.translator/testData/box/esModules/crossModuleRefPerModule") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class CrossModuleRefPerModule extends AbstractIrBoxJsES6Test { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR_ES6, testDataFilePath); + } + + public void testAllFilesPresentInCrossModuleRefPerModule() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules/crossModuleRefPerModule"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS_IR_ES6, true); + } + + @TestMetadata("callableObjectRef.kt") + public void testCallableObjectRef() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerModule/callableObjectRef.kt"); + } + + @TestMetadata("constructor.kt") + public void testConstructor() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerModule/constructor.kt"); + } + + @TestMetadata("inheritance.kt") + public void testInheritance() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerModule/inheritance.kt"); + } + + @TestMetadata("inlineModule.kt") + public void testInlineModule() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerModule/inlineModule.kt"); + } + + @TestMetadata("inlineModuleNonIndentifier.kt") + public void testInlineModuleNonIndentifier() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerModule/inlineModuleNonIndentifier.kt"); + } + + @TestMetadata("lambda.kt") + public void testLambda() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerModule/lambda.kt"); + } + + @TestMetadata("object.kt") + public void testObject() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerModule/object.kt"); + } + + @TestMetadata("objectInInlineClosure.kt") + public void testObjectInInlineClosure() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerModule/objectInInlineClosure.kt"); + } + + @TestMetadata("objectIsObject.kt") + public void testObjectIsObject() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerModule/objectIsObject.kt"); + } + + @TestMetadata("topLevelExtension.kt") + public void testTopLevelExtension() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerModule/topLevelExtension.kt"); + } + + @TestMetadata("topLevelFunction.kt") + public void testTopLevelFunction() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerModule/topLevelFunction.kt"); + } + + @TestMetadata("topLevelMutableProperty.kt") + public void testTopLevelMutableProperty() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerModule/topLevelMutableProperty.kt"); + } + + @TestMetadata("topLevelProperty.kt") + public void testTopLevelProperty() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerModule/topLevelProperty.kt"); + } + } + + @TestMetadata("js/js.translator/testData/box/esModules/export") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Export extends AbstractIrBoxJsES6Test { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR_ES6, testDataFilePath); + } + + public void testAllFilesPresentInExport() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules/export"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS_IR_ES6, true); + } + + @TestMetadata("exportAllFile.kt") + public void testExportAllFile() throws Exception { + runTest("js/js.translator/testData/box/esModules/export/exportAllFile.kt"); + } + + @TestMetadata("nonIndetifierModuleName.kt") + public void testNonIndetifierModuleName() throws Exception { + runTest("js/js.translator/testData/box/esModules/export/nonIndetifierModuleName.kt"); + } + + @TestMetadata("overriddenChainNonExportIntermediate.kt") + public void testOverriddenChainNonExportIntermediate() throws Exception { + runTest("js/js.translator/testData/box/esModules/export/overriddenChainNonExportIntermediate.kt"); + } + + @TestMetadata("overriddenExternalMethodWithSameNameMethod.kt") + public void testOverriddenExternalMethodWithSameNameMethod() throws Exception { + runTest("js/js.translator/testData/box/esModules/export/overriddenExternalMethodWithSameNameMethod.kt"); + } + + @TestMetadata("overriddenExternalMethodWithSameStableNameMethod.kt") + public void testOverriddenExternalMethodWithSameStableNameMethod() throws Exception { + runTest("js/js.translator/testData/box/esModules/export/overriddenExternalMethodWithSameStableNameMethod.kt"); + } + + @TestMetadata("reservedModuleName.kt") + public void testReservedModuleName() throws Exception { + runTest("js/js.translator/testData/box/esModules/export/reservedModuleName.kt"); + } + } + + @TestMetadata("js/js.translator/testData/box/esModules/incremental") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Incremental extends AbstractIrBoxJsES6Test { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR_ES6, testDataFilePath); + } + + public void testAllFilesPresentInIncremental() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules/incremental"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS_IR_ES6, true); + } + + @TestMetadata("jsModule.kt") + public void testJsModule() throws Exception { + runTest("js/js.translator/testData/box/esModules/incremental/jsModule.kt"); + } + } + + @TestMetadata("js/js.translator/testData/box/esModules/inline") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Inline extends AbstractIrBoxJsES6Test { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR_ES6, testDataFilePath); + } + + public void testAllFilesPresentInInline() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules/inline"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS_IR_ES6, true); + } + + @TestMetadata("inlinedObjectLiteralIsCheck.kt") + public void testInlinedObjectLiteralIsCheck() throws Exception { + runTest("js/js.translator/testData/box/esModules/inline/inlinedObjectLiteralIsCheck.kt"); + } + } + + @TestMetadata("js/js.translator/testData/box/esModules/jsExport") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class JsExport extends AbstractIrBoxJsES6Test { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR_ES6, testDataFilePath); + } + + public void testAllFilesPresentInJsExport() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules/jsExport"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS_IR_ES6, true); + } + + @TestMetadata("dataClass.kt") + public void testDataClass() throws Exception { + runTest("js/js.translator/testData/box/esModules/jsExport/dataClass.kt"); + } + + @TestMetadata("exportedDefaultStub.kt") + public void testExportedDefaultStub() throws Exception { + runTest("js/js.translator/testData/box/esModules/jsExport/exportedDefaultStub.kt"); + } + + @TestMetadata("jsExportInClass.kt") + public void testJsExportInClass() throws Exception { + runTest("js/js.translator/testData/box/esModules/jsExport/jsExportInClass.kt"); + } + + @TestMetadata("recursiveExport.kt") + public void testRecursiveExport() throws Exception { + runTest("js/js.translator/testData/box/esModules/jsExport/recursiveExport.kt"); + } + } + + @TestMetadata("js/js.translator/testData/box/esModules/jsModule") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class JsModule extends AbstractIrBoxJsES6Test { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR_ES6, testDataFilePath); + } + + public void testAllFilesPresentInJsModule() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules/jsModule"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS_IR_ES6, true); + } + + @TestMetadata("externalClass.kt") + public void testExternalClass() throws Exception { + runTest("js/js.translator/testData/box/esModules/jsModule/externalClass.kt"); + } + + @TestMetadata("externalClassNameClash.kt") + public void testExternalClassNameClash() throws Exception { + runTest("js/js.translator/testData/box/esModules/jsModule/externalClassNameClash.kt"); + } + + @TestMetadata("externalClassWithDefaults.kt") + public void testExternalClassWithDefaults() throws Exception { + runTest("js/js.translator/testData/box/esModules/jsModule/externalClassWithDefaults.kt"); + } + + @TestMetadata("externalConstructor.kt") + public void testExternalConstructor() throws Exception { + runTest("js/js.translator/testData/box/esModules/jsModule/externalConstructor.kt"); + } + + @TestMetadata("externalFunction.kt") + public void testExternalFunction() throws Exception { + runTest("js/js.translator/testData/box/esModules/jsModule/externalFunction.kt"); + } + + @TestMetadata("externalFunctionNameClash.kt") + public void testExternalFunctionNameClash() throws Exception { + runTest("js/js.translator/testData/box/esModules/jsModule/externalFunctionNameClash.kt"); + } + + @TestMetadata("externalObject.kt") + public void testExternalObject() throws Exception { + runTest("js/js.translator/testData/box/esModules/jsModule/externalObject.kt"); + } + + @TestMetadata("externalPackage.kt") + public void testExternalPackage() throws Exception { + runTest("js/js.translator/testData/box/esModules/jsModule/externalPackage.kt"); + } + + @TestMetadata("externalPackageInDifferentFile.kt") + public void testExternalPackageInDifferentFile() throws Exception { + runTest("js/js.translator/testData/box/esModules/jsModule/externalPackageInDifferentFile.kt"); + } + + @TestMetadata("externalProperty.kt") + public void testExternalProperty() throws Exception { + runTest("js/js.translator/testData/box/esModules/jsModule/externalProperty.kt"); + } + + @TestMetadata("interfaces.kt") + public void testInterfaces() throws Exception { + runTest("js/js.translator/testData/box/esModules/jsModule/interfaces.kt"); + } + + @TestMetadata("topLevelVarargFun.kt") + public void testTopLevelVarargFun() throws Exception { + runTest("js/js.translator/testData/box/esModules/jsModule/topLevelVarargFun.kt"); + } + } + + @TestMetadata("js/js.translator/testData/box/esModules/jsName") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class JsName extends AbstractIrBoxJsES6Test { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR_ES6, testDataFilePath); + } + + public void testAllFilesPresentInJsName() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules/jsName"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS_IR_ES6, true); + } + + @TestMetadata("defaultJsName.kt") + public void testDefaultJsName() throws Exception { + runTest("js/js.translator/testData/box/esModules/jsName/defaultJsName.kt"); + } + + @TestMetadata("jsTopLevelClashes.kt") + public void testJsTopLevelClashes() throws Exception { + runTest("js/js.translator/testData/box/esModules/jsName/jsTopLevelClashes.kt"); + } + } + + @TestMetadata("js/js.translator/testData/box/esModules/native") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Native extends AbstractIrBoxJsES6Test { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR_ES6, testDataFilePath); + } + + public void testAllFilesPresentInNative() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules/native"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS_IR_ES6, true); + } + + @TestMetadata("inheritanceInNativeClass.kt") + public void testInheritanceInNativeClass() throws Exception { + runTest("js/js.translator/testData/box/esModules/native/inheritanceInNativeClass.kt"); + } + } + } + @TestMetadata("js/js.translator/testData/box/examples") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) @@ -2385,21 +2873,11 @@ public class IrBoxJsES6TestGenerated extends AbstractIrBoxJsES6Test { runTest("js/js.translator/testData/box/expression/function/manglingClashFunctionsAndClasses.kt"); } - @TestMetadata("manglingClashWithFunctionsWithoutParameters.kt") - public void testManglingClashWithFunctionsWithoutParameters() throws Exception { - runTest("js/js.translator/testData/box/expression/function/manglingClashWithFunctionsWithoutParameters.kt"); - } - @TestMetadata("manglingImportedFromObjectWithNI.kt") public void testManglingImportedFromObjectWithNI() throws Exception { runTest("js/js.translator/testData/box/expression/function/manglingImportedFromObjectWithNI.kt"); } - @TestMetadata("manglingStability.kt") - public void testManglingStability() throws Exception { - runTest("js/js.translator/testData/box/expression/function/manglingStability.kt"); - } - @TestMetadata("namedArguments.kt") public void testNamedArguments() throws Exception { runTest("js/js.translator/testData/box/expression/function/namedArguments.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java index 8623146aa1e..4db5c4ba63c 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java @@ -20145,11 +20145,6 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes runTest("compiler/testData/codegen/box/properties/lazyInitializationOrder.kt"); } - @TestMetadata("lazyInitializationPure.kt") - public void testLazyInitializationPure() throws Exception { - runTest("compiler/testData/codegen/box/properties/lazyInitializationPure.kt"); - } - @TestMetadata("lazyInitializationSplitPerModule.kt") public void testLazyInitializationSplitPerModule() throws Exception { runTest("compiler/testData/codegen/box/properties/lazyInitializationSplitPerModule.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrBoxJsTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrBoxJsTestGenerated.java index c205a5286f4..12ad7fdea54 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrBoxJsTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrBoxJsTestGenerated.java @@ -1587,6 +1587,494 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest { } } + @TestMetadata("js/js.translator/testData/box/esModules") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class EsModules extends AbstractIrBoxJsTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath); + } + + public void testAllFilesPresentInEsModules() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS_IR, true); + } + + @TestMetadata("js/js.translator/testData/box/esModules/crossModuleRef") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class CrossModuleRef extends AbstractIrBoxJsTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath); + } + + public void testAllFilesPresentInCrossModuleRef() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules/crossModuleRef"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS_IR, true); + } + + @TestMetadata("callableObjectRef.kt") + public void testCallableObjectRef() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRef/callableObjectRef.kt"); + } + + @TestMetadata("constructor.kt") + public void testConstructor() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRef/constructor.kt"); + } + + @TestMetadata("inheritance.kt") + public void testInheritance() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRef/inheritance.kt"); + } + + @TestMetadata("inlineJsModule.kt") + public void testInlineJsModule() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRef/inlineJsModule.kt"); + } + + @TestMetadata("inlineJsModuleNonIdentifier.kt") + public void testInlineJsModuleNonIdentifier() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRef/inlineJsModuleNonIdentifier.kt"); + } + + @TestMetadata("inlineJsModulePackage.kt") + public void testInlineJsModulePackage() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRef/inlineJsModulePackage.kt"); + } + + @TestMetadata("inlineModule.kt") + public void testInlineModule() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRef/inlineModule.kt"); + } + + @TestMetadata("inlineModuleNonIndentifier.kt") + public void testInlineModuleNonIndentifier() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRef/inlineModuleNonIndentifier.kt"); + } + + @TestMetadata("lambda.kt") + public void testLambda() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRef/lambda.kt"); + } + + @TestMetadata("object.kt") + public void testObject() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRef/object.kt"); + } + + @TestMetadata("objectInInlineClosure.kt") + public void testObjectInInlineClosure() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRef/objectInInlineClosure.kt"); + } + + @TestMetadata("objectIsObject.kt") + public void testObjectIsObject() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRef/objectIsObject.kt"); + } + + @TestMetadata("topLevelExtension.kt") + public void testTopLevelExtension() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRef/topLevelExtension.kt"); + } + + @TestMetadata("topLevelFunction.kt") + public void testTopLevelFunction() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRef/topLevelFunction.kt"); + } + + @TestMetadata("topLevelMutableProperty.kt") + public void testTopLevelMutableProperty() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRef/topLevelMutableProperty.kt"); + } + + @TestMetadata("topLevelProperty.kt") + public void testTopLevelProperty() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRef/topLevelProperty.kt"); + } + } + + @TestMetadata("js/js.translator/testData/box/esModules/crossModuleRefPerFile") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class CrossModuleRefPerFile extends AbstractIrBoxJsTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath); + } + + public void testAllFilesPresentInCrossModuleRefPerFile() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules/crossModuleRefPerFile"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS_IR, true); + } + + @TestMetadata("callableObjectRef.kt") + public void testCallableObjectRef() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerFile/callableObjectRef.kt"); + } + + @TestMetadata("constructor.kt") + public void testConstructor() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerFile/constructor.kt"); + } + + @TestMetadata("inheritance.kt") + public void testInheritance() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerFile/inheritance.kt"); + } + + @TestMetadata("inlineModule.kt") + public void testInlineModule() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerFile/inlineModule.kt"); + } + + @TestMetadata("inlineModuleNonIndentifier.kt") + public void testInlineModuleNonIndentifier() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerFile/inlineModuleNonIndentifier.kt"); + } + + @TestMetadata("lambda.kt") + public void testLambda() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerFile/lambda.kt"); + } + + @TestMetadata("object.kt") + public void testObject() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerFile/object.kt"); + } + + @TestMetadata("objectInInlineClosure.kt") + public void testObjectInInlineClosure() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerFile/objectInInlineClosure.kt"); + } + + @TestMetadata("objectIsObject.kt") + public void testObjectIsObject() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerFile/objectIsObject.kt"); + } + + @TestMetadata("topLevelExtension.kt") + public void testTopLevelExtension() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerFile/topLevelExtension.kt"); + } + + @TestMetadata("topLevelFunction.kt") + public void testTopLevelFunction() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerFile/topLevelFunction.kt"); + } + + @TestMetadata("topLevelMutableProperty.kt") + public void testTopLevelMutableProperty() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerFile/topLevelMutableProperty.kt"); + } + + @TestMetadata("topLevelProperty.kt") + public void testTopLevelProperty() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerFile/topLevelProperty.kt"); + } + } + + @TestMetadata("js/js.translator/testData/box/esModules/crossModuleRefPerModule") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class CrossModuleRefPerModule extends AbstractIrBoxJsTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath); + } + + public void testAllFilesPresentInCrossModuleRefPerModule() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules/crossModuleRefPerModule"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS_IR, true); + } + + @TestMetadata("callableObjectRef.kt") + public void testCallableObjectRef() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerModule/callableObjectRef.kt"); + } + + @TestMetadata("constructor.kt") + public void testConstructor() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerModule/constructor.kt"); + } + + @TestMetadata("inheritance.kt") + public void testInheritance() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerModule/inheritance.kt"); + } + + @TestMetadata("inlineModule.kt") + public void testInlineModule() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerModule/inlineModule.kt"); + } + + @TestMetadata("inlineModuleNonIndentifier.kt") + public void testInlineModuleNonIndentifier() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerModule/inlineModuleNonIndentifier.kt"); + } + + @TestMetadata("lambda.kt") + public void testLambda() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerModule/lambda.kt"); + } + + @TestMetadata("object.kt") + public void testObject() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerModule/object.kt"); + } + + @TestMetadata("objectInInlineClosure.kt") + public void testObjectInInlineClosure() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerModule/objectInInlineClosure.kt"); + } + + @TestMetadata("objectIsObject.kt") + public void testObjectIsObject() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerModule/objectIsObject.kt"); + } + + @TestMetadata("topLevelExtension.kt") + public void testTopLevelExtension() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerModule/topLevelExtension.kt"); + } + + @TestMetadata("topLevelFunction.kt") + public void testTopLevelFunction() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerModule/topLevelFunction.kt"); + } + + @TestMetadata("topLevelMutableProperty.kt") + public void testTopLevelMutableProperty() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerModule/topLevelMutableProperty.kt"); + } + + @TestMetadata("topLevelProperty.kt") + public void testTopLevelProperty() throws Exception { + runTest("js/js.translator/testData/box/esModules/crossModuleRefPerModule/topLevelProperty.kt"); + } + } + + @TestMetadata("js/js.translator/testData/box/esModules/export") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Export extends AbstractIrBoxJsTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath); + } + + public void testAllFilesPresentInExport() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules/export"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS_IR, true); + } + + @TestMetadata("exportAllFile.kt") + public void testExportAllFile() throws Exception { + runTest("js/js.translator/testData/box/esModules/export/exportAllFile.kt"); + } + + @TestMetadata("nonIndetifierModuleName.kt") + public void testNonIndetifierModuleName() throws Exception { + runTest("js/js.translator/testData/box/esModules/export/nonIndetifierModuleName.kt"); + } + + @TestMetadata("overriddenChainNonExportIntermediate.kt") + public void testOverriddenChainNonExportIntermediate() throws Exception { + runTest("js/js.translator/testData/box/esModules/export/overriddenChainNonExportIntermediate.kt"); + } + + @TestMetadata("overriddenExternalMethodWithSameNameMethod.kt") + public void testOverriddenExternalMethodWithSameNameMethod() throws Exception { + runTest("js/js.translator/testData/box/esModules/export/overriddenExternalMethodWithSameNameMethod.kt"); + } + + @TestMetadata("overriddenExternalMethodWithSameStableNameMethod.kt") + public void testOverriddenExternalMethodWithSameStableNameMethod() throws Exception { + runTest("js/js.translator/testData/box/esModules/export/overriddenExternalMethodWithSameStableNameMethod.kt"); + } + + @TestMetadata("reservedModuleName.kt") + public void testReservedModuleName() throws Exception { + runTest("js/js.translator/testData/box/esModules/export/reservedModuleName.kt"); + } + } + + @TestMetadata("js/js.translator/testData/box/esModules/incremental") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Incremental extends AbstractIrBoxJsTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath); + } + + public void testAllFilesPresentInIncremental() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules/incremental"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS_IR, true); + } + + @TestMetadata("jsModule.kt") + public void testJsModule() throws Exception { + runTest("js/js.translator/testData/box/esModules/incremental/jsModule.kt"); + } + } + + @TestMetadata("js/js.translator/testData/box/esModules/inline") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Inline extends AbstractIrBoxJsTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath); + } + + public void testAllFilesPresentInInline() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules/inline"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS_IR, true); + } + + @TestMetadata("inlinedObjectLiteralIsCheck.kt") + public void testInlinedObjectLiteralIsCheck() throws Exception { + runTest("js/js.translator/testData/box/esModules/inline/inlinedObjectLiteralIsCheck.kt"); + } + } + + @TestMetadata("js/js.translator/testData/box/esModules/jsExport") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class JsExport extends AbstractIrBoxJsTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath); + } + + public void testAllFilesPresentInJsExport() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules/jsExport"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS_IR, true); + } + + @TestMetadata("dataClass.kt") + public void testDataClass() throws Exception { + runTest("js/js.translator/testData/box/esModules/jsExport/dataClass.kt"); + } + + @TestMetadata("exportedDefaultStub.kt") + public void testExportedDefaultStub() throws Exception { + runTest("js/js.translator/testData/box/esModules/jsExport/exportedDefaultStub.kt"); + } + + @TestMetadata("jsExportInClass.kt") + public void testJsExportInClass() throws Exception { + runTest("js/js.translator/testData/box/esModules/jsExport/jsExportInClass.kt"); + } + + @TestMetadata("recursiveExport.kt") + public void testRecursiveExport() throws Exception { + runTest("js/js.translator/testData/box/esModules/jsExport/recursiveExport.kt"); + } + } + + @TestMetadata("js/js.translator/testData/box/esModules/jsModule") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class JsModule extends AbstractIrBoxJsTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath); + } + + public void testAllFilesPresentInJsModule() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules/jsModule"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS_IR, true); + } + + @TestMetadata("externalClass.kt") + public void testExternalClass() throws Exception { + runTest("js/js.translator/testData/box/esModules/jsModule/externalClass.kt"); + } + + @TestMetadata("externalClassNameClash.kt") + public void testExternalClassNameClash() throws Exception { + runTest("js/js.translator/testData/box/esModules/jsModule/externalClassNameClash.kt"); + } + + @TestMetadata("externalClassWithDefaults.kt") + public void testExternalClassWithDefaults() throws Exception { + runTest("js/js.translator/testData/box/esModules/jsModule/externalClassWithDefaults.kt"); + } + + @TestMetadata("externalConstructor.kt") + public void testExternalConstructor() throws Exception { + runTest("js/js.translator/testData/box/esModules/jsModule/externalConstructor.kt"); + } + + @TestMetadata("externalFunction.kt") + public void testExternalFunction() throws Exception { + runTest("js/js.translator/testData/box/esModules/jsModule/externalFunction.kt"); + } + + @TestMetadata("externalFunctionNameClash.kt") + public void testExternalFunctionNameClash() throws Exception { + runTest("js/js.translator/testData/box/esModules/jsModule/externalFunctionNameClash.kt"); + } + + @TestMetadata("externalObject.kt") + public void testExternalObject() throws Exception { + runTest("js/js.translator/testData/box/esModules/jsModule/externalObject.kt"); + } + + @TestMetadata("externalPackage.kt") + public void testExternalPackage() throws Exception { + runTest("js/js.translator/testData/box/esModules/jsModule/externalPackage.kt"); + } + + @TestMetadata("externalPackageInDifferentFile.kt") + public void testExternalPackageInDifferentFile() throws Exception { + runTest("js/js.translator/testData/box/esModules/jsModule/externalPackageInDifferentFile.kt"); + } + + @TestMetadata("externalProperty.kt") + public void testExternalProperty() throws Exception { + runTest("js/js.translator/testData/box/esModules/jsModule/externalProperty.kt"); + } + + @TestMetadata("interfaces.kt") + public void testInterfaces() throws Exception { + runTest("js/js.translator/testData/box/esModules/jsModule/interfaces.kt"); + } + + @TestMetadata("topLevelVarargFun.kt") + public void testTopLevelVarargFun() throws Exception { + runTest("js/js.translator/testData/box/esModules/jsModule/topLevelVarargFun.kt"); + } + } + + @TestMetadata("js/js.translator/testData/box/esModules/jsName") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class JsName extends AbstractIrBoxJsTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath); + } + + public void testAllFilesPresentInJsName() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules/jsName"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS_IR, true); + } + + @TestMetadata("defaultJsName.kt") + public void testDefaultJsName() throws Exception { + runTest("js/js.translator/testData/box/esModules/jsName/defaultJsName.kt"); + } + + @TestMetadata("jsTopLevelClashes.kt") + public void testJsTopLevelClashes() throws Exception { + runTest("js/js.translator/testData/box/esModules/jsName/jsTopLevelClashes.kt"); + } + } + + @TestMetadata("js/js.translator/testData/box/esModules/native") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Native extends AbstractIrBoxJsTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath); + } + + public void testAllFilesPresentInNative() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules/native"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS_IR, true); + } + + @TestMetadata("inheritanceInNativeClass.kt") + public void testInheritanceInNativeClass() throws Exception { + runTest("js/js.translator/testData/box/esModules/native/inheritanceInNativeClass.kt"); + } + } + } + @TestMetadata("js/js.translator/testData/box/examples") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) @@ -2385,21 +2873,11 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest { runTest("js/js.translator/testData/box/expression/function/manglingClashFunctionsAndClasses.kt"); } - @TestMetadata("manglingClashWithFunctionsWithoutParameters.kt") - public void testManglingClashWithFunctionsWithoutParameters() throws Exception { - runTest("js/js.translator/testData/box/expression/function/manglingClashWithFunctionsWithoutParameters.kt"); - } - @TestMetadata("manglingImportedFromObjectWithNI.kt") public void testManglingImportedFromObjectWithNI() throws Exception { runTest("js/js.translator/testData/box/expression/function/manglingImportedFromObjectWithNI.kt"); } - @TestMetadata("manglingStability.kt") - public void testManglingStability() throws Exception { - runTest("js/js.translator/testData/box/expression/function/manglingStability.kt"); - } - @TestMetadata("namedArguments.kt") public void testNamedArguments() throws Exception { runTest("js/js.translator/testData/box/expression/function/namedArguments.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index eaed052c3b5..77f863c2fc0 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -19551,11 +19551,6 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/properties/lazyInitializationOrder.kt"); } - @TestMetadata("lazyInitializationPure.kt") - public void testLazyInitializationPure() throws Exception { - runTest("compiler/testData/codegen/box/properties/lazyInitializationPure.kt"); - } - @TestMetadata("lazyInitializationSplitPerModule.kt") public void testLazyInitializationSplitPerModule() throws Exception { runTest("compiler/testData/codegen/box/properties/lazyInitializationSplitPerModule.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java index c945a85e90b..a8f77ac27ee 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java @@ -1592,6 +1592,159 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest { } } + @TestMetadata("js/js.translator/testData/box/esModules") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class EsModules extends AbstractBoxJsTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath); + } + + public void testAllFilesPresentInEsModules() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS, true); + } + + @TestMetadata("js/js.translator/testData/box/esModules/crossModuleRef") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class CrossModuleRef extends AbstractBoxJsTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath); + } + + public void testAllFilesPresentInCrossModuleRef() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules/crossModuleRef"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS, true); + } + } + + @TestMetadata("js/js.translator/testData/box/esModules/crossModuleRefPerFile") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class CrossModuleRefPerFile extends AbstractBoxJsTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath); + } + + public void testAllFilesPresentInCrossModuleRefPerFile() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules/crossModuleRefPerFile"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS, true); + } + } + + @TestMetadata("js/js.translator/testData/box/esModules/crossModuleRefPerModule") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class CrossModuleRefPerModule extends AbstractBoxJsTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath); + } + + public void testAllFilesPresentInCrossModuleRefPerModule() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules/crossModuleRefPerModule"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS, true); + } + } + + @TestMetadata("js/js.translator/testData/box/esModules/export") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Export extends AbstractBoxJsTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath); + } + + 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); + } + + @TestMetadata("overriddenExternalMethodWithSameStableNameMethod.kt") + public void testOverriddenExternalMethodWithSameStableNameMethod() throws Exception { + runTest("js/js.translator/testData/box/esModules/export/overriddenExternalMethodWithSameStableNameMethod.kt"); + } + + @TestMetadata("reservedModuleName.kt") + public void testReservedModuleName() throws Exception { + runTest("js/js.translator/testData/box/esModules/export/reservedModuleName.kt"); + } + } + + @TestMetadata("js/js.translator/testData/box/esModules/incremental") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Incremental extends AbstractBoxJsTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath); + } + + public void testAllFilesPresentInIncremental() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules/incremental"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS, true); + } + } + + @TestMetadata("js/js.translator/testData/box/esModules/inline") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Inline extends AbstractBoxJsTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath); + } + + public void testAllFilesPresentInInline() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules/inline"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS, true); + } + } + + @TestMetadata("js/js.translator/testData/box/esModules/jsExport") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class JsExport extends AbstractBoxJsTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath); + } + + public void testAllFilesPresentInJsExport() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules/jsExport"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS, true); + } + } + + @TestMetadata("js/js.translator/testData/box/esModules/jsModule") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class JsModule extends AbstractBoxJsTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath); + } + + public void testAllFilesPresentInJsModule() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules/jsModule"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS, true); + } + } + + @TestMetadata("js/js.translator/testData/box/esModules/jsName") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class JsName extends AbstractBoxJsTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath); + } + + public void testAllFilesPresentInJsName() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules/jsName"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS, true); + } + } + + @TestMetadata("js/js.translator/testData/box/esModules/native") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Native extends AbstractBoxJsTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath); + } + + public void testAllFilesPresentInNative() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules/native"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS, true); + } + } + } + @TestMetadata("js/js.translator/testData/box/examples") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/LegacyJsTypeScriptExportTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/LegacyJsTypeScriptExportTestGenerated.java deleted file mode 100644 index b9b0061f6b0..00000000000 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/LegacyJsTypeScriptExportTestGenerated.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright 2010-2021 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.semantics; - -import com.intellij.testFramework.TestDataPath; -import org.jetbrains.kotlin.test.JUnit3RunnerWithInners; -import org.jetbrains.kotlin.test.KotlinTestUtils; -import org.jetbrains.kotlin.test.util.KtTestUtil; -import org.jetbrains.kotlin.test.TargetBackend; -import org.jetbrains.kotlin.test.TestMetadata; -import org.junit.runner.RunWith; - -import java.io.File; -import java.util.regex.Pattern; - -/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ -@SuppressWarnings("all") -@TestMetadata("js/js.translator/testData/typescript-export") -@TestDataPath("$PROJECT_ROOT") -@RunWith(JUnit3RunnerWithInners.class) -public class LegacyJsTypeScriptExportTestGenerated extends AbstractLegacyJsTypeScriptExportTest { - private void runTest(String testDataFilePath) throws Exception { - KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath); - } - - public void testAllFilesPresentInTypescript_export() throws Exception { - KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/typescript-export"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS, true); - } - - @TestMetadata("js/js.translator/testData/typescript-export/constructors") - @TestDataPath("$PROJECT_ROOT") - @RunWith(JUnit3RunnerWithInners.class) - public static class Constructors extends AbstractLegacyJsTypeScriptExportTest { - private void runTest(String testDataFilePath) throws Exception { - KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath); - } - - public void testAllFilesPresentInConstructors() throws Exception { - KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/typescript-export/constructors"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS, true); - } - } - - @TestMetadata("js/js.translator/testData/typescript-export/declarations") - @TestDataPath("$PROJECT_ROOT") - @RunWith(JUnit3RunnerWithInners.class) - public static class Declarations extends AbstractLegacyJsTypeScriptExportTest { - private void runTest(String testDataFilePath) throws Exception { - KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath); - } - - public void testAllFilesPresentInDeclarations() throws Exception { - KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/typescript-export/declarations"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS, true); - } - - @TestMetadata("declarations.kt") - public void testDeclarations() throws Exception { - runTest("js/js.translator/testData/typescript-export/declarations/declarations.kt"); - } - } - - @TestMetadata("js/js.translator/testData/typescript-export/inheritance") - @TestDataPath("$PROJECT_ROOT") - @RunWith(JUnit3RunnerWithInners.class) - public static class Inheritance extends AbstractLegacyJsTypeScriptExportTest { - private void runTest(String testDataFilePath) throws Exception { - KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath); - } - - public void testAllFilesPresentInInheritance() throws Exception { - KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/typescript-export/inheritance"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS, true); - } - - @TestMetadata("inheritance.kt") - public void testInheritance() throws Exception { - runTest("js/js.translator/testData/typescript-export/inheritance/inheritance.kt"); - } - } - - @TestMetadata("js/js.translator/testData/typescript-export/moduleSystems") - @TestDataPath("$PROJECT_ROOT") - @RunWith(JUnit3RunnerWithInners.class) - public static class ModuleSystems extends AbstractLegacyJsTypeScriptExportTest { - private void runTest(String testDataFilePath) throws Exception { - KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath); - } - - public void testAllFilesPresentInModuleSystems() throws Exception { - KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/typescript-export/moduleSystems"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS, true); - } - - @TestMetadata("commonjs.kt") - public void testCommonjs() throws Exception { - runTest("js/js.translator/testData/typescript-export/moduleSystems/commonjs.kt"); - } - - @TestMetadata("plain.kt") - public void testPlain() throws Exception { - runTest("js/js.translator/testData/typescript-export/moduleSystems/plain.kt"); - } - - @TestMetadata("umd.kt") - public void testUmd() throws Exception { - runTest("js/js.translator/testData/typescript-export/moduleSystems/umd.kt"); - } - } - - @TestMetadata("js/js.translator/testData/typescript-export/namespaces") - @TestDataPath("$PROJECT_ROOT") - @RunWith(JUnit3RunnerWithInners.class) - public static class Namespaces extends AbstractLegacyJsTypeScriptExportTest { - private void runTest(String testDataFilePath) throws Exception { - KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath); - } - - public void testAllFilesPresentInNamespaces() throws Exception { - KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/typescript-export/namespaces"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS, true); - } - - @TestMetadata("namespaces.kt") - public void testNamespaces() throws Exception { - runTest("js/js.translator/testData/typescript-export/namespaces/namespaces.kt"); - } - } - - @TestMetadata("js/js.translator/testData/typescript-export/primitives") - @TestDataPath("$PROJECT_ROOT") - @RunWith(JUnit3RunnerWithInners.class) - public static class Primitives extends AbstractLegacyJsTypeScriptExportTest { - private void runTest(String testDataFilePath) throws Exception { - KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath); - } - - public void testAllFilesPresentInPrimitives() throws Exception { - KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/typescript-export/primitives"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS, true); - } - - @TestMetadata("primitives.kt") - public void testPrimitives() throws Exception { - runTest("js/js.translator/testData/typescript-export/primitives/primitives.kt"); - } - } - - @TestMetadata("js/js.translator/testData/typescript-export/selectiveExport") - @TestDataPath("$PROJECT_ROOT") - @RunWith(JUnit3RunnerWithInners.class) - public static class SelectiveExport extends AbstractLegacyJsTypeScriptExportTest { - private void runTest(String testDataFilePath) throws Exception { - KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath); - } - - public void testAllFilesPresentInSelectiveExport() throws Exception { - KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/typescript-export/selectiveExport"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS, true); - } - - @TestMetadata("selectiveExport.kt") - public void testSelectiveExport() throws Exception { - runTest("js/js.translator/testData/typescript-export/selectiveExport/selectiveExport.kt"); - } - } - - @TestMetadata("js/js.translator/testData/typescript-export/visibility") - @TestDataPath("$PROJECT_ROOT") - @RunWith(JUnit3RunnerWithInners.class) - public static class Visibility extends AbstractLegacyJsTypeScriptExportTest { - private void runTest(String testDataFilePath) throws Exception { - KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath); - } - - public void testAllFilesPresentInVisibility() throws Exception { - KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/typescript-export/visibility"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS, true); - } - - @TestMetadata("visibility.kt") - public void testVisibility() throws Exception { - runTest("js/js.translator/testData/typescript-export/visibility/visibility.kt"); - } - } -} diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/general/ModuleWrapperTranslation.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/general/ModuleWrapperTranslation.kt index b1dec94e724..28d2e6a6f22 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/general/ModuleWrapperTranslation.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/general/ModuleWrapperTranslation.kt @@ -31,6 +31,7 @@ object ModuleWrapperTranslation { ModuleKind.COMMON_JS -> wrapCommonJs(function, importedModules, program) ModuleKind.UMD -> wrapUmd(moduleId, function, importedModules, program) ModuleKind.PLAIN -> wrapPlain(moduleId, function, importedModules, program) + ModuleKind.ES -> error("ES modules are not supported in legacy wrapper") } } diff --git a/js/js.translator/testData/box/esModules/crossModuleRef/callableObjectRef.kt b/js/js.translator/testData/box/esModules/crossModuleRef/callableObjectRef.kt new file mode 100644 index 00000000000..c8b462c7f59 --- /dev/null +++ b/js/js.translator/testData/box/esModules/crossModuleRef/callableObjectRef.kt @@ -0,0 +1,27 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +// MODULE: lib +// FILE: lib.kt +package lib + +object O { + operator fun invoke() = "OK" +} + +inline fun callO() = O() + +// MODULE: main(lib) +// FILE: main.kt +package main + +import lib.* + +fun box(): String { + val a = O() + if (a != "OK") return "fail: simple: $a" + + val b = callO() + if (b != "OK") return "fail: inline: $a" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/crossModuleRef/constructor.kt b/js/js.translator/testData/box/esModules/crossModuleRef/constructor.kt new file mode 100644 index 00000000000..abd13beed3b --- /dev/null +++ b/js/js.translator/testData/box/esModules/crossModuleRef/constructor.kt @@ -0,0 +1,72 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +// MODULE: lib +// FILE: lib.kt +package lib + +class A(val x: Int) { + constructor(a: Int, b: Int) : this(a + b) +} + +external class B(x: Int) { + constructor(a: Int, b: Int) + + val x: Int +} + +// TODO: may be useful after implementing local classes in inline functions +/* +inline fun foo(p: Int, q: Int, r: Int): Pair { + class C(val x : Int) { + constructor(a: Int, b: Int) : this(a + b) + } + return Pair(C(p).x, C(q, r).x) +} +*/ + +inline fun callPrimaryConstructor(x: Int) = A(x).x + +inline fun callSecondaryConstructor(x: Int, y: Int) = A(x, y).x + +// FILE: lib.js + +function B(x, y) { + this.x = x; + if (typeof y !== 'undefined') { + this.x += y; + } +} + +// MODULE: main(lib) +// FILE: main.kt +package main + +import lib.* + +fun box(): String { + val a = A(23).x + if (a != 23) return "fail: primary constructor: $a" + + val b = A(40, 2).x + if (b != 42) return "fail: secondary constructor: $b" + + val c = B(99).x + if (c != 99) return "fail: native primary constructor: $c" + + val d = B(100, 11).x + if (d != 111) return "fail: native secondary constructor: $d" + + /* + val (e, f) = foo(123, 320, 1) + if (e != 123) return "fail: local primary constructor: $e" + if (f != 321) return "fail: local secondary constructor: $f" + */ + + val g = callPrimaryConstructor(55) + if (g != 55) return "fail: primary constructor from inline function: $g" + + val h = callSecondaryConstructor(990, 9) + if (h != 999) return "fail: secondary constructor from inline function: $h" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/crossModuleRef/inheritance.kt b/js/js.translator/testData/box/esModules/crossModuleRef/inheritance.kt new file mode 100644 index 00000000000..b709cfb6947 --- /dev/null +++ b/js/js.translator/testData/box/esModules/crossModuleRef/inheritance.kt @@ -0,0 +1,27 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +// MODULE: lib +// FILE: lib.kt + +package lib + +open class A { + fun foo() = 23 +} + +// MODULE: main(lib) +// FILE: main.kt + +package main + +import lib.A + +class B : A() { + fun bar() = foo() + 1 +} + +fun box(): String { + val result = B().bar() + if (result != 24) return "fail: $result" + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/crossModuleRef/inlineJsModule.kt b/js/js.translator/testData/box/esModules/crossModuleRef/inlineJsModule.kt new file mode 100644 index 00000000000..7973f872dd3 --- /dev/null +++ b/js/js.translator/testData/box/esModules/crossModuleRef/inlineJsModule.kt @@ -0,0 +1,20 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +// FILE: lib1.mjs +export default function() { + return "OK"; +} + +// MODULE: lib2 +// FILE: lib2.kt +@JsModule("./lib1.mjs") +external fun foo(): String + +// MODULE: lib3(lib2) +// FILE: lib3.kt +inline fun bar() = foo() + +// MODULE: main(lib3) +// FILE: main.kt + +fun box() = bar() \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/crossModuleRef/inlineJsModuleNonIdentifier.kt b/js/js.translator/testData/box/esModules/crossModuleRef/inlineJsModuleNonIdentifier.kt new file mode 100644 index 00000000000..060803f0aed --- /dev/null +++ b/js/js.translator/testData/box/esModules/crossModuleRef/inlineJsModuleNonIdentifier.kt @@ -0,0 +1,20 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +// FILE: lib-1.mjs +export default function foo() { + return "OK"; +} + +// MODULE: lib2 +// FILE: lib2.kt +@JsModule("./lib-1.mjs") +external fun foo(): String + +// MODULE: lib3(lib2) +// FILE: lib3.kt +inline fun bar() = foo() + +// MODULE: main(lib3) +// FILE: main.kt + +fun box() = bar() \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/crossModuleRef/inlineJsModulePackage.kt b/js/js.translator/testData/box/esModules/crossModuleRef/inlineJsModulePackage.kt new file mode 100644 index 00000000000..cead6a639c0 --- /dev/null +++ b/js/js.translator/testData/box/esModules/crossModuleRef/inlineJsModulePackage.kt @@ -0,0 +1,21 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +// FILE: lib1.mjs +export function foo() { + return "OK"; +} + +// MODULE: lib2 +// FILE: lib2.kt +@file:JsModule("./lib1.mjs") + +external fun foo(): String + +// MODULE: lib3(lib2) +// FILE: lib3.kt +inline fun bar() = foo() + +// MODULE: main(lib3) +// FILE: main.kt + +fun box() = bar() \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/crossModuleRef/inlineModule.kt b/js/js.translator/testData/box/esModules/crossModuleRef/inlineModule.kt new file mode 100644 index 00000000000..2f867720562 --- /dev/null +++ b/js/js.translator/testData/box/esModules/crossModuleRef/inlineModule.kt @@ -0,0 +1,16 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +// MODULE: lib1 +// FILE: lib1.kt + +fun foo() = "OK" + +// MODULE: lib2(lib1) +// FILE: lib2.kt + +inline fun bar() = foo() + +// MODULE: main(lib1, lib2) +// FILE: main.kt + +fun box() = bar() \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/crossModuleRef/inlineModuleNonIndentifier.kt b/js/js.translator/testData/box/esModules/crossModuleRef/inlineModuleNonIndentifier.kt new file mode 100644 index 00000000000..41bbe12a982 --- /dev/null +++ b/js/js.translator/testData/box/esModules/crossModuleRef/inlineModuleNonIndentifier.kt @@ -0,0 +1,16 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +// MODULE: 1 +// FILE: lib1.kt + +fun foo() = "OK" + +// MODULE: 2(1) +// FILE: lib2.kt + +inline fun bar() = foo() + +// MODULE: main(2) +// FILE: main.kt + +fun box() = bar() \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/crossModuleRef/lambda.kt b/js/js.translator/testData/box/esModules/crossModuleRef/lambda.kt new file mode 100644 index 00000000000..ac19600bfef --- /dev/null +++ b/js/js.translator/testData/box/esModules/crossModuleRef/lambda.kt @@ -0,0 +1,19 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +// MODULE: lib +// FILE: lib.kt +package lib + +fun bar(f: () -> String) = f() + +inline fun foo(): String { + return bar { "OK" } +} + +// MODULE: main(lib) +// FILE: main.kt +package main + +import lib.* + +fun box() = foo() \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/crossModuleRef/object.kt b/js/js.translator/testData/box/esModules/crossModuleRef/object.kt new file mode 100644 index 00000000000..c7137adea11 --- /dev/null +++ b/js/js.translator/testData/box/esModules/crossModuleRef/object.kt @@ -0,0 +1,37 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +// MODULE: lib +// FILE: lib.kt +package lib + +var log = "" + +object O { + init { + log += "O.init;" + } + + fun result() = "OK" +} + +fun getResult(): String { + log += "before;" + val result = O.result() + log += "after;" + return result +} + +// MODULE: main(lib) +// FILE: main.kt +package main + +import lib.* + +fun box(): String { + val result = getResult() + if (result != "OK") return "fail: unexpected result: $result" + + if (log != "before;O.init;after;") return "fail: wrong evaluation order: $log" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/crossModuleRef/objectInInlineClosure.kt b/js/js.translator/testData/box/esModules/crossModuleRef/objectInInlineClosure.kt new file mode 100644 index 00000000000..8fcfa773925 --- /dev/null +++ b/js/js.translator/testData/box/esModules/crossModuleRef/objectInInlineClosure.kt @@ -0,0 +1,27 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +// MODULE: lib +// FILE: lib.kt +package lib + +object O { + val result = "OK" + + inline fun foo(): String { + val o = object { + fun bar() = O + } + return fetch(o.bar()) + } +} + +fun fetch(o: O) = o.result + + +// MODULE: main(lib) +// FILE: main.kt +package main + +import lib.* + +fun box() = O.foo() \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/crossModuleRef/objectIsObject.kt b/js/js.translator/testData/box/esModules/crossModuleRef/objectIsObject.kt new file mode 100644 index 00000000000..448c4ec323b --- /dev/null +++ b/js/js.translator/testData/box/esModules/crossModuleRef/objectIsObject.kt @@ -0,0 +1,21 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +// MODULE: lib +// FILE: lib.kt +package lib + +object O + +// MODULE: main(lib) +// FILE: main.kt +package main + +import lib.* + +fun box(): String { + var o: Any = O + if (o !is O) return "fail1" + if (!(o is O)) return "fail2" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/crossModuleRef/topLevelExtension.kt b/js/js.translator/testData/box/esModules/crossModuleRef/topLevelExtension.kt new file mode 100644 index 00000000000..ed3547b1460 --- /dev/null +++ b/js/js.translator/testData/box/esModules/crossModuleRef/topLevelExtension.kt @@ -0,0 +1,44 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +// MODULE: lib +// FILE: lib.kt + +package lib + +class A(val x: Int) + +fun A.foo() = 23 + x + +inline fun A.baz() = 99 + x + +inline fun A.callFoo() = foo() + +inline fun A.buzz(): Int { + val o = object { + fun f() = 111 + x + } + return o.f() +} + +// MODULE: main(lib) +// FILE: main.kt + +package main + +import lib.* + +fun box(): String { + val a = A(1).foo() + if (a != 24) return "fail: simple function: $a" + + val c = A(1).baz() + if (c != 100) return "fail: inline function: $c" + + val d = A(1).buzz() + if (d != 112) return "fail: inline function with object expression: $d" + + val e = A(2).callFoo() + if (e != 25) return "fail: inline function calling another function: $e" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/crossModuleRef/topLevelFunction.kt b/js/js.translator/testData/box/esModules/crossModuleRef/topLevelFunction.kt new file mode 100644 index 00000000000..d5c87041d1e --- /dev/null +++ b/js/js.translator/testData/box/esModules/crossModuleRef/topLevelFunction.kt @@ -0,0 +1,51 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +// MODULE: lib +// FILE: lib.kt + +package lib + +fun foo() = 23 + +external fun bar(): Int = definedExternally + +inline fun baz() = 99 + +inline fun callFoo() = foo() + +inline fun buzz(): Int { + val o = object { + fun f() = 111 + } + return o.f() +} + +// FILE: lib.js + +function bar() { + return 42; +} + +// MODULE: main(lib) +// FILE: main.kt + +package main + +fun box(): String { + val a = lib.foo() + if (a != 23) return "fail: simple function: $a" + + val b = lib.bar() + if (b != 42) return "fail: native function: $b" + + val c = lib.baz() + if (c != 99) return "fail: inline function: $c" + + val d = lib.buzz() + if (d != 111) return "fail: inline function with object expression: $d" + + val e = lib.callFoo() + if (e != 23) return "fail: inline function calling another function: $e" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/crossModuleRef/topLevelMutableProperty.kt b/js/js.translator/testData/box/esModules/crossModuleRef/topLevelMutableProperty.kt new file mode 100644 index 00000000000..a43bbd4fe50 --- /dev/null +++ b/js/js.translator/testData/box/esModules/crossModuleRef/topLevelMutableProperty.kt @@ -0,0 +1,38 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +// MODULE: lib +// FILE: lib.kt +package lib + +var foo = 23 + +var bar: Int = 42 + get() = field + set(value) { + field = value + } + +@JsName("faz") var baz = 99 + +// MODULE: main(lib) +// FILE: lib.kt +package main + +import lib.* + +fun box(): String { + if (foo != 23) return "fail: simple property initial value: $foo" + foo = 24 + if (foo != 24) return "fail: simple property new value: $foo" + + if (bar != 42) return "fail: property with accessor initial value: $bar" + bar = 43 + if (bar != 43) return "fail: property with accessor new value: $bar" + + if (baz != 99) return "fail: renamed property initial value: $baz" + baz = 100 + if (baz != 100) return "fail: renamed property new value: $baz" + + + return "OK" +} diff --git a/js/js.translator/testData/box/esModules/crossModuleRef/topLevelProperty.kt b/js/js.translator/testData/box/esModules/crossModuleRef/topLevelProperty.kt new file mode 100644 index 00000000000..2346c6874fb --- /dev/null +++ b/js/js.translator/testData/box/esModules/crossModuleRef/topLevelProperty.kt @@ -0,0 +1,48 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +// MODULE: lib +// FILE: lib.kt +package lib + +val foo = 23 + +val boo: Int + get() = 42 + +external val bar: Int = definedExternally + +external val far: Int + get() = definedExternally + +// TODO: annotations like this are not serialized properly. Uncomment after KT-14529 gets fixed +/* +val fuzz: Int + @JsName("getBuzz") get() = 55 + */ + +inline fun fetchFoo() = foo + +@JsName("fee") +val tee = 2525 + +// FILE: lib.js + +var bar = 99 +var far = 111 + +// MODULE: main(lib) +// FILE: lib.kt +package main + +import lib.* + +fun box(): String { + if (foo != 23) return "fail: simple property: $foo" + if (boo != 42) return "fail: property with accessor: $boo" + if (bar != 99) return "fail: native property: $bar" + if (far != 111) return "fail: native property with accessor: $far" + //if (fuzz != 55) return "fail: property with JsName on accessor: $fuzz" + if (tee != 2525) return "fail: native property with JsName: $tee" + + return "OK" +} diff --git a/js/js.translator/testData/box/esModules/crossModuleRefPerFile/callableObjectRef.kt b/js/js.translator/testData/box/esModules/crossModuleRefPerFile/callableObjectRef.kt new file mode 100644 index 00000000000..bd1e137e96f --- /dev/null +++ b/js/js.translator/testData/box/esModules/crossModuleRefPerFile/callableObjectRef.kt @@ -0,0 +1,29 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +// SPLIT_PER_FILE +// EXPECTED_REACHABLE_NODES: 1289 +// MODULE: lib +// FILE: lib.kt +package lib + +object O { + operator fun invoke() = "OK" +} + +inline fun callO() = O() + +// MODULE: main(lib) +// FILE: main.kt +package main + +import lib.* + +fun box(): String { + val a = O() + if (a != "OK") return "fail: simple: $a" + + val b = callO() + if (b != "OK") return "fail: inline: $a" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/crossModuleRefPerFile/constructor.kt b/js/js.translator/testData/box/esModules/crossModuleRefPerFile/constructor.kt new file mode 100644 index 00000000000..d6ad65372e3 --- /dev/null +++ b/js/js.translator/testData/box/esModules/crossModuleRefPerFile/constructor.kt @@ -0,0 +1,74 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +// SPLIT_PER_FILE +// EXPECTED_REACHABLE_NODES: 1291 +// MODULE: lib +// FILE: lib.kt +package lib + +class A(val x: Int) { + constructor(a: Int, b: Int) : this(a + b) +} + +external class B(x: Int) { + constructor(a: Int, b: Int) + + val x: Int +} + +// TODO: may be useful after implementing local classes in inline functions +/* +inline fun foo(p: Int, q: Int, r: Int): Pair { + class C(val x : Int) { + constructor(a: Int, b: Int) : this(a + b) + } + return Pair(C(p).x, C(q, r).x) +} +*/ + +inline fun callPrimaryConstructor(x: Int) = A(x).x + +inline fun callSecondaryConstructor(x: Int, y: Int) = A(x, y).x + +// FILE: lib.js + +function B(x, y) { + this.x = x; + if (typeof y !== 'undefined') { + this.x += y; + } +} + +// MODULE: main(lib) +// FILE: main.kt +package main + +import lib.* + +fun box(): String { + val a = A(23).x + if (a != 23) return "fail: primary constructor: $a" + + val b = A(40, 2).x + if (b != 42) return "fail: secondary constructor: $b" + + val c = B(99).x + if (c != 99) return "fail: native primary constructor: $c" + + val d = B(100, 11).x + if (d != 111) return "fail: native secondary constructor: $d" + + /* + val (e, f) = foo(123, 320, 1) + if (e != 123) return "fail: local primary constructor: $e" + if (f != 321) return "fail: local secondary constructor: $f" + */ + + val g = callPrimaryConstructor(55) + if (g != 55) return "fail: primary constructor from inline function: $g" + + val h = callSecondaryConstructor(990, 9) + if (h != 999) return "fail: secondary constructor from inline function: $h" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/crossModuleRefPerFile/inheritance.kt b/js/js.translator/testData/box/esModules/crossModuleRefPerFile/inheritance.kt new file mode 100644 index 00000000000..fe2e815715c --- /dev/null +++ b/js/js.translator/testData/box/esModules/crossModuleRefPerFile/inheritance.kt @@ -0,0 +1,29 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +// SPLIT_PER_FILE +// EXPECTED_REACHABLE_NODES: 1292 +// MODULE: lib +// FILE: lib.kt + +package lib + +open class A { + fun foo() = 23 +} + +// MODULE: main(lib) +// FILE: main.kt + +package main + +import lib.A + +class B : A() { + fun bar() = foo() + 1 +} + +fun box(): String { + val result = B().bar() + if (result != 24) return "fail: $result" + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/crossModuleRefPerFile/inlineModule.kt b/js/js.translator/testData/box/esModules/crossModuleRefPerFile/inlineModule.kt new file mode 100644 index 00000000000..aac352e50b9 --- /dev/null +++ b/js/js.translator/testData/box/esModules/crossModuleRefPerFile/inlineModule.kt @@ -0,0 +1,18 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +// SPLIT_PER_FILE +// EXPECTED_REACHABLE_NODES: 1283 +// MODULE: lib1 +// FILE: lib1.kt + +fun foo() = "OK" + +// MODULE: lib2(lib1) +// FILE: lib2.kt + +inline fun bar() = foo() + +// MODULE: main(lib1, lib2) +// FILE: main.kt + +fun box() = bar() \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/crossModuleRefPerFile/inlineModuleNonIndentifier.kt b/js/js.translator/testData/box/esModules/crossModuleRefPerFile/inlineModuleNonIndentifier.kt new file mode 100644 index 00000000000..92bf6be1f41 --- /dev/null +++ b/js/js.translator/testData/box/esModules/crossModuleRefPerFile/inlineModuleNonIndentifier.kt @@ -0,0 +1,18 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +// SPLIT_PER_FILE +// EXPECTED_REACHABLE_NODES: 1283 +// MODULE: 1 +// FILE: lib1.kt + +fun foo() = "OK" + +// MODULE: 2(1) +// FILE: lib2.kt + +inline fun bar() = foo() + +// MODULE: main(2) +// FILE: main.kt + +fun box() = bar() \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/crossModuleRefPerFile/lambda.kt b/js/js.translator/testData/box/esModules/crossModuleRefPerFile/lambda.kt new file mode 100644 index 00000000000..343980a8ccd --- /dev/null +++ b/js/js.translator/testData/box/esModules/crossModuleRefPerFile/lambda.kt @@ -0,0 +1,21 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +// SPLIT_PER_FILE +// EXPECTED_REACHABLE_NODES: 1283 +// MODULE: lib +// FILE: lib.kt +package lib + +fun bar(f: () -> String) = f() + +inline fun foo(): String { + return bar { "OK" } +} + +// MODULE: main(lib) +// FILE: main.kt +package main + +import lib.* + +fun box() = foo() \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/crossModuleRefPerFile/object.kt b/js/js.translator/testData/box/esModules/crossModuleRefPerFile/object.kt new file mode 100644 index 00000000000..36dc9f07b09 --- /dev/null +++ b/js/js.translator/testData/box/esModules/crossModuleRefPerFile/object.kt @@ -0,0 +1,39 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +// SPLIT_PER_FILE +// EXPECTED_REACHABLE_NODES: 1289 +// MODULE: lib +// FILE: lib.kt +package lib + +var log = "" + +object O { + init { + log += "O.init;" + } + + fun result() = "OK" +} + +fun getResult(): String { + log += "before;" + val result = O.result() + log += "after;" + return result +} + +// MODULE: main(lib) +// FILE: main.kt +package main + +import lib.* + +fun box(): String { + val result = getResult() + if (result != "OK") return "fail: unexpected result: $result" + + if (log != "before;O.init;after;") return "fail: wrong evaluation order: $log" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/crossModuleRefPerFile/objectInInlineClosure.kt b/js/js.translator/testData/box/esModules/crossModuleRefPerFile/objectInInlineClosure.kt new file mode 100644 index 00000000000..7e899dcc1b4 --- /dev/null +++ b/js/js.translator/testData/box/esModules/crossModuleRefPerFile/objectInInlineClosure.kt @@ -0,0 +1,29 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +// SPLIT_PER_FILE +// EXPECTED_REACHABLE_NODES: 1382 +// MODULE: lib +// FILE: lib.kt +package lib + +object O { + val result = "OK" + + inline fun foo(): String { + val o = object { + fun bar() = O + } + return fetch(o.bar()) + } +} + +fun fetch(o: O) = o.result + + +// MODULE: main(lib) +// FILE: main.kt +package main + +import lib.* + +fun box() = O.foo() \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/crossModuleRefPerFile/objectIsObject.kt b/js/js.translator/testData/box/esModules/crossModuleRefPerFile/objectIsObject.kt new file mode 100644 index 00000000000..ad947fa20d8 --- /dev/null +++ b/js/js.translator/testData/box/esModules/crossModuleRefPerFile/objectIsObject.kt @@ -0,0 +1,23 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +// SPLIT_PER_FILE +// EXPECTED_REACHABLE_NODES: 1284 +// MODULE: lib +// FILE: lib.kt +package lib + +object O + +// MODULE: main(lib) +// FILE: main.kt +package main + +import lib.* + +fun box(): String { + var o: Any = O + if (o !is O) return "fail1" + if (!(o is O)) return "fail2" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/crossModuleRefPerFile/topLevelExtension.kt b/js/js.translator/testData/box/esModules/crossModuleRefPerFile/topLevelExtension.kt new file mode 100644 index 00000000000..e51847ae75b --- /dev/null +++ b/js/js.translator/testData/box/esModules/crossModuleRefPerFile/topLevelExtension.kt @@ -0,0 +1,46 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +// SPLIT_PER_FILE +// EXPECTED_REACHABLE_NODES: 1290 +// MODULE: lib +// FILE: lib.kt + +package lib + +class A(val x: Int) + +fun A.foo() = 23 + x + +inline fun A.baz() = 99 + x + +inline fun A.callFoo() = foo() + +inline fun A.buzz(): Int { + val o = object { + fun f() = 111 + x + } + return o.f() +} + +// MODULE: main(lib) +// FILE: main.kt + +package main + +import lib.* + +fun box(): String { + val a = A(1).foo() + if (a != 24) return "fail: simple function: $a" + + val c = A(1).baz() + if (c != 100) return "fail: inline function: $c" + + val d = A(1).buzz() + if (d != 112) return "fail: inline function with object expression: $d" + + val e = A(2).callFoo() + if (e != 25) return "fail: inline function calling another function: $e" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/crossModuleRefPerFile/topLevelFunction.kt b/js/js.translator/testData/box/esModules/crossModuleRefPerFile/topLevelFunction.kt new file mode 100644 index 00000000000..3cfbc5dd0b5 --- /dev/null +++ b/js/js.translator/testData/box/esModules/crossModuleRefPerFile/topLevelFunction.kt @@ -0,0 +1,53 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +// SPLIT_PER_FILE +// EXPECTED_REACHABLE_NODES: 1287 +// MODULE: lib +// FILE: lib.kt + +package lib + +fun foo() = 23 + +external fun bar(): Int = definedExternally + +inline fun baz() = 99 + +inline fun callFoo() = foo() + +inline fun buzz(): Int { + val o = object { + fun f() = 111 + } + return o.f() +} + +// FILE: lib.js + +function bar() { + return 42; +} + +// MODULE: main(lib) +// FILE: main.kt + +package main + +fun box(): String { + val a = lib.foo() + if (a != 23) return "fail: simple function: $a" + + val b = lib.bar() + if (b != 42) return "fail: native function: $b" + + val c = lib.baz() + if (c != 99) return "fail: inline function: $c" + + val d = lib.buzz() + if (d != 111) return "fail: inline function with object expression: $d" + + val e = lib.callFoo() + if (e != 23) return "fail: inline function calling another function: $e" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/crossModuleRefPerFile/topLevelMutableProperty.kt b/js/js.translator/testData/box/esModules/crossModuleRefPerFile/topLevelMutableProperty.kt new file mode 100644 index 00000000000..70ffe8cfa4b --- /dev/null +++ b/js/js.translator/testData/box/esModules/crossModuleRefPerFile/topLevelMutableProperty.kt @@ -0,0 +1,40 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +// SPLIT_PER_FILE +// EXPECTED_REACHABLE_NODES: 1286 +// MODULE: lib +// FILE: lib.kt +package lib + +var foo = 23 + +var bar: Int = 42 + get() = field + set(value) { + field = value + } + +@JsName("faz") var baz = 99 + +// MODULE: main(lib) +// FILE: lib.kt +package main + +import lib.* + +fun box(): String { + if (foo != 23) return "fail: simple property initial value: $foo" + foo = 24 + if (foo != 24) return "fail: simple property new value: $foo" + + if (bar != 42) return "fail: property with accessor initial value: $bar" + bar = 43 + if (bar != 43) return "fail: property with accessor new value: $bar" + + if (baz != 99) return "fail: renamed property initial value: $baz" + baz = 100 + if (baz != 100) return "fail: renamed property new value: $baz" + + + return "OK" +} diff --git a/js/js.translator/testData/box/esModules/crossModuleRefPerFile/topLevelProperty.kt b/js/js.translator/testData/box/esModules/crossModuleRefPerFile/topLevelProperty.kt new file mode 100644 index 00000000000..68c47a4ba36 --- /dev/null +++ b/js/js.translator/testData/box/esModules/crossModuleRefPerFile/topLevelProperty.kt @@ -0,0 +1,50 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +// SPLIT_PER_FILE +// EXPECTED_REACHABLE_NODES: 1287 +// MODULE: lib +// FILE: lib.kt +package lib + +val foo = 23 + +val boo: Int + get() = 42 + +external val bar: Int = definedExternally + +external val far: Int + get() = definedExternally + +// TODO: annotations like this are not serialized properly. Uncomment after KT-14529 gets fixed +/* +val fuzz: Int + @JsName("getBuzz") get() = 55 + */ + +inline fun fetchFoo() = foo + +@JsName("fee") +val tee = 2525 + +// FILE: lib.js + +var bar = 99 +var far = 111 + +// MODULE: main(lib) +// FILE: lib.kt +package main + +import lib.* + +fun box(): String { + if (foo != 23) return "fail: simple property: $foo" + if (boo != 42) return "fail: property with accessor: $boo" + if (bar != 99) return "fail: native property: $bar" + if (far != 111) return "fail: native property with accessor: $far" + //if (fuzz != 55) return "fail: property with JsName on accessor: $fuzz" + if (tee != 2525) return "fail: native property with JsName: $tee" + + return "OK" +} diff --git a/js/js.translator/testData/box/esModules/crossModuleRefPerModule/callableObjectRef.kt b/js/js.translator/testData/box/esModules/crossModuleRefPerModule/callableObjectRef.kt new file mode 100644 index 00000000000..d58a9bc56b5 --- /dev/null +++ b/js/js.translator/testData/box/esModules/crossModuleRefPerModule/callableObjectRef.kt @@ -0,0 +1,29 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +// SPLIT_PER_MODULE +// EXPECTED_REACHABLE_NODES: 1289 +// MODULE: lib +// FILE: lib.kt +package lib + +object O { + operator fun invoke() = "OK" +} + +inline fun callO() = O() + +// MODULE: main(lib) +// FILE: main.kt +package main + +import lib.* + +fun box(): String { + val a = O() + if (a != "OK") return "fail: simple: $a" + + val b = callO() + if (b != "OK") return "fail: inline: $a" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/crossModuleRefPerModule/constructor.kt b/js/js.translator/testData/box/esModules/crossModuleRefPerModule/constructor.kt new file mode 100644 index 00000000000..cf7d717a452 --- /dev/null +++ b/js/js.translator/testData/box/esModules/crossModuleRefPerModule/constructor.kt @@ -0,0 +1,74 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +// SPLIT_PER_MODULE +// EXPECTED_REACHABLE_NODES: 1291 +// MODULE: lib +// FILE: lib.kt +package lib + +class A(val x: Int) { + constructor(a: Int, b: Int) : this(a + b) +} + +external class B(x: Int) { + constructor(a: Int, b: Int) + + val x: Int +} + +// TODO: may be useful after implementing local classes in inline functions +/* +inline fun foo(p: Int, q: Int, r: Int): Pair { + class C(val x : Int) { + constructor(a: Int, b: Int) : this(a + b) + } + return Pair(C(p).x, C(q, r).x) +} +*/ + +inline fun callPrimaryConstructor(x: Int) = A(x).x + +inline fun callSecondaryConstructor(x: Int, y: Int) = A(x, y).x + +// FILE: lib.js + +function B(x, y) { + this.x = x; + if (typeof y !== 'undefined') { + this.x += y; + } +} + +// MODULE: main(lib) +// FILE: main.kt +package main + +import lib.* + +fun box(): String { + val a = A(23).x + if (a != 23) return "fail: primary constructor: $a" + + val b = A(40, 2).x + if (b != 42) return "fail: secondary constructor: $b" + + val c = B(99).x + if (c != 99) return "fail: native primary constructor: $c" + + val d = B(100, 11).x + if (d != 111) return "fail: native secondary constructor: $d" + + /* + val (e, f) = foo(123, 320, 1) + if (e != 123) return "fail: local primary constructor: $e" + if (f != 321) return "fail: local secondary constructor: $f" + */ + + val g = callPrimaryConstructor(55) + if (g != 55) return "fail: primary constructor from inline function: $g" + + val h = callSecondaryConstructor(990, 9) + if (h != 999) return "fail: secondary constructor from inline function: $h" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/crossModuleRefPerModule/inheritance.kt b/js/js.translator/testData/box/esModules/crossModuleRefPerModule/inheritance.kt new file mode 100644 index 00000000000..624dfe3e992 --- /dev/null +++ b/js/js.translator/testData/box/esModules/crossModuleRefPerModule/inheritance.kt @@ -0,0 +1,29 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +// SPLIT_PER_MODULE +// EXPECTED_REACHABLE_NODES: 1292 +// MODULE: lib +// FILE: lib.kt + +package lib + +open class A { + fun foo() = 23 +} + +// MODULE: main(lib) +// FILE: main.kt + +package main + +import lib.A + +class B : A() { + fun bar() = foo() + 1 +} + +fun box(): String { + val result = B().bar() + if (result != 24) return "fail: $result" + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/crossModuleRefPerModule/inlineModule.kt b/js/js.translator/testData/box/esModules/crossModuleRefPerModule/inlineModule.kt new file mode 100644 index 00000000000..4baa520dac6 --- /dev/null +++ b/js/js.translator/testData/box/esModules/crossModuleRefPerModule/inlineModule.kt @@ -0,0 +1,18 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +// SPLIT_PER_MODULE +// EXPECTED_REACHABLE_NODES: 1283 +// MODULE: lib1 +// FILE: lib1.kt + +fun foo() = "OK" + +// MODULE: lib2(lib1) +// FILE: lib2.kt + +inline fun bar() = foo() + +// MODULE: main(lib1, lib2) +// FILE: main.kt + +fun box() = bar() \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/crossModuleRefPerModule/inlineModuleNonIndentifier.kt b/js/js.translator/testData/box/esModules/crossModuleRefPerModule/inlineModuleNonIndentifier.kt new file mode 100644 index 00000000000..17e46ea8ebd --- /dev/null +++ b/js/js.translator/testData/box/esModules/crossModuleRefPerModule/inlineModuleNonIndentifier.kt @@ -0,0 +1,18 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +// SPLIT_PER_MODULE +// EXPECTED_REACHABLE_NODES: 1283 +// MODULE: 1 +// FILE: lib1.kt + +fun foo() = "OK" + +// MODULE: 2(1) +// FILE: lib2.kt + +inline fun bar() = foo() + +// MODULE: main(2) +// FILE: main.kt + +fun box() = bar() \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/crossModuleRefPerModule/lambda.kt b/js/js.translator/testData/box/esModules/crossModuleRefPerModule/lambda.kt new file mode 100644 index 00000000000..bb5b64fc183 --- /dev/null +++ b/js/js.translator/testData/box/esModules/crossModuleRefPerModule/lambda.kt @@ -0,0 +1,21 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +// SPLIT_PER_MODULE +// EXPECTED_REACHABLE_NODES: 1283 +// MODULE: lib +// FILE: lib.kt +package lib + +fun bar(f: () -> String) = f() + +inline fun foo(): String { + return bar { "OK" } +} + +// MODULE: main(lib) +// FILE: main.kt +package main + +import lib.* + +fun box() = foo() \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/crossModuleRefPerModule/object.kt b/js/js.translator/testData/box/esModules/crossModuleRefPerModule/object.kt new file mode 100644 index 00000000000..366491dbfff --- /dev/null +++ b/js/js.translator/testData/box/esModules/crossModuleRefPerModule/object.kt @@ -0,0 +1,39 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +// SPLIT_PER_MODULE +// EXPECTED_REACHABLE_NODES: 1289 +// MODULE: lib +// FILE: lib.kt +package lib + +var log = "" + +object O { + init { + log += "O.init;" + } + + fun result() = "OK" +} + +fun getResult(): String { + log += "before;" + val result = O.result() + log += "after;" + return result +} + +// MODULE: main(lib) +// FILE: main.kt +package main + +import lib.* + +fun box(): String { + val result = getResult() + if (result != "OK") return "fail: unexpected result: $result" + + if (log != "before;O.init;after;") return "fail: wrong evaluation order: $log" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/crossModuleRefPerModule/objectInInlineClosure.kt b/js/js.translator/testData/box/esModules/crossModuleRefPerModule/objectInInlineClosure.kt new file mode 100644 index 00000000000..7b1524e4f5c --- /dev/null +++ b/js/js.translator/testData/box/esModules/crossModuleRefPerModule/objectInInlineClosure.kt @@ -0,0 +1,29 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +// SPLIT_PER_MODULE +// EXPECTED_REACHABLE_NODES: 1382 +// MODULE: lib +// FILE: lib.kt +package lib + +object O { + val result = "OK" + + inline fun foo(): String { + val o = object { + fun bar() = O + } + return fetch(o.bar()) + } +} + +fun fetch(o: O) = o.result + + +// MODULE: main(lib) +// FILE: main.kt +package main + +import lib.* + +fun box() = O.foo() \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/crossModuleRefPerModule/objectIsObject.kt b/js/js.translator/testData/box/esModules/crossModuleRefPerModule/objectIsObject.kt new file mode 100644 index 00000000000..fa336b0e6b9 --- /dev/null +++ b/js/js.translator/testData/box/esModules/crossModuleRefPerModule/objectIsObject.kt @@ -0,0 +1,23 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +// SPLIT_PER_MODULE +// EXPECTED_REACHABLE_NODES: 1284 +// MODULE: lib +// FILE: lib.kt +package lib + +object O + +// MODULE: main(lib) +// FILE: main.kt +package main + +import lib.* + +fun box(): String { + var o: Any = O + if (o !is O) return "fail1" + if (!(o is O)) return "fail2" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/crossModuleRefPerModule/topLevelExtension.kt b/js/js.translator/testData/box/esModules/crossModuleRefPerModule/topLevelExtension.kt new file mode 100644 index 00000000000..5ffd7ee6f68 --- /dev/null +++ b/js/js.translator/testData/box/esModules/crossModuleRefPerModule/topLevelExtension.kt @@ -0,0 +1,46 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +// SPLIT_PER_MODULE +// EXPECTED_REACHABLE_NODES: 1290 +// MODULE: lib +// FILE: lib.kt + +package lib + +class A(val x: Int) + +fun A.foo() = 23 + x + +inline fun A.baz() = 99 + x + +inline fun A.callFoo() = foo() + +inline fun A.buzz(): Int { + val o = object { + fun f() = 111 + x + } + return o.f() +} + +// MODULE: main(lib) +// FILE: main.kt + +package main + +import lib.* + +fun box(): String { + val a = A(1).foo() + if (a != 24) return "fail: simple function: $a" + + val c = A(1).baz() + if (c != 100) return "fail: inline function: $c" + + val d = A(1).buzz() + if (d != 112) return "fail: inline function with object expression: $d" + + val e = A(2).callFoo() + if (e != 25) return "fail: inline function calling another function: $e" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/crossModuleRefPerModule/topLevelFunction.kt b/js/js.translator/testData/box/esModules/crossModuleRefPerModule/topLevelFunction.kt new file mode 100644 index 00000000000..5f48bcf4d13 --- /dev/null +++ b/js/js.translator/testData/box/esModules/crossModuleRefPerModule/topLevelFunction.kt @@ -0,0 +1,53 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +// SPLIT_PER_MODULE +// EXPECTED_REACHABLE_NODES: 1287 +// MODULE: lib +// FILE: lib.kt + +package lib + +fun foo() = 23 + +external fun bar(): Int = definedExternally + +inline fun baz() = 99 + +inline fun callFoo() = foo() + +inline fun buzz(): Int { + val o = object { + fun f() = 111 + } + return o.f() +} + +// FILE: lib.js + +function bar() { + return 42; +} + +// MODULE: main(lib) +// FILE: main.kt + +package main + +fun box(): String { + val a = lib.foo() + if (a != 23) return "fail: simple function: $a" + + val b = lib.bar() + if (b != 42) return "fail: native function: $b" + + val c = lib.baz() + if (c != 99) return "fail: inline function: $c" + + val d = lib.buzz() + if (d != 111) return "fail: inline function with object expression: $d" + + val e = lib.callFoo() + if (e != 23) return "fail: inline function calling another function: $e" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/crossModuleRefPerModule/topLevelMutableProperty.kt b/js/js.translator/testData/box/esModules/crossModuleRefPerModule/topLevelMutableProperty.kt new file mode 100644 index 00000000000..6c27c79acc9 --- /dev/null +++ b/js/js.translator/testData/box/esModules/crossModuleRefPerModule/topLevelMutableProperty.kt @@ -0,0 +1,40 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +// SPLIT_PER_MODULE +// EXPECTED_REACHABLE_NODES: 1286 +// MODULE: lib +// FILE: lib.kt +package lib + +var foo = 23 + +var bar: Int = 42 + get() = field + set(value) { + field = value + } + +@JsName("faz") var baz = 99 + +// MODULE: main(lib) +// FILE: lib.kt +package main + +import lib.* + +fun box(): String { + if (foo != 23) return "fail: simple property initial value: $foo" + foo = 24 + if (foo != 24) return "fail: simple property new value: $foo" + + if (bar != 42) return "fail: property with accessor initial value: $bar" + bar = 43 + if (bar != 43) return "fail: property with accessor new value: $bar" + + if (baz != 99) return "fail: renamed property initial value: $baz" + baz = 100 + if (baz != 100) return "fail: renamed property new value: $baz" + + + return "OK" +} diff --git a/js/js.translator/testData/box/esModules/crossModuleRefPerModule/topLevelProperty.kt b/js/js.translator/testData/box/esModules/crossModuleRefPerModule/topLevelProperty.kt new file mode 100644 index 00000000000..69fdad63032 --- /dev/null +++ b/js/js.translator/testData/box/esModules/crossModuleRefPerModule/topLevelProperty.kt @@ -0,0 +1,50 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +// SPLIT_PER_MODULE +// EXPECTED_REACHABLE_NODES: 1287 +// MODULE: lib +// FILE: lib.kt +package lib + +val foo = 23 + +val boo: Int + get() = 42 + +external val bar: Int = definedExternally + +external val far: Int + get() = definedExternally + +// TODO: annotations like this are not serialized properly. Uncomment after KT-14529 gets fixed +/* +val fuzz: Int + @JsName("getBuzz") get() = 55 + */ + +inline fun fetchFoo() = foo + +@JsName("fee") +val tee = 2525 + +// FILE: lib.js + +var bar = 99 +var far = 111 + +// MODULE: main(lib) +// FILE: lib.kt +package main + +import lib.* + +fun box(): String { + if (foo != 23) return "fail: simple property: $foo" + if (boo != 42) return "fail: property with accessor: $boo" + if (bar != 99) return "fail: native property: $bar" + if (far != 111) return "fail: native property with accessor: $far" + //if (fuzz != 55) return "fail: property with JsName on accessor: $fuzz" + if (tee != 2525) return "fail: native property with JsName: $tee" + + return "OK" +} diff --git a/js/js.translator/testData/box/esModules/export/exportAllFile.kt b/js/js.translator/testData/box/esModules/export/exportAllFile.kt new file mode 100644 index 00000000000..9e9ff53b535 --- /dev/null +++ b/js/js.translator/testData/box/esModules/export/exportAllFile.kt @@ -0,0 +1,23 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// EXPECTED_REACHABLE_NODES: 1252 +// INFER_MAIN_MODULE +// ES_MODULES + +// MODULE: export-all-file +// FILE: lib.kt +@file:JsExport + +abstract class A { + abstract fun foo(k: String): String +} + +class B : A() { + override fun foo(k: String): String { + return "O" + k + } +} + +// FILE: entry.mjs +// ENTRY_ES_MODULE +import { B } from "./export-all-file/index.js"; +console.assert(new B().foo("K") == "OK"); \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/export/nonIndetifierModuleName.kt b/js/js.translator/testData/box/esModules/export/nonIndetifierModuleName.kt new file mode 100644 index 00000000000..0cda461d083 --- /dev/null +++ b/js/js.translator/testData/box/esModules/export/nonIndetifierModuleName.kt @@ -0,0 +1,16 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// SKIP_MINIFICATION +// INFER_MAIN_MODULE +// SKIP_NODE_JS +// ES_MODULES + +// MODULE: non-identifier-module-name +// FILE: lib.kt +@JsName("foo") +@JsExport +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"); diff --git a/js/js.translator/testData/box/esModules/export/overriddenChainNonExportIntermediate.kt b/js/js.translator/testData/box/esModules/export/overriddenChainNonExportIntermediate.kt new file mode 100644 index 00000000000..529b2e6d5de --- /dev/null +++ b/js/js.translator/testData/box/esModules/export/overriddenChainNonExportIntermediate.kt @@ -0,0 +1,39 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// EXPECTED_REACHABLE_NODES: 1252 +// INFER_MAIN_MODULE + +// ES_MODULES +// MODULE: overriden-chain-non-export-intermediate +// FILE: lib.kt +@JsExport +abstract class A { + abstract fun foo(): String + + abstract fun bar(): String +} + +abstract class B : A() { + abstract fun baz(): String + + override fun foo(): String = "foo" +} + +@JsExport +class C : B() { + override fun bar(): String = "bar" + override fun baz(): String = "baz" + + fun bay(): String = "bay" +} + +// FILE: entry.mjs +// ENTRY_ES_MODULE +import { C } from "./overriden-chain-non-export-intermediate/index.js"; + +function test(c) { + if (c.foo() === "foo" && c.bar() === "bar" && c.bay() == "bay") return "OK" + + return "fail" +} + +console.assert(test(new C()) == "OK"); \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/export/overriddenExternalMethodWithSameNameMethod.kt b/js/js.translator/testData/box/esModules/export/overriddenExternalMethodWithSameNameMethod.kt new file mode 100644 index 00000000000..e2a6fdeedd9 --- /dev/null +++ b/js/js.translator/testData/box/esModules/export/overriddenExternalMethodWithSameNameMethod.kt @@ -0,0 +1,41 @@ +// EXPECTED_REACHABLE_NODES: 1252 +// INFER_MAIN_MODULE +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES + +// MODULE: overriden-external-method-with-same-name-method +// FILE: lib.kt +external abstract class Foo { + abstract fun o(): String +} + +abstract class Bar : Foo() { + abstract fun String.o(): String + + override fun o(): String { + return "O".o() + } +} + +@JsExport +class Baz : Bar() { + override fun String.o(): String { + return this + } +} + +// FILE: foo.js +function Foo() {} +Foo.prototype.k = function() { + return "K" +} + +// FILE: entry.mjs +// ENTRY_ES_MODULE +import { Baz } from "./overriden-external-method-with-same-name-method/index.js"; + +function test(foo) { + return foo.o() + foo.k() +} + +console.assert(test(new Baz()) == "OK"); \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/export/overriddenExternalMethodWithSameStableNameMethod.kt b/js/js.translator/testData/box/esModules/export/overriddenExternalMethodWithSameStableNameMethod.kt new file mode 100644 index 00000000000..66bce108e06 --- /dev/null +++ b/js/js.translator/testData/box/esModules/export/overriddenExternalMethodWithSameStableNameMethod.kt @@ -0,0 +1,44 @@ +// EXPECTED_REACHABLE_NODES: 1252 +// IGNORE_BACKEND: JS +// INFER_MAIN_MODULE +// ES_MODULES + +// MODULE: overriden-external-method-with-same-stable-name-method +// FILE: lib.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() + } +} + +@JsExport +class Baz : Bar() { + override fun String.o(): String { + return this + } +} + +// FILE: foo.js +function Foo() {} +Foo.prototype.k = function() { + return "K" +} + +// FILE: entry.mjs +// ENTRY_ES_MODULE +import { Baz } from "./overriden-external-method-with-same-stable-name-method/index.js"; + +function test(foo) { + const oStable = foo.oStable("OK") + if (oStable !== "OK") return "false: " + oStable + return foo.o() + foo.k() +} + +console.assert(test(new Baz()) == "OK"); \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/export/reservedModuleName.kt b/js/js.translator/testData/box/esModules/export/reservedModuleName.kt new file mode 100644 index 00000000000..bc3173f5d91 --- /dev/null +++ b/js/js.translator/testData/box/esModules/export/reservedModuleName.kt @@ -0,0 +1,17 @@ +// IGNORE_BACKEND: JS +// EXPECTED_REACHABLE_NODES: 1270 +// SKIP_MINIFICATION +// INFER_MAIN_MODULE +// ES_MODULES + +// MODULE: if +// FILE: lib.kt +@JsName("foo") +@JsExport +public fun foo(k: String): String = "O$k" + +// FILE: entry.mjs +// ENTRY_ES_MODULE +import { foo } from "./if/index.js"; + +console.assert(foo("K") == "OK"); diff --git a/js/js.translator/testData/box/esModules/incremental/jsModule.kt b/js/js.translator/testData/box/esModules/incremental/jsModule.kt new file mode 100644 index 00000000000..cd31acd3f3d --- /dev/null +++ b/js/js.translator/testData/box/esModules/incremental/jsModule.kt @@ -0,0 +1,41 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES + +// MODULE: lib +// FILE: a.kt +@file:JsModule("./foo.mjs") + +external fun fooF(): String + +// FILE: b.kt +@file:JsModule("./bar.mjs") + +external fun barF(): String + +// FILE: c.kt +// RECOMPILE +fun dummyF() = "dummy" + +// MODULE: main(lib) +// FILE: main.kt + +fun box(): String { + val foo = fooF() + if (foo != "foo") return "fail1: $foo" + + val bar = barF() + if (bar != "bar") return "fail2: $bar" + + return "OK" +} + + +// FILE: foo.mjs +export function fooF() { + return "foo"; +} + +// FILE: bar.mjs +export function barF() { + return "bar"; +} \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/inline/inlinedObjectLiteralIsCheck.kt b/js/js.translator/testData/box/esModules/inline/inlinedObjectLiteralIsCheck.kt new file mode 100644 index 00000000000..a045b6b1f9d --- /dev/null +++ b/js/js.translator/testData/box/esModules/inline/inlinedObjectLiteralIsCheck.kt @@ -0,0 +1,35 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES + +// FILE: main.kt +interface I { + fun ok(): String +} + +inline fun ok(): I { + return object : I { + override fun ok() = "OK" + } +} + +@JsName("convolutedOk") +@JsExport +inline fun convolutedOk(): I { + val fail = object : I { + override fun ok() = "fail" + }.ok() + + return ok() +} + +@JsExport +fun testOk(ok: Any): String { + if (ok !is I) return "fail" + return ok.ok() +} + +// FILE: entry.mjs +// ENTRY_ES_MODULE +import { convolutedOk, testOk } from "./JS_TESTS/index.js"; + +console.assert(testOk(convolutedOk()) == "OK"); diff --git a/js/js.translator/testData/box/esModules/jsExport/dataClass.kt b/js/js.translator/testData/box/esModules/jsExport/dataClass.kt new file mode 100644 index 00000000000..3a09882fc55 --- /dev/null +++ b/js/js.translator/testData/box/esModules/jsExport/dataClass.kt @@ -0,0 +1,55 @@ +// DONT_TARGET_EXACT_BACKEND: JS + +// SKIP_DCE_DRIVEN +// SKIP_MINIFICATION +// ES_MODULES + +// FILE: api.kt + +@JsExport +data class Point(val x: Int, val y: Int) { + override fun toString(): String = "[${x}::${y}]" +} + +// we need his class to make sure that there's more than one ping method in existence - due to peculiarities of current namer otherwise test can pass but JsExport won't be actually respected +data class AltPoint(val x: Int, val y: Int) + +// FILE: main.kt +external interface JsResult { + val copy00: String + val copy01: String + val copy10: String + val copy11: String + val component1: Int + val component2: Int +} + +@JsModule("./dataClass.mjs") +external fun jsBox(): JsResult + +fun box(): String { + val res = jsBox() + if (res.copy00 != "[3::7]") { + return "Fail1: ${res.copy00}" + } + if (res.copy01 != "[3::11]") { + return "Fail2: ${res.copy01}" + } + if (res.copy10 != "[15::7]") { + return "Fail3: ${res.copy10}" + } + if (res.copy11 != "[13::11]") { + return "Fail4: ${res.copy11}" + } + if (res.component1 != 3) { + return "Fail5: ${res.component1}" + } + if (res.component2 != 7) { + return "Fail6: ${res.component2}" + } + + + + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/jsExport/dataClass.mjs b/js/js.translator/testData/box/esModules/jsExport/dataClass.mjs new file mode 100644 index 00000000000..395af68d4cb --- /dev/null +++ b/js/js.translator/testData/box/esModules/jsExport/dataClass.mjs @@ -0,0 +1,14 @@ +import { Point } from "./JS_TESTS/index.js"; + +export default function() { + var p = new Point(3, 7); + + return { + "copy00": p.copy().toString(), + "copy01": p.copy(undefined, 11).toString(), + "copy10": p.copy(15).toString(), + "copy11": p.copy(13, 11).toString(), + "component1": p.component1(), + "component2": p.component2() + }; +}; diff --git a/js/js.translator/testData/box/esModules/jsExport/exportedDefaultStub.kt b/js/js.translator/testData/box/esModules/jsExport/exportedDefaultStub.kt new file mode 100644 index 00000000000..424839e54d3 --- /dev/null +++ b/js/js.translator/testData/box/esModules/jsExport/exportedDefaultStub.kt @@ -0,0 +1,118 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// SKIP_DCE_DRIVEN +// SKIP_MINIFICATION +// ES_MODULES + +@JsExport +fun ping(a: String = "A", b: Int = 1): String { + return "$a::$b" +} + +@JsExport +open class Ping(private val defaultSeed: Int = 3) { + private fun calculate(n: Int) = n * n + fun ping(s: Int = defaultSeed, c: (Int) -> Int = ::calculate): Int { + return c(s) + } +} + +@JsExport +class Pong: Ping() + +@JsExport +@JsName("pong") +fun bing(a: String = "A", b: Int = 1): String { + return "$b::$a" +} + +@JsExport +class Foo { + @JsName("foo") + fun value(value: Long = 5L) = if (value == 5L) "C" else "fail" +} + +@JsExport +fun transform(i: Int = 10, t: (Int) -> Int = {it * it}): Int { + return t(i) +} + +external interface JsResult { + val ping00: String + val ping01: String + val ping10: String + val ping11: String + + val pong00: String + val pong01: String + val pong10: String + val pong11: String + + val transform00: Int + val transform11: Int + + val Ping_ping00a: Int + val Ping_ping00b: Int + val Ping_ping11: Int + + val Pong_ping00: Int + + val Foo: String +} + +@JsModule("./exportedDefaultStub.mjs") +external fun jsBox(): JsResult + +fun box(): String { + val res = jsBox() + if (res.ping00 != "A::1") { + return "fail0: ${res.ping00}" + } + if (res.ping01 != "A::10") { + return "fail1: ${res.ping01}" + } + if (res.ping10 != "X::1") { + return "fail2: ${res.ping10}" + } + if (res.ping11 != "Z::5") { + return "fail3: ${res.ping11}" + } + + if (res.pong00 != "1::A") { + return "fail4: ${res.pong00}" + } + if (res.pong01 != "10::A") { + return "fail5: ${res.pong01}" + } + if (res.pong10 != "1::X") { + return "fail6: ${res.pong10}" + } + if (res.pong11 != "5::Z") { + return "fail7: ${res.pong11}" + } + + if (res.transform00 != 100) { + return "fail8: ${res.transform00}" + } + if (res.transform11 != -125) { + return "fail9: ${res.transform11}" + } + + if (res.Ping_ping00a != 9) { + return "fail10: ${res.Ping_ping00a}" + } + if (res.Ping_ping00b != 100) { + return "fail11: ${res.Ping_ping00b}" + } + if (res.Ping_ping11 != -64) { + return "fail12: ${res.Ping_ping11}" + } + if (res.Pong_ping00 != 9) { + return "fail13: ${res.Pong_ping00}" + } + + if (res.Foo != "C") { + return "fail14: ${res.Foo}" + } + + return "OK" +} diff --git a/js/js.translator/testData/box/esModules/jsExport/exportedDefaultStub.mjs b/js/js.translator/testData/box/esModules/jsExport/exportedDefaultStub.mjs new file mode 100644 index 00000000000..9298790992a --- /dev/null +++ b/js/js.translator/testData/box/esModules/jsExport/exportedDefaultStub.mjs @@ -0,0 +1,36 @@ +import * as api from "./JS_TESTS/index.js"; + +export default function() { + var ping = api.ping; + var pong = api.pong; + var transform = api.transform; + var Ping = api.Ping; + var Pong = api.Pong; + var Foo = api.Foo; + + return { + "ping00": ping(), + "ping01": ping(undefined, 10), + "ping10": ping("X"), + "ping11": ping("Z", 5), + + "pong00": pong(), + "pong01": pong(undefined, 10), + "pong10": pong("X"), + "pong11": pong("Z", 5), + + "transform00": transform(), + "transform11": transform(-5, function (it) { + return it * it * it + }), + + "Ping_ping00a": new Ping().ping(), + "Ping_ping00b": new Ping(10).ping(), + "Ping_ping11": new Ping().ping(-4, function (it) { + return it * it * it + }), + + "Pong_ping00": new Pong().ping(), + "Foo": new Foo().foo() + }; +} \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/jsExport/jsExportInClass.kt b/js/js.translator/testData/box/esModules/jsExport/jsExportInClass.kt new file mode 100644 index 00000000000..feed0c5a578 --- /dev/null +++ b/js/js.translator/testData/box/esModules/jsExport/jsExportInClass.kt @@ -0,0 +1,38 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// SKIP_MINIFICATION +// ES_MODULES +// FILE: api.kt + +@JsExport +class A() { + fun ping() = "ping" +} + +@JsExport +class B() { + @JsName("pong") + fun ping() = "pong" +} + +// we need his class to make sure that there's more than one ping method in existence - due to peculiarities of current namer otherwise test can pass but JsExport won't be actually respected +class C() { + fun ping() = "pong" +} + + +// FILE: main.kt +external interface JsResult { + val res: String +} + +@JsModule("./jsExportInClass.mjs") +external fun jsBox(): JsResult + +fun box(): String { + val res = jsBox().res + if (res != "pingpong") { + return "Fail: ${res}" + } + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/jsExport/jsExportInClass.mjs b/js/js.translator/testData/box/esModules/jsExport/jsExportInClass.mjs new file mode 100644 index 00000000000..9a175cb67c4 --- /dev/null +++ b/js/js.translator/testData/box/esModules/jsExport/jsExportInClass.mjs @@ -0,0 +1,7 @@ +import { A, B } from "./JS_TESTS/index.js"; + +export default function() { + return { + "res": (new A().ping()) + (new B().pong()) + }; +}; diff --git a/js/js.translator/testData/box/esModules/jsExport/recursiveExport.kt b/js/js.translator/testData/box/esModules/jsExport/recursiveExport.kt new file mode 100644 index 00000000000..3ee07432bcf --- /dev/null +++ b/js/js.translator/testData/box/esModules/jsExport/recursiveExport.kt @@ -0,0 +1,28 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// SKIP_MINIFICATION +// ES_MODULES + +// FILE: api.kt +@JsExport +class Something> { + fun ping(): String { + return "OK" + } +} + +@JsExport +fun ping(s: Something<*>): String { + return s.ping() +} + +// FILE: main.kt +external interface JsResult { + val pingCall: () -> String +} + +@JsModule("./recursiveExport.mjs") +external fun jsBox(): JsResult + +fun box(): String { + return jsBox().pingCall() +} diff --git a/js/js.translator/testData/box/esModules/jsExport/recursiveExport.mjs b/js/js.translator/testData/box/esModules/jsExport/recursiveExport.mjs new file mode 100644 index 00000000000..121b5333623 --- /dev/null +++ b/js/js.translator/testData/box/esModules/jsExport/recursiveExport.mjs @@ -0,0 +1,9 @@ +import { ping, Something } from "./JS_TESTS/index.js" + +export default function() { + return { + "pingCall": function() { + return ping(new Something()) + }, + }; +}; \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/jsModule/externalClass.kt b/js/js.translator/testData/box/esModules/jsModule/externalClass.kt new file mode 100644 index 00000000000..ada29327748 --- /dev/null +++ b/js/js.translator/testData/box/esModules/jsModule/externalClass.kt @@ -0,0 +1,33 @@ +// EXPECTED_REACHABLE_NODES: 1284 +// ES_MODULES +// DONT_TARGET_EXACT_BACKEND: JS + +package foo + +@JsModule("./externalClass.mjs") +external class A(x: Int = definedExternally) { + val x: Int + + fun foo(y: Int): Int = definedExternally + + fun bar(vararg arg: String): String = definedExternally +} + +class C { + val e = arrayOf("e") + val f = arrayOf("f") + val a = A(1) + + fun qux() = a.bar(*e, *f) +} + + +fun box(): String { + val a = A(23) + assertEquals(23, a.x) + assertEquals(65, a.foo(42)) + + assertEquals(C().qux(), "(ef)") + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/jsModule/externalClass.mjs b/js/js.translator/testData/box/esModules/jsModule/externalClass.mjs new file mode 100644 index 00000000000..848fe5da703 --- /dev/null +++ b/js/js.translator/testData/box/esModules/jsModule/externalClass.mjs @@ -0,0 +1,11 @@ +export default function A(x) { + this.x = x; +} + +A.prototype.foo = function (y) { + return this.x + y; +}; + +A.prototype.bar = function() { + return "(" + Array.prototype.join.call(arguments, "") + ")"; +}; diff --git a/js/js.translator/testData/box/esModules/jsModule/externalClassNameClash.kt b/js/js.translator/testData/box/esModules/jsModule/externalClassNameClash.kt new file mode 100644 index 00000000000..c52dc845bd0 --- /dev/null +++ b/js/js.translator/testData/box/esModules/jsModule/externalClassNameClash.kt @@ -0,0 +1,62 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +// FILE: a.kt +@file:JsModule("./a.mjs") +package a + +external class A { + fun foo(): String +} + +external fun bar(): Int + +external val prop: Int + +// FILE: b.kt +@file:JsModule("./b.mjs") +package b + +external class A { + fun foo(): String +} + +external fun bar(): Int + +external var prop: Int + +// FILE: main.kt + +import a.A as O +import b.A as K + +fun box(): String { + if (a.bar() != 1) return "fail 1" + if (a.prop != 10) return "fail 2" + if (b.bar() != 2) return "fail 3" + if (b.prop != 20) return "fail 4" + + return O().foo() + K().foo() +} + +// FILE: a.mjs +export function A() {} + +A.prototype.foo = function () { + return "O"; +}; + +export function bar() { return 1; } + +export let prop = 10 + + +// FILE: b.mjs +export function A() {} + +A.prototype.foo = function () { + return "K"; +}; + +export function bar() { return 2; } + +export let prop = 20; \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/jsModule/externalClassWithDefaults.kt b/js/js.translator/testData/box/esModules/jsModule/externalClassWithDefaults.kt new file mode 100644 index 00000000000..1abf29b8c15 --- /dev/null +++ b/js/js.translator/testData/box/esModules/jsModule/externalClassWithDefaults.kt @@ -0,0 +1,46 @@ +// EXPECTED_REACHABLE_NODES: 1284 +// ES_MODULES +// DONT_TARGET_EXACT_BACKEND: JS + +package foo + +@JsModule("./externalClassWithDefaults.mjs") +external open class A(ss: String = definedExternally) { + val s: String + fun foo(y: String = definedExternally): String = definedExternally + fun bar(y: String = definedExternally): String = definedExternally +} + +class C: A { + constructor(ss: String) : super(ss) {} + constructor() : super() {} + + fun qux(s: String = "O") = s +} + + +fun box(): String { + val a = A() + val c = C() + + val r1 = a.foo("O") + c.foo() + if (r1 != "OK") return "Fail1: $r1" + + val r2 = a.bar() + c.bar("K") + if (r2 != "OK") return "Fail2: $r2" + + val r3 = c.qux() + c.qux("K") + if (r3 != "OK") return "Fail3: $r3" + + if (a.s != "A") return "Fail4: ${a.s}" + if (c.s != "A") return "Fail5: ${c.s}" + + val a2 = A("A2") + val c2 = C("C2") + + val r6 = a2.s + c2.s + if (r6 != "A2C2") return "Fail6: $r6" + + return "OK" + +} \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/jsModule/externalClassWithDefaults.mjs b/js/js.translator/testData/box/esModules/jsModule/externalClassWithDefaults.mjs new file mode 100644 index 00000000000..1a1ebc0996c --- /dev/null +++ b/js/js.translator/testData/box/esModules/jsModule/externalClassWithDefaults.mjs @@ -0,0 +1,9 @@ +export default function A(ss) { + this.s = ss || "A" +} +A.prototype.foo = function (y) { + return y || "K"; +}; +A.prototype.bar = function (y) { + return y || "O"; +}; diff --git a/js/js.translator/testData/box/esModules/jsModule/externalConstructor.kt b/js/js.translator/testData/box/esModules/jsModule/externalConstructor.kt new file mode 100644 index 00000000000..47a9d24d3c8 --- /dev/null +++ b/js/js.translator/testData/box/esModules/jsModule/externalConstructor.kt @@ -0,0 +1,26 @@ +// EXPECTED_REACHABLE_NODES: 1334 +// ES_MODULES +// DONT_TARGET_EXACT_BACKEND: JS + +package foo + +@JsModule("./externalConstructor.mjs") +open external class A(data: String) { + constructor(data: Int) + constructor(data: Boolean) + + val data: Any +} + +class B(data: String) : A(data) + +class C(data: Int) : A(data) + +class D(data: Boolean) : A(data) + +fun box(): String { + assertEquals("13", B("13").data) + assertEquals(42, C(42).data) + assertEquals(true, D(true).data) + return "OK" +} diff --git a/js/js.translator/testData/box/esModules/jsModule/externalConstructor.mjs b/js/js.translator/testData/box/esModules/jsModule/externalConstructor.mjs new file mode 100644 index 00000000000..4882be91a6b --- /dev/null +++ b/js/js.translator/testData/box/esModules/jsModule/externalConstructor.mjs @@ -0,0 +1,3 @@ +export default function (data) { + this.data = data +} diff --git a/js/js.translator/testData/box/esModules/jsModule/externalFunction.kt b/js/js.translator/testData/box/esModules/jsModule/externalFunction.kt new file mode 100644 index 00000000000..63b09a4abc6 --- /dev/null +++ b/js/js.translator/testData/box/esModules/jsModule/externalFunction.kt @@ -0,0 +1,11 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +package foo + +@JsModule("./externalFunction.mjs") +external fun foo(y: Int): Int = definedExternally + +fun box(): String { + assertEquals(65, foo(42)) + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/jsModule/externalFunction.mjs b/js/js.translator/testData/box/esModules/jsModule/externalFunction.mjs new file mode 100644 index 00000000000..b80e3d97391 --- /dev/null +++ b/js/js.translator/testData/box/esModules/jsModule/externalFunction.mjs @@ -0,0 +1,3 @@ +export default function(y) { + return 23 + y; +} \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/jsModule/externalFunctionNameClash.kt b/js/js.translator/testData/box/esModules/jsModule/externalFunctionNameClash.kt new file mode 100644 index 00000000000..1b351fe6ff6 --- /dev/null +++ b/js/js.translator/testData/box/esModules/jsModule/externalFunctionNameClash.kt @@ -0,0 +1,14 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +package foo + +@JsModule("./externalFunctionNameClash.mjs") +external fun foo(y: Int): Int = definedExternally + +fun foo(y: String): String = y + "K" + +fun box(): String { + val foo10 = foo(10) + if (foo10 != 33) return "Fail: $foo10" + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/jsModule/externalFunctionNameClash.mjs b/js/js.translator/testData/box/esModules/jsModule/externalFunctionNameClash.mjs new file mode 100644 index 00000000000..b80e3d97391 --- /dev/null +++ b/js/js.translator/testData/box/esModules/jsModule/externalFunctionNameClash.mjs @@ -0,0 +1,3 @@ +export default function(y) { + return 23 + y; +} \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/jsModule/externalObject.kt b/js/js.translator/testData/box/esModules/jsModule/externalObject.kt new file mode 100644 index 00000000000..12c5ce444a2 --- /dev/null +++ b/js/js.translator/testData/box/esModules/jsModule/externalObject.kt @@ -0,0 +1,16 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +package foo + +@JsModule("./externalObject.mjs") +external object A { + val x: Int = definedExternally + + fun foo(y: Int): Int = definedExternally +} + +fun box(): String { + assertEquals(23, A.x) + assertEquals(65, A.foo(42)) + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/jsModule/externalObject.mjs b/js/js.translator/testData/box/esModules/jsModule/externalObject.mjs new file mode 100644 index 00000000000..5910b6ddaed --- /dev/null +++ b/js/js.translator/testData/box/esModules/jsModule/externalObject.mjs @@ -0,0 +1,6 @@ +export default { + x: 23, + foo: function(y) { + return this.x + y; + } +}; \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/jsModule/externalPackage.kt b/js/js.translator/testData/box/esModules/jsModule/externalPackage.kt new file mode 100644 index 00000000000..f3be1beffb8 --- /dev/null +++ b/js/js.translator/testData/box/esModules/jsModule/externalPackage.kt @@ -0,0 +1,45 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +// FILE: a.kt +@file:JsModule("./externalPackage.mjs") +package foo + +external class A(x: Int) { + val x: Int + + fun foo(y: Int): Int = definedExternally + + class Nested { + val y: Int + } +} + +external object B { + val x: Int = definedExternally + + fun foo(y: Int): Int = definedExternally +} + +external fun foo(y: Int): Int = definedExternally + +external val bar: Int = definedExternally + +// FILE: b.kt +package foo + +fun box(): String { + val a = A(23) + assertEquals(23, a.x) + assertEquals(65, a.foo(42)) + + val nested = A.Nested() + assertEquals(55, nested.y) + + assertEquals(123, B.x) + assertEquals(265, B.foo(142)) + + assertEquals(365, foo(42)) + assertEquals(423, bar) + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/jsModule/externalPackage.mjs b/js/js.translator/testData/box/esModules/jsModule/externalPackage.mjs new file mode 100644 index 00000000000..da3a03f4fb8 --- /dev/null +++ b/js/js.translator/testData/box/esModules/jsModule/externalPackage.mjs @@ -0,0 +1,24 @@ +export function A(x) { + this.x = x; +} +A.prototype.foo = function (y) { + return this.x + y; +}; + +function Nested() { + this.y = 55; +} +A.Nested = Nested; + +export var B = { + x: 123, + foo: function(y) { + return this.x + y; + } +}; + +export function foo(y) { + return 323 + y; +} + +export var bar = 423; diff --git a/js/js.translator/testData/box/esModules/jsModule/externalPackageInDifferentFile.js b/js/js.translator/testData/box/esModules/jsModule/externalPackageInDifferentFile.js new file mode 100644 index 00000000000..ebc42fcf001 --- /dev/null +++ b/js/js.translator/testData/box/esModules/jsModule/externalPackageInDifferentFile.js @@ -0,0 +1,5 @@ +C = { + f: function() { + return 12345; + } +}; \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/jsModule/externalPackageInDifferentFile.kt b/js/js.translator/testData/box/esModules/jsModule/externalPackageInDifferentFile.kt new file mode 100644 index 00000000000..a5ff720cd9d --- /dev/null +++ b/js/js.translator/testData/box/esModules/jsModule/externalPackageInDifferentFile.kt @@ -0,0 +1,47 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +// FILE: lib.kt +@file:JsModule("./externalPackageInDifferentFile.mjs") +package foo + +external class A(x: Int = definedExternally) { + val x: Int + + fun foo(y: Int): Int = definedExternally +} + +external object B { + val x: Int = definedExternally + + fun foo(y: Int): Int = definedExternally +} + +external fun foo(y: Int): Int = definedExternally + +external val bar: Int = definedExternally + +// FILE: lib2.kt +package foo + +external object C { + fun f(): Int = definedExternally +} + +// FILE: main.kt +package foo + +fun box(): String { + val a = A(23) + assertEquals(23, a.x) + assertEquals(65, a.foo(42)) + + assertEquals(123, B.x) + assertEquals(265, B.foo(142)) + + assertEquals(365, foo(42)) + assertEquals(423, bar) + + assertEquals(12345, C.f()) + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/jsModule/externalPackageInDifferentFile.mjs b/js/js.translator/testData/box/esModules/jsModule/externalPackageInDifferentFile.mjs new file mode 100644 index 00000000000..05d313576b2 --- /dev/null +++ b/js/js.translator/testData/box/esModules/jsModule/externalPackageInDifferentFile.mjs @@ -0,0 +1,21 @@ +function A(x) { + this.x = x; +} +A.prototype.foo = function (y) { + return this.x + y; +}; + +var B = { + x: 123, + foo: function(y) { + return this.x + y; + } +}; + +function foo(y) { + return 323 + y; +} + +var bar = 423; + +export { A, B, foo, bar }; \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/jsModule/externalProperty.kt b/js/js.translator/testData/box/esModules/jsModule/externalProperty.kt new file mode 100644 index 00000000000..0cfd2c840d5 --- /dev/null +++ b/js/js.translator/testData/box/esModules/jsModule/externalProperty.kt @@ -0,0 +1,11 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +package foo + +@JsModule("./externalProperty.mjs") +external val foo: Int = definedExternally + +fun box(): String { + assertEquals(23, foo) + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/jsModule/externalProperty.mjs b/js/js.translator/testData/box/esModules/jsModule/externalProperty.mjs new file mode 100644 index 00000000000..19835cac6f8 --- /dev/null +++ b/js/js.translator/testData/box/esModules/jsModule/externalProperty.mjs @@ -0,0 +1 @@ +export default 23; \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/jsModule/interfaces.kt b/js/js.translator/testData/box/esModules/jsModule/interfaces.kt new file mode 100644 index 00000000000..c01aa0e44a1 --- /dev/null +++ b/js/js.translator/testData/box/esModules/jsModule/interfaces.kt @@ -0,0 +1,33 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +// FILE: bar.kt +@file:JsModule("./interfaces.mjs") +@file:JsQualifier("foo") +package foo + +external interface Bar { + fun ping(): String +} + +// FILE: baz.kt +@file:JsModule("./interfaces.mjs") +package boo + +external interface Baz { + fun pong(): Int +} + +// FILE: root.kt +@file:JsModule("./interfaces.mjs") +import foo.Bar +import boo.Baz + +external val bar: Bar +external val baz: Baz + +// FILE: test.kt +fun box(): String { + if (bar.ping() != "ping" || baz.pong() != 194) return "Fail" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/jsModule/interfaces.mjs b/js/js.translator/testData/box/esModules/jsModule/interfaces.mjs new file mode 100644 index 00000000000..b5027cc52aa --- /dev/null +++ b/js/js.translator/testData/box/esModules/jsModule/interfaces.mjs @@ -0,0 +1,12 @@ +export var bar = { + ping() { + return "ping" + } +}; + +export var baz = { + pong() { + return 194 + } +}; + diff --git a/js/js.translator/testData/box/esModules/jsModule/topLevelVarargFun.kt b/js/js.translator/testData/box/esModules/jsModule/topLevelVarargFun.kt new file mode 100644 index 00000000000..93b07a89f54 --- /dev/null +++ b/js/js.translator/testData/box/esModules/jsModule/topLevelVarargFun.kt @@ -0,0 +1,15 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +@JsModule("./topLevelVarargFun.mjs") +external fun foo(vararg arg: String): String + +fun box(): String { + val x = arrayOf("a", "b") + var r = foo(*x) + if (r != "(ab)") return "fail1: $r" + + r = foo("c", "d") + if (r != "(cd)") return "fail2: $r" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/jsModule/topLevelVarargFun.mjs b/js/js.translator/testData/box/esModules/jsModule/topLevelVarargFun.mjs new file mode 100644 index 00000000000..a447c76b06d --- /dev/null +++ b/js/js.translator/testData/box/esModules/jsModule/topLevelVarargFun.mjs @@ -0,0 +1,3 @@ +export default function() { + return "(" + Array.prototype.join.call(arguments, "") + ")"; +}; diff --git a/js/js.translator/testData/box/esModules/jsName/defaultJsName.kt b/js/js.translator/testData/box/esModules/jsName/defaultJsName.kt new file mode 100644 index 00000000000..8ebe95c2b9c --- /dev/null +++ b/js/js.translator/testData/box/esModules/jsName/defaultJsName.kt @@ -0,0 +1,34 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +// MODULE: main +// FILE: lib.kt +@file:JsModule("./foo.mjs") +package lib + +@JsName("default") +external val foo: Int + +// FILE: lib2.kt +@file:JsModule("./bar.mjs") +package lib + +@JsName("default") +external fun foo(): Int + +// FILE: main.kt +package main + +import lib.* + +fun box(): String { + if (foo != 23 && foo() != 23) return "fail" + return "OK" +} + +// FILE: foo.mjs + +export default 23; + +// FILE: bar.mjs + +export default function() { return 23; }; \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/jsName/jsTopLevelClashes.kt b/js/js.translator/testData/box/esModules/jsName/jsTopLevelClashes.kt new file mode 100644 index 00000000000..474d0532028 --- /dev/null +++ b/js/js.translator/testData/box/esModules/jsName/jsTopLevelClashes.kt @@ -0,0 +1,32 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES +// MODULE: main +// FILE: lib.kt +@file:JsModule("./foo.mjs") +package lib + +@JsName("test") +external val foo: Int + +// FILE: lib2.kt +@file:JsModule("./bar.mjs") +package lib + +@JsName("test") +external val bar: Int + +// FILE: main.kt +package main + +import lib.* + +fun box(): String { + if (foo != 23 || bar != 45) return "fail" + return "OK" +} + +// FILE: foo.mjs +export var test = 23; + +// FILE: bar.mjs +export var test = 45; \ No newline at end of file diff --git a/js/js.translator/testData/box/esModules/native/inheritanceInNativeClass.kt b/js/js.translator/testData/box/esModules/native/inheritanceInNativeClass.kt new file mode 100644 index 00000000000..a5e8fab9678 --- /dev/null +++ b/js/js.translator/testData/box/esModules/native/inheritanceInNativeClass.kt @@ -0,0 +1,59 @@ +// DONT_TARGET_EXACT_BACKEND: JS +// ES_MODULES + +// FILE: main.kt + +@JsExport +open class A { + @JsName("foo") + open protected fun foo(n: Int) = 23 + + @JsName("bar") + fun bar(n: Int) = foo(n) + 100 +} + +@JsExport +open class B { + @JsName("foo") + protected fun foo(n: Int) = 42 + + @JsName("bar") + open fun bar(n: Int) = 142 +} + +// FILE: entry.mjs +// ENTRY_ES_MODULE + +import { A, B } from "./JS_TESTS/index.js"; + +function createA() { + function ADerived() { + } + ADerived.prototype = Object.create(A.prototype); + ADerived.prototype.foo = function(n) { + return 24; + }; + return new ADerived(); +} + +function createB() { + function BDerived() { + } + BDerived.prototype = Object.create(B.prototype); + BDerived.prototype.bar = function(n) { + return this.foo(n); + }; + return new BDerived(); +} + +function box() { + let a = createA(); + if (a.bar(0) != 124) return "fail1"; + + let b = createB(); + if (b.bar(0) != 42) return "fail2"; + + return "OK"; +} + +console.assert(box() == "OK"); diff --git a/js/js.translator/testData/box/expression/function/manglingClashWithFunctionsWithoutParameters.kt b/js/js.translator/testData/box/expression/function/manglingClashWithFunctionsWithoutParameters.kt index ede215602e4..de54c637813 100644 --- a/js/js.translator/testData/box/expression/function/manglingClashWithFunctionsWithoutParameters.kt +++ b/js/js.translator/testData/box/expression/function/manglingClashWithFunctionsWithoutParameters.kt @@ -1,4 +1,7 @@ +// DONT_TARGET_EXACT_BACKEND: JS_IR +// DONT_TARGET_EXACT_BACKEND: JS_IR_ES6 // EXPECTED_REACHABLE_NODES: 1303 + package foo fun foo(i: Int): String = "foo" + i diff --git a/js/js.translator/testData/box/expression/function/manglingStability.kt b/js/js.translator/testData/box/expression/function/manglingStability.kt index ae2e543bc36..d14e55bb81b 100644 --- a/js/js.translator/testData/box/expression/function/manglingStability.kt +++ b/js/js.translator/testData/box/expression/function/manglingStability.kt @@ -1,4 +1,7 @@ +// DONT_TARGET_EXACT_BACKEND: JS_IR +// DONT_TARGET_EXACT_BACKEND: JS_IR_ES6 // EXPECTED_REACHABLE_NODES: 1334 + package foo diff --git a/js/js.translator/testData/box/native/eval.kt b/js/js.translator/testData/box/native/eval.kt index 4da2663adb0..a119f735195 100644 --- a/js/js.translator/testData/box/native/eval.kt +++ b/js/js.translator/testData/box/native/eval.kt @@ -1,6 +1,5 @@ // SKIP_MINIFICATION -@JsExport val top = "TOP LEVEL" fun box(): String { @@ -10,8 +9,10 @@ fun box(): String { assertEquals(5, eval("3 + 2")) - val PACKAGE = "JS_TESTS" - assertEquals(top, eval("$PACKAGE.top")) + if (testUtils.isLegacyBackend()) { + val PACKAGE = "JS_TESTS" + assertEquals(top, eval("$PACKAGE.top")) + } return "OK" } \ No newline at end of file diff --git a/js/js.translator/testData/typescript-export/constructors/constructors.d.ts b/js/js.translator/testData/typescript-export/constructors/constructors.d.ts index 5c712041e5e..ba056a916fb 100644 --- a/js/js.translator/testData/typescript-export/constructors/constructors.d.ts +++ b/js/js.translator/testData/typescript-export/constructors/constructors.d.ts @@ -19,17 +19,17 @@ declare namespace JS_TESTS { static createFromString(y: string): ClassWithMultipleSecondaryCtors; static createFromInts(y: number, z: number): ClassWithMultipleSecondaryCtors; } + class DerivedClassWithSecondaryCtor extends OpenClassWithMixedConstructors { + private constructor(); + static delegateToPrimary(y: string): DerivedClassWithSecondaryCtor; + static delegateToCreateFromInts(y: number, z: number): DerivedClassWithSecondaryCtor; + } class OpenClassWithMixedConstructors { constructor(x: string); readonly x: string; static createFromStrings(y: string, z: string): OpenClassWithMixedConstructors; static createFromInts(y: number, z: number): OpenClassWithMixedConstructors; } - class DerivedClassWithSecondaryCtor extends OpenClassWithMixedConstructors { - private constructor(); - static delegateToPrimary(y: string): DerivedClassWithSecondaryCtor; - static delegateToCreateFromInts(y: number, z: number): DerivedClassWithSecondaryCtor; - } class KotlinGreeter { constructor(greeting: string); readonly greeting: string; diff --git a/js/js.translator/testData/typescript-export/inheritance/inheritance.d.ts b/js/js.translator/testData/typescript-export/inheritance/inheritance.d.ts index 1c92ff5378c..85c100f5f83 100644 --- a/js/js.translator/testData/typescript-export/inheritance/inheritance.d.ts +++ b/js/js.translator/testData/typescript-export/inheritance/inheritance.d.ts @@ -13,20 +13,6 @@ declare namespace JS_TESTS { } } namespace foo { - abstract class AC implements foo.I2 { - constructor(); - x: string; - abstract readonly y: boolean; - abstract z(z: number): void; - readonly acProp: string; - abstract readonly acAbstractProp: string; - } - class OC extends foo.AC implements foo.I { - constructor(y: boolean, acAbstractProp: string); - readonly y: boolean; - readonly acAbstractProp: string; - z(z: number): void; - } class FC extends foo.OC { constructor(); } @@ -36,4 +22,22 @@ declare namespace JS_TESTS { foo(): number; } & foo.OC; } + namespace foo { + abstract class AC implements foo.I2 { + constructor(); + x: string; + abstract readonly y: boolean; + abstract z(z: number): void; + readonly acProp: string; + abstract readonly acAbstractProp: string; + } + } + namespace foo { + class OC extends foo.AC implements foo.I { + constructor(y: boolean, acAbstractProp: string); + readonly y: boolean; + readonly acAbstractProp: string; + z(z: number): void; + } + } }