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 ce6bebc932c..a4a03a7c138 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 @@ -43,6 +43,7 @@ import java.io.File * Kotlin, _ can be renamed by minifier, quotes type can be changed too (" to ') */ private val DEFINE_MODULE_PATTERN = "(\\w+)\\.defineModule\\(\\s*(['\"])(\\w+)\\2\\s*,\\s*(\\w+)\\s*\\)".toRegex() +private val DEFINE_MODULE_FIND_PATTERN = ".defineModule(" class FunctionReader(private val context: TranslationContext) { /** @@ -68,12 +69,20 @@ class FunctionReader(private val context: TranslationContext) { val libs = config.libraries.map { File(it) } JsLibraryUtils.traverseJsLibraries(libs) { fileContent, path -> - val matcher = DEFINE_MODULE_PATTERN.toPattern().matcher(fileContent) + var current = 0 - while (matcher.find()) { - val moduleName = matcher.group(3) - val moduleVariable = matcher.group(4) - val kotlinVariable = matcher.group(1) + while (true) { + var index = fileContent.indexOf(DEFINE_MODULE_FIND_PATTERN, current) + if (index < 0) break + + current = index + 1 + index = rewindToFirstAlpha(fileContent, index) + val preciseMatcher = DEFINE_MODULE_PATTERN.toPattern().matcher(offset(fileContent, index)) + if (!preciseMatcher.lookingAt()) continue + + val moduleName = preciseMatcher.group(3) + val moduleVariable = preciseMatcher.group(4) + val kotlinVariable = preciseMatcher.group(1) assert(moduleName !in moduleJsDefinition) { "Module is defined in more, than one file" } moduleJsDefinition[moduleName] = fileContent moduleRootVariable[moduleName] = moduleVariable @@ -82,6 +91,32 @@ class FunctionReader(private val context: TranslationContext) { } } + private fun rewindToFirstAlpha(text: String, index: Int): Int { + var result = index + while (result > 0 && isAlphaNum(text[result - 1])) { + --result + } + return result + } + + private fun offset(text: String, offset: Int) = object : CharSequence { + override val length: Int + get() = text.length - offset + + override fun get(index: Int) = text[index + offset] + + override fun subSequence(startIndex: Int, endIndex: Int) = text.subSequence(startIndex + offset, endIndex + offset) + + override fun toString() = text.substring(offset) + } + + private fun isAlphaNum(c: Char) = when (c) { + in 'A'..'Z', + in 'a'..'z', + in '0'..'9' -> true + else -> false + } + private val functionCache = object : SLRUCache(50, 50) { override fun createValue(descriptor: CallableDescriptor): JsFunction = readFunction(descriptor).sure { "Could not read function: $descriptor" }