diff --git a/src/loader.js b/src/loader.js index 2e182aa5..5c0b04b1 100644 --- a/src/loader.js +++ b/src/loader.js @@ -44,22 +44,31 @@ const MiniCssExtractPlugin = require("./index"); * @returns {string} */ function hotLoader(content, context) { - const accept = context.locals - ? "" - : "module.hot.accept(undefined, cssReload);"; - + const localsJsonString = JSON.stringify(JSON.stringify(context.locals)); return `${content} if(module.hot) { - // ${Date.now()} - var cssReload = require(${stringifyRequest( - context.loaderContext, - path.join(__dirname, "hmr/hotModuleReplacement.js") - )})(module.id, ${JSON.stringify({ - ...context.options, - locals: !!context.locals, - })}); - module.hot.dispose(cssReload); - ${accept} + (function() { + var localsJsonString = ${localsJsonString}; + // ${Date.now()} + var cssReload = require(${stringifyRequest( + context.loaderContext, + path.join(__dirname, "hmr/hotModuleReplacement.js") + )})(module.id, ${JSON.stringify(context.options)}); + // only invalidate when locals change + if ( + module.hot.data && + module.hot.data.value && + module.hot.data.value !== localsJsonString + ) { + module.hot.invalidate(); + } else { + module.hot.accept(); + } + module.hot.dispose(function(data) { + data.value = localsJsonString; + cssReload(); + }); + })(); } `; } @@ -563,3 +572,4 @@ function loader(content) { module.exports = loader; module.exports.pitch = pitch; +module.exports.hotLoader = hotLoader; diff --git a/test/HMR.test.js b/test/HMR.test.js index 79ee30e6..1c781d9b 100644 --- a/test/HMR.test.js +++ b/test/HMR.test.js @@ -5,6 +5,7 @@ /* eslint-disable no-console */ import hotModuleReplacement from "../src/hmr/hotModuleReplacement"; +import { hotLoader } from "../src/loader"; function getLoadEvent() { const event = document.createEvent("Event"); @@ -361,4 +362,29 @@ describe("HMR", () => { done(); }, 100); }); + + it("hotLoader works for non-locals", () => { + const o = Date.now; + Date.now = () => 1; + const code = hotLoader("//content;", { + loaderContext: { + context: __dirname, + }, + }); + Date.now = o; + expect(code).toMatchSnapshot(); + }); + + it("hotLoader works for locals", () => { + const o = Date.now; + Date.now = () => 1; + const code = hotLoader("//content;", { + loaderContext: { + context: __dirname, + }, + locals: { foo: "bar" }, + }); + Date.now = o; + expect(code).toMatchSnapshot(); + }); }); diff --git a/test/__snapshots__/HMR.test.js.snap b/test/__snapshots__/HMR.test.js.snap index ee4d6eef..608bd559 100644 --- a/test/__snapshots__/HMR.test.js.snap +++ b/test/__snapshots__/HMR.test.js.snap @@ -1,5 +1,57 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`HMR hotLoader works for locals 1`] = ` +"//content; + if(module.hot) { + (function() { + var localsJsonString = \\"{\\\\\\"foo\\\\\\":\\\\\\"bar\\\\\\"}\\"; + // 1 + var cssReload = require(\\"../src/hmr/hotModuleReplacement.js\\")(module.id, undefined); + // only invalidate when locals change + if ( + module.hot.data && + module.hot.data.value && + module.hot.data.value !== localsJsonString + ) { + module.hot.invalidate(); + } else { + module.hot.accept(); + } + module.hot.dispose(function(data) { + data.value = localsJsonString; + cssReload(); + }); + })(); + } + " +`; + +exports[`HMR hotLoader works for non-locals 1`] = ` +"//content; + if(module.hot) { + (function() { + var localsJsonString = undefined; + // 1 + var cssReload = require(\\"../src/hmr/hotModuleReplacement.js\\")(module.id, undefined); + // only invalidate when locals change + if ( + module.hot.data && + module.hot.data.value && + module.hot.data.value !== localsJsonString + ) { + module.hot.invalidate(); + } else { + module.hot.accept(); + } + module.hot.dispose(function(data) { + data.value = localsJsonString; + cssReload(); + }); + })(); + } + " +`; + exports[`HMR should handle error event 1`] = `"[HMR] css reload %s"`; exports[`HMR should handle error event 2`] = `""`; diff --git a/test/cases/hmr-locals/expected/main.css b/test/cases/hmr-locals/expected/main.css new file mode 100644 index 00000000..c5589a3f --- /dev/null +++ b/test/cases/hmr-locals/expected/main.css @@ -0,0 +1,7 @@ +/*!************************************************************************************************!*\ + !*** css ../../../node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[0].use[1]!./index.css ***! + \************************************************************************************************/ +.VoofDB21D_QzDbRdwMiY { + color: red; +} + diff --git a/test/cases/hmr-locals/expected/main.js b/test/cases/hmr-locals/expected/main.js new file mode 100644 index 00000000..69b2e238 --- /dev/null +++ b/test/cases/hmr-locals/expected/main.js @@ -0,0 +1,1587 @@ +/******/ (() => { // webpackBootstrap +/******/ var __webpack_modules__ = ({ + +/***/ "../../../src/hmr/hotModuleReplacement.js": +/*!************************************************!*\ + !*** ../../../src/hmr/hotModuleReplacement.js ***! + \************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/* eslint-env browser */ +/* + eslint-disable + no-console, + func-names +*/ + +/** @typedef {any} TODO */ + +const normalizeUrl = __webpack_require__(/*! ./normalize-url */ "../../../src/hmr/normalize-url.js"); + +const srcByModuleId = Object.create(null); + +const noDocument = typeof document === "undefined"; + +const { forEach } = Array.prototype; + +/** + * @param {function} fn + * @param {number} time + * @returns {(function(): void)|*} + */ +function debounce(fn, time) { + let timeout = 0; + + return function () { + // @ts-ignore + const self = this; + // eslint-disable-next-line prefer-rest-params + const args = arguments; + + const functionCall = function functionCall() { + return fn.apply(self, args); + }; + + clearTimeout(timeout); + + // @ts-ignore + timeout = setTimeout(functionCall, time); + }; +} + +function noop() {} + +/** + * @param {TODO} moduleId + * @returns {TODO} + */ +function getCurrentScriptUrl(moduleId) { + let src = srcByModuleId[moduleId]; + + if (!src) { + if (document.currentScript) { + ({ src } = /** @type {HTMLScriptElement} */ (document.currentScript)); + } else { + const scripts = document.getElementsByTagName("script"); + const lastScriptTag = scripts[scripts.length - 1]; + + if (lastScriptTag) { + ({ src } = lastScriptTag); + } + } + + srcByModuleId[moduleId] = src; + } + + /** + * @param {string} fileMap + * @returns {null | string[]} + */ + return function (fileMap) { + if (!src) { + return null; + } + + const splitResult = src.split(/([^\\/]+)\.js$/); + const filename = splitResult && splitResult[1]; + + if (!filename) { + return [src.replace(".js", ".css")]; + } + + if (!fileMap) { + return [src.replace(".js", ".css")]; + } + + return fileMap.split(",").map((mapRule) => { + const reg = new RegExp(`${filename}\\.js$`, "g"); + + return normalizeUrl( + src.replace(reg, `${mapRule.replace(/{fileName}/g, filename)}.css`) + ); + }); + }; +} + +/** + * @param {TODO} el + * @param {string} [url] + */ +function updateCss(el, url) { + if (!url) { + if (!el.href) { + return; + } + + // eslint-disable-next-line + url = el.href.split("?")[0]; + } + + if (!isUrlRequest(/** @type {string} */ (url))) { + return; + } + + if (el.isLoaded === false) { + // We seem to be about to replace a css link that hasn't loaded yet. + // We're probably changing the same file more than once. + return; + } + + if (!url || !(url.indexOf(".css") > -1)) { + return; + } + + // eslint-disable-next-line no-param-reassign + el.visited = true; + + const newEl = el.cloneNode(); + + newEl.isLoaded = false; + + newEl.addEventListener("load", () => { + if (newEl.isLoaded) { + return; + } + + newEl.isLoaded = true; + el.parentNode.removeChild(el); + }); + + newEl.addEventListener("error", () => { + if (newEl.isLoaded) { + return; + } + + newEl.isLoaded = true; + el.parentNode.removeChild(el); + }); + + newEl.href = `${url}?${Date.now()}`; + + if (el.nextSibling) { + el.parentNode.insertBefore(newEl, el.nextSibling); + } else { + el.parentNode.appendChild(newEl); + } +} + +/** + * @param {string} href + * @param {TODO} src + * @returns {TODO} + */ +function getReloadUrl(href, src) { + let ret; + + // eslint-disable-next-line no-param-reassign + href = normalizeUrl(href); + + src.some( + /** + * @param {string} url + */ + // eslint-disable-next-line array-callback-return + (url) => { + if (href.indexOf(src) > -1) { + ret = url; + } + } + ); + + return ret; +} + +/** + * @param {string} [src] + * @returns {boolean} + */ +function reloadStyle(src) { + if (!src) { + return false; + } + + const elements = document.querySelectorAll("link"); + let loaded = false; + + forEach.call(elements, (el) => { + if (!el.href) { + return; + } + + const url = getReloadUrl(el.href, src); + + if (!isUrlRequest(url)) { + return; + } + + if (el.visited === true) { + return; + } + + if (url) { + updateCss(el, url); + + loaded = true; + } + }); + + return loaded; +} + +function reloadAll() { + const elements = document.querySelectorAll("link"); + + forEach.call(elements, (el) => { + if (el.visited === true) { + return; + } + + updateCss(el); + }); +} + +/** + * @param {string} url + * @returns {boolean} + */ +function isUrlRequest(url) { + // An URL is not an request if + + // It is not http or https + if (!/^[a-zA-Z][a-zA-Z\d+\-.]*:/.test(url)) { + return false; + } + + return true; +} + +/** + * @param {TODO} moduleId + * @param {TODO} options + * @returns {TODO} + */ +module.exports = function (moduleId, options) { + if (noDocument) { + console.log("no window.document found, will not HMR CSS"); + + return noop; + } + + const getScriptSrc = getCurrentScriptUrl(moduleId); + + function update() { + const src = getScriptSrc(options.filename); + const reloaded = reloadStyle(src); + + if (options.locals) { + console.log("[HMR] Detected local css modules. Reload all css"); + + reloadAll(); + + return; + } + + if (reloaded) { + console.log("[HMR] css reload %s", src.join(" ")); + } else { + console.log("[HMR] Reload all css"); + + reloadAll(); + } + } + + return debounce(update, 50); +}; + + +/***/ }), + +/***/ "../../../src/hmr/normalize-url.js": +/*!*****************************************!*\ + !*** ../../../src/hmr/normalize-url.js ***! + \*****************************************/ +/***/ ((module) => { + +/* eslint-disable */ + +/** + * @param {string[]} pathComponents + * @returns {string} + */ +function normalizeUrl(pathComponents) { + return pathComponents + .reduce(function (accumulator, item) { + switch (item) { + case "..": + accumulator.pop(); + break; + case ".": + break; + default: + accumulator.push(item); + } + + return accumulator; + }, /** @type {string[]} */ ([])) + .join("/"); +} + +/** + * @param {string} urlString + * @returns {string} + */ +module.exports = function (urlString) { + urlString = urlString.trim(); + + if (/^data:/i.test(urlString)) { + return urlString; + } + + var protocol = + urlString.indexOf("//") !== -1 ? urlString.split("//")[0] + "//" : ""; + var components = urlString.replace(new RegExp(protocol, "i"), "").split("/"); + var host = components[0].toLowerCase().replace(/\.$/, ""); + + components[0] = ""; + + var path = normalizeUrl(components); + + return protocol + host + path; +}; + + +/***/ }), + +/***/ "./index.css": +/*!*******************!*\ + !*** ./index.css ***! + \*******************/ +/***/ ((module, __webpack_exports__, __webpack_require__) => { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) +/* harmony export */ }); +// extracted by mini-css-extract-plugin +/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({"x":"VoofDB21D_QzDbRdwMiY"}); + if(true) { + (function() { + var localsJsonString = "{\"x\":\"VoofDB21D_QzDbRdwMiY\"}"; + // + var cssReload = __webpack_require__(/*! ../../../src/hmr/hotModuleReplacement.js */ "../../../src/hmr/hotModuleReplacement.js")(module.id, {}); + // only invalidate when locals change + if ( + module.hot.data && + module.hot.data.value && + module.hot.data.value !== localsJsonString + ) { + module.hot.invalidate(); + } else { + module.hot.accept(); + } + module.hot.dispose(function(data) { + data.value = localsJsonString; + cssReload(); + }); + })(); + } + + +/***/ }) + +/******/ }); +/************************************************************************/ +/******/ // The module cache +/******/ var __webpack_module_cache__ = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ // Check if module is in cache +/******/ var cachedModule = __webpack_module_cache__[moduleId]; +/******/ if (cachedModule !== undefined) { +/******/ if (cachedModule.error !== undefined) throw cachedModule.error; +/******/ return cachedModule.exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = __webpack_module_cache__[moduleId] = { +/******/ id: moduleId, +/******/ // no module.loaded needed +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ try { +/******/ var execOptions = { id: moduleId, module: module, factory: __webpack_modules__[moduleId], require: __webpack_require__ }; +/******/ __webpack_require__.i.forEach(function(handler) { handler(execOptions); }); +/******/ module = execOptions.module; +/******/ execOptions.factory.call(module.exports, module, module.exports, execOptions.require); +/******/ } catch(e) { +/******/ module.error = e; +/******/ throw e; +/******/ } +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = __webpack_modules__; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = __webpack_module_cache__; +/******/ +/******/ // expose the module execution interceptor +/******/ __webpack_require__.i = []; +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/define property getters */ +/******/ (() => { +/******/ // define getter functions for harmony exports +/******/ __webpack_require__.d = (exports, definition) => { +/******/ for(var key in definition) { +/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { +/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); +/******/ } +/******/ } +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/get javascript update chunk filename */ +/******/ (() => { +/******/ // This function allow to reference all chunks +/******/ __webpack_require__.hu = (chunkId) => { +/******/ // return url for filenames based on template +/******/ return "" + chunkId + "." + __webpack_require__.h() + ".hot-update.js"; +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/get mini-css chunk filename */ +/******/ (() => { +/******/ // This function allow to reference async chunks +/******/ __webpack_require__.miniCssF = (chunkId) => { +/******/ // return url for filenames based on template +/******/ return undefined; +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/get update manifest filename */ +/******/ (() => { +/******/ __webpack_require__.hmrF = () => ("main." + __webpack_require__.h() + ".hot-update.json"); +/******/ })(); +/******/ +/******/ /* webpack/runtime/getFullHash */ +/******/ (() => { +/******/ __webpack_require__.h = () => ("xxxxxxxxxxxxxxxxxxxxxx") +/******/ })(); +/******/ +/******/ /* webpack/runtime/global */ +/******/ (() => { +/******/ __webpack_require__.g = (function() { +/******/ if (typeof globalThis === 'object') return globalThis; +/******/ try { +/******/ return this || new Function('return this')(); +/******/ } catch (e) { +/******/ if (typeof window === 'object') return window; +/******/ } +/******/ })(); +/******/ })(); +/******/ +/******/ /* webpack/runtime/hasOwnProperty shorthand */ +/******/ (() => { +/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) +/******/ })(); +/******/ +/******/ /* webpack/runtime/load script */ +/******/ (() => { +/******/ var inProgress = {}; +/******/ // data-webpack is not used as build has no uniqueName +/******/ // loadScript function to load a script via script tag +/******/ __webpack_require__.l = (url, done, key, chunkId) => { +/******/ if(inProgress[url]) { inProgress[url].push(done); return; } +/******/ var script, needAttach; +/******/ if(key !== undefined) { +/******/ var scripts = document.getElementsByTagName("script"); +/******/ for(var i = 0; i < scripts.length; i++) { +/******/ var s = scripts[i]; +/******/ if(s.getAttribute("src") == url) { script = s; break; } +/******/ } +/******/ } +/******/ if(!script) { +/******/ needAttach = true; +/******/ script = document.createElement('script'); +/******/ +/******/ script.charset = 'utf-8'; +/******/ script.timeout = 120; +/******/ if (__webpack_require__.nc) { +/******/ script.setAttribute("nonce", __webpack_require__.nc); +/******/ } +/******/ +/******/ +/******/ script.src = url; +/******/ } +/******/ inProgress[url] = [done]; +/******/ var onScriptComplete = (prev, event) => { +/******/ // avoid mem leaks in IE. +/******/ script.onerror = script.onload = null; +/******/ clearTimeout(timeout); +/******/ var doneFns = inProgress[url]; +/******/ delete inProgress[url]; +/******/ script.parentNode && script.parentNode.removeChild(script); +/******/ doneFns && doneFns.forEach((fn) => (fn(event))); +/******/ if(prev) return prev(event); +/******/ } +/******/ var timeout = setTimeout(onScriptComplete.bind(null, undefined, { type: 'timeout', target: script }), 120000); +/******/ script.onerror = onScriptComplete.bind(null, script.onerror); +/******/ script.onload = onScriptComplete.bind(null, script.onload); +/******/ needAttach && document.head.appendChild(script); +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/hot module replacement */ +/******/ (() => { +/******/ var currentModuleData = {}; +/******/ var installedModules = __webpack_require__.c; +/******/ +/******/ // module and require creation +/******/ var currentChildModule; +/******/ var currentParents = []; +/******/ +/******/ // status +/******/ var registeredStatusHandlers = []; +/******/ var currentStatus = "idle"; +/******/ +/******/ // while downloading +/******/ var blockingPromises = 0; +/******/ var blockingPromisesWaiting = []; +/******/ +/******/ // The update info +/******/ var currentUpdateApplyHandlers; +/******/ var queuedInvalidatedModules; +/******/ +/******/ __webpack_require__.hmrD = currentModuleData; +/******/ +/******/ __webpack_require__.i.push(function (options) { +/******/ var module = options.module; +/******/ var require = createRequire(options.require, options.id); +/******/ module.hot = createModuleHotObject(options.id, module); +/******/ module.parents = currentParents; +/******/ module.children = []; +/******/ currentParents = []; +/******/ options.require = require; +/******/ }); +/******/ +/******/ __webpack_require__.hmrC = {}; +/******/ __webpack_require__.hmrI = {}; +/******/ +/******/ function createRequire(require, moduleId) { +/******/ var me = installedModules[moduleId]; +/******/ if (!me) return require; +/******/ var fn = function (request) { +/******/ if (me.hot.active) { +/******/ if (installedModules[request]) { +/******/ var parents = installedModules[request].parents; +/******/ if (parents.indexOf(moduleId) === -1) { +/******/ parents.push(moduleId); +/******/ } +/******/ } else { +/******/ currentParents = [moduleId]; +/******/ currentChildModule = request; +/******/ } +/******/ if (me.children.indexOf(request) === -1) { +/******/ me.children.push(request); +/******/ } +/******/ } else { +/******/ console.warn( +/******/ "[HMR] unexpected require(" + +/******/ request + +/******/ ") from disposed module " + +/******/ moduleId +/******/ ); +/******/ currentParents = []; +/******/ } +/******/ return require(request); +/******/ }; +/******/ var createPropertyDescriptor = function (name) { +/******/ return { +/******/ configurable: true, +/******/ enumerable: true, +/******/ get: function () { +/******/ return require[name]; +/******/ }, +/******/ set: function (value) { +/******/ require[name] = value; +/******/ } +/******/ }; +/******/ }; +/******/ for (var name in require) { +/******/ if (Object.prototype.hasOwnProperty.call(require, name) && name !== "e") { +/******/ Object.defineProperty(fn, name, createPropertyDescriptor(name)); +/******/ } +/******/ } +/******/ fn.e = function (chunkId, fetchPriority) { +/******/ return trackBlockingPromise(require.e(chunkId, fetchPriority)); +/******/ }; +/******/ return fn; +/******/ } +/******/ +/******/ function createModuleHotObject(moduleId, me) { +/******/ var _main = currentChildModule !== moduleId; +/******/ var hot = { +/******/ // private stuff +/******/ _acceptedDependencies: {}, +/******/ _acceptedErrorHandlers: {}, +/******/ _declinedDependencies: {}, +/******/ _selfAccepted: false, +/******/ _selfDeclined: false, +/******/ _selfInvalidated: false, +/******/ _disposeHandlers: [], +/******/ _main: _main, +/******/ _requireSelf: function () { +/******/ currentParents = me.parents.slice(); +/******/ currentChildModule = _main ? undefined : moduleId; +/******/ __webpack_require__(moduleId); +/******/ }, +/******/ +/******/ // Module API +/******/ active: true, +/******/ accept: function (dep, callback, errorHandler) { +/******/ if (dep === undefined) hot._selfAccepted = true; +/******/ else if (typeof dep === "function") hot._selfAccepted = dep; +/******/ else if (typeof dep === "object" && dep !== null) { +/******/ for (var i = 0; i < dep.length; i++) { +/******/ hot._acceptedDependencies[dep[i]] = callback || function () {}; +/******/ hot._acceptedErrorHandlers[dep[i]] = errorHandler; +/******/ } +/******/ } else { +/******/ hot._acceptedDependencies[dep] = callback || function () {}; +/******/ hot._acceptedErrorHandlers[dep] = errorHandler; +/******/ } +/******/ }, +/******/ decline: function (dep) { +/******/ if (dep === undefined) hot._selfDeclined = true; +/******/ else if (typeof dep === "object" && dep !== null) +/******/ for (var i = 0; i < dep.length; i++) +/******/ hot._declinedDependencies[dep[i]] = true; +/******/ else hot._declinedDependencies[dep] = true; +/******/ }, +/******/ dispose: function (callback) { +/******/ hot._disposeHandlers.push(callback); +/******/ }, +/******/ addDisposeHandler: function (callback) { +/******/ hot._disposeHandlers.push(callback); +/******/ }, +/******/ removeDisposeHandler: function (callback) { +/******/ var idx = hot._disposeHandlers.indexOf(callback); +/******/ if (idx >= 0) hot._disposeHandlers.splice(idx, 1); +/******/ }, +/******/ invalidate: function () { +/******/ this._selfInvalidated = true; +/******/ switch (currentStatus) { +/******/ case "idle": +/******/ currentUpdateApplyHandlers = []; +/******/ Object.keys(__webpack_require__.hmrI).forEach(function (key) { +/******/ __webpack_require__.hmrI[key]( +/******/ moduleId, +/******/ currentUpdateApplyHandlers +/******/ ); +/******/ }); +/******/ setStatus("ready"); +/******/ break; +/******/ case "ready": +/******/ Object.keys(__webpack_require__.hmrI).forEach(function (key) { +/******/ __webpack_require__.hmrI[key]( +/******/ moduleId, +/******/ currentUpdateApplyHandlers +/******/ ); +/******/ }); +/******/ break; +/******/ case "prepare": +/******/ case "check": +/******/ case "dispose": +/******/ case "apply": +/******/ (queuedInvalidatedModules = queuedInvalidatedModules || []).push( +/******/ moduleId +/******/ ); +/******/ break; +/******/ default: +/******/ // ignore requests in error states +/******/ break; +/******/ } +/******/ }, +/******/ +/******/ // Management API +/******/ check: hotCheck, +/******/ apply: hotApply, +/******/ status: function (l) { +/******/ if (!l) return currentStatus; +/******/ registeredStatusHandlers.push(l); +/******/ }, +/******/ addStatusHandler: function (l) { +/******/ registeredStatusHandlers.push(l); +/******/ }, +/******/ removeStatusHandler: function (l) { +/******/ var idx = registeredStatusHandlers.indexOf(l); +/******/ if (idx >= 0) registeredStatusHandlers.splice(idx, 1); +/******/ }, +/******/ +/******/ //inherit from previous dispose call +/******/ data: currentModuleData[moduleId] +/******/ }; +/******/ currentChildModule = undefined; +/******/ return hot; +/******/ } +/******/ +/******/ function setStatus(newStatus) { +/******/ currentStatus = newStatus; +/******/ var results = []; +/******/ +/******/ for (var i = 0; i < registeredStatusHandlers.length; i++) +/******/ results[i] = registeredStatusHandlers[i].call(null, newStatus); +/******/ +/******/ return Promise.all(results).then(function () {}); +/******/ } +/******/ +/******/ function unblock() { +/******/ if (--blockingPromises === 0) { +/******/ setStatus("ready").then(function () { +/******/ if (blockingPromises === 0) { +/******/ var list = blockingPromisesWaiting; +/******/ blockingPromisesWaiting = []; +/******/ for (var i = 0; i < list.length; i++) { +/******/ list[i](); +/******/ } +/******/ } +/******/ }); +/******/ } +/******/ } +/******/ +/******/ function trackBlockingPromise(promise) { +/******/ switch (currentStatus) { +/******/ case "ready": +/******/ setStatus("prepare"); +/******/ /* fallthrough */ +/******/ case "prepare": +/******/ blockingPromises++; +/******/ promise.then(unblock, unblock); +/******/ return promise; +/******/ default: +/******/ return promise; +/******/ } +/******/ } +/******/ +/******/ function waitForBlockingPromises(fn) { +/******/ if (blockingPromises === 0) return fn(); +/******/ return new Promise(function (resolve) { +/******/ blockingPromisesWaiting.push(function () { +/******/ resolve(fn()); +/******/ }); +/******/ }); +/******/ } +/******/ +/******/ function hotCheck(applyOnUpdate) { +/******/ if (currentStatus !== "idle") { +/******/ throw new Error("check() is only allowed in idle status"); +/******/ } +/******/ return setStatus("check") +/******/ .then(__webpack_require__.hmrM) +/******/ .then(function (update) { +/******/ if (!update) { +/******/ return setStatus(applyInvalidatedModules() ? "ready" : "idle").then( +/******/ function () { +/******/ return null; +/******/ } +/******/ ); +/******/ } +/******/ +/******/ return setStatus("prepare").then(function () { +/******/ var updatedModules = []; +/******/ currentUpdateApplyHandlers = []; +/******/ +/******/ return Promise.all( +/******/ Object.keys(__webpack_require__.hmrC).reduce(function ( +/******/ promises, +/******/ key +/******/ ) { +/******/ __webpack_require__.hmrC[key]( +/******/ update.c, +/******/ update.r, +/******/ update.m, +/******/ promises, +/******/ currentUpdateApplyHandlers, +/******/ updatedModules +/******/ ); +/******/ return promises; +/******/ }, []) +/******/ ).then(function () { +/******/ return waitForBlockingPromises(function () { +/******/ if (applyOnUpdate) { +/******/ return internalApply(applyOnUpdate); +/******/ } else { +/******/ return setStatus("ready").then(function () { +/******/ return updatedModules; +/******/ }); +/******/ } +/******/ }); +/******/ }); +/******/ }); +/******/ }); +/******/ } +/******/ +/******/ function hotApply(options) { +/******/ if (currentStatus !== "ready") { +/******/ return Promise.resolve().then(function () { +/******/ throw new Error( +/******/ "apply() is only allowed in ready status (state: " + +/******/ currentStatus + +/******/ ")" +/******/ ); +/******/ }); +/******/ } +/******/ return internalApply(options); +/******/ } +/******/ +/******/ function internalApply(options) { +/******/ options = options || {}; +/******/ +/******/ applyInvalidatedModules(); +/******/ +/******/ var results = currentUpdateApplyHandlers.map(function (handler) { +/******/ return handler(options); +/******/ }); +/******/ currentUpdateApplyHandlers = undefined; +/******/ +/******/ var errors = results +/******/ .map(function (r) { +/******/ return r.error; +/******/ }) +/******/ .filter(Boolean); +/******/ +/******/ if (errors.length > 0) { +/******/ return setStatus("abort").then(function () { +/******/ throw errors[0]; +/******/ }); +/******/ } +/******/ +/******/ // Now in "dispose" phase +/******/ var disposePromise = setStatus("dispose"); +/******/ +/******/ results.forEach(function (result) { +/******/ if (result.dispose) result.dispose(); +/******/ }); +/******/ +/******/ // Now in "apply" phase +/******/ var applyPromise = setStatus("apply"); +/******/ +/******/ var error; +/******/ var reportError = function (err) { +/******/ if (!error) error = err; +/******/ }; +/******/ +/******/ var outdatedModules = []; +/******/ results.forEach(function (result) { +/******/ if (result.apply) { +/******/ var modules = result.apply(reportError); +/******/ if (modules) { +/******/ for (var i = 0; i < modules.length; i++) { +/******/ outdatedModules.push(modules[i]); +/******/ } +/******/ } +/******/ } +/******/ }); +/******/ +/******/ return Promise.all([disposePromise, applyPromise]).then(function () { +/******/ // handle errors in accept handlers and self accepted module load +/******/ if (error) { +/******/ return setStatus("fail").then(function () { +/******/ throw error; +/******/ }); +/******/ } +/******/ +/******/ if (queuedInvalidatedModules) { +/******/ return internalApply(options).then(function (list) { +/******/ outdatedModules.forEach(function (moduleId) { +/******/ if (list.indexOf(moduleId) < 0) list.push(moduleId); +/******/ }); +/******/ return list; +/******/ }); +/******/ } +/******/ +/******/ return setStatus("idle").then(function () { +/******/ return outdatedModules; +/******/ }); +/******/ }); +/******/ } +/******/ +/******/ function applyInvalidatedModules() { +/******/ if (queuedInvalidatedModules) { +/******/ if (!currentUpdateApplyHandlers) currentUpdateApplyHandlers = []; +/******/ Object.keys(__webpack_require__.hmrI).forEach(function (key) { +/******/ queuedInvalidatedModules.forEach(function (moduleId) { +/******/ __webpack_require__.hmrI[key]( +/******/ moduleId, +/******/ currentUpdateApplyHandlers +/******/ ); +/******/ }); +/******/ }); +/******/ queuedInvalidatedModules = undefined; +/******/ return true; +/******/ } +/******/ } +/******/ })(); +/******/ +/******/ /* webpack/runtime/publicPath */ +/******/ (() => { +/******/ var scriptUrl; +/******/ if (__webpack_require__.g.importScripts) scriptUrl = __webpack_require__.g.location + ""; +/******/ var document = __webpack_require__.g.document; +/******/ if (!scriptUrl && document) { +/******/ if (document.currentScript) +/******/ scriptUrl = document.currentScript.src; +/******/ if (!scriptUrl) { +/******/ var scripts = document.getElementsByTagName("script"); +/******/ if(scripts.length) { +/******/ var i = scripts.length - 1; +/******/ while (i > -1 && (!scriptUrl || !/^http(s?):/.test(scriptUrl))) scriptUrl = scripts[i--].src; +/******/ } +/******/ } +/******/ } +/******/ // When supporting browsers where an automatic publicPath is not supported you must specify an output.publicPath manually via configuration +/******/ // or pass an empty string ("") and set the __webpack_public_path__ variable from your code to use your own logic. +/******/ if (!scriptUrl) throw new Error("Automatic publicPath is not supported in this browser"); +/******/ scriptUrl = scriptUrl.replace(/#.*$/, "").replace(/\?.*$/, "").replace(/\/[^\/]+$/, "/"); +/******/ __webpack_require__.p = scriptUrl; +/******/ })(); +/******/ +/******/ /* webpack/runtime/css loading */ +/******/ (() => { +/******/ if (typeof document === "undefined") return; +/******/ var createStylesheet = (chunkId, fullhref, oldTag, resolve, reject) => { +/******/ var linkTag = document.createElement("link"); +/******/ +/******/ linkTag.rel = "stylesheet"; +/******/ linkTag.type = "text/css"; +/******/ if (__webpack_require__.nc) { +/******/ linkTag.nonce = __webpack_require__.nc; +/******/ } +/******/ var onLinkComplete = (event) => { +/******/ // avoid mem leaks. +/******/ linkTag.onerror = linkTag.onload = null; +/******/ if (event.type === 'load') { +/******/ resolve(); +/******/ } else { +/******/ var errorType = event && event.type; +/******/ var realHref = event && event.target && event.target.href || fullhref; +/******/ var err = new Error("Loading CSS chunk " + chunkId + " failed.\n(" + errorType + ": " + realHref + ")"); +/******/ err.name = "ChunkLoadError"; +/******/ err.code = "CSS_CHUNK_LOAD_FAILED"; +/******/ err.type = errorType; +/******/ err.request = realHref; +/******/ if (linkTag.parentNode) linkTag.parentNode.removeChild(linkTag) +/******/ reject(err); +/******/ } +/******/ } +/******/ linkTag.onerror = linkTag.onload = onLinkComplete; +/******/ linkTag.href = fullhref; +/******/ +/******/ +/******/ if (oldTag) { +/******/ oldTag.parentNode.insertBefore(linkTag, oldTag.nextSibling); +/******/ } else { +/******/ document.head.appendChild(linkTag); +/******/ } +/******/ return linkTag; +/******/ }; +/******/ var findStylesheet = (href, fullhref) => { +/******/ var existingLinkTags = document.getElementsByTagName("link"); +/******/ for(var i = 0; i < existingLinkTags.length; i++) { +/******/ var tag = existingLinkTags[i]; +/******/ var dataHref = tag.getAttribute("data-href") || tag.getAttribute("href"); +/******/ if(tag.rel === "stylesheet" && (dataHref === href || dataHref === fullhref)) return tag; +/******/ } +/******/ var existingStyleTags = document.getElementsByTagName("style"); +/******/ for(var i = 0; i < existingStyleTags.length; i++) { +/******/ var tag = existingStyleTags[i]; +/******/ var dataHref = tag.getAttribute("data-href"); +/******/ if(dataHref === href || dataHref === fullhref) return tag; +/******/ } +/******/ }; +/******/ var loadStylesheet = (chunkId) => { +/******/ return new Promise((resolve, reject) => { +/******/ var href = __webpack_require__.miniCssF(chunkId); +/******/ var fullhref = __webpack_require__.p + href; +/******/ if(findStylesheet(href, fullhref)) return resolve(); +/******/ createStylesheet(chunkId, fullhref, null, resolve, reject); +/******/ }); +/******/ } +/******/ // no chunk loading +/******/ +/******/ var oldTags = []; +/******/ var newTags = []; +/******/ var applyHandler = (options) => { +/******/ return { dispose: () => { +/******/ for(var i = 0; i < oldTags.length; i++) { +/******/ var oldTag = oldTags[i]; +/******/ if(oldTag.parentNode) oldTag.parentNode.removeChild(oldTag); +/******/ } +/******/ oldTags.length = 0; +/******/ }, apply: () => { +/******/ for(var i = 0; i < newTags.length; i++) newTags[i].rel = "stylesheet"; +/******/ newTags.length = 0; +/******/ } }; +/******/ } +/******/ __webpack_require__.hmrC.miniCss = (chunkIds, removedChunks, removedModules, promises, applyHandlers, updatedModulesList) => { +/******/ applyHandlers.push(applyHandler); +/******/ chunkIds.forEach((chunkId) => { +/******/ var href = __webpack_require__.miniCssF(chunkId); +/******/ var fullhref = __webpack_require__.p + href; +/******/ var oldTag = findStylesheet(href, fullhref); +/******/ if(!oldTag) return; +/******/ promises.push(new Promise((resolve, reject) => { +/******/ var tag = createStylesheet(chunkId, fullhref, oldTag, () => { +/******/ tag.as = "style"; +/******/ tag.rel = "preload"; +/******/ resolve(); +/******/ }, reject); +/******/ oldTags.push(oldTag); +/******/ newTags.push(tag); +/******/ })); +/******/ }); +/******/ } +/******/ })(); +/******/ +/******/ /* webpack/runtime/jsonp chunk loading */ +/******/ (() => { +/******/ // no baseURI +/******/ +/******/ // object to store loaded and loading chunks +/******/ // undefined = chunk not loaded, null = chunk preloaded/prefetched +/******/ // [resolve, reject, Promise] = chunk loading, 0 = chunk loaded +/******/ var installedChunks = __webpack_require__.hmrS_jsonp = __webpack_require__.hmrS_jsonp || { +/******/ "main": 0 +/******/ }; +/******/ +/******/ // no chunk on demand loading +/******/ +/******/ // no prefetching +/******/ +/******/ // no preloaded +/******/ +/******/ var currentUpdatedModulesList; +/******/ var waitingUpdateResolves = {}; +/******/ function loadUpdateChunk(chunkId, updatedModulesList) { +/******/ currentUpdatedModulesList = updatedModulesList; +/******/ return new Promise((resolve, reject) => { +/******/ waitingUpdateResolves[chunkId] = resolve; +/******/ // start update chunk loading +/******/ var url = __webpack_require__.p + __webpack_require__.hu(chunkId); +/******/ // create error before stack unwound to get useful stacktrace later +/******/ var error = new Error(); +/******/ var loadingEnded = (event) => { +/******/ if(waitingUpdateResolves[chunkId]) { +/******/ waitingUpdateResolves[chunkId] = undefined +/******/ var errorType = event && (event.type === 'load' ? 'missing' : event.type); +/******/ var realSrc = event && event.target && event.target.src; +/******/ error.message = 'Loading hot update chunk ' + chunkId + ' failed.\n(' + errorType + ': ' + realSrc + ')'; +/******/ error.name = 'ChunkLoadError'; +/******/ error.type = errorType; +/******/ error.request = realSrc; +/******/ reject(error); +/******/ } +/******/ }; +/******/ __webpack_require__.l(url, loadingEnded); +/******/ }); +/******/ } +/******/ +/******/ self["webpackHotUpdate"] = (chunkId, moreModules, runtime) => { +/******/ for(var moduleId in moreModules) { +/******/ if(__webpack_require__.o(moreModules, moduleId)) { +/******/ currentUpdate[moduleId] = moreModules[moduleId]; +/******/ if(currentUpdatedModulesList) currentUpdatedModulesList.push(moduleId); +/******/ } +/******/ } +/******/ if(runtime) currentUpdateRuntime.push(runtime); +/******/ if(waitingUpdateResolves[chunkId]) { +/******/ waitingUpdateResolves[chunkId](); +/******/ waitingUpdateResolves[chunkId] = undefined; +/******/ } +/******/ }; +/******/ +/******/ var currentUpdateChunks; +/******/ var currentUpdate; +/******/ var currentUpdateRemovedChunks; +/******/ var currentUpdateRuntime; +/******/ function applyHandler(options) { +/******/ if (__webpack_require__.f) delete __webpack_require__.f.jsonpHmr; +/******/ currentUpdateChunks = undefined; +/******/ function getAffectedModuleEffects(updateModuleId) { +/******/ var outdatedModules = [updateModuleId]; +/******/ var outdatedDependencies = {}; +/******/ +/******/ var queue = outdatedModules.map(function (id) { +/******/ return { +/******/ chain: [id], +/******/ id: id +/******/ }; +/******/ }); +/******/ while (queue.length > 0) { +/******/ var queueItem = queue.pop(); +/******/ var moduleId = queueItem.id; +/******/ var chain = queueItem.chain; +/******/ var module = __webpack_require__.c[moduleId]; +/******/ if ( +/******/ !module || +/******/ (module.hot._selfAccepted && !module.hot._selfInvalidated) +/******/ ) +/******/ continue; +/******/ if (module.hot._selfDeclined) { +/******/ return { +/******/ type: "self-declined", +/******/ chain: chain, +/******/ moduleId: moduleId +/******/ }; +/******/ } +/******/ if (module.hot._main) { +/******/ return { +/******/ type: "unaccepted", +/******/ chain: chain, +/******/ moduleId: moduleId +/******/ }; +/******/ } +/******/ for (var i = 0; i < module.parents.length; i++) { +/******/ var parentId = module.parents[i]; +/******/ var parent = __webpack_require__.c[parentId]; +/******/ if (!parent) continue; +/******/ if (parent.hot._declinedDependencies[moduleId]) { +/******/ return { +/******/ type: "declined", +/******/ chain: chain.concat([parentId]), +/******/ moduleId: moduleId, +/******/ parentId: parentId +/******/ }; +/******/ } +/******/ if (outdatedModules.indexOf(parentId) !== -1) continue; +/******/ if (parent.hot._acceptedDependencies[moduleId]) { +/******/ if (!outdatedDependencies[parentId]) +/******/ outdatedDependencies[parentId] = []; +/******/ addAllToSet(outdatedDependencies[parentId], [moduleId]); +/******/ continue; +/******/ } +/******/ delete outdatedDependencies[parentId]; +/******/ outdatedModules.push(parentId); +/******/ queue.push({ +/******/ chain: chain.concat([parentId]), +/******/ id: parentId +/******/ }); +/******/ } +/******/ } +/******/ +/******/ return { +/******/ type: "accepted", +/******/ moduleId: updateModuleId, +/******/ outdatedModules: outdatedModules, +/******/ outdatedDependencies: outdatedDependencies +/******/ }; +/******/ } +/******/ +/******/ function addAllToSet(a, b) { +/******/ for (var i = 0; i < b.length; i++) { +/******/ var item = b[i]; +/******/ if (a.indexOf(item) === -1) a.push(item); +/******/ } +/******/ } +/******/ +/******/ // at begin all updates modules are outdated +/******/ // the "outdated" status can propagate to parents if they don't accept the children +/******/ var outdatedDependencies = {}; +/******/ var outdatedModules = []; +/******/ var appliedUpdate = {}; +/******/ +/******/ var warnUnexpectedRequire = function warnUnexpectedRequire(module) { +/******/ console.warn( +/******/ "[HMR] unexpected require(" + module.id + ") to disposed module" +/******/ ); +/******/ }; +/******/ +/******/ for (var moduleId in currentUpdate) { +/******/ if (__webpack_require__.o(currentUpdate, moduleId)) { +/******/ var newModuleFactory = currentUpdate[moduleId]; +/******/ /** @type {TODO} */ +/******/ var result; +/******/ if (newModuleFactory) { +/******/ result = getAffectedModuleEffects(moduleId); +/******/ } else { +/******/ result = { +/******/ type: "disposed", +/******/ moduleId: moduleId +/******/ }; +/******/ } +/******/ /** @type {Error|false} */ +/******/ var abortError = false; +/******/ var doApply = false; +/******/ var doDispose = false; +/******/ var chainInfo = ""; +/******/ if (result.chain) { +/******/ chainInfo = "\nUpdate propagation: " + result.chain.join(" -> "); +/******/ } +/******/ switch (result.type) { +/******/ case "self-declined": +/******/ if (options.onDeclined) options.onDeclined(result); +/******/ if (!options.ignoreDeclined) +/******/ abortError = new Error( +/******/ "Aborted because of self decline: " + +/******/ result.moduleId + +/******/ chainInfo +/******/ ); +/******/ break; +/******/ case "declined": +/******/ if (options.onDeclined) options.onDeclined(result); +/******/ if (!options.ignoreDeclined) +/******/ abortError = new Error( +/******/ "Aborted because of declined dependency: " + +/******/ result.moduleId + +/******/ " in " + +/******/ result.parentId + +/******/ chainInfo +/******/ ); +/******/ break; +/******/ case "unaccepted": +/******/ if (options.onUnaccepted) options.onUnaccepted(result); +/******/ if (!options.ignoreUnaccepted) +/******/ abortError = new Error( +/******/ "Aborted because " + moduleId + " is not accepted" + chainInfo +/******/ ); +/******/ break; +/******/ case "accepted": +/******/ if (options.onAccepted) options.onAccepted(result); +/******/ doApply = true; +/******/ break; +/******/ case "disposed": +/******/ if (options.onDisposed) options.onDisposed(result); +/******/ doDispose = true; +/******/ break; +/******/ default: +/******/ throw new Error("Unexception type " + result.type); +/******/ } +/******/ if (abortError) { +/******/ return { +/******/ error: abortError +/******/ }; +/******/ } +/******/ if (doApply) { +/******/ appliedUpdate[moduleId] = newModuleFactory; +/******/ addAllToSet(outdatedModules, result.outdatedModules); +/******/ for (moduleId in result.outdatedDependencies) { +/******/ if (__webpack_require__.o(result.outdatedDependencies, moduleId)) { +/******/ if (!outdatedDependencies[moduleId]) +/******/ outdatedDependencies[moduleId] = []; +/******/ addAllToSet( +/******/ outdatedDependencies[moduleId], +/******/ result.outdatedDependencies[moduleId] +/******/ ); +/******/ } +/******/ } +/******/ } +/******/ if (doDispose) { +/******/ addAllToSet(outdatedModules, [result.moduleId]); +/******/ appliedUpdate[moduleId] = warnUnexpectedRequire; +/******/ } +/******/ } +/******/ } +/******/ currentUpdate = undefined; +/******/ +/******/ // Store self accepted outdated modules to require them later by the module system +/******/ var outdatedSelfAcceptedModules = []; +/******/ for (var j = 0; j < outdatedModules.length; j++) { +/******/ var outdatedModuleId = outdatedModules[j]; +/******/ var module = __webpack_require__.c[outdatedModuleId]; +/******/ if ( +/******/ module && +/******/ (module.hot._selfAccepted || module.hot._main) && +/******/ // removed self-accepted modules should not be required +/******/ appliedUpdate[outdatedModuleId] !== warnUnexpectedRequire && +/******/ // when called invalidate self-accepting is not possible +/******/ !module.hot._selfInvalidated +/******/ ) { +/******/ outdatedSelfAcceptedModules.push({ +/******/ module: outdatedModuleId, +/******/ require: module.hot._requireSelf, +/******/ errorHandler: module.hot._selfAccepted +/******/ }); +/******/ } +/******/ } +/******/ +/******/ var moduleOutdatedDependencies; +/******/ +/******/ return { +/******/ dispose: function () { +/******/ currentUpdateRemovedChunks.forEach(function (chunkId) { +/******/ delete installedChunks[chunkId]; +/******/ }); +/******/ currentUpdateRemovedChunks = undefined; +/******/ +/******/ var idx; +/******/ var queue = outdatedModules.slice(); +/******/ while (queue.length > 0) { +/******/ var moduleId = queue.pop(); +/******/ var module = __webpack_require__.c[moduleId]; +/******/ if (!module) continue; +/******/ +/******/ var data = {}; +/******/ +/******/ // Call dispose handlers +/******/ var disposeHandlers = module.hot._disposeHandlers; +/******/ for (j = 0; j < disposeHandlers.length; j++) { +/******/ disposeHandlers[j].call(null, data); +/******/ } +/******/ __webpack_require__.hmrD[moduleId] = data; +/******/ +/******/ // disable module (this disables requires from this module) +/******/ module.hot.active = false; +/******/ +/******/ // remove module from cache +/******/ delete __webpack_require__.c[moduleId]; +/******/ +/******/ // when disposing there is no need to call dispose handler +/******/ delete outdatedDependencies[moduleId]; +/******/ +/******/ // remove "parents" references from all children +/******/ for (j = 0; j < module.children.length; j++) { +/******/ var child = __webpack_require__.c[module.children[j]]; +/******/ if (!child) continue; +/******/ idx = child.parents.indexOf(moduleId); +/******/ if (idx >= 0) { +/******/ child.parents.splice(idx, 1); +/******/ } +/******/ } +/******/ } +/******/ +/******/ // remove outdated dependency from module children +/******/ var dependency; +/******/ for (var outdatedModuleId in outdatedDependencies) { +/******/ if (__webpack_require__.o(outdatedDependencies, outdatedModuleId)) { +/******/ module = __webpack_require__.c[outdatedModuleId]; +/******/ if (module) { +/******/ moduleOutdatedDependencies = +/******/ outdatedDependencies[outdatedModuleId]; +/******/ for (j = 0; j < moduleOutdatedDependencies.length; j++) { +/******/ dependency = moduleOutdatedDependencies[j]; +/******/ idx = module.children.indexOf(dependency); +/******/ if (idx >= 0) module.children.splice(idx, 1); +/******/ } +/******/ } +/******/ } +/******/ } +/******/ }, +/******/ apply: function (reportError) { +/******/ // insert new code +/******/ for (var updateModuleId in appliedUpdate) { +/******/ if (__webpack_require__.o(appliedUpdate, updateModuleId)) { +/******/ __webpack_require__.m[updateModuleId] = appliedUpdate[updateModuleId]; +/******/ } +/******/ } +/******/ +/******/ // run new runtime modules +/******/ for (var i = 0; i < currentUpdateRuntime.length; i++) { +/******/ currentUpdateRuntime[i](__webpack_require__); +/******/ } +/******/ +/******/ // call accept handlers +/******/ for (var outdatedModuleId in outdatedDependencies) { +/******/ if (__webpack_require__.o(outdatedDependencies, outdatedModuleId)) { +/******/ var module = __webpack_require__.c[outdatedModuleId]; +/******/ if (module) { +/******/ moduleOutdatedDependencies = +/******/ outdatedDependencies[outdatedModuleId]; +/******/ var callbacks = []; +/******/ var errorHandlers = []; +/******/ var dependenciesForCallbacks = []; +/******/ for (var j = 0; j < moduleOutdatedDependencies.length; j++) { +/******/ var dependency = moduleOutdatedDependencies[j]; +/******/ var acceptCallback = +/******/ module.hot._acceptedDependencies[dependency]; +/******/ var errorHandler = +/******/ module.hot._acceptedErrorHandlers[dependency]; +/******/ if (acceptCallback) { +/******/ if (callbacks.indexOf(acceptCallback) !== -1) continue; +/******/ callbacks.push(acceptCallback); +/******/ errorHandlers.push(errorHandler); +/******/ dependenciesForCallbacks.push(dependency); +/******/ } +/******/ } +/******/ for (var k = 0; k < callbacks.length; k++) { +/******/ try { +/******/ callbacks[k].call(null, moduleOutdatedDependencies); +/******/ } catch (err) { +/******/ if (typeof errorHandlers[k] === "function") { +/******/ try { +/******/ errorHandlers[k](err, { +/******/ moduleId: outdatedModuleId, +/******/ dependencyId: dependenciesForCallbacks[k] +/******/ }); +/******/ } catch (err2) { +/******/ if (options.onErrored) { +/******/ options.onErrored({ +/******/ type: "accept-error-handler-errored", +/******/ moduleId: outdatedModuleId, +/******/ dependencyId: dependenciesForCallbacks[k], +/******/ error: err2, +/******/ originalError: err +/******/ }); +/******/ } +/******/ if (!options.ignoreErrored) { +/******/ reportError(err2); +/******/ reportError(err); +/******/ } +/******/ } +/******/ } else { +/******/ if (options.onErrored) { +/******/ options.onErrored({ +/******/ type: "accept-errored", +/******/ moduleId: outdatedModuleId, +/******/ dependencyId: dependenciesForCallbacks[k], +/******/ error: err +/******/ }); +/******/ } +/******/ if (!options.ignoreErrored) { +/******/ reportError(err); +/******/ } +/******/ } +/******/ } +/******/ } +/******/ } +/******/ } +/******/ } +/******/ +/******/ // Load self accepted modules +/******/ for (var o = 0; o < outdatedSelfAcceptedModules.length; o++) { +/******/ var item = outdatedSelfAcceptedModules[o]; +/******/ var moduleId = item.module; +/******/ try { +/******/ item.require(moduleId); +/******/ } catch (err) { +/******/ if (typeof item.errorHandler === "function") { +/******/ try { +/******/ item.errorHandler(err, { +/******/ moduleId: moduleId, +/******/ module: __webpack_require__.c[moduleId] +/******/ }); +/******/ } catch (err2) { +/******/ if (options.onErrored) { +/******/ options.onErrored({ +/******/ type: "self-accept-error-handler-errored", +/******/ moduleId: moduleId, +/******/ error: err2, +/******/ originalError: err +/******/ }); +/******/ } +/******/ if (!options.ignoreErrored) { +/******/ reportError(err2); +/******/ reportError(err); +/******/ } +/******/ } +/******/ } else { +/******/ if (options.onErrored) { +/******/ options.onErrored({ +/******/ type: "self-accept-errored", +/******/ moduleId: moduleId, +/******/ error: err +/******/ }); +/******/ } +/******/ if (!options.ignoreErrored) { +/******/ reportError(err); +/******/ } +/******/ } +/******/ } +/******/ } +/******/ +/******/ return outdatedModules; +/******/ } +/******/ }; +/******/ } +/******/ __webpack_require__.hmrI.jsonp = function (moduleId, applyHandlers) { +/******/ if (!currentUpdate) { +/******/ currentUpdate = {}; +/******/ currentUpdateRuntime = []; +/******/ currentUpdateRemovedChunks = []; +/******/ applyHandlers.push(applyHandler); +/******/ } +/******/ if (!__webpack_require__.o(currentUpdate, moduleId)) { +/******/ currentUpdate[moduleId] = __webpack_require__.m[moduleId]; +/******/ } +/******/ }; +/******/ __webpack_require__.hmrC.jsonp = function ( +/******/ chunkIds, +/******/ removedChunks, +/******/ removedModules, +/******/ promises, +/******/ applyHandlers, +/******/ updatedModulesList +/******/ ) { +/******/ applyHandlers.push(applyHandler); +/******/ currentUpdateChunks = {}; +/******/ currentUpdateRemovedChunks = removedChunks; +/******/ currentUpdate = removedModules.reduce(function (obj, key) { +/******/ obj[key] = false; +/******/ return obj; +/******/ }, {}); +/******/ currentUpdateRuntime = []; +/******/ chunkIds.forEach(function (chunkId) { +/******/ if ( +/******/ __webpack_require__.o(installedChunks, chunkId) && +/******/ installedChunks[chunkId] !== undefined +/******/ ) { +/******/ promises.push(loadUpdateChunk(chunkId, updatedModulesList)); +/******/ currentUpdateChunks[chunkId] = true; +/******/ } else { +/******/ currentUpdateChunks[chunkId] = false; +/******/ } +/******/ }); +/******/ if (__webpack_require__.f) { +/******/ __webpack_require__.f.jsonpHmr = function (chunkId, promises) { +/******/ if ( +/******/ currentUpdateChunks && +/******/ __webpack_require__.o(currentUpdateChunks, chunkId) && +/******/ !currentUpdateChunks[chunkId] +/******/ ) { +/******/ promises.push(loadUpdateChunk(chunkId)); +/******/ currentUpdateChunks[chunkId] = true; +/******/ } +/******/ }; +/******/ } +/******/ }; +/******/ +/******/ __webpack_require__.hmrM = () => { +/******/ if (typeof fetch === "undefined") throw new Error("No browser support: need fetch API"); +/******/ return fetch(__webpack_require__.p + __webpack_require__.hmrF()).then((response) => { +/******/ if(response.status === 404) return; // no update available +/******/ if(!response.ok) throw new Error("Failed to fetch update manifest " + response.statusText); +/******/ return response.json(); +/******/ }); +/******/ }; +/******/ +/******/ // no on chunks loaded +/******/ +/******/ // no jsonp function +/******/ })(); +/******/ +/************************************************************************/ +/******/ +/******/ // module cache are used so entry inlining is disabled +/******/ // startup +/******/ // Load entry module and return exports +/******/ var __webpack_exports__ = __webpack_require__("./index.css"); +/******/ +/******/ })() +; \ No newline at end of file diff --git a/test/cases/hmr-locals/index.css b/test/cases/hmr-locals/index.css new file mode 100644 index 00000000..739f1581 --- /dev/null +++ b/test/cases/hmr-locals/index.css @@ -0,0 +1,3 @@ +.x { + color: red; +} diff --git a/test/cases/hmr-locals/webpack.config.js b/test/cases/hmr-locals/webpack.config.js new file mode 100644 index 00000000..639b6511 --- /dev/null +++ b/test/cases/hmr-locals/webpack.config.js @@ -0,0 +1,33 @@ +import { HotModuleReplacementPlugin } from "webpack"; + +import Self from "../../../src"; + +module.exports = { + entry: "./index.css", + mode: "development", + devtool: false, + module: { + rules: [ + { + test: /\.css$/, + use: [ + { + loader: Self.loader, + }, + { + loader: "css-loader", + options: { + modules: true, + }, + }, + ], + }, + ], + }, + plugins: [ + new HotModuleReplacementPlugin(), + new Self({ + filename: "[name].css", + }), + ], +}; diff --git a/test/cases/hmr/expected/main.js b/test/cases/hmr/expected/main.js index 39fc3d64..593668a5 100644 --- a/test/cases/hmr/expected/main.js +++ b/test/cases/hmr/expected/main.js @@ -363,10 +363,25 @@ __webpack_require__.r(__webpack_exports__); // extracted by mini-css-extract-plugin if(true) { - // - var cssReload = __webpack_require__(/*! ../../../src/hmr/hotModuleReplacement.js */ "../../../src/hmr/hotModuleReplacement.js")(module.id, {"locals":false}); - module.hot.dispose(cssReload); - module.hot.accept(undefined, cssReload); + (function() { + var localsJsonString = undefined; + // + var cssReload = __webpack_require__(/*! ../../../src/hmr/hotModuleReplacement.js */ "../../../src/hmr/hotModuleReplacement.js")(module.id, {}); + // only invalidate when locals change + if ( + module.hot.data && + module.hot.data.value && + module.hot.data.value !== localsJsonString + ) { + module.hot.invalidate(); + } else { + module.hot.accept(); + } + module.hot.dispose(function(data) { + data.value = localsJsonString; + cssReload(); + }); + })(); } diff --git a/types/loader.d.ts b/types/loader.d.ts index a007af71..64ba61f4 100644 --- a/types/loader.d.ts +++ b/types/loader.d.ts @@ -10,6 +10,7 @@ declare function loader( declare namespace loader { export { pitch, + hotLoader, Schema, Compiler, Compilation, @@ -33,6 +34,40 @@ declare function pitch( this: import("webpack").LoaderContext, request: string ): void; +/** @typedef {import("schema-utils/declarations/validate").Schema} Schema */ +/** @typedef {import("webpack").Compiler} Compiler */ +/** @typedef {import("webpack").Compilation} Compilation */ +/** @typedef {import("webpack").Chunk} Chunk */ +/** @typedef {import("webpack").Module} Module */ +/** @typedef {import("webpack").sources.Source} Source */ +/** @typedef {import("webpack").AssetInfo} AssetInfo */ +/** @typedef {import("webpack").NormalModule} NormalModule */ +/** @typedef {import("./index.js").LoaderOptions} LoaderOptions */ +/** @typedef {{ [key: string]: string | function }} Locals */ +/** @typedef {any} TODO */ +/** + * @typedef {Object} Dependency + * @property {string} identifier + * @property {string | null} context + * @property {Buffer} content + * @property {string} media + * @property {string} [supports] + * @property {string} [layer] + * @property {Buffer} [sourceMap] + */ +/** + * @param {string} content + * @param {{ loaderContext: import("webpack").LoaderContext, options: LoaderOptions, locals: Locals | undefined }} context + * @returns {string} + */ +declare function hotLoader( + content: string, + context: { + loaderContext: import("webpack").LoaderContext; + options: LoaderOptions; + locals: Locals | undefined; + } +): string; type Schema = import("schema-utils/declarations/validate").Schema; type Compiler = import("webpack").Compiler; type Compilation = import("webpack").Compilation;