From b280e891e9f4f1ceb59cd2d6710007fab5afa321 Mon Sep 17 00:00:00 2001 From: Alexey Tsvetkov Date: Fri, 6 Mar 2015 14:55:18 +0300 Subject: [PATCH] JS: read compiled js modules --- .../jetbrains/kotlin/utils/LibraryUtils.kt | 24 ++++++++ .../js/config/LibrarySourcesConfig.java | 5 ++ .../kotlin/js/inline/FunctionReader.kt | 56 +++++++++++++++++++ 3 files changed, 85 insertions(+) create mode 100644 js/js.inliner/src/org/jetbrains/kotlin/js/inline/FunctionReader.kt diff --git a/compiler/util/src/org/jetbrains/kotlin/utils/LibraryUtils.kt b/compiler/util/src/org/jetbrains/kotlin/utils/LibraryUtils.kt index ee70e0a7501..54074ac55f3 100644 --- a/compiler/util/src/org/jetbrains/kotlin/utils/LibraryUtils.kt +++ b/compiler/util/src/org/jetbrains/kotlin/utils/LibraryUtils.kt @@ -28,6 +28,7 @@ import java.util.jar.JarFile import java.util.jar.Manifest import java.util.zip.ZipFile import kotlin.platform.platformStatic +import org.jetbrains.kotlin.utils.fileUtils.* public object LibraryUtils { private val LOG = Logger.getInstance(javaClass()) @@ -107,6 +108,29 @@ public object LibraryUtils { } } + platformStatic + public fun readJsFiles(libraries: List): List { + val files = arrayListOf() + val libs = libraries.map { File(it) }.filter { it.exists() } + + for (lib in libs) { + when { + lib.isDirectory() -> + traverseDirectoryWithReportingIOException(lib) { (file, path) -> + files.add(FileUtil.loadFile(file)) + } + FileUtil.isJarOrZip(lib) -> + traverseArchiveWithReportingIOException(lib) { (content, path) -> + files.add(content) + } + else -> + throw IllegalArgumentException("Unknown library format (directory or zip expected): $lib") + } + } + + return files + } + private fun processDirectory(dir: File, action: (File, String) -> Unit) { FileUtil.processFilesRecursively(dir, object : Processor { override fun process(file: File): Boolean { diff --git a/js/js.frontend/src/org/jetbrains/kotlin/js/config/LibrarySourcesConfig.java b/js/js.frontend/src/org/jetbrains/kotlin/js/config/LibrarySourcesConfig.java index e1430665113..063c8f885ee 100644 --- a/js/js.frontend/src/org/jetbrains/kotlin/js/config/LibrarySourcesConfig.java +++ b/js/js.frontend/src/org/jetbrains/kotlin/js/config/LibrarySourcesConfig.java @@ -67,6 +67,11 @@ public class LibrarySourcesConfig extends Config { this.files = files; } + @NotNull + public List getLibraries() { + return files; + } + @NotNull @Override protected List generateLibFiles() { 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 new file mode 100644 index 00000000000..19dc2edb738 --- /dev/null +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/FunctionReader.kt @@ -0,0 +1,56 @@ +/* + * Copyright 2010-2015 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.inline + +import org.jetbrains.kotlin.js.config.LibrarySourcesConfig +import org.jetbrains.kotlin.js.translate.context.TranslationContext +import org.jetbrains.kotlin.utils.* + +import java.io.* + +// TODO: add hash checksum to defineModule? +/** + * Matches string like Kotlin.defineModule("stdlib", _) + * 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() + +public class FunctionReader(private val context: TranslationContext) { + /** + * Maps module name to .js file content, that contains this module definition. + * One file can contain more than one module definition. + */ + private val moduleJsDefinition = hashMapOf(); + + { + val config = context.getConfig() as LibrarySourcesConfig + val libs = config.getLibraries().map { File(it) } + val jsLibs = libs.filter { it.exists() && LibraryUtils.isKotlinJavascriptLibrary(it) } + val files = LibraryUtils.readJsFiles(jsLibs.map { it.getPath() }.toList()) + + for (file in files) { + val matcher = DEFINE_MODULE_PATTERN.matcher(file) + + while (matcher.find()) { + val moduleName = matcher.group(3) + assert(moduleName !in moduleJsDefinition) { "Module is defined in more, than one file" } + moduleJsDefinition[moduleName] = file + } + } + } + +}