* Emits the JS shim with HMR self-acceptance. When `extracting` is true the * HTML module is also the document the browser is viewing, so the shim * additionally patches `document.body` and `document.title` on every hot * update so the rendered page reflects the new HTML without a full * rel
(module, html, extracting, runtimeTemplate)
| 496 | * @returns {string} JS shim source |
| 497 | */ |
| 498 | _renderHmrShim(module, html, extracting, runtimeTemplate) { |
| 499 | const declare = runtimeTemplate.renderConst(); |
| 500 | const acceptBlock = extracting |
| 501 | ? [ |
| 502 | "module.hot.accept();", |
| 503 | // Mask `<!-- … -->` comments — replace their characters |
| 504 | // with spaces, preserving length — before any tag regex |
| 505 | // runs. Masking (rather than deleting) keeps string offsets |
| 506 | // stable, so the body/title content can be sliced back out |
| 507 | // of the original HTML with comments intact, while a |
| 508 | // `<body>`/`</body>`/`<title>` inside a comment can no |
| 509 | // longer fool the tag regexes (the non-greedy `*?` would |
| 510 | // otherwise stop at the FIRST `</body>` it sees, even one |
| 511 | // inside a comment). |
| 512 | `${declare} __webpack_mask_comments__ = ${runtimeTemplate.returningFunction( |
| 513 | `h.replace(/<!--[\\s\\S]*?-->/g, ${runtimeTemplate.returningFunction( |
| 514 | 'c.replace(/[^\\n]/g, " ")', |
| 515 | "c" |
| 516 | )})`, |
| 517 | "h" |
| 518 | )};`, |
| 519 | // Mask comments once per evaluation; reused for every |
| 520 | // tag-boundary search (head/body/title and the dispose-time |
| 521 | // head diff) so a large page isn't re-scanned per section. |
| 522 | `${declare} __webpack_masked_html__ = __webpack_mask_comments__(__webpack_html__);`, |
| 523 | // Slice the inner content of `<tag>…</tag>` out of the original |
| 524 | // HTML, using the pre-masked copy to locate the tag boundaries. |
| 525 | `${declare} __webpack_extract__ = ${runtimeTemplate.basicFunction( |
| 526 | "tag", |
| 527 | [ |
| 528 | `${declare} open = new RegExp("<" + tag + "[^>]*>", "i").exec(__webpack_masked_html__);`, |
| 529 | "if (!open) return null;", |
| 530 | `${declare} start = open.index + open[0].length;`, |
| 531 | `${declare} close = new RegExp("</" + tag + ">", "i").exec(__webpack_masked_html__.slice(start));`, |
| 532 | "if (!close) return null;", |
| 533 | "return __webpack_html__.slice(start, start + close.index);" |
| 534 | ] |
| 535 | )};`, |
| 536 | `${declare} __webpack_extract_head__ = ${runtimeTemplate.basicFunction( |
| 537 | "", |
| 538 | [ |
| 539 | // Mask only the small extracted head so a comment-only head |
| 540 | // edit doesn't force a full reload. |
| 541 | `${declare} head = __webpack_extract__("head");`, |
| 542 | 'return head === null ? "" : __webpack_mask_comments__(head).replace(/<title[^>]*>[\\s\\S]*?<\\/title>/i, "").trim();' |
| 543 | ] |
| 544 | )};`, |
| 545 | "if (module.hot.data && typeof document !== 'undefined') {", |
| 546 | Template.indent([ |
| 547 | `${declare} __webpack_new_head__ = __webpack_extract_head__();`, |
| 548 | "if (module.hot.data.__webpack_head__ !== undefined && __webpack_new_head__ !== module.hot.data.__webpack_head__ && typeof window !== 'undefined' && window.location && typeof window.location.reload === 'function') {", |
| 549 | Template.indent("window.location.reload();"), |
| 550 | "} else {", |
| 551 | Template.indent([ |
| 552 | `${declare} __webpack_body__ = __webpack_extract__("body");`, |
| 553 | "if (__webpack_body__ !== null && document.body) document.body.innerHTML = __webpack_body__;", |
| 554 | `${declare} __webpack_title__ = __webpack_extract__("title");`, |
| 555 | "if (__webpack_title__ !== null) document.title = __webpack_title__;" |
no test coverage detected