source: frontend/node_modules/webpack/lib/dependencies/HarmonyDetectionParserPlugin.js

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 11 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 3.6 KB
Line 
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra
4*/
5
6"use strict";
7
8const { JAVASCRIPT_MODULE_TYPE_ESM } = require("../ModuleTypeConstants");
9const EnvironmentNotSupportAsyncWarning = require("../errors/EnvironmentNotSupportAsyncWarning");
10const DynamicExports = require("./DynamicExports");
11const HarmonyCompatibilityDependency = require("./HarmonyCompatibilityDependency");
12const HarmonyExports = require("./HarmonyExports");
13
14/** @typedef {import("../Module").BuildMeta} BuildMeta */
15/** @typedef {import("../javascript/JavascriptParser")} JavascriptParser */
16
17const PLUGIN_NAME = "HarmonyDetectionParserPlugin";
18
19module.exports = class HarmonyDetectionParserPlugin {
20 /**
21 * Applies the plugin by registering its hooks on the compiler.
22 * @param {JavascriptParser} parser the parser
23 * @returns {void}
24 */
25 apply(parser) {
26 parser.hooks.program.tap(PLUGIN_NAME, (ast) => {
27 const isStrictHarmony =
28 parser.state.module.type === JAVASCRIPT_MODULE_TYPE_ESM;
29 const isHarmony =
30 isStrictHarmony ||
31 ast.body.some(
32 (statement) =>
33 statement.type === "ImportDeclaration" ||
34 statement.type === "ExportDefaultDeclaration" ||
35 statement.type === "ExportNamedDeclaration" ||
36 statement.type === "ExportAllDeclaration"
37 );
38 if (isHarmony) {
39 const module = parser.state.module;
40 const compatDep = new HarmonyCompatibilityDependency();
41 compatDep.loc = {
42 start: {
43 line: -1,
44 column: 0
45 },
46 end: {
47 line: -1,
48 column: 0
49 },
50 index: -3
51 };
52 module.addPresentationalDependency(compatDep);
53 DynamicExports.bailout(parser.state);
54 HarmonyExports.enable(parser.state, isStrictHarmony);
55 parser.scope.isStrict = true;
56 }
57 });
58
59 parser.hooks.topLevelAwait.tap(PLUGIN_NAME, () => {
60 const module = parser.state.module;
61 if (!HarmonyExports.isEnabled(parser.state)) {
62 throw new Error(
63 "Top-level-await is only supported in EcmaScript Modules"
64 );
65 }
66 /** @type {BuildMeta} */
67 (module.buildMeta).async = true;
68 EnvironmentNotSupportAsyncWarning.check(
69 module,
70 parser.state.compilation.runtimeTemplate,
71 "topLevelAwait"
72 );
73 });
74
75 /**
76 * Returns true if in harmony.
77 * @returns {boolean | undefined} true if in harmony
78 */
79 const skipInHarmony = () => {
80 if (HarmonyExports.isEnabled(parser.state)) {
81 return true;
82 }
83 };
84
85 /**
86 * Returns null if in harmony.
87 * @returns {null | undefined} null if in harmony
88 */
89 const nullInHarmony = () => {
90 if (HarmonyExports.isEnabled(parser.state)) {
91 return null;
92 }
93 };
94
95 /**
96 * Walks call arguments so import bindings used inside callbacks are
97 * still tracked, then skips default AMD/CommonJS handling.
98 * @param {import("estree").CallExpression} expr call expression
99 * @returns {boolean | undefined} true if in harmony
100 */
101 const walkArgumentsAndSkipInHarmony = (expr) => {
102 if (HarmonyExports.isEnabled(parser.state)) {
103 if (expr.arguments) parser.walkExpressions(expr.arguments);
104 return true;
105 }
106 };
107
108 const nonHarmonyIdentifiers = ["define", "exports"];
109 for (const identifier of nonHarmonyIdentifiers) {
110 parser.hooks.evaluateTypeof
111 .for(identifier)
112 .tap(PLUGIN_NAME, nullInHarmony);
113 parser.hooks.typeof.for(identifier).tap(PLUGIN_NAME, skipInHarmony);
114 parser.hooks.evaluate.for(identifier).tap(PLUGIN_NAME, nullInHarmony);
115 parser.hooks.expression.for(identifier).tap(PLUGIN_NAME, skipInHarmony);
116 parser.hooks.call
117 .for(identifier)
118 .tap(
119 PLUGIN_NAME,
120 identifier === "define"
121 ? walkArgumentsAndSkipInHarmony
122 : skipInHarmony
123 );
124 }
125 }
126};
Note: See TracBrowser for help on using the repository browser.