[JS CLI] Support sourcemap generation for IR BE in CLI
#KT-46551 In Progress
This commit is contained in:
committed by
teamcityserver
parent
5a3efc1a98
commit
2460f5f9ae
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
* 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.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -516,7 +516,7 @@ public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static String calculateSourceMapSourceRoot(
|
static String calculateSourceMapSourceRoot(
|
||||||
@NotNull MessageCollector messageCollector,
|
@NotNull MessageCollector messageCollector,
|
||||||
@NotNull K2JSCompilerArguments arguments
|
@NotNull K2JSCompilerArguments arguments
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -284,10 +284,10 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
val jsCode = if (arguments.irDce && !arguments.irDceDriven) compiledModule.outputsAfterDce!! else compiledModule.outputs!!
|
val outputs = if (arguments.irDce && !arguments.irDceDriven) compiledModule.outputsAfterDce!! else compiledModule.outputs!!
|
||||||
outputFile.writeText(jsCode.jsCode)
|
outputFile.write(outputs)
|
||||||
jsCode.dependencies.forEach { (name, content) ->
|
outputs.dependencies.forEach { (name, content) ->
|
||||||
outputFile.resolveSibling("$name.js").writeText(content)
|
outputFile.resolveSibling("$name.js").write(content)
|
||||||
}
|
}
|
||||||
if (arguments.generateDts) {
|
if (arguments.generateDts) {
|
||||||
val dtsFile = outputFile.withReplacedExtensionOrNull(outputFile.extension, "d.ts")!!
|
val dtsFile = outputFile.withReplacedExtensionOrNull(outputFile.extension, "d.ts")!!
|
||||||
@@ -298,6 +298,15 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
|
|||||||
return OK
|
return OK
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun File.write(outputs: CompilationOutputs) {
|
||||||
|
writeText(outputs.jsCode)
|
||||||
|
outputs.sourceMap?.let {
|
||||||
|
val mapFile = resolveSibling("$name.map")
|
||||||
|
appendText("\n//# sourceMappingURL=${mapFile.name}")
|
||||||
|
mapFile.writeText(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun setupPlatformSpecificArgumentsAndServices(
|
override fun setupPlatformSpecificArgumentsAndServices(
|
||||||
configuration: CompilerConfiguration,
|
configuration: CompilerConfiguration,
|
||||||
arguments: K2JSCompilerArguments,
|
arguments: K2JSCompilerArguments,
|
||||||
@@ -310,9 +319,22 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
|
|||||||
}
|
}
|
||||||
configuration.put(JSConfigurationKeys.TARGET, EcmaVersion.defaultVersion())
|
configuration.put(JSConfigurationKeys.TARGET, EcmaVersion.defaultVersion())
|
||||||
|
|
||||||
// TODO: Support source maps
|
|
||||||
if (arguments.sourceMap) {
|
if (arguments.sourceMap) {
|
||||||
messageCollector.report(WARNING, "source-map argument is not supported yet", null)
|
configuration.put(JSConfigurationKeys.SOURCE_MAP, true)
|
||||||
|
if (arguments.sourceMapPrefix != null) {
|
||||||
|
configuration.put(JSConfigurationKeys.SOURCE_MAP_PREFIX, arguments.sourceMapPrefix!!)
|
||||||
|
}
|
||||||
|
|
||||||
|
var sourceMapSourceRoots = arguments.sourceMapBaseDirs
|
||||||
|
if (sourceMapSourceRoots == null && StringUtil.isNotEmpty(arguments.sourceMapPrefix)) {
|
||||||
|
sourceMapSourceRoots = K2JSCompiler.calculateSourceMapSourceRoot(messageCollector, arguments)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sourceMapSourceRoots != null) {
|
||||||
|
val sourceMapSourceRootList = StringUtil.split(sourceMapSourceRoots, File.pathSeparator)
|
||||||
|
configuration.put(JSConfigurationKeys.SOURCE_MAP_SOURCE_ROOTS, sourceMapSourceRootList)
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (arguments.sourceMapPrefix != null) {
|
if (arguments.sourceMapPrefix != null) {
|
||||||
messageCollector.report(WARNING, "source-map-prefix argument has no effect without source map", null)
|
messageCollector.report(WARNING, "source-map-prefix argument has no effect without source map", null)
|
||||||
|
|||||||
@@ -32,7 +32,11 @@ class CompilerResult(
|
|||||||
val tsDefinitions: String? = null
|
val tsDefinitions: String? = null
|
||||||
)
|
)
|
||||||
|
|
||||||
class CompilationOutputs(val jsCode: String, val dependencies: Iterable<Pair<String, String>> = emptyList())
|
class CompilationOutputs(
|
||||||
|
val jsCode: String,
|
||||||
|
val sourceMap: String? = null,
|
||||||
|
val dependencies: Iterable<Pair<String, CompilationOutputs>> = emptyList()
|
||||||
|
)
|
||||||
|
|
||||||
fun compile(
|
fun compile(
|
||||||
project: Project,
|
project: Project,
|
||||||
|
|||||||
+52
-12
@@ -5,8 +5,8 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
|
package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
|
||||||
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.CompilerResult
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.CompilationOutputs
|
import org.jetbrains.kotlin.ir.backend.js.CompilationOutputs
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.CompilerResult
|
||||||
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||||
import org.jetbrains.kotlin.ir.backend.js.eliminateDeadDeclarations
|
import org.jetbrains.kotlin.ir.backend.js.eliminateDeadDeclarations
|
||||||
import org.jetbrains.kotlin.ir.backend.js.export.ExportModelGenerator
|
import org.jetbrains.kotlin.ir.backend.js.export.ExportModelGenerator
|
||||||
@@ -19,9 +19,17 @@ import org.jetbrains.kotlin.ir.declarations.*
|
|||||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
import org.jetbrains.kotlin.ir.util.isEffectivelyExternal
|
import org.jetbrains.kotlin.ir.util.isEffectivelyExternal
|
||||||
import org.jetbrains.kotlin.ir.util.isInterface
|
import org.jetbrains.kotlin.ir.util.isInterface
|
||||||
|
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.backend.ast.*
|
||||||
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
||||||
|
import org.jetbrains.kotlin.js.config.SourceMapSourceEmbedding
|
||||||
|
import org.jetbrains.kotlin.js.sourceMap.SourceFilePathResolver
|
||||||
|
import org.jetbrains.kotlin.js.sourceMap.SourceMap3Builder
|
||||||
|
import org.jetbrains.kotlin.js.sourceMap.SourceMapBuilderConsumer
|
||||||
|
import org.jetbrains.kotlin.js.util.TextOutputImpl
|
||||||
import org.jetbrains.kotlin.utils.DFS
|
import org.jetbrains.kotlin.utils.DFS
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
class IrModuleToJsTransformer(
|
class IrModuleToJsTransformer(
|
||||||
private val backendContext: JsIrBackendContext,
|
private val backendContext: JsIrBackendContext,
|
||||||
@@ -104,16 +112,14 @@ class IrModuleToJsTransformer(
|
|||||||
)
|
)
|
||||||
}.reversed()
|
}.reversed()
|
||||||
|
|
||||||
return CompilationOutputs(mainModule, dependencies)
|
return CompilationOutputs(mainModule.jsCode, mainModule.sourceMap, dependencies)
|
||||||
} else {
|
} else {
|
||||||
return CompilationOutputs(
|
return generateWrappedModuleBody2(
|
||||||
generateWrappedModuleBody2(
|
modules,
|
||||||
modules,
|
emptyList(),
|
||||||
emptyList(),
|
exportedModule,
|
||||||
exportedModule,
|
namer,
|
||||||
namer,
|
EmptyCrossModuleReferenceInfo
|
||||||
EmptyCrossModuleReferenceInfo
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -124,7 +130,7 @@ class IrModuleToJsTransformer(
|
|||||||
exportedModule: ExportedModule,
|
exportedModule: ExportedModule,
|
||||||
namer: NameTables,
|
namer: NameTables,
|
||||||
refInfo: CrossModuleReferenceInfo
|
refInfo: CrossModuleReferenceInfo
|
||||||
): String {
|
): CompilationOutputs {
|
||||||
|
|
||||||
val nameGenerator = refInfo.withReferenceTracking(
|
val nameGenerator = refInfo.withReferenceTracking(
|
||||||
IrNamerImpl(newNameTables = namer, backendContext),
|
IrNamerImpl(newNameTables = namer, backendContext),
|
||||||
@@ -188,7 +194,41 @@ class IrModuleToJsTransformer(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return program.toString()
|
val jsCode = TextOutputImpl()
|
||||||
|
|
||||||
|
val configuration = backendContext.configuration
|
||||||
|
val sourceMapPrefix = configuration.get(JSConfigurationKeys.SOURCE_MAP_PREFIX, "")
|
||||||
|
val sourceMapsEnabled = configuration.getBoolean(JSConfigurationKeys.SOURCE_MAP)
|
||||||
|
|
||||||
|
val sourceMapBuilder = SourceMap3Builder(null, jsCode, sourceMapPrefix)
|
||||||
|
val sourceMapBuilderConsumer =
|
||||||
|
if (sourceMapsEnabled) {
|
||||||
|
val sourceRoots = configuration.get(JSConfigurationKeys.SOURCE_MAP_SOURCE_ROOTS, emptyList<String>()).map(::File)
|
||||||
|
val generateRelativePathsInSourceMap = sourceMapPrefix.isEmpty() && sourceRoots.isEmpty()
|
||||||
|
val outputDir = if (generateRelativePathsInSourceMap) configuration.get(JSConfigurationKeys.OUTPUT_DIR) else null
|
||||||
|
|
||||||
|
val pathResolver = SourceFilePathResolver(sourceRoots, outputDir)
|
||||||
|
|
||||||
|
val sourceMapContentEmbedding =
|
||||||
|
configuration.get(JSConfigurationKeys.SOURCE_MAP_EMBED_SOURCES, SourceMapSourceEmbedding.INLINING)
|
||||||
|
|
||||||
|
SourceMapBuilderConsumer(
|
||||||
|
File("."),
|
||||||
|
sourceMapBuilder,
|
||||||
|
pathResolver,
|
||||||
|
sourceMapContentEmbedding == SourceMapSourceEmbedding.ALWAYS,
|
||||||
|
sourceMapContentEmbedding != SourceMapSourceEmbedding.NEVER
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
|
program.accept(JsToStringGenerationVisitor(jsCode, sourceMapBuilderConsumer ?: NoOpSourceLocationConsumer))
|
||||||
|
|
||||||
|
return CompilationOutputs(
|
||||||
|
jsCode.toString(),
|
||||||
|
if(sourceMapsEnabled) sourceMapBuilder.build() else null
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrModuleFragment.externalModuleName(): String {
|
private fun IrModuleFragment.externalModuleName(): String {
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ public class SourceMap3Builder implements SourceMapBuilder {
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
JsonObject json = new JsonObject();
|
JsonObject json = new JsonObject();
|
||||||
json.getProperties().put("version", new JsonNumber(3));
|
json.getProperties().put("version", new JsonNumber(3));
|
||||||
json.getProperties().put("file", new JsonString(generatedFile.getName()));
|
if (generatedFile != null) json.getProperties().put("file", new JsonString(generatedFile.getName()));
|
||||||
appendSources(json);
|
appendSources(json);
|
||||||
appendSourcesContent(json);
|
appendSourcesContent(json);
|
||||||
json.getProperties().put("names", new JsonArray());
|
json.getProperties().put("names", new JsonArray());
|
||||||
|
|||||||
@@ -230,8 +230,8 @@ abstract class BasicIrBoxTest(
|
|||||||
|
|
||||||
val dependencyPaths = mutableListOf<String>()
|
val dependencyPaths = mutableListOf<String>()
|
||||||
|
|
||||||
dependencies.forEach { (moduleId, code) ->
|
dependencies.forEach { (moduleId, outputs) ->
|
||||||
val wrappedCode = wrapWithModuleEmulationMarkers(code, config.moduleKind, moduleId)
|
val wrappedCode = wrapWithModuleEmulationMarkers(outputs.jsCode, config.moduleKind, moduleId)
|
||||||
val dependencyPath = outputFile.absolutePath.replace("_v5.js", "-${moduleId}_v5.js")
|
val dependencyPath = outputFile.absolutePath.replace("_v5.js", "-${moduleId}_v5.js")
|
||||||
dependencyPaths += dependencyPath
|
dependencyPaths += dependencyPath
|
||||||
File(dependencyPath).write(wrappedCode)
|
File(dependencyPath).write(wrappedCode)
|
||||||
|
|||||||
Reference in New Issue
Block a user