From 97605a97da1d034d075be1d6f4b372fffac4a5c8 Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Tue, 21 Jun 2016 14:26:52 +0300 Subject: [PATCH] KT-3008: multiple minor fixes after code review --- .../arguments/K2JsArgumentConstants.java | 5 + .../jetbrains/kotlin/cli/js/K2JSCompiler.java | 10 +- .../utils/KotlinJavascriptMetadataUtils.kt | 2 +- .../KotlinCompilerConfigurableTab.java | 4 +- .../kotlin/js/inline/FunctionReader.kt | 2 +- .../js/KotlinJavascriptSerializationUtil.kt | 6 +- .../test/semantics/MultiModuleWrappersTest.kt | 16 -- .../kotlin/js/facade/TranslationResult.kt | 3 +- .../js/translate/context/StandardClasses.java | 2 - .../js/translate/context/StaticContext.java | 8 +- .../general/ModuleWrapperTranslation.java | 194 ------------------ .../general/ModuleWrapperTranslation.kt | 146 +++++++++++++ .../js/translate/general/Translation.java | 13 +- .../js/translate/utils/JsDescriptorUtils.java | 2 +- js/js.translator/testData/closure-wrapper.txt | 5 +- .../testData/export_Kotlin_if_possible.js | 3 - js/js.translator/testData/kotlin_lib.js | 7 +- js/js.translator/testData/kotlin_lib_ecma5.js | 16 +- js/js.translator/testData/maps.js | 3 +- js/js.translator/testData/merge.js | 13 +- 20 files changed, 190 insertions(+), 270 deletions(-) delete mode 100644 js/js.translator/src/org/jetbrains/kotlin/js/translate/general/ModuleWrapperTranslation.java create mode 100644 js/js.translator/src/org/jetbrains/kotlin/js/translate/general/ModuleWrapperTranslation.kt delete mode 100644 js/js.translator/testData/export_Kotlin_if_possible.js 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 99fbc7e9ace..d371674c044 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 @@ -19,4 +19,9 @@ package org.jetbrains.kotlin.cli.common.arguments; public interface K2JsArgumentConstants { String CALL = "call"; String NO_CALL = "noCall"; + + String MODULE_PLAIN = "plain"; + String MODULE_AMD = "amd"; + String MODULE_COMMONJS = "commonjs"; + String MODULE_UMD = "umd"; } diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/js/K2JSCompiler.java b/compiler/cli/src/org/jetbrains/kotlin/cli/js/K2JSCompiler.java index 3f4df66a308..2478aff6063 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/js/K2JSCompiler.java +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/js/K2JSCompiler.java @@ -74,10 +74,10 @@ public class K2JSCompiler extends CLICompiler { private static final Map moduleKindMap = new HashMap(); static { - moduleKindMap.put(K2JSCompilerArguments.MODULE_PLAIN, ModuleKind.PLAIN); - moduleKindMap.put(K2JSCompilerArguments.MODULE_COMMONJS, ModuleKind.COMMON_JS); - moduleKindMap.put(K2JSCompilerArguments.MODULE_AMD, ModuleKind.AMD); - moduleKindMap.put(K2JSCompilerArguments.MODULE_UMD, ModuleKind.UMD); + moduleKindMap.put(K2JsArgumentConstants.MODULE_PLAIN, ModuleKind.PLAIN); + moduleKindMap.put(K2JsArgumentConstants.MODULE_COMMONJS, ModuleKind.COMMON_JS); + moduleKindMap.put(K2JsArgumentConstants.MODULE_AMD, ModuleKind.AMD); + moduleKindMap.put(K2JsArgumentConstants.MODULE_UMD, ModuleKind.UMD); } public static void main(String... args) { @@ -289,7 +289,7 @@ public class K2JSCompiler extends CLICompiler { ModuleKind moduleKind = moduleKindName != null ? moduleKindMap.get(moduleKindName) : ModuleKind.PLAIN; if (moduleKind == null) { messageCollector.report(CompilerMessageSeverity.ERROR, "Unknown module kind: " + moduleKindName + ". " + - "valid values are: plain, amd, commonjs, umd", + "Valid values are: plain, amd, commonjs, umd", CompilerMessageLocation.NO_LOCATION); } configuration.put(JSConfigurationKeys.MODULE_KIND, moduleKind); diff --git a/compiler/util/src/org/jetbrains/kotlin/utils/KotlinJavascriptMetadataUtils.kt b/compiler/util/src/org/jetbrains/kotlin/utils/KotlinJavascriptMetadataUtils.kt index 4327c714fad..d94a0be9de7 100644 --- a/compiler/util/src/org/jetbrains/kotlin/utils/KotlinJavascriptMetadataUtils.kt +++ b/compiler/util/src/org/jetbrains/kotlin/utils/KotlinJavascriptMetadataUtils.kt @@ -31,7 +31,7 @@ class JsBinaryVersion(vararg numbers: Int) : BinaryVersion(*numbers) { companion object { @JvmField - val INSTANCE = JsBinaryVersion(0, 3, 0) + val INSTANCE = JsBinaryVersion(0, 4, 0) @JvmField val INVALID_VERSION = JsBinaryVersion() diff --git a/idea/src/org/jetbrains/kotlin/idea/compiler/configuration/KotlinCompilerConfigurableTab.java b/idea/src/org/jetbrains/kotlin/idea/compiler/configuration/KotlinCompilerConfigurableTab.java index e60cdb5a12c..8b76a36ac2a 100644 --- a/idea/src/org/jetbrains/kotlin/idea/compiler/configuration/KotlinCompilerConfigurableTab.java +++ b/idea/src/org/jetbrains/kotlin/idea/compiler/configuration/KotlinCompilerConfigurableTab.java @@ -33,6 +33,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments; import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments; +import org.jetbrains.kotlin.cli.common.arguments.K2JsArgumentConstants; import org.jetbrains.kotlin.config.CompilerSettings; import org.jetbrains.kotlin.idea.KotlinBundle; import org.jetbrains.kotlin.idea.PluginStartupComponent; @@ -51,7 +52,8 @@ public class KotlinCompilerConfigurableTab implements SearchableConfigurable, Co "CommonJS/node.js", "UMD (detect AMD or CommonJS if available, fallback to plain)" ); - private static final List moduleKindIds = asList("plain", "amd", "commonjs", "umd"); + private static final List moduleKindIds = asList(K2JsArgumentConstants.MODULE_PLAIN, K2JsArgumentConstants.MODULE_AMD, + K2JsArgumentConstants.MODULE_COMMONJS, K2JsArgumentConstants.MODULE_UMD); private final CommonCompilerArguments commonCompilerArguments; private final K2JSCompilerArguments k2jsCompilerArguments; private final CompilerSettings compilerSettings; diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/FunctionReader.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/FunctionReader.kt index daf06e65074..2f88cc231a4 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/FunctionReader.kt +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/FunctionReader.kt @@ -150,7 +150,7 @@ class FunctionReader(private val context: TranslationContext) { val function = parseFunction(source, offset, ThrowExceptionOnErrorReporter, JsRootScope(JsProgram(""))) val moduleName = getExternalModuleName(descriptor)!! val moduleNameLiteral = context.program().getStringLiteral(moduleName) - val moduleReference = context.namer().getModuleReference(moduleNameLiteral) + val moduleReference = context.namer().getModuleReference(moduleNameLiteral) val replacements = hashMapOf(moduleRootVariable[moduleName]!! to moduleReference, moduleKotlinVariable[moduleName]!! to Namer.kotlinObject()) 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 cac0baa5bf3..663c69bd17a 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 @@ -58,10 +58,8 @@ object KotlinJavascriptSerializationUtil { @JvmStatic fun readModule(metadata: ByteArray, storageManager: StorageManager, kotlinModule: ModuleDescriptor): JsModuleDescriptor { - val prototype = metadata.toContentMap() - - val packageFragmentProvider = createPackageFragmentProvider(kotlinModule, prototype.contentMap, storageManager) - return JsModuleDescriptor(kotlinModule.name.asString(), prototype.kind, prototype.imported, packageFragmentProvider) + val jsModule = metadata.readAsContentMap(kotlinModule.name.asString()) + return jsModule.copy(createPackageFragmentProvider(kotlinModule, jsModule.data, storageManager)) } @JvmStatic private fun createPackageFragmentProvider(moduleDescriptor: ModuleDescriptor, contentMap: Map, diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/MultiModuleWrappersTest.kt b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/MultiModuleWrappersTest.kt index 5025b7900c6..0aef8385a96 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/MultiModuleWrappersTest.kt +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/MultiModuleWrappersTest.kt @@ -14,22 +14,6 @@ * limitations under the License. */ -/* - * Copyright 2010-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package org.jetbrains.kotlin.js.test.semantics import org.jetbrains.kotlin.js.test.MultipleModulesTranslationTest diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/facade/TranslationResult.kt b/js/js.translator/src/org/jetbrains/kotlin/js/facade/TranslationResult.kt index d04bf2ed340..0da4fd783be 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/facade/TranslationResult.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/facade/TranslationResult.kt @@ -37,7 +37,6 @@ import java.io.File import java.util.* abstract class TranslationResult protected constructor(val diagnostics: Diagnostics) { - class Fail(diagnostics: Diagnostics) : TranslationResult(diagnostics) class Success( @@ -80,7 +79,7 @@ abstract class TranslationResult protected constructor(val diagnostics: Diagnost data = moduleDescriptor, kind = config.moduleKind, imported = importedModules - ); + ) val metaFileContent = KotlinJavascriptSerializationUtil.metadataAsString(moduleDescription) val sourceFilesForMetaFile = ArrayList(sourceFiles) val jsMetaFile = SimpleOutputFile(sourceFilesForMetaFile, metaFileName, metaFileContent) diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/StandardClasses.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/StandardClasses.java index 233d4315147..cfb02fbd035 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/StandardClasses.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/StandardClasses.java @@ -113,8 +113,6 @@ public final class StandardClasses { standardClasses.declare().forFQ("kotlin.Comparable").kotlinClass("Comparable"); standardClasses.declare().forFQ("kotlin.Throwable").kotlinClass("Throwable"); - - standardClasses.declare().forFQ("kotlin.Annotation").kotlinClass("Annotation"); } diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/StaticContext.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/StaticContext.java index 3bd0ad0355a..4f55be55afe 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/StaticContext.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/StaticContext.java @@ -113,7 +113,7 @@ public final class StaticContext { @NotNull private final Map importedModules = new LinkedHashMap(); - private Map importedModulesSafe; + private Map readOnlyImportedModules; //TODO: too many parameters in constructor private StaticContext( @@ -173,10 +173,10 @@ public final class StaticContext { @NotNull public Map getImportedModules() { - if (importedModulesSafe == null) { - importedModulesSafe = Collections.unmodifiableMap(importedModules); + if (readOnlyImportedModules == null) { + readOnlyImportedModules = Collections.unmodifiableMap(importedModules); } - return importedModulesSafe; + return readOnlyImportedModules; } @NotNull diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/general/ModuleWrapperTranslation.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/general/ModuleWrapperTranslation.java deleted file mode 100644 index c1db6f6fd58..00000000000 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/general/ModuleWrapperTranslation.java +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright 2010-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.js.translate.general; - -import com.google.dart.compiler.backend.js.ast.*; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.kotlin.js.translate.context.Namer; -import org.jetbrains.kotlin.js.translate.utils.JsAstUtils; -import org.jetbrains.kotlin.serialization.js.ModuleKind; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -public final class ModuleWrapperTranslation { - private ModuleWrapperTranslation() { - } - - @NotNull - public static List wrapIfNecessary( - @Nullable String moduleId, - @NotNull JsExpression function, - @NotNull List importedModules, - @NotNull JsProgram program, - @NotNull ModuleKind kind - ) { - switch (kind) { - case AMD: - return wrapAmd(moduleId, function, importedModules, program); - case COMMON_JS: - return wrapCommonJs(function, importedModules, program); - case UMD: - return wrapUmd(moduleId, function, importedModules, program); - case PLAIN: - default: - return wrapPlain(moduleId, function, importedModules, program); - } - } - - @NotNull - private static List wrapUmd( - @Nullable String moduleId, - @NotNull JsExpression function, - @NotNull List importedModules, - @NotNull JsProgram program - ) { - JsScope scope = program.getScope(); - JsName rootName = scope.declareName("root"); - JsName factoryName = scope.declareName("factory"); - JsName defineName = scope.declareName("define"); - JsName exportsName = scope.declareName("exports"); - - JsExpression amdTest = JsAstUtils.and(JsAstUtils.typeOfIs(defineName.makeRef(), program.getStringLiteral("function")), - new JsNameRef("amd", defineName.makeRef())); - JsExpression commonJsTest = JsAstUtils.typeOfIs(exportsName.makeRef(), program.getStringLiteral("object")); - - JsBlock amdBody = new JsBlock(wrapAmd(moduleId, factoryName.makeRef(), importedModules, program)); - JsBlock commonJsBody = new JsBlock(wrapCommonJs(factoryName.makeRef(), importedModules, program)); - JsInvocation plainInvocation = makePlainInvocation(factoryName.makeRef(), importedModules, program); - - JsExpression plainExpr; - if (moduleId != null) { - JsExpression lhs = Namer.requiresEscaping(moduleId) ? - new JsArrayAccess(rootName.makeRef(), program.getStringLiteral(moduleId)) : - new JsNameRef(scope.declareName(moduleId), rootName.makeRef()); - plainExpr = JsAstUtils.assignment(lhs, plainInvocation); - } - else { - plainExpr = plainInvocation; - } - - JsStatement selector = JsAstUtils.newJsIf(amdTest, amdBody, JsAstUtils.newJsIf(commonJsTest, commonJsBody, plainExpr.makeStmt())); - JsFunction adapter = new JsFunction(program.getScope(), new JsBlock(selector), "UMD adapter"); - adapter.getParameters().add(new JsParameter(rootName)); - adapter.getParameters().add(new JsParameter(factoryName)); - - return Collections.singletonList(new JsInvocation(adapter, JsLiteral.THIS, function).makeStmt()); - } - - @NotNull - private static List wrapAmd( - @Nullable String moduleId, - @NotNull JsExpression function, - @NotNull List importedModules, - @NotNull JsProgram program - ) { - JsScope scope = program.getScope(); - JsName defineName = scope.declareName("define"); - List invocationArgs = new ArrayList(); - - if (moduleId != null) { - invocationArgs.add(program.getStringLiteral(moduleId)); - } - - List moduleNameList = new ArrayList(importedModules.size()); - for (ImportedModule importedModule : importedModules) { - moduleNameList.add(program.getStringLiteral(importedModule.id)); - } - invocationArgs.add(new JsArrayLiteral(moduleNameList)); - - invocationArgs.add(function); - - JsInvocation invocation = new JsInvocation(defineName.makeRef(), invocationArgs); - return Collections.singletonList(invocation.makeStmt()); - } - - @NotNull - private static List wrapCommonJs( - @NotNull JsExpression function, - @NotNull List importedModules, - @NotNull JsProgram program - ) { - JsScope scope = program.getScope(); - JsName moduleName = scope.declareName("module"); - JsName requireName = scope.declareName("require"); - - List invocationArgs = new ArrayList(); - for (ImportedModule importedModule : importedModules) { - invocationArgs.add(new JsInvocation(requireName.makeRef(), program.getStringLiteral(importedModule.id))); - } - - JsInvocation invocation = new JsInvocation(function, invocationArgs); - JsExpression assignment = JsAstUtils.assignment(new JsNameRef("exports", moduleName.makeRef()), invocation); - return Collections.singletonList(assignment.makeStmt()); - } - - @NotNull - private static List wrapPlain( - @Nullable String moduleId, - @NotNull JsExpression function, - @NotNull List importedModules, - @NotNull JsProgram program - ) { - JsInvocation invocation = makePlainInvocation(function, importedModules, program); - - JsStatement statement; - if (moduleId == null) { - statement = invocation.makeStmt(); - } - else { - statement = Namer.requiresEscaping(moduleId) ? - JsAstUtils.assignment(makePlainModuleRef(moduleId, program), invocation).makeStmt() : - JsAstUtils.newVar(program.getRootScope().declareName(moduleId), invocation); - } - - return Collections.singletonList(statement); - } - - @NotNull - private static JsInvocation makePlainInvocation(@NotNull JsExpression function, @NotNull List importedModules, - @NotNull JsProgram program) { - List invocationArgs = new ArrayList(importedModules.size()); - - for (ImportedModule importedModule : importedModules) { - invocationArgs.add(makePlainModuleRef(importedModule.id, program)); - } - - return new JsInvocation(function, invocationArgs); - } - - @NotNull - private static JsExpression makePlainModuleRef(@NotNull String moduleId, @NotNull JsProgram program) { - // TODO: we could use `this.moduleName` syntax. However, this does not work for `kotlin` module in Rhino, since - // we run kotlin.js in a parent scope. Consider better solution - return Namer.requiresEscaping(moduleId) ? - new JsArrayAccess(JsLiteral.THIS, program.getStringLiteral(moduleId)) : - program.getScope().declareName(moduleId).makeRef(); - } - - static final class ImportedModule { - @NotNull public final String id; - @NotNull public final JsName name; - - public ImportedModule(@NotNull String id, @NotNull JsName name) { - this.id = id; - this.name = name; - } - } -} 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 new file mode 100644 index 00000000000..0c41412157b --- /dev/null +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/general/ModuleWrapperTranslation.kt @@ -0,0 +1,146 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.js.translate.general + +import com.google.dart.compiler.backend.js.ast.* +import org.jetbrains.kotlin.js.translate.context.Namer +import org.jetbrains.kotlin.js.translate.utils.JsAstUtils +import org.jetbrains.kotlin.serialization.js.ModuleKind + +object ModuleWrapperTranslation { + @JvmStatic fun wrapIfNecessary( + moduleId: String?, function: JsExpression, importedModules: List, + program: JsProgram, kind: ModuleKind + ): List { + return when (kind) { + ModuleKind.AMD -> wrapAmd(moduleId, function, importedModules, program) + ModuleKind.COMMON_JS -> wrapCommonJs(function, importedModules, program) + ModuleKind.UMD -> wrapUmd(moduleId, function, importedModules, program) + ModuleKind.PLAIN -> wrapPlain(moduleId, function, importedModules, program) + } + } + + private fun wrapUmd( + moduleId: String?, function: JsExpression, + importedModules: List, program: JsProgram + ): List { + val scope = program.scope + val defineName = scope.declareName("define") + val exportsName = scope.declareName("exports") + + val adapterBody = JsBlock() + val adapter = JsFunction(program.scope, adapterBody, "Adapter") + val rootName = adapter.scope.declareName("root") + val factoryName = adapter.scope.declareName("factory") + adapter.parameters += JsParameter(rootName) + adapter.parameters += JsParameter(factoryName) + + val amdTest = JsAstUtils.and(JsAstUtils.typeOfIs(defineName.makeRef(), program.getStringLiteral("function")), + JsNameRef("amd", defineName.makeRef())) + val commonJsTest = JsAstUtils.typeOfIs(exportsName.makeRef(), program.getStringLiteral("object")) + + val amdBody = JsBlock(wrapAmd(moduleId, factoryName.makeRef(), importedModules, program)) + val commonJsBody = JsBlock(wrapCommonJs(factoryName.makeRef(), importedModules, program)) + val plainInvocation = makePlainInvocation(factoryName.makeRef(), importedModules, program) + + val plainExpr: JsExpression = if (moduleId != null) { + val lhs: JsExpression = if (Namer.requiresEscaping(moduleId)) { + JsArrayAccess(rootName.makeRef(), program.getStringLiteral(moduleId)) + } + else { + JsNameRef(scope.declareName(moduleId), rootName.makeRef()) + } + JsAstUtils.assignment(lhs, plainInvocation) + } + else { + plainInvocation + } + + val selector = JsAstUtils.newJsIf(amdTest, amdBody, JsAstUtils.newJsIf(commonJsTest, commonJsBody, plainExpr.makeStmt())) + adapterBody.statements += selector + + return listOf(JsInvocation(adapter, JsLiteral.THIS, function).makeStmt()) + } + + private fun wrapAmd( + moduleId: String?,function: JsExpression, + importedModules: List, program: JsProgram + ): List { + val scope = program.scope + val defineName = scope.declareName("define") + val invocationArgs = mutableListOf() + + if (moduleId != null) { + invocationArgs += program.getStringLiteral(moduleId) + } + + val moduleNameList = importedModules.map { program.getStringLiteral(it) } + invocationArgs += JsArrayLiteral(moduleNameList) + invocationArgs += function + + val invocation = JsInvocation(defineName.makeRef(), invocationArgs) + return listOf(invocation.makeStmt()) + } + + private fun wrapCommonJs(function: JsExpression, importedModules: List, program: JsProgram): List { + val scope = program.scope + val moduleName = scope.declareName("module") + val requireName = scope.declareName("require") + + val invocationArgs = importedModules.map { JsInvocation(requireName.makeRef(), program.getStringLiteral(it)) } + val invocation = JsInvocation(function, invocationArgs) + val assignment = JsAstUtils.assignment(JsNameRef("exports", moduleName.makeRef()), invocation) + return listOf(assignment.makeStmt()) + } + + private fun wrapPlain( + moduleId: String?, function: JsExpression, + importedModules: List, program: JsProgram + ): List { + val invocation = makePlainInvocation(function, importedModules, program) + + val statement = if (moduleId == null) { + invocation.makeStmt() + } + else { + if (Namer.requiresEscaping(moduleId)) { + JsAstUtils.assignment(makePlainModuleRef(moduleId, program), invocation).makeStmt() + } + else { + JsAstUtils.newVar(program.rootScope.declareName(moduleId), invocation) + } + } + + return listOf(statement) + } + + private fun makePlainInvocation(function: JsExpression, importedModules: List, program: JsProgram): JsInvocation { + val invocationArgs = importedModules.map { makePlainModuleRef(it, program) } + return JsInvocation(function, invocationArgs) + } + + private fun makePlainModuleRef(moduleId: String, program: JsProgram): JsExpression { + // TODO: we could use `this.moduleName` syntax. However, this does not work for `kotlin` module in Rhino, since + // we run kotlin.js in a parent scope. Consider better solution + return if (Namer.requiresEscaping(moduleId)) { + JsArrayAccess(JsLiteral.THIS, program.getStringLiteral(moduleId)) + } + else { + program.scope.declareName(moduleId).makeRef() + } + } +} diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/general/Translation.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/general/Translation.java index 023d852665d..25131f889bd 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/general/Translation.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/general/Translation.java @@ -37,7 +37,6 @@ import org.jetbrains.kotlin.js.translate.declaration.PackageDeclarationTranslato import org.jetbrains.kotlin.js.translate.expression.ExpressionVisitor; import org.jetbrains.kotlin.js.translate.expression.FunctionTranslator; import org.jetbrains.kotlin.js.translate.expression.PatternTranslator; -import org.jetbrains.kotlin.js.translate.general.ModuleWrapperTranslation.ImportedModule; import org.jetbrains.kotlin.js.translate.test.JSRhinoUnitTester; import org.jetbrains.kotlin.js.translate.test.JSTestGenerator; import org.jetbrains.kotlin.js.translate.test.JSTester; @@ -50,7 +49,6 @@ import org.jetbrains.kotlin.psi.KtFile; import org.jetbrains.kotlin.psi.KtNamedFunction; import org.jetbrains.kotlin.resolve.BindingTrace; import org.jetbrains.kotlin.resolve.bindingContextUtil.BindingContextUtilsKt; -import org.jetbrains.kotlin.serialization.js.ModuleKind; import org.jetbrains.kotlin.utils.ExceptionUtilsKt; import java.util.ArrayList; @@ -58,7 +56,7 @@ import java.util.Collection; import java.util.Collections; import java.util.List; -import static org.jetbrains.kotlin.js.translate.general.ModuleWrapperTranslation.wrapIfNecessary; +import static org.jetbrains.kotlin.js.translate.general.ModuleWrapperTranslation.*; import static org.jetbrains.kotlin.js.translate.utils.BindingUtils.getFunctionDescriptor; import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.convertToStatement; import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.toStringLiteralList; @@ -213,16 +211,15 @@ public final class Translation { mayBeGenerateTests(files, config, rootBlock, context); // Invoke function passing modules as arguments - // This should help minifier tool to recognize references to this modules as local variables and make them shorter. - List importedModuleList = new ArrayList(); + // This should help minifier tool to recognize references to these modules as local variables and make them shorter. + List importedModuleList = new ArrayList(); JsName kotlinName = program.getScope().declareName(Namer.KOTLIN_NAME); rootFunction.getParameters().add(new JsParameter((kotlinName))); - importedModuleList.add(new ImportedModule(Namer.KOTLIN_LOWER_NAME, kotlinName)); + importedModuleList.add(Namer.KOTLIN_LOWER_NAME); for (String importedModule : staticContext.getImportedModules().keySet()) { rootFunction.getParameters().add(new JsParameter(staticContext.getImportedModules().get(importedModule))); - JsName globalId = program.getScope().declareName(Namer.suggestedModuleName(importedModule)); - importedModuleList.add(new ImportedModule(importedModule, globalId)); + importedModuleList.add(importedModule); } if (mainCallParameters.shouldBeGenerated()) { diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/JsDescriptorUtils.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/JsDescriptorUtils.java index 44f1d1ec7dc..4e05677e5da 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/JsDescriptorUtils.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/JsDescriptorUtils.java @@ -197,7 +197,7 @@ public final class JsDescriptorUtils { return element.getContainingFile().getUserData(LibrarySourcesConfig.EXTERNAL_MODULE_NAME); } - public static String getModuleNameFromDescriptorName(DeclarationDescriptor descriptor) { + private static String getModuleNameFromDescriptorName(DeclarationDescriptor descriptor) { ModuleDescriptor moduleDescriptor = DescriptorUtils.getContainingModule(descriptor); String moduleName = moduleDescriptor.getName().asString(); return moduleName.substring(1, moduleName.length() - 1); diff --git a/js/js.translator/testData/closure-wrapper.txt b/js/js.translator/testData/closure-wrapper.txt index b6ab157c0f6..ec90b7bb9cb 100644 --- a/js/js.translator/testData/closure-wrapper.txt +++ b/js/js.translator/testData/closure-wrapper.txt @@ -8,12 +8,11 @@ } }(this, function () { var Kotlin = {}; - var kotlin = Kotlin; function require() { return Kotlin; } var module = {}; %output% - Kotlin.modules.kotlin = mergedRoot; - return mergedRoot; + Kotlin.modules.kotlin = Kotlin; + return Kotlin; })); \ No newline at end of file diff --git a/js/js.translator/testData/export_Kotlin_if_possible.js b/js/js.translator/testData/export_Kotlin_if_possible.js deleted file mode 100644 index c5e6266980d..00000000000 --- a/js/js.translator/testData/export_Kotlin_if_possible.js +++ /dev/null @@ -1,3 +0,0 @@ -if (typeof module !== 'undefined' && module.exports) { - module.exports = Kotlin; -} \ No newline at end of file diff --git a/js/js.translator/testData/kotlin_lib.js b/js/js.translator/testData/kotlin_lib.js index e5b3e2fdc5d..06111c172fa 100644 --- a/js/js.translator/testData/kotlin_lib.js +++ b/js/js.translator/testData/kotlin_lib.js @@ -340,8 +340,6 @@ } }); - Kotlin.Annotation = Kotlin.createTraitNow(null); - Kotlin.Enum = Kotlin.createClassNow(null, function () { this.name$ = void 0; @@ -1240,8 +1238,7 @@ } return obj1; }; - - Kotlin.lazyInitClasses = Kotlin.lazyInitClasses || []; - Kotlin.lazyInitClasses.push(lazyInitClasses); + + Kotlin.createDefinition(lazyInitClasses, Kotlin); })(Kotlin); diff --git a/js/js.translator/testData/kotlin_lib_ecma5.js b/js/js.translator/testData/kotlin_lib_ecma5.js index 5f7cbdd12c3..1d94390f7f0 100644 --- a/js/js.translator/testData/kotlin_lib_ecma5.js +++ b/js/js.translator/testData/kotlin_lib_ecma5.js @@ -186,8 +186,7 @@ //noinspection JSUnfilteredForInLoop Object.defineProperty(constructor, innerTypeName, { get: innerType, - configurable: true, - enumerable: true + configurable: true }); } } @@ -226,7 +225,7 @@ Kotlin.createClass = function (basesFun, constructor, properties, staticProperties) { function $o() { var klass = Kotlin.createClassNow(getBases(basesFun), constructor, properties, staticProperties); - Object.defineProperty(this, $o.className, {value: klass, enumerable: true}); + Object.defineProperty(this, $o.className, {value: klass}); if (staticProperties && staticProperties.object_initializer$) { staticProperties.object_initializer$(klass); } @@ -302,7 +301,7 @@ Kotlin.createTrait = function (basesFun, properties, staticProperties) { function $o() { var klass = Kotlin.createTraitNow(getBases(basesFun), properties, staticProperties); - Object.defineProperty(this, $o.className, {value: klass, enumerable: true}); + Object.defineProperty(this, $o.className, {value: klass}); return klass; } @@ -325,7 +324,7 @@ var obj = new klass(); var metadata = klass.$metadata$; metadata.type = Kotlin.TYPE.OBJECT; - Object.defineProperty(this, $o.className, {value: obj, enumerable: true}); + Object.defineProperty(this, $o.className, {value: obj}); defineNestedTypes(obj, klass.$metadata$.types); copyProperties(obj, metadata.staticMembers); if (metadata.baseClass != null) { @@ -512,8 +511,7 @@ members[p].className = p; Object.defineProperty(definition, p, { get: members[p], - configurable: true, - enumerable: true + configurable: true }); } else { @@ -538,11 +536,11 @@ Kotlin.definePackage = function (initializer, members) { var definition = createDefinition(members); if (initializer === null) { - return {value: definition, enumerable: true}; + return {value: definition}; } else { var getter = createPackageGetter(definition, initializer); - return {get: getter, enumerable: true}; + return {get: getter}; } }; diff --git a/js/js.translator/testData/maps.js b/js/js.translator/testData/maps.js index e3b8fcebfbb..b5d0c17ad2f 100644 --- a/js/js.translator/testData/maps.js +++ b/js/js.translator/testData/maps.js @@ -1124,6 +1124,5 @@ Object.defineProperty(Kotlin, "ComplexHashSet", { get : function () { return Kotlin.HashSet; }}); - Kotlin.lazyInitClasses = Kotlin.lazyInitClasses || []; - Kotlin.lazyInitClasses.push(lazyInitClasses); + Kotlin.createDefinition(lazyInitClasses, Kotlin); }(Kotlin)); diff --git a/js/js.translator/testData/merge.js b/js/js.translator/testData/merge.js index 12902ffc742..91039d5ac8d 100644 --- a/js/js.translator/testData/merge.js +++ b/js/js.translator/testData/merge.js @@ -1,11 +1,6 @@ -var stdlib = module.exports; -var mergedRoot = Kotlin; - -for (var propertyName in stdlib) { - Kotlin[propertyName] = stdlib[propertyName]; -} (function () { - for (var i = 0; i < Kotlin.lazyInitClasses.length; ++i) { - Kotlin.createDefinition(Kotlin.lazyInitClasses[i], mergedRoot); - } + var stdlib = module.exports; + Object.getOwnPropertyNames(stdlib).forEach(function(propertyName) { + Kotlin[propertyName] = stdlib[propertyName]; + }); })();