Allow to embed source files into JS source maps
This commit is contained in:
@@ -48,6 +48,15 @@ open class DefaultValues(val defaultValue: String, val possibleValues: List<Stri
|
|||||||
listOf("\"plain\"", "\"amd\"", "\"commonjs\"", "\"umd\"")
|
listOf("\"plain\"", "\"amd\"", "\"commonjs\"", "\"umd\"")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
object JsSourceMapContentModes : DefaultValues(
|
||||||
|
"\"${K2JsArgumentConstants.SOURCE_MAP_SOURCE_CONTENT_INLINING}\"",
|
||||||
|
listOf(
|
||||||
|
K2JsArgumentConstants.SOURCE_MAP_SOURCE_CONTENT_NEVER,
|
||||||
|
K2JsArgumentConstants.SOURCE_MAP_SOURCE_CONTENT_ALWAYS,
|
||||||
|
K2JsArgumentConstants.SOURCE_MAP_SOURCE_CONTENT_INLINING
|
||||||
|
).map { "\"$it\""}
|
||||||
|
)
|
||||||
|
|
||||||
object JsMain : DefaultValues(
|
object JsMain : DefaultValues(
|
||||||
"\"" + CALL + "\"",
|
"\"" + CALL + "\"",
|
||||||
listOf("\"" + CALL + "\"", "\"" + NO_CALL + "\"")
|
listOf("\"" + CALL + "\"", "\"" + NO_CALL + "\"")
|
||||||
|
|||||||
+8
@@ -52,6 +52,14 @@ public class K2JSCompilerArguments extends CommonCompilerArguments {
|
|||||||
)
|
)
|
||||||
public String sourceMapSourceRoots;
|
public String sourceMapSourceRoots;
|
||||||
|
|
||||||
|
@GradleOption(DefaultValues.JsSourceMapContentModes.class)
|
||||||
|
@Argument(
|
||||||
|
value = "-source-map-embed-sources",
|
||||||
|
valueDescription = "{ always, never, inlining }",
|
||||||
|
description = "Embed source files into source map"
|
||||||
|
)
|
||||||
|
public String sourceMapEmbedSources;
|
||||||
|
|
||||||
@GradleOption(DefaultValues.BooleanTrueDefault.class)
|
@GradleOption(DefaultValues.BooleanTrueDefault.class)
|
||||||
@Argument(value = "-meta-info", description = "Generate .meta.js and .kjsm files with metadata. Use to create a library")
|
@Argument(value = "-meta-info", description = "Generate .meta.js and .kjsm files with metadata. Use to create a library")
|
||||||
public boolean metaInfo;
|
public boolean metaInfo;
|
||||||
|
|||||||
+4
@@ -24,4 +24,8 @@ public interface K2JsArgumentConstants {
|
|||||||
String MODULE_AMD = "amd";
|
String MODULE_AMD = "amd";
|
||||||
String MODULE_COMMONJS = "commonjs";
|
String MODULE_COMMONJS = "commonjs";
|
||||||
String MODULE_UMD = "umd";
|
String MODULE_UMD = "umd";
|
||||||
|
|
||||||
|
String SOURCE_MAP_SOURCE_CONTENT_ALWAYS = "always";
|
||||||
|
String SOURCE_MAP_SOURCE_CONTENT_NEVER = "never";
|
||||||
|
String SOURCE_MAP_SOURCE_CONTENT_INLINING = "inlining";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ import org.jetbrains.kotlin.js.analyzer.JsAnalysisResult;
|
|||||||
import org.jetbrains.kotlin.js.config.EcmaVersion;
|
import org.jetbrains.kotlin.js.config.EcmaVersion;
|
||||||
import org.jetbrains.kotlin.js.config.JSConfigurationKeys;
|
import org.jetbrains.kotlin.js.config.JSConfigurationKeys;
|
||||||
import org.jetbrains.kotlin.js.config.JsConfig;
|
import org.jetbrains.kotlin.js.config.JsConfig;
|
||||||
|
import org.jetbrains.kotlin.js.config.SourceMapSourceEmbedding;
|
||||||
import org.jetbrains.kotlin.js.facade.K2JSTranslator;
|
import org.jetbrains.kotlin.js.facade.K2JSTranslator;
|
||||||
import org.jetbrains.kotlin.js.facade.MainCallParameters;
|
import org.jetbrains.kotlin.js.facade.MainCallParameters;
|
||||||
import org.jetbrains.kotlin.js.facade.TranslationResult;
|
import org.jetbrains.kotlin.js.facade.TranslationResult;
|
||||||
@@ -74,12 +75,17 @@ import static org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.*
|
|||||||
|
|
||||||
public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments> {
|
public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments> {
|
||||||
private static final Map<String, ModuleKind> moduleKindMap = new HashMap<>();
|
private static final Map<String, ModuleKind> moduleKindMap = new HashMap<>();
|
||||||
|
private static final Map<String, SourceMapSourceEmbedding> sourceMapContentEmbeddingMap = new LinkedHashMap<>();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
moduleKindMap.put(K2JsArgumentConstants.MODULE_PLAIN, ModuleKind.PLAIN);
|
moduleKindMap.put(K2JsArgumentConstants.MODULE_PLAIN, ModuleKind.PLAIN);
|
||||||
moduleKindMap.put(K2JsArgumentConstants.MODULE_COMMONJS, ModuleKind.COMMON_JS);
|
moduleKindMap.put(K2JsArgumentConstants.MODULE_COMMONJS, ModuleKind.COMMON_JS);
|
||||||
moduleKindMap.put(K2JsArgumentConstants.MODULE_AMD, ModuleKind.AMD);
|
moduleKindMap.put(K2JsArgumentConstants.MODULE_AMD, ModuleKind.AMD);
|
||||||
moduleKindMap.put(K2JsArgumentConstants.MODULE_UMD, ModuleKind.UMD);
|
moduleKindMap.put(K2JsArgumentConstants.MODULE_UMD, ModuleKind.UMD);
|
||||||
|
|
||||||
|
sourceMapContentEmbeddingMap.put(K2JsArgumentConstants.SOURCE_MAP_SOURCE_CONTENT_ALWAYS, SourceMapSourceEmbedding.ALWAYS);
|
||||||
|
sourceMapContentEmbeddingMap.put(K2JsArgumentConstants.SOURCE_MAP_SOURCE_CONTENT_NEVER, SourceMapSourceEmbedding.NEVER);
|
||||||
|
sourceMapContentEmbeddingMap.put(K2JsArgumentConstants.SOURCE_MAP_SOURCE_CONTENT_INLINING, SourceMapSourceEmbedding.INLINING);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String... args) {
|
public static void main(String... args) {
|
||||||
@@ -357,8 +363,25 @@ public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments> {
|
|||||||
messageCollector.report(
|
messageCollector.report(
|
||||||
ERROR, "Unknown module kind: " + moduleKindName + ". Valid values are: plain, amd, commonjs, umd", null
|
ERROR, "Unknown module kind: " + moduleKindName + ". Valid values are: plain, amd, commonjs, umd", null
|
||||||
);
|
);
|
||||||
|
moduleKind = ModuleKind.PLAIN;
|
||||||
}
|
}
|
||||||
configuration.put(JSConfigurationKeys.MODULE_KIND, moduleKind);
|
configuration.put(JSConfigurationKeys.MODULE_KIND, moduleKind);
|
||||||
|
|
||||||
|
String sourceMapEmbedContentString = arguments.sourceMapEmbedSources;
|
||||||
|
SourceMapSourceEmbedding sourceMapContentEmbedding = sourceMapEmbedContentString != null ?
|
||||||
|
sourceMapContentEmbeddingMap.get(sourceMapEmbedContentString) :
|
||||||
|
SourceMapSourceEmbedding.INLINING;
|
||||||
|
if (sourceMapContentEmbedding == null) {
|
||||||
|
String message = "Unknown source map source embedding mode: " + sourceMapEmbedContentString + ". Valid values are: " +
|
||||||
|
StringUtil.join(sourceMapContentEmbeddingMap.keySet(), ", ");
|
||||||
|
messageCollector.report(ERROR, message, null);
|
||||||
|
sourceMapContentEmbedding = SourceMapSourceEmbedding.INLINING;
|
||||||
|
}
|
||||||
|
configuration.put(JSConfigurationKeys.SOURCE_MAP_EMBED_SOURCES, sourceMapContentEmbedding);
|
||||||
|
|
||||||
|
if (!arguments.sourceMap && sourceMapEmbedContentString != null) {
|
||||||
|
messageCollector.report(WARNING, "source-map-embed-sources argument has no effect without source map", null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
Vendored
+2
@@ -7,6 +7,8 @@ where possible options include:
|
|||||||
-source-map-prefix Prefix for paths in a source map
|
-source-map-prefix Prefix for paths in a source map
|
||||||
-source-map-source-roots <path>
|
-source-map-source-roots <path>
|
||||||
Base directories which are used to calculate relative paths to source files in source map
|
Base directories which are used to calculate relative paths to source files in source map
|
||||||
|
-source-map-embed-sources { always, never, inlining }
|
||||||
|
Embed source files into source map
|
||||||
-meta-info Generate .meta.js and .kjsm files with metadata. Use to create a library
|
-meta-info Generate .meta.js and .kjsm files with metadata. Use to create a library
|
||||||
-target { v5 } Generate JS files for specific ECMA version
|
-target { v5 } Generate JS files for specific ECMA version
|
||||||
-module-kind { plain, amd, commonjs, umd }
|
-module-kind { plain, amd, commonjs, umd }
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
$TESTDATA_DIR$/sourceMap.kt
|
||||||
|
-no-stdlib
|
||||||
|
-source-map
|
||||||
|
-source-map-embed-sources
|
||||||
|
always
|
||||||
|
-output
|
||||||
|
$TEMP_DIR$/out.js
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
OK
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
// EXISTS: out.js
|
||||||
|
// CONTAINS: out.js.map, "sourceMap.kt"
|
||||||
|
// CONTAINS: out.js.map, "var log = \"\"\n\nfun foo(x: String) {
|
||||||
@@ -539,6 +539,12 @@ public class CliTestGenerated extends AbstractCliTest {
|
|||||||
doJsTest(fileName);
|
doJsTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("sourceMapEmbedSources.args")
|
||||||
|
public void testSourceMapEmbedSources() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cli/js/sourceMapEmbedSources.args");
|
||||||
|
doJsTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("sourceMapPrefix.args")
|
@TestMetadata("sourceMapPrefix.args")
|
||||||
public void testSourceMapPrefix() throws Exception {
|
public void testSourceMapPrefix() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cli/js/sourceMapPrefix.args");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cli/js/sourceMapPrefix.args");
|
||||||
|
|||||||
@@ -124,7 +124,9 @@ object JsLibraryUtils {
|
|||||||
librariesWithoutSourceMaps += JsLibrary(content, relativePath, null)
|
librariesWithoutSourceMaps += JsLibrary(content, relativePath, null)
|
||||||
}
|
}
|
||||||
else if (entryName.endsWith(KotlinJavascriptMetadataUtils.JS_MAP_EXT)) {
|
else if (entryName.endsWith(KotlinJavascriptMetadataUtils.JS_MAP_EXT)) {
|
||||||
possibleMapFiles[entryName.removeSuffix(KotlinJavascriptMetadataUtils.JS_MAP_EXT)] = entry
|
val correspondingJsPath = entryName.removeSuffix(KotlinJavascriptMetadataUtils.JS_MAP_EXT) +
|
||||||
|
KotlinJavascriptMetadataUtils.JS_EXT
|
||||||
|
possibleMapFiles[correspondingJsPath] = entry
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,8 +16,31 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.js.backend.ast
|
package org.jetbrains.kotlin.js.backend.ast
|
||||||
|
|
||||||
|
import java.io.Reader
|
||||||
|
|
||||||
data class JsLocation(
|
data class JsLocation(
|
||||||
val file: String,
|
override val file: String,
|
||||||
val startLine: Int,
|
override val startLine: Int,
|
||||||
val startChar: Int
|
override val startChar: Int
|
||||||
)
|
) : JsLocationWithSource {
|
||||||
|
override val identityObject: Any? = null
|
||||||
|
override val sourceProvider: () -> Reader? = { null }
|
||||||
|
|
||||||
|
override fun asSimpleLocation(): JsLocation = this
|
||||||
|
}
|
||||||
|
|
||||||
|
interface JsLocationWithSource {
|
||||||
|
val file: String
|
||||||
|
val startLine: Int
|
||||||
|
val startChar: Int
|
||||||
|
val identityObject: Any?
|
||||||
|
val sourceProvider: () -> Reader?
|
||||||
|
|
||||||
|
fun asSimpleLocation(): JsLocation
|
||||||
|
}
|
||||||
|
|
||||||
|
class JsLocationWithEmbeddedSource(
|
||||||
|
private val location: JsLocation,
|
||||||
|
override val identityObject: Any?,
|
||||||
|
override val sourceProvider: () -> Reader?
|
||||||
|
) : JsLocationWithSource by location
|
||||||
@@ -35,6 +35,9 @@ public class JSConfigurationKeys {
|
|||||||
public static final CompilerConfigurationKey<List<String>> SOURCE_MAP_SOURCE_ROOTS =
|
public static final CompilerConfigurationKey<List<String>> SOURCE_MAP_SOURCE_ROOTS =
|
||||||
CompilerConfigurationKey.create("base directories used to calculate relative paths for source map");
|
CompilerConfigurationKey.create("base directories used to calculate relative paths for source map");
|
||||||
|
|
||||||
|
public static final CompilerConfigurationKey<SourceMapSourceEmbedding> SOURCE_MAP_EMBED_SOURCES =
|
||||||
|
CompilerConfigurationKey.create("embed source files into source map");
|
||||||
|
|
||||||
public static final CompilerConfigurationKey<Boolean> META_INFO =
|
public static final CompilerConfigurationKey<Boolean> META_INFO =
|
||||||
CompilerConfigurationKey.create("generate .meta.js and .kjsm files");
|
CompilerConfigurationKey.create("generate .meta.js and .kjsm files");
|
||||||
|
|
||||||
|
|||||||
@@ -113,6 +113,11 @@ public class JsConfig {
|
|||||||
return configuration.get(JSConfigurationKeys.SOURCE_MAP_SOURCE_ROOTS, Collections.singletonList("."));
|
return configuration.get(JSConfigurationKeys.SOURCE_MAP_SOURCE_ROOTS, Collections.singletonList("."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public SourceMapSourceEmbedding getSourceMapContentEmbedding() {
|
||||||
|
return configuration.get(JSConfigurationKeys.SOURCE_MAP_EMBED_SOURCES, SourceMapSourceEmbedding.INLINING);
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public List<String> getFriends() {
|
public List<String> getFriends() {
|
||||||
if (getConfiguration().getBoolean(JSConfigurationKeys.FRIEND_PATHS_DISABLED)) return Collections.emptyList();
|
if (getConfiguration().getBoolean(JSConfigurationKeys.FRIEND_PATHS_DISABLED)) return Collections.emptyList();
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2017 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.config;
|
||||||
|
|
||||||
|
public enum SourceMapSourceEmbedding {
|
||||||
|
NEVER,
|
||||||
|
ALWAYS,
|
||||||
|
INLINING
|
||||||
|
}
|
||||||
@@ -16,7 +16,9 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.js.parser.sourcemaps
|
package org.jetbrains.kotlin.js.parser.sourcemaps
|
||||||
|
|
||||||
class SourceMap {
|
import java.io.Reader
|
||||||
|
|
||||||
|
class SourceMap(val sourceContentResolver: (String) -> Reader?) {
|
||||||
val groups = mutableListOf<SourceMapGroup>()
|
val groups = mutableListOf<SourceMapGroup>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-5
@@ -16,10 +16,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.js.parser.sourcemaps
|
package org.jetbrains.kotlin.js.parser.sourcemaps
|
||||||
|
|
||||||
import org.jetbrains.kotlin.js.backend.ast.JsLocation
|
import org.jetbrains.kotlin.js.backend.ast.*
|
||||||
import org.jetbrains.kotlin.js.backend.ast.JsNode
|
|
||||||
import org.jetbrains.kotlin.js.backend.ast.RecursiveJsVisitor
|
|
||||||
import org.jetbrains.kotlin.js.backend.ast.SourceInfoAwareJsNode
|
|
||||||
|
|
||||||
class SourceMapLocationRemapper(val sourceMaps: Map<String, SourceMap>) {
|
class SourceMapLocationRemapper(val sourceMaps: Map<String, SourceMap>) {
|
||||||
fun remap(node: JsNode) {
|
fun remap(node: JsNode) {
|
||||||
@@ -62,7 +59,8 @@ class SourceMapLocationRemapper(val sourceMaps: Map<String, SourceMap>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val segment = group.segments[lastSegmentIndex]
|
val segment = group.segments[lastSegmentIndex]
|
||||||
node.source = JsLocation(segment.sourceFileName, segment.sourceLineNumber, segment.sourceColumnNumber)
|
val location = JsLocation(segment.sourceFileName, segment.sourceLineNumber, segment.sourceColumnNumber)
|
||||||
|
node.source = JsLocationWithEmbeddedSource(location, sourceMap) { sourceMap.sourceContentResolver(segment.sourceFileName) }
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import org.json.JSONObject
|
|||||||
import org.json.JSONTokener
|
import org.json.JSONTokener
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.io.Reader
|
import java.io.Reader
|
||||||
|
import java.io.StringReader
|
||||||
|
|
||||||
object SourceMapParser {
|
object SourceMapParser {
|
||||||
@Throws(IOException::class)
|
@Throws(IOException::class)
|
||||||
@@ -72,6 +73,20 @@ object SourceMapParser {
|
|||||||
emptyList()
|
emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val sourcesContent: List<String?> = if (jsonObject.has("sourcesContent")) {
|
||||||
|
val sourcesContentProperty = jsonObject.get("sourcesContent") as? JSONArray ?:
|
||||||
|
return SourceMapError("'sourcesContent' property is not of array type")
|
||||||
|
if (sourcesContentProperty.any { it != JSONObject.NULL && it !is String? }) {
|
||||||
|
return SourceMapError("'sources' array must contain strings")
|
||||||
|
}
|
||||||
|
sourcesContentProperty.map { if (it == JSONObject.NULL) null else it as String? }
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
val sourcePathToContent = sources.zip(sourcesContent).associate { it }
|
||||||
|
|
||||||
if (!jsonObject.has("mappings")) return SourceMapError("'mappings' property not found")
|
if (!jsonObject.has("mappings")) return SourceMapError("'mappings' property not found")
|
||||||
val mappings = jsonObject.get("mappings") as? String ?: return SourceMapError("'mappings' property is not of string type")
|
val mappings = jsonObject.get("mappings") as? String ?: return SourceMapError("'mappings' property is not of string type")
|
||||||
|
|
||||||
@@ -80,7 +95,7 @@ object SourceMapParser {
|
|||||||
var sourceColumn = 0
|
var sourceColumn = 0
|
||||||
var sourceIndex = 0
|
var sourceIndex = 0
|
||||||
val stream = MappingStream(mappings)
|
val stream = MappingStream(mappings)
|
||||||
val sourceMap = SourceMap()
|
val sourceMap = SourceMap { sourcePathToContent[it]?.let { StringReader(it) } }
|
||||||
var currentGroup = SourceMapGroup().also { sourceMap.groups += it }
|
var currentGroup = SourceMapGroup().also { sourceMap.groups += it }
|
||||||
|
|
||||||
while (!stream.isEof) {
|
while (!stream.isEof) {
|
||||||
|
|||||||
+13
-2
@@ -22,11 +22,14 @@ import org.jetbrains.kotlin.protobuf.CodedInputStream
|
|||||||
import org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.*
|
import org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.*
|
||||||
import org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.Expression.ExpressionCase
|
import org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.Expression.ExpressionCase
|
||||||
import org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.Statement.StatementCase
|
import org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.Statement.StatementCase
|
||||||
|
import java.io.File
|
||||||
|
import java.io.FileInputStream
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
|
import java.io.InputStreamReader
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import org.jetbrains.kotlin.resolve.inline.InlineStrategy as KotlinInlineStrategy
|
import org.jetbrains.kotlin.resolve.inline.InlineStrategy as KotlinInlineStrategy
|
||||||
|
|
||||||
class JsAstDeserializer(program: JsProgram) {
|
class JsAstDeserializer(program: JsProgram, private val sourceRoots: Iterable<File>) {
|
||||||
private val scope = JsRootScope(program)
|
private val scope = JsRootScope(program)
|
||||||
private val stringTable = mutableListOf<String>()
|
private val stringTable = mutableListOf<String>()
|
||||||
private val nameTable = mutableListOf<Name>()
|
private val nameTable = mutableListOf<Name>()
|
||||||
@@ -515,7 +518,15 @@ class JsAstDeserializer(program: JsProgram) {
|
|||||||
}
|
}
|
||||||
val node = action()
|
val node = action()
|
||||||
if (deserializedLocation != null) {
|
if (deserializedLocation != null) {
|
||||||
node.source = deserializedLocation
|
val contentFile = sourceRoots
|
||||||
|
.map { File(it, file) }
|
||||||
|
.firstOrNull { it.exists() }
|
||||||
|
node.source = if (contentFile != null) {
|
||||||
|
JsLocationWithEmbeddedSource(deserializedLocation, null) { InputStreamReader(FileInputStream(contentFile), "UTF-8") }
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
deserializedLocation
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (shouldUpdateFile) {
|
if (shouldUpdateFile) {
|
||||||
fileStack.pop()
|
fileStack.pop()
|
||||||
|
|||||||
@@ -386,7 +386,7 @@ class JsAstSerializer(private val pathResolver: (File) -> String) {
|
|||||||
val name = nameRef.name
|
val name = nameRef.name
|
||||||
val qualifier = nameRef.qualifier
|
val qualifier = nameRef.qualifier
|
||||||
if (name != null) {
|
if (name != null) {
|
||||||
if (qualifier != null || (nameRef.inlineStrategy?.isInline ?: false)) {
|
if (qualifier != null || nameRef.inlineStrategy?.isInline == true) {
|
||||||
val nameRefBuilder = NameReference.newBuilder()
|
val nameRefBuilder = NameReference.newBuilder()
|
||||||
nameRefBuilder.nameId = serialize(name)
|
nameRefBuilder.nameId = serialize(name)
|
||||||
if (qualifier != null) {
|
if (qualifier != null) {
|
||||||
@@ -589,7 +589,7 @@ class JsAstSerializer(private val pathResolver: (File) -> String) {
|
|||||||
private fun extractLocation(node: JsNode): JsLocation? {
|
private fun extractLocation(node: JsNode): JsLocation? {
|
||||||
val source = node.source
|
val source = node.source
|
||||||
return when (source) {
|
return when (source) {
|
||||||
is JsLocation -> source
|
is JsLocationWithSource -> source.asSimpleLocation()
|
||||||
is PsiElement -> extractLocation(source)
|
is PsiElement -> extractLocation(source)
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import org.jetbrains.kotlin.js.backend.ast.*
|
|||||||
import org.jetbrains.kotlin.js.config.EcmaVersion
|
import org.jetbrains.kotlin.js.config.EcmaVersion
|
||||||
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
||||||
import org.jetbrains.kotlin.js.config.JsConfig
|
import org.jetbrains.kotlin.js.config.JsConfig
|
||||||
|
import org.jetbrains.kotlin.js.config.SourceMapSourceEmbedding
|
||||||
import org.jetbrains.kotlin.js.dce.DeadCodeElimination
|
import org.jetbrains.kotlin.js.dce.DeadCodeElimination
|
||||||
import org.jetbrains.kotlin.js.dce.InputFile
|
import org.jetbrains.kotlin.js.dce.InputFile
|
||||||
import org.jetbrains.kotlin.js.facade.*
|
import org.jetbrains.kotlin.js.facade.*
|
||||||
@@ -284,45 +285,63 @@ abstract class BasicBoxTest(
|
|||||||
val additionalFiles = globalCommonFiles + localCommonFiles + additionalCommonFiles
|
val additionalFiles = globalCommonFiles + localCommonFiles + additionalCommonFiles
|
||||||
val psiFiles = createPsiFiles(testFiles + additionalFiles)
|
val psiFiles = createPsiFiles(testFiles + additionalFiles)
|
||||||
|
|
||||||
val config = createConfig(module, dependencies, friends, multiModule, additionalMetadata = null)
|
val sourceDirs = (testFiles + additionalFiles).map { File(it).parent }.distinct()
|
||||||
|
val config = createConfig(sourceDirs, module, dependencies, friends, multiModule, additionalMetadata = null)
|
||||||
val outputFile = File(outputFileName)
|
val outputFile = File(outputFileName)
|
||||||
|
|
||||||
translateFiles(psiFiles.map(TranslationUnit::SourceFile), outputFile, config, outputPrefixFile, outputPostfixFile, mainCallParameters)
|
translateFiles(psiFiles.map(TranslationUnit::SourceFile), outputFile, config, outputPrefixFile, outputPostfixFile, mainCallParameters)
|
||||||
|
|
||||||
if (module.hasFilesToRecompile) {
|
if (module.hasFilesToRecompile) {
|
||||||
val incrementalDir = File(outputFile.parentFile, "incremental/" + outputFile.nameWithoutExtension)
|
checkIncrementalCompilation(sourceDirs, module, kotlinFiles, additionalFiles, dependencies, friends, multiModule, outputFile,
|
||||||
val serializedMetadata = mutableListOf<File>()
|
outputPrefixFile, outputPostfixFile, mainCallParameters)
|
||||||
val translationUnits = kotlinFiles.withIndex().map { (index, file) ->
|
}
|
||||||
if (file.recompile) {
|
}
|
||||||
TranslationUnit.SourceFile(createPsiFile(file.fileName))
|
|
||||||
}
|
private fun checkIncrementalCompilation(
|
||||||
else {
|
sourceDirs: List<String>,
|
||||||
serializedMetadata += File(incrementalDir, "$index.$METADATA_EXTENSION")
|
module: TestModule,
|
||||||
val astFile = File(incrementalDir, "$index.$AST_EXTENSION")
|
kotlinFiles: List<TestFile>,
|
||||||
TranslationUnit.BinaryAst(FileUtil.loadFileBytes(astFile))
|
additionalFiles: List<String>,
|
||||||
}
|
dependencies: List<String>,
|
||||||
|
friends: List<String>,
|
||||||
|
multiModule: Boolean,
|
||||||
|
outputFile: File,
|
||||||
|
outputPrefixFile: File?,
|
||||||
|
outputPostfixFile: File?,
|
||||||
|
mainCallParameters: MainCallParameters
|
||||||
|
) {
|
||||||
|
val incrementalDir = File(outputFile.parentFile, "incremental/" + outputFile.nameWithoutExtension)
|
||||||
|
val serializedMetadata = mutableListOf<File>()
|
||||||
|
val translationUnits = kotlinFiles.withIndex().map { (index, file) ->
|
||||||
|
if (file.recompile) {
|
||||||
|
TranslationUnit.SourceFile(createPsiFile(file.fileName))
|
||||||
}
|
}
|
||||||
val allTranslationUnits = translationUnits + additionalFiles.withIndex().map { (index, _) ->
|
else {
|
||||||
val astFile = File(incrementalDir, "${index + translationUnits.size}.$AST_EXTENSION")
|
serializedMetadata += File(incrementalDir, "$index.$METADATA_EXTENSION")
|
||||||
|
val astFile = File(incrementalDir, "$index.$AST_EXTENSION")
|
||||||
TranslationUnit.BinaryAst(FileUtil.loadFileBytes(astFile))
|
TranslationUnit.BinaryAst(FileUtil.loadFileBytes(astFile))
|
||||||
}
|
}
|
||||||
|
|
||||||
val headerFile = File(incrementalDir, HEADER_FILE)
|
|
||||||
val recompiledConfig = createConfig(module, dependencies, friends, multiModule, Pair(headerFile,serializedMetadata))
|
|
||||||
val recompiledOutputFile = File(outputFile.parentFile, outputFile.nameWithoutExtension + "-recompiled.js")
|
|
||||||
|
|
||||||
translateFiles(allTranslationUnits, recompiledOutputFile, recompiledConfig, outputPrefixFile, outputPostfixFile,
|
|
||||||
mainCallParameters)
|
|
||||||
|
|
||||||
val originalOutput = FileUtil.loadFile(outputFile)
|
|
||||||
val recompiledOutput = removeRecompiledSuffix(FileUtil.loadFile(recompiledOutputFile))
|
|
||||||
TestCase.assertEquals("Output file changed after recompilation", originalOutput, recompiledOutput)
|
|
||||||
|
|
||||||
val originalSourceMap = FileUtil.loadFile(File(outputFile.parentFile, outputFile.name + ".map"))
|
|
||||||
val recompiledSourceMap = removeRecompiledSuffix(
|
|
||||||
FileUtil.loadFile(File(recompiledOutputFile.parentFile, recompiledOutputFile.name + ".map")))
|
|
||||||
TestCase.assertEquals("Source map file changed after recompilation", originalSourceMap, recompiledSourceMap)
|
|
||||||
}
|
}
|
||||||
|
val allTranslationUnits = translationUnits + additionalFiles.withIndex().map { (index, _) ->
|
||||||
|
val astFile = File(incrementalDir, "${index + translationUnits.size}.$AST_EXTENSION")
|
||||||
|
TranslationUnit.BinaryAst(FileUtil.loadFileBytes(astFile))
|
||||||
|
}
|
||||||
|
|
||||||
|
val headerFile = File(incrementalDir, HEADER_FILE)
|
||||||
|
val recompiledConfig = createConfig(sourceDirs, module, dependencies, friends, multiModule, Pair(headerFile,serializedMetadata))
|
||||||
|
val recompiledOutputFile = File(outputFile.parentFile, outputFile.nameWithoutExtension + "-recompiled.js")
|
||||||
|
|
||||||
|
translateFiles(allTranslationUnits, recompiledOutputFile, recompiledConfig, outputPrefixFile, outputPostfixFile,
|
||||||
|
mainCallParameters)
|
||||||
|
|
||||||
|
val originalOutput = FileUtil.loadFile(outputFile)
|
||||||
|
val recompiledOutput = removeRecompiledSuffix(FileUtil.loadFile(recompiledOutputFile))
|
||||||
|
TestCase.assertEquals("Output file changed after recompilation", originalOutput, recompiledOutput)
|
||||||
|
|
||||||
|
val originalSourceMap = FileUtil.loadFile(File(outputFile.parentFile, outputFile.name + ".map"))
|
||||||
|
val recompiledSourceMap = removeRecompiledSuffix(
|
||||||
|
FileUtil.loadFile(File(recompiledOutputFile.parentFile, recompiledOutputFile.name + ".map")))
|
||||||
|
TestCase.assertEquals("Source map file changed after recompilation", originalSourceMap, recompiledSourceMap)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun removeRecompiledSuffix(text: String): String = text.replace("-recompiled.js", ".js")
|
private fun removeRecompiledSuffix(text: String): String = text.replace("-recompiled.js", ".js")
|
||||||
@@ -411,7 +430,7 @@ abstract class BasicBoxTest(
|
|||||||
|
|
||||||
val output = TextOutputImpl()
|
val output = TextOutputImpl()
|
||||||
val pathResolver = SourceFilePathResolver(mutableListOf(File(".")))
|
val pathResolver = SourceFilePathResolver(mutableListOf(File(".")))
|
||||||
val sourceMapBuilder = SourceMap3Builder(outputFile, output, "", SourceMapBuilderConsumer(pathResolver))
|
val sourceMapBuilder = SourceMap3Builder(outputFile, output, "", SourceMapBuilderConsumer(pathResolver, false, false))
|
||||||
generatedProgram.accept(JsSourceGenerationVisitor(output, sourceMapBuilder))
|
generatedProgram.accept(JsSourceGenerationVisitor(output, sourceMapBuilder))
|
||||||
val code = output.toString()
|
val code = output.toString()
|
||||||
val generatedSourceMap = sourceMapBuilder.build()
|
val generatedSourceMap = sourceMapBuilder.build()
|
||||||
@@ -454,7 +473,9 @@ abstract class BasicBoxTest(
|
|||||||
private fun createPsiFiles(fileNames: List<String>): List<KtFile> = fileNames.map(this::createPsiFile)
|
private fun createPsiFiles(fileNames: List<String>): List<KtFile> = fileNames.map(this::createPsiFile)
|
||||||
|
|
||||||
private fun createConfig(
|
private fun createConfig(
|
||||||
module: TestModule, dependencies: List<String>, friends: List<String>, multiModule: Boolean, additionalMetadata: Pair<File, List<File>>?
|
sourceDirs: List<String>,
|
||||||
|
module: TestModule, dependencies: List<String>, friends: List<String>, multiModule: Boolean,
|
||||||
|
additionalMetadata: Pair<File, List<File>>?
|
||||||
): JsConfig {
|
): JsConfig {
|
||||||
val configuration = environment.configuration.copy()
|
val configuration = environment.configuration.copy()
|
||||||
|
|
||||||
@@ -475,6 +496,8 @@ abstract class BasicBoxTest(
|
|||||||
configuration.put(JSConfigurationKeys.META_INFO, multiModule)
|
configuration.put(JSConfigurationKeys.META_INFO, multiModule)
|
||||||
configuration.put(JSConfigurationKeys.SERIALIZE_FRAGMENTS, hasFilesToRecompile)
|
configuration.put(JSConfigurationKeys.SERIALIZE_FRAGMENTS, hasFilesToRecompile)
|
||||||
configuration.put(JSConfigurationKeys.SOURCE_MAP, hasFilesToRecompile || generateSourceMap)
|
configuration.put(JSConfigurationKeys.SOURCE_MAP, hasFilesToRecompile || generateSourceMap)
|
||||||
|
configuration.put(JSConfigurationKeys.SOURCE_MAP_SOURCE_ROOTS, sourceDirs)
|
||||||
|
configuration.put(JSConfigurationKeys.SOURCE_MAP_EMBED_SOURCES, module.sourceMapSourceEmbedding)
|
||||||
|
|
||||||
if (additionalMetadata != null) {
|
if (additionalMetadata != null) {
|
||||||
val metadata = PackagesWithHeaderMetadata(
|
val metadata = PackagesWithHeaderMetadata(
|
||||||
@@ -570,6 +593,10 @@ abstract class BasicBoxTest(
|
|||||||
currentModule.languageVersion = LanguageVersion.fromVersionString(version)
|
currentModule.languageVersion = LanguageVersion.fromVersionString(version)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SOURCE_MAP_SOURCE_EMBEDDING.find(text)?.let { match ->
|
||||||
|
currentModule.sourceMapSourceEmbedding = SourceMapSourceEmbedding.valueOf(match.groupValues[1])
|
||||||
|
}
|
||||||
|
|
||||||
return TestFile(temporaryFile.absolutePath, currentModule, recompile = RECOMPILE_PATTERN.matcher(text).find())
|
return TestFile(temporaryFile.absolutePath, currentModule, recompile = RECOMPILE_PATTERN.matcher(text).find())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -599,6 +626,7 @@ abstract class BasicBoxTest(
|
|||||||
var inliningDisabled = false
|
var inliningDisabled = false
|
||||||
val files = mutableListOf<TestFile>()
|
val files = mutableListOf<TestFile>()
|
||||||
var languageVersion: LanguageVersion? = null
|
var languageVersion: LanguageVersion? = null
|
||||||
|
var sourceMapSourceEmbedding = SourceMapSourceEmbedding.NEVER
|
||||||
|
|
||||||
val hasFilesToRecompile get() = files.any { it.recompile }
|
val hasFilesToRecompile get() = files.any { it.recompile }
|
||||||
}
|
}
|
||||||
@@ -623,6 +651,7 @@ abstract class BasicBoxTest(
|
|||||||
private val EXPECTED_REACHABLE_NODES_DIRECTIVE = "EXPECTED_REACHABLE_NODES"
|
private val EXPECTED_REACHABLE_NODES_DIRECTIVE = "EXPECTED_REACHABLE_NODES"
|
||||||
private val EXPECTED_REACHABLE_NODES = Pattern.compile("^// *$EXPECTED_REACHABLE_NODES_DIRECTIVE: *([0-9]+) *$", Pattern.MULTILINE)
|
private val EXPECTED_REACHABLE_NODES = Pattern.compile("^// *$EXPECTED_REACHABLE_NODES_DIRECTIVE: *([0-9]+) *$", Pattern.MULTILINE)
|
||||||
private val RECOMPILE_PATTERN = Pattern.compile("^// *RECOMPILE *$", Pattern.MULTILINE)
|
private val RECOMPILE_PATTERN = Pattern.compile("^// *RECOMPILE *$", Pattern.MULTILINE)
|
||||||
|
private val SOURCE_MAP_SOURCE_EMBEDDING = Regex("^// *SOURCE_MAP_EMBED_SOURCES: ([A-Z]+)*\$", RegexOption.MULTILINE)
|
||||||
private val AST_EXTENSION = "jsast"
|
private val AST_EXTENSION = "jsast"
|
||||||
private val METADATA_EXTENSION = "jsmeta"
|
private val METADATA_EXTENSION = "jsmeta"
|
||||||
private val HEADER_FILE = "header.$METADATA_EXTENSION"
|
private val HEADER_FILE = "header.$METADATA_EXTENSION"
|
||||||
|
|||||||
@@ -3539,6 +3539,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("sourceMapSourceEmbedding.kt")
|
||||||
|
public void testSourceMapSourceEmbedding() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/incremental/sourceMapSourceEmbedding.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("syntheticStatement.kt")
|
@TestMetadata("syntheticStatement.kt")
|
||||||
public void testSyntheticStatement() throws Exception {
|
public void testSyntheticStatement() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/incremental/syntheticStatement.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/incremental/syntheticStatement.kt");
|
||||||
|
|||||||
+1
-1
@@ -68,7 +68,7 @@ class AmbiguousAstSourcePropagation : RecursiveJsVisitor() {
|
|||||||
private fun propagate(node: JsNode) {
|
private fun propagate(node: JsNode) {
|
||||||
if (!sourceDefined) {
|
if (!sourceDefined) {
|
||||||
val source = node.source
|
val source = node.source
|
||||||
if (source is JsLocation || source is PsiElement) {
|
if (source is JsLocationWithSource || source is PsiElement) {
|
||||||
sourceDefined = true
|
sourceDefined = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ class LineCollector : RecursiveJsVisitor() {
|
|||||||
val document = file.viewProvider.document!!
|
val document = file.viewProvider.document!!
|
||||||
document.getLineNumber(offset)
|
document.getLineNumber(offset)
|
||||||
}
|
}
|
||||||
is JsLocation -> {
|
is JsLocationWithSource -> {
|
||||||
source.startLine
|
source.startLine
|
||||||
}
|
}
|
||||||
else -> null
|
else -> null
|
||||||
|
|||||||
@@ -21,19 +21,29 @@ import com.intellij.psi.PsiElement;
|
|||||||
import com.intellij.psi.PsiFile;
|
import com.intellij.psi.PsiFile;
|
||||||
import com.intellij.util.PairConsumer;
|
import com.intellij.util.PairConsumer;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.kotlin.js.backend.ast.JsLocation;
|
import org.jetbrains.kotlin.js.backend.ast.JsLocationWithSource;
|
||||||
import org.jetbrains.kotlin.js.sourceMap.SourceFilePathResolver;
|
import org.jetbrains.kotlin.js.sourceMap.SourceFilePathResolver;
|
||||||
import org.jetbrains.kotlin.js.sourceMap.SourceMapBuilder;
|
import org.jetbrains.kotlin.js.sourceMap.SourceMapBuilder;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.*;
|
||||||
import java.io.IOException;
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public class SourceMapBuilderConsumer implements PairConsumer<SourceMapBuilder, Object> {
|
public class SourceMapBuilderConsumer implements PairConsumer<SourceMapBuilder, Object> {
|
||||||
@NotNull
|
@NotNull
|
||||||
private final SourceFilePathResolver pathResolver;
|
private final SourceFilePathResolver pathResolver;
|
||||||
|
|
||||||
public SourceMapBuilderConsumer(@NotNull SourceFilePathResolver pathResolver) {
|
private final boolean provideCurrentModuleContent;
|
||||||
|
|
||||||
|
private final boolean provideExternalModuleContent;
|
||||||
|
|
||||||
|
public SourceMapBuilderConsumer(
|
||||||
|
@NotNull SourceFilePathResolver pathResolver,
|
||||||
|
boolean provideCurrentModuleContent, boolean provideExternalModuleContent
|
||||||
|
) {
|
||||||
this.pathResolver = pathResolver;
|
this.pathResolver = pathResolver;
|
||||||
|
this.provideCurrentModuleContent = provideCurrentModuleContent;
|
||||||
|
this.provideExternalModuleContent = provideExternalModuleContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -49,15 +59,31 @@ public class SourceMapBuilderConsumer implements PairConsumer<SourceMapBuilder,
|
|||||||
|
|
||||||
File file = new File(psiFile.getViewProvider().getVirtualFile().getPath());
|
File file = new File(psiFile.getViewProvider().getVirtualFile().getPath());
|
||||||
try {
|
try {
|
||||||
builder.addMapping(pathResolver.getPathRelativeToSourceRoots(file), line, column);
|
Supplier<Reader> contentSupplier;
|
||||||
|
if (provideCurrentModuleContent) {
|
||||||
|
contentSupplier = () -> {
|
||||||
|
try {
|
||||||
|
return new InputStreamReader(new FileInputStream(file), Charset.forName("UTF-8"));
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
contentSupplier = () -> null;
|
||||||
|
}
|
||||||
|
builder.addMapping(pathResolver.getPathRelativeToSourceRoots(file), null, contentSupplier, line, column);
|
||||||
}
|
}
|
||||||
catch (IOException e) {
|
catch (IOException e) {
|
||||||
throw new RuntimeException("IO error occurred generating source maps", e);
|
throw new RuntimeException("IO error occurred generating source maps", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (sourceInfo instanceof JsLocation) {
|
else if (sourceInfo instanceof JsLocationWithSource) {
|
||||||
JsLocation location = (JsLocation) sourceInfo;
|
JsLocationWithSource location = (JsLocationWithSource) sourceInfo;
|
||||||
builder.addMapping(location.getFile(), location.getStartLine(), location.getStartChar());
|
Supplier<Reader> contentSupplier = provideExternalModuleContent ? location.getSourceProvider()::invoke : () -> null;
|
||||||
|
builder.addMapping(location.getFile(), location.getIdentityObject(), contentSupplier,
|
||||||
|
location.getStartLine(), location.getStartChar());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
|||||||
import org.jetbrains.kotlin.js.backend.ast.JsProgram
|
import org.jetbrains.kotlin.js.backend.ast.JsProgram
|
||||||
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
||||||
import org.jetbrains.kotlin.js.config.JsConfig
|
import org.jetbrains.kotlin.js.config.JsConfig
|
||||||
|
import org.jetbrains.kotlin.js.config.SourceMapSourceEmbedding
|
||||||
import org.jetbrains.kotlin.js.sourceMap.JsSourceGenerationVisitor
|
import org.jetbrains.kotlin.js.sourceMap.JsSourceGenerationVisitor
|
||||||
import org.jetbrains.kotlin.js.sourceMap.SourceFilePathResolver
|
import org.jetbrains.kotlin.js.sourceMap.SourceFilePathResolver
|
||||||
import org.jetbrains.kotlin.js.sourceMap.SourceMap3Builder
|
import org.jetbrains.kotlin.js.sourceMap.SourceMap3Builder
|
||||||
@@ -61,8 +62,13 @@ abstract class TranslationResult protected constructor(val diagnostics: Diagnost
|
|||||||
val sourceMapBuilder =
|
val sourceMapBuilder =
|
||||||
if (config.configuration.getBoolean(JSConfigurationKeys.SOURCE_MAP)) {
|
if (config.configuration.getBoolean(JSConfigurationKeys.SOURCE_MAP)) {
|
||||||
val sourceRoots = config.sourceMapRoots.map { File(it) }
|
val sourceRoots = config.sourceMapRoots.map { File(it) }
|
||||||
|
val sourceMapContentEmbedding = config.sourceMapContentEmbedding
|
||||||
val pathResolver = SourceFilePathResolver(sourceRoots)
|
val pathResolver = SourceFilePathResolver(sourceRoots)
|
||||||
SourceMap3Builder(outputFile, output, config.sourceMapPrefix, SourceMapBuilderConsumer(pathResolver))
|
val consumer = SourceMapBuilderConsumer(
|
||||||
|
pathResolver,
|
||||||
|
sourceMapContentEmbedding == SourceMapSourceEmbedding.ALWAYS,
|
||||||
|
sourceMapContentEmbedding != SourceMapSourceEmbedding.NEVER)
|
||||||
|
SourceMap3Builder(outputFile, output, config.sourceMapPrefix, consumer)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
null
|
null
|
||||||
|
|||||||
@@ -16,15 +16,19 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.js.sourceMap;
|
package org.jetbrains.kotlin.js.sourceMap;
|
||||||
|
|
||||||
import org.jetbrains.kotlin.js.common.SourceInfo;
|
|
||||||
import org.jetbrains.kotlin.js.util.TextOutput;
|
|
||||||
import com.intellij.openapi.util.text.StringUtil;
|
import com.intellij.openapi.util.text.StringUtil;
|
||||||
import com.intellij.util.PairConsumer;
|
import com.intellij.util.PairConsumer;
|
||||||
import gnu.trove.TObjectIntHashMap;
|
import gnu.trove.TObjectIntHashMap;
|
||||||
|
import kotlin.io.TextStreamsKt;
|
||||||
|
import org.jetbrains.kotlin.js.backend.JsToStringGenerationVisitor;
|
||||||
|
import org.jetbrains.kotlin.js.common.SourceInfo;
|
||||||
|
import org.jetbrains.kotlin.js.util.TextOutput;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.Reader;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public class SourceMap3Builder implements SourceMapBuilder {
|
public class SourceMap3Builder implements SourceMapBuilder {
|
||||||
private final StringBuilder out = new StringBuilder(8192);
|
private final StringBuilder out = new StringBuilder(8192);
|
||||||
@@ -33,18 +37,16 @@ public class SourceMap3Builder implements SourceMapBuilder {
|
|||||||
private final String pathPrefix;
|
private final String pathPrefix;
|
||||||
private final PairConsumer<SourceMapBuilder, Object> sourceInfoConsumer;
|
private final PairConsumer<SourceMapBuilder, Object> sourceInfoConsumer;
|
||||||
|
|
||||||
private String lastSource;
|
private final TObjectIntHashMap<SourceKey> sources = new TObjectIntHashMap<SourceKey>() {
|
||||||
private int lastSourceIndex;
|
|
||||||
|
|
||||||
private final TObjectIntHashMap<String> sources = new TObjectIntHashMap<String>() {
|
|
||||||
@Override
|
@Override
|
||||||
public int get(String key) {
|
public int get(SourceKey key) {
|
||||||
int index = index(key);
|
int index = index(key);
|
||||||
return index < 0 ? -1 : _values[index];
|
return index < 0 ? -1 : _values[index];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private final List<String> orderedSources = new ArrayList<>();
|
private final List<String> orderedSources = new ArrayList<>();
|
||||||
|
private final List<Supplier<Reader>> orderedSourceContentSuppliers = new ArrayList<>();
|
||||||
|
|
||||||
private int previousGeneratedColumn = -1;
|
private int previousGeneratedColumn = -1;
|
||||||
private int previousSourceIndex;
|
private int previousSourceIndex;
|
||||||
@@ -68,7 +70,11 @@ public class SourceMap3Builder implements SourceMapBuilder {
|
|||||||
public String build() {
|
public String build() {
|
||||||
StringBuilder sb = new StringBuilder(out.length() + (128 * orderedSources.size()));
|
StringBuilder sb = new StringBuilder(out.length() + (128 * orderedSources.size()));
|
||||||
sb.append("{\"version\":3,\"file\":\"").append(generatedFile.getName()).append('"').append(',');
|
sb.append("{\"version\":3,\"file\":\"").append(generatedFile.getName()).append('"').append(',');
|
||||||
|
|
||||||
appendSources(sb);
|
appendSources(sb);
|
||||||
|
sb.append(",");
|
||||||
|
appendSourcesContent(sb);
|
||||||
|
|
||||||
sb.append(",\"names\":[");
|
sb.append(",\"names\":[");
|
||||||
sb.append("],\"mappings\":\"");
|
sb.append("],\"mappings\":\"");
|
||||||
sb.append(out);
|
sb.append(out);
|
||||||
@@ -86,7 +92,29 @@ public class SourceMap3Builder implements SourceMapBuilder {
|
|||||||
else {
|
else {
|
||||||
isNotFirst = true;
|
isNotFirst = true;
|
||||||
}
|
}
|
||||||
sb.append('"').append(pathPrefix).append(source).append('"');
|
sb.append(JsToStringGenerationVisitor.javaScriptString(pathPrefix + source, true));
|
||||||
|
}
|
||||||
|
sb.append(']');
|
||||||
|
}
|
||||||
|
|
||||||
|
private void appendSourcesContent(StringBuilder sb) {
|
||||||
|
boolean isNotFirst = false;
|
||||||
|
sb.append('"').append("sourcesContent").append("\":[");
|
||||||
|
for (Supplier<Reader> contentSupplier : orderedSourceContentSuppliers) {
|
||||||
|
if (isNotFirst) {
|
||||||
|
sb.append(',');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
isNotFirst = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Reader reader = contentSupplier.get();
|
||||||
|
if (reader != null) {
|
||||||
|
sb.append(JsToStringGenerationVisitor.javaScriptString(TextStreamsKt.readText(reader), true));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sb.append("null");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
sb.append(']');
|
sb.append(']');
|
||||||
}
|
}
|
||||||
@@ -110,26 +138,21 @@ public class SourceMap3Builder implements SourceMapBuilder {
|
|||||||
sourceInfoConsumer.consume(this, sourceInfo);
|
sourceInfoConsumer.consume(this, sourceInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getSourceIndex(String source) {
|
private int getSourceIndex(String source, Object identityObject, Supplier<Reader> contentSupplier) {
|
||||||
if (source.equals(lastSource)) {
|
SourceKey key = new SourceKey(source, identityObject);
|
||||||
return lastSourceIndex;
|
int sourceIndex = sources.get(key);
|
||||||
}
|
|
||||||
|
|
||||||
int sourceIndex = sources.get(source);
|
|
||||||
if (sourceIndex == -1) {
|
if (sourceIndex == -1) {
|
||||||
sourceIndex = orderedSources.size();
|
sourceIndex = orderedSources.size();
|
||||||
sources.put(source, sourceIndex);
|
sources.put(key, sourceIndex);
|
||||||
orderedSources.add(source);
|
orderedSources.add(source);
|
||||||
|
orderedSourceContentSuppliers.add(contentSupplier);
|
||||||
}
|
}
|
||||||
|
|
||||||
lastSource = source;
|
|
||||||
lastSourceIndex = sourceIndex;
|
|
||||||
|
|
||||||
return sourceIndex;
|
return sourceIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addMapping(String source, int sourceLine, int sourceColumn) {
|
public void addMapping(String source, Object identityObject, Supplier<Reader> sourceContent, int sourceLine, int sourceColumn) {
|
||||||
source = source.replace(File.separatorChar, '/');
|
source = source.replace(File.separatorChar, '/');
|
||||||
boolean newGroupStarted = previousGeneratedColumn == -1;
|
boolean newGroupStarted = previousGeneratedColumn == -1;
|
||||||
if (newGroupStarted) {
|
if (newGroupStarted) {
|
||||||
@@ -148,7 +171,7 @@ public class SourceMap3Builder implements SourceMapBuilder {
|
|||||||
// assert columnDiff != 0;
|
// assert columnDiff != 0;
|
||||||
Base64VLQ.encode(out, columnDiff);
|
Base64VLQ.encode(out, columnDiff);
|
||||||
previousGeneratedColumn = textOutput.getColumn();
|
previousGeneratedColumn = textOutput.getColumn();
|
||||||
int sourceIndex = getSourceIndex(source);
|
int sourceIndex = getSourceIndex(source, identityObject, sourceContent);
|
||||||
Base64VLQ.encode(out, sourceIndex - previousSourceIndex);
|
Base64VLQ.encode(out, sourceIndex - previousSourceIndex);
|
||||||
previousSourceIndex = sourceIndex;
|
previousSourceIndex = sourceIndex;
|
||||||
|
|
||||||
@@ -200,4 +223,34 @@ public class SourceMap3Builder implements SourceMapBuilder {
|
|||||||
while (value > 0);
|
while (value > 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static final class SourceKey {
|
||||||
|
private final String sourcePath;
|
||||||
|
private final Object identityKey;
|
||||||
|
|
||||||
|
SourceKey(String sourcePath, Object identityKey) {
|
||||||
|
this.sourcePath = sourcePath;
|
||||||
|
this.identityKey = identityKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (!(o instanceof SourceKey)) return false;
|
||||||
|
|
||||||
|
SourceKey key = (SourceKey) o;
|
||||||
|
|
||||||
|
if (!sourcePath.equals(key.sourcePath)) return false;
|
||||||
|
if (identityKey != null ? !identityKey.equals(key.identityKey) : key.identityKey != null) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result = sourcePath.hashCode();
|
||||||
|
result = 31 * result + (identityKey != null ? identityKey.hashCode() : 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,13 +17,15 @@
|
|||||||
package org.jetbrains.kotlin.js.sourceMap;
|
package org.jetbrains.kotlin.js.sourceMap;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.Reader;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public interface SourceMapBuilder {
|
public interface SourceMapBuilder {
|
||||||
void newLine();
|
void newLine();
|
||||||
|
|
||||||
void skipLinesAtBeginning(int count);
|
void skipLinesAtBeginning(int count);
|
||||||
|
|
||||||
void addMapping(String source, int sourceLine, int sourceColumn);
|
void addMapping(String source, Object identityObject, Supplier<Reader> sourceContent, int sourceLine, int sourceColumn);
|
||||||
|
|
||||||
void processSourceInfo(Object info);
|
void processSourceInfo(Object info);
|
||||||
|
|
||||||
|
|||||||
@@ -61,7 +61,9 @@ import org.jetbrains.kotlin.types.TypeUtils;
|
|||||||
import org.jetbrains.kotlin.utils.ExceptionUtilsKt;
|
import org.jetbrains.kotlin.utils.ExceptionUtilsKt;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.File;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static org.jetbrains.kotlin.js.translate.general.ModuleWrapperTranslation.wrapIfNecessary;
|
import static org.jetbrains.kotlin.js.translate.general.ModuleWrapperTranslation.wrapIfNecessary;
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.convertToStatement;
|
import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.convertToStatement;
|
||||||
@@ -274,7 +276,8 @@ public final class Translation {
|
|||||||
|
|
||||||
Map<KtFile, List<DeclarationDescriptor>> fileMemberScopes = new HashMap<>();
|
Map<KtFile, List<DeclarationDescriptor>> fileMemberScopes = new HashMap<>();
|
||||||
|
|
||||||
JsAstDeserializer deserializer = new JsAstDeserializer(program);
|
List<File> sourceRoots = config.getSourceMapRoots().stream().map(File::new).collect(Collectors.toList());
|
||||||
|
JsAstDeserializer deserializer = new JsAstDeserializer(program, sourceRoots);
|
||||||
for (TranslationUnit unit : units) {
|
for (TranslationUnit unit : units) {
|
||||||
if (unit instanceof TranslationUnit.SourceFile) {
|
if (unit instanceof TranslationUnit.SourceFile) {
|
||||||
KtFile file = ((TranslationUnit.SourceFile) unit).getFile();
|
KtFile file = ((TranslationUnit.SourceFile) unit).getFile();
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
// EXPECTED_REACHABLE_NODES: 489
|
||||||
|
// SOURCE_MAP_EMBED_SOURCES: ALWAYS
|
||||||
|
// FILE: a.kt
|
||||||
|
fun foo() = "O"
|
||||||
|
|
||||||
|
// FILE: b.kt
|
||||||
|
// RECOMPILE
|
||||||
|
fun bar() = "K"
|
||||||
|
|
||||||
|
// FILE: main.kt
|
||||||
|
// RECOMPILE
|
||||||
|
fun box() = foo() + bar()
|
||||||
+18
@@ -196,4 +196,22 @@ class Kotlin2JsGradlePluginIT : BaseGradleIT() {
|
|||||||
assertTrue("Source map should contain reference to $sourceFilePath") { map.contains("\"$sourceFilePath\"") }
|
assertTrue("Source map should contain reference to $sourceFilePath") { map.contains("\"$sourceFilePath\"") }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testKotlinJsSourceMapInline() {
|
||||||
|
val project = Project("kotlin2JsProjectWithSourceMapInline", "2.10")
|
||||||
|
|
||||||
|
project.build("build") {
|
||||||
|
assertSuccessful()
|
||||||
|
|
||||||
|
val mapFilePath = "app/build/classes/main/app_main.js.map"
|
||||||
|
assertFileExists(mapFilePath)
|
||||||
|
val map = fileInWorkingDir(mapFilePath).readText()
|
||||||
|
|
||||||
|
assertTrue("Source map should contain reference to main.kt") { map.contains("\"main.kt\"") }
|
||||||
|
assertTrue("Source map should contain reference to foo.kt") { map.contains("\"foo.kt\"") }
|
||||||
|
assertTrue("Source map should contain source of main.kt") { map.contains("\"fun main(args: Array<String>) {\\n") }
|
||||||
|
assertTrue("Source map should contain source of foo.kt") { map.contains("\"inline fun foo(): String {\\n") }
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
fun main(args: Array<String>) {
|
||||||
|
println(foo())
|
||||||
|
}
|
||||||
+36
@@ -0,0 +1,36 @@
|
|||||||
|
buildscript {
|
||||||
|
repositories {
|
||||||
|
mavenLocal()
|
||||||
|
}
|
||||||
|
dependencies {
|
||||||
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
allprojects {
|
||||||
|
apply plugin: 'kotlin2js'
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenLocal()
|
||||||
|
mavenCentral()
|
||||||
|
maven { url "https://dl.bintray.com/kotlin/kotlin-dev/" }
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compile "org.jetbrains.kotlin:kotlin-stdlib-js:$kotlin_version"
|
||||||
|
}
|
||||||
|
|
||||||
|
compileKotlin2Js {
|
||||||
|
kotlinOptions.freeCompilerArgs = [ "-Xskip-metadata-version-check" ]
|
||||||
|
kotlinOptions.sourceMap = true
|
||||||
|
kotlinOptions.sourceMapEmbedSources = "always"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
project("app") {
|
||||||
|
dependencies {
|
||||||
|
compile project(":lib")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
inline fun foo(): String {
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
include ':app', ':lib'
|
||||||
+7
@@ -48,6 +48,13 @@ interface KotlinJsOptions : org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
|
|||||||
*/
|
*/
|
||||||
var sourceMap: kotlin.Boolean
|
var sourceMap: kotlin.Boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Embed source files into source map
|
||||||
|
* Possible values: "never", "always", "inlining"
|
||||||
|
* Default value: "inlining"
|
||||||
|
*/
|
||||||
|
var sourceMapEmbedSources: kotlin.String
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prefix for paths in a source map
|
* Prefix for paths in a source map
|
||||||
* Default value: null
|
* Default value: null
|
||||||
|
|||||||
+7
@@ -59,6 +59,11 @@ internal abstract class KotlinJsOptionsBase : org.jetbrains.kotlin.gradle.dsl.Ko
|
|||||||
get() = sourceMapField ?: false
|
get() = sourceMapField ?: false
|
||||||
set(value) { sourceMapField = value }
|
set(value) { sourceMapField = value }
|
||||||
|
|
||||||
|
private var sourceMapEmbedSourcesField: kotlin.String? = null
|
||||||
|
override var sourceMapEmbedSources: kotlin.String
|
||||||
|
get() = sourceMapEmbedSourcesField ?: "inlining"
|
||||||
|
set(value) { sourceMapEmbedSourcesField = value }
|
||||||
|
|
||||||
private var sourceMapPrefixField: kotlin.String?? = null
|
private var sourceMapPrefixField: kotlin.String?? = null
|
||||||
override var sourceMapPrefix: kotlin.String?
|
override var sourceMapPrefix: kotlin.String?
|
||||||
get() = sourceMapPrefixField ?: null
|
get() = sourceMapPrefixField ?: null
|
||||||
@@ -86,6 +91,7 @@ internal abstract class KotlinJsOptionsBase : org.jetbrains.kotlin.gradle.dsl.Ko
|
|||||||
noStdlibField?.let { args.noStdlib = it }
|
noStdlibField?.let { args.noStdlib = it }
|
||||||
outputFileField?.let { args.outputFile = it }
|
outputFileField?.let { args.outputFile = it }
|
||||||
sourceMapField?.let { args.sourceMap = it }
|
sourceMapField?.let { args.sourceMap = it }
|
||||||
|
sourceMapEmbedSourcesField?.let { args.sourceMapEmbedSources = it }
|
||||||
sourceMapPrefixField?.let { args.sourceMapPrefix = it }
|
sourceMapPrefixField?.let { args.sourceMapPrefix = it }
|
||||||
targetField?.let { args.target = it }
|
targetField?.let { args.target = it }
|
||||||
typedArraysField?.let { args.typedArrays = it }
|
typedArraysField?.let { args.typedArrays = it }
|
||||||
@@ -104,6 +110,7 @@ internal fun org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments.fil
|
|||||||
noStdlib = true
|
noStdlib = true
|
||||||
outputFile = null
|
outputFile = null
|
||||||
sourceMap = false
|
sourceMap = false
|
||||||
|
sourceMapEmbedSources = "inlining"
|
||||||
sourceMapPrefix = null
|
sourceMapPrefix = null
|
||||||
target = "v5"
|
target = "v5"
|
||||||
typedArrays = false
|
typedArrays = false
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>org.jetbrains.kotlin</groupId>
|
||||||
|
<artifactId>test-js-sourceMapEmbedSources</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jetbrains.kotlin</groupId>
|
||||||
|
<artifactId>kotlin-stdlib-js</artifactId>
|
||||||
|
<version>${kotlin.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>kotlin-maven-plugin</artifactId>
|
||||||
|
<groupId>org.jetbrains.kotlin</groupId>
|
||||||
|
<version>${kotlin.version}</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>compile</id>
|
||||||
|
<goals>
|
||||||
|
<goal>js</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
<configuration>
|
||||||
|
<sourceMap>true</sourceMap>
|
||||||
|
<sourceMapEmbedSources>always</sourceMapEmbedSources>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
package org.jetbrains
|
||||||
|
|
||||||
|
fun bar() = "OK"
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
source(new File(basedir, "../../../verify-common.bsh").getAbsolutePath());
|
||||||
|
|
||||||
|
assertFileContains("target/js/test-js-sourceMapEmbedSources.js.map", "\"org/jetbrains/HelloWorld.kt\"");
|
||||||
|
assertFileContains("target/js/test-js-sourceMapEmbedSources.js.map", "\"package org.jetbrains\\n\\nfun bar() = \\\"OK\\\"");
|
||||||
+4
@@ -70,6 +70,9 @@ public class K2JSCompilerMojo extends KotlinCompileMojoBase<K2JSCompilerArgument
|
|||||||
@Parameter
|
@Parameter
|
||||||
private String sourceMapPrefix;
|
private String sourceMapPrefix;
|
||||||
|
|
||||||
|
@Parameter(defaultValue = "inlining")
|
||||||
|
private String sourceMapEmbedSources;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main invocation behaviour. Possible values are <b>call</b> and <b>noCall</b>.
|
* Main invocation behaviour. Possible values are <b>call</b> and <b>noCall</b>.
|
||||||
*/
|
*/
|
||||||
@@ -110,6 +113,7 @@ public class K2JSCompilerMojo extends KotlinCompileMojoBase<K2JSCompilerArgument
|
|||||||
|
|
||||||
arguments.sourceMap = sourceMap;
|
arguments.sourceMap = sourceMap;
|
||||||
arguments.sourceMapPrefix = sourceMapPrefix;
|
arguments.sourceMapPrefix = sourceMapPrefix;
|
||||||
|
arguments.sourceMapEmbedSources = sourceMapEmbedSources;
|
||||||
|
|
||||||
if (outputFile != null) {
|
if (outputFile != null) {
|
||||||
ConcurrentMap<String, List<String>> collector = getOutputDirectoriesCollector();
|
ConcurrentMap<String, List<String>> collector = getOutputDirectoriesCollector();
|
||||||
|
|||||||
Reference in New Issue
Block a user