| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199 |
- /*
- MIT License http://www.opensource.org/licenses/mit-license.php
- Author Ivan Kopeykin @vankop
- */
- "use strict";
- const { InlinedUsedName } = require("../optimize/InlineExports");
- const {
- getDependencyUsedByExportsCondition
- } = require("../optimize/InnerGraph");
- const makeSerializable = require("../util/makeSerializable");
- const { ExportPresenceModes } = require("./HarmonyImportDependency");
- const HarmonyImportSpecifierDependency = require("./HarmonyImportSpecifierDependency");
- const { ImportPhase } = require("./ImportPhase");
- /** @import { ReplaceSource } from "webpack-sources" */
- /** @import Dependency, { GetConditionFn } from "../Dependency" */
- /** @import { DependencyTemplateContext } from "../DependencyTemplate" */
- /** @import { BuildMeta } from "../Module" */
- /** @import ModuleGraph from "../ModuleGraph" */
- /** @import ModuleGraphConnection from "../ModuleGraphConnection" */
- /** @import { ImportAttributes, Range } from "../javascript/JavascriptParser" */
- /** @typedef {import("../serialization/ObjectMiddleware").ObjectDeserializerContext<string[]>} ObjectDeserializerContext */
- /** @typedef {import("../serialization/ObjectMiddleware").ObjectSerializerContext<string[]>} ObjectSerializerContext */
- /** @import { Ids } from "./HarmonyImportDependency" */
- /**
- * Dependency for static evaluating import specifier. e.g.
- * @example
- * import a from "a";
- * "x" in a;
- * a.x !== undefined; // if x value statically analyzable
- */
- class HarmonyEvaluatedImportSpecifierDependency extends HarmonyImportSpecifierDependency {
- // read by `HarmonyImportGuard` in place of `instanceof`, which would cycle
- get isHarmonyEvaluatedImportSpecifier() {
- return true;
- }
- /**
- * Creates an instance of HarmonyEvaluatedImportSpecifierDependency.
- * @param {string} request the request string
- * @param {number} sourceOrder source order
- * @param {Ids} ids ids
- * @param {string} name name
- * @param {Range} range location in source code
- * @param {ImportAttributes | undefined} attributes import assertions
- * @param {string} operator operator
- */
- constructor(request, sourceOrder, ids, name, range, attributes, operator) {
- super(
- request,
- sourceOrder,
- ids,
- name,
- range,
- ExportPresenceModes.NONE,
- ImportPhase.Evaluation,
- attributes,
- []
- );
- /** @type {string} */
- this.operator = operator;
- }
- get type() {
- return `evaluated X ${this.operator} harmony import specifier`;
- }
- /**
- * Returns function to determine if the connection is active.
- * @param {ModuleGraph} moduleGraph module graph
- * @returns {null | false | GetConditionFn} function to determine if the connection is active
- */
- getCondition(moduleGraph) {
- // Existence check is independent of inlining; skip the base class's
- // inline-sensitivity, which would wrongly deactivate the connection.
- return getDependencyUsedByExportsCondition(this, moduleGraph);
- }
- /**
- * Serializes this instance into the provided serializer context.
- * @param {ObjectSerializerContext} context context
- */
- serialize(context) {
- super.serialize(context);
- const { write } = context;
- write(this.operator);
- }
- /**
- * Restores this instance from the provided deserializer context.
- * @param {ObjectDeserializerContext} context context
- */
- deserialize(context) {
- super.deserialize(context);
- const { read } = context;
- this.operator = read();
- }
- }
- makeSerializable(
- HarmonyEvaluatedImportSpecifierDependency,
- "webpack/lib/dependencies/HarmonyEvaluatedImportSpecifierDependency"
- );
- HarmonyEvaluatedImportSpecifierDependency.Template = class HarmonyEvaluatedImportSpecifierDependencyTemplate extends (
- HarmonyImportSpecifierDependency.Template
- ) {
- /**
- * Applies the plugin by registering its hooks on the compiler.
- * @param {Dependency} dependency the dependency for which the template should be applied
- * @param {ReplaceSource} source the current replace source which can be modified
- * @param {DependencyTemplateContext} templateContext the context object
- * @returns {void}
- */
- apply(dependency, source, templateContext) {
- const dep =
- /** @type {HarmonyEvaluatedImportSpecifierDependency} */
- (dependency);
- const { module, moduleGraph, runtime } = templateContext;
- const connection = moduleGraph.getConnection(dep);
- // Skip rendering depending when dependency is conditional
- if (connection && !connection.isTargetActive(runtime)) return;
- const exportsInfo = moduleGraph.getExportsInfo(
- /** @type {ModuleGraphConnection} */ (connection).module
- );
- const ids = dep.getIds(moduleGraph);
- /** @type {boolean | undefined | null} */
- let value;
- const exportsType =
- /** @type {ModuleGraphConnection} */
- (connection).module.getExportsType(
- moduleGraph,
- /** @type {BuildMeta} */
- (module.buildMeta).strictHarmonyModule
- );
- switch (exportsType) {
- case "default-with-named": {
- if (ids[0] === "default") {
- value =
- ids.length === 1 || exportsInfo.isExportProvided(ids.slice(1));
- } else {
- value = exportsInfo.isExportProvided(ids);
- }
- break;
- }
- case "namespace": {
- value =
- ids[0] === "__esModule"
- ? ids.length === 1 || undefined
- : exportsInfo.isExportProvided(ids);
- break;
- }
- case "dynamic": {
- if (ids[0] !== "default") {
- value = exportsInfo.isExportProvided(ids);
- }
- break;
- }
- // default-only could lead to runtime error, when default value is primitive
- }
- if (typeof value === "boolean") {
- source.replace(dep.range[0], dep.range[1] - 1, ` ${value}`);
- } else {
- const usedName = exportsInfo.getUsedName(ids, runtime);
- if (usedName instanceof InlinedUsedName) {
- // Inlined exports only work with ESM export dependency
- // which only existed in modules with `namespace` exportsType.
- throw new Error(
- "Evaluated import specifier dependency has inlined export name: This should not happen"
- );
- }
- const code = this._getCodeForIds(
- dep,
- source,
- templateContext,
- ids.slice(0, -1),
- connection
- );
- source.replace(
- dep.range[0],
- dep.range[1] - 1,
- `${
- usedName ? JSON.stringify(usedName[usedName.length - 1]) : '""'
- } in ${code}`
- );
- }
- }
- };
- module.exports = HarmonyEvaluatedImportSpecifierDependency;
|