org.scalajs.linker.standard.ModuleSet.scala Maven / Gradle / Ivy
/*
* Scala.js (https://www.scala-js.org/)
*
* Copyright EPFL.
*
* Licensed under Apache License 2.0
* (https://www.apache.org/licenses/LICENSE-2.0).
*
* See the NOTICE file distributed with this work for
* additional information regarding copyright ownership.
*/
package org.scalajs.linker.standard
import org.scalajs.ir.Names.ClassName
import org.scalajs.ir.Trees.TopLevelExportDef
import org.scalajs.linker.interface.ModuleInitializer
/** A set of linked Scala.js modules.
*
* The Scala.js linker distinguishes three types of modules:
*
* - External Modules: Modules that are imported through native JS
* types/members. These are not generated by Scala.js but need to be provided
* by the user. For example, the Node.js `fs` module.
* - Public Modules: Scala.js-produced modules intended for import by user
* code. Only these modules may hold top level exports (but may contain more).
* Public modules may not be imported by other Scala.js produced modules.
* - Internal Modules: Scala.js-produced modules only relevant for splitting.
* These are only intended to be imported by other Scala.js-produced modules.
*
* Note that a ModuleSet may contain no modules at all. This happens if there
* are no public modules.
*/
final class ModuleSet private[linker] (
val coreSpec: CoreSpec,
val modules: List[ModuleSet.Module],
/** Abstract classes may not have any definitions, but are still required
* for proper code generation.
*
* For example, a native JS class that is needed for its load spec.
*/
val abstractClasses: List[LinkedClass],
val globalInfo: LinkedGlobalInfo
) {
require(modules.isEmpty || modules.count(_.isRoot) == 1,
"Must have exactly one root module")
}
object ModuleSet {
/* ModuleID is not an AnyVal because it is used a lot in Maps as key.
* An AnyVal would cause a lot of boxing/unboxing.
*/
final class ModuleID(val id: String) {
override def toString(): String = s"ModuleID($id)"
override def equals(that: Any): Boolean = that match {
case that: ModuleID => this.id == that.id
case _ => false
}
override def hashCode(): Int = id.##
}
object ModuleID {
def apply(id: String): ModuleID = new ModuleID(id)
}
final class Module(
val id: ModuleID,
val internalDependencies: Set[ModuleID],
val externalDependencies: Set[String],
val public: Boolean,
val classDefs: List[LinkedClass],
val topLevelExports: List[LinkedTopLevelExport],
val initializers: Seq[ModuleInitializer.Initializer]
) {
require(public || topLevelExports.isEmpty,
"Only public modules may have top-level exports")
require(!internalDependencies.contains(id),
"A module may not depend on itself")
def isRoot: Boolean = internalDependencies.isEmpty
}
}