From 99bf65ffa1a7dc31438ac2f5be7008abbb170528 Mon Sep 17 00:00:00 2001 From: Kuitos Date: Mon, 8 Jan 2024 20:58:59 +0800 Subject: [PATCH] feat: support huge inline-script who might be split into multiple chunks during transfer (#2878) * feat: support huge inline-script who might be split into multiple chunks during transfer * Create wise-ravens-prove.md --- .changeset/wise-ravens-prove.md | 8 ++++ packages/loader/src/index.ts | 5 +-- packages/loader/src/writable-dom/index.ts | 33 +++++++++++----- packages/qiankun/src/version.ts | 2 +- packages/sandbox/src/core/globals.ts | 38 +++++++++++++++++++ .../src/patchers/dynamicAppend/common.ts | 2 - .../shared/src/assets-transpilers/script.ts | 10 +---- .../shared/src/assets-transpilers/types.ts | 2 +- 8 files changed, 76 insertions(+), 24 deletions(-) create mode 100644 .changeset/wise-ravens-prove.md diff --git a/.changeset/wise-ravens-prove.md b/.changeset/wise-ravens-prove.md new file mode 100644 index 000000000..f628c8bf2 --- /dev/null +++ b/.changeset/wise-ravens-prove.md @@ -0,0 +1,8 @@ +--- +"@qiankunjs/loader": patch +"qiankun": patch +"@qiankunjs/sandbox": patch +"@qiankunjs/shared": patch +--- + +feat: support huge inline-script who might be split into multiple chunks during transfer diff --git a/packages/loader/src/index.ts b/packages/loader/src/index.ts index 18fe43091..bc6157e54 100644 --- a/packages/loader/src/index.ts +++ b/packages/loader/src/index.ts @@ -85,15 +85,14 @@ export async function loadEntry(entry: Entry, container: HTMLElement, opts: L ), ) .pipeTo( - new WritableDOMStream(container, null, (clone, node) => { + new WritableDOMStream(container, null, (clone) => { let transformerOpts: AssetsTranspilerOpts = { fetch, sandbox, - rawNode: node as unknown as Node, }; let queueDeferScript: () => void; - const deferScriptMode = isDeferScript(node as unknown as HTMLScriptElement); + const deferScriptMode = isDeferScript(clone as unknown as HTMLScriptElement); if (deferScriptMode) { const { deferred, prevDeferred, queue } = prepareDeferredQueue(deferQueue); transformerOpts = { diff --git a/packages/loader/src/writable-dom/index.ts b/packages/loader/src/writable-dom/index.ts index ab09d789c..3820b5a9e 100644 --- a/packages/loader/src/writable-dom/index.ts +++ b/packages/loader/src/writable-dom/index.ts @@ -37,19 +37,19 @@ type WritableDOM = { new ( target: ParentNode, previousSibling?: ChildNode | null, - assetTransformer?: (clone: Node, node: Node) => Node, + assetTransformer?: (clone: Node) => Node, ): WritableStream; ( target: ParentNode, previousSibling?: ChildNode | null, - assetTransformer?: (clone: Node, node: Node) => Node, + assetTransformer?: (clone: T) => T, ): Writable; }; function writableDOM( this: unknown, target: ParentNode, previousSibling?: ChildNode | null, - assetTransformer?: (clone: T, node: T) => T, + assetTransformer?: (clone: T) => T, ): Writable | WritableStream { if (this instanceof writableDOM) { return new WritableStream(writableDOM(target, previousSibling, assetTransformer)); @@ -85,7 +85,7 @@ function writableDOM( } }, close() { - appendInlineTextIfNeeded(pendingText, inlineHostNode); + appendInlineTextIfNeeded(pendingText, inlineHostNode, assetTransformer); return isBlocked ? new Promise((_) => (resolve = _)) : Promise.resolve(); }, @@ -102,7 +102,7 @@ function writableDOM( while ((node = walker.nextNode())) { const link = getPreloadLink((scanNode = node)); if (link) { - const transformedLink = typeof assetTransformer === 'function' ? assetTransformer(link, link) : link; + const transformedLink = typeof assetTransformer === 'function' ? assetTransformer(link) : link; transformedLink.onload = transformedLink.onerror = () => target.removeChild(transformedLink); target.insertBefore(transformedLink, nextSibling); } @@ -141,11 +141,11 @@ function writableDOM( if (isInlineHost(parentNode!)) { inlineHostNode = parentNode; } else { - appendInlineTextIfNeeded(previousPendingText, inlineHostNode); + appendInlineTextIfNeeded(previousPendingText, inlineHostNode, assetTransformer); inlineHostNode = null; if (typeof assetTransformer === 'function') { - clone = assetTransformer(clone, node); + clone = assetTransformer(clone); } if (parentNode === target) { @@ -234,9 +234,24 @@ function getPreloadLink(node: any) { return link; } -function appendInlineTextIfNeeded(pendingText: Text | null, inlineTextHostNode: Node | null) { +function appendInlineTextIfNeeded( + pendingText: Text | null, + inlineTextHostNode: Node | null, + assetTransformer?: (clone: T) => T, +) { if (pendingText && inlineTextHostNode) { - inlineTextHostNode.appendChild(pendingText); + let textNode = pendingText; + + if (typeof assetTransformer === 'function') { + // copy the text node and host node and then get the transformed text node, thus we can append the transformed text node to live host + const graftedHost = document.importNode(inlineTextHostNode, false); + const graftedText = document.importNode(textNode, false); + graftedHost.appendChild(graftedText); + const transformedHost = assetTransformer(graftedHost); + textNode = transformedHost.firstChild as Text; + } + + inlineTextHostNode.appendChild(textNode); } } diff --git a/packages/qiankun/src/version.ts b/packages/qiankun/src/version.ts index 190d2c68b..a7250834f 100644 --- a/packages/qiankun/src/version.ts +++ b/packages/qiankun/src/version.ts @@ -1 +1 @@ -export const version = '3.0.0-rc.15'; \ No newline at end of file +export { version } from '../package.json'; diff --git a/packages/sandbox/src/core/globals.ts b/packages/sandbox/src/core/globals.ts index 3ead7b791..af46ab3fc 100644 --- a/packages/sandbox/src/core/globals.ts +++ b/packages/sandbox/src/core/globals.ts @@ -126,6 +126,7 @@ export const globalsInBrowser = [ "CloseEvent", "Comment", "CompositionEvent", + "CompressionStream", "confirm", "console", "ConstantSourceNode", @@ -168,6 +169,7 @@ export const globalsInBrowser = [ "DataTransfer", "DataTransferItem", "DataTransferItemList", + "DecompressionStream", "defaultstatus", "defaultStatus", "DelayNode", @@ -358,6 +360,7 @@ export const globalsInBrowser = [ "MediaStream", "MediaStreamAudioDestinationNode", "MediaStreamAudioSourceNode", + "MediaStreamConstraints", "MediaStreamEvent", "MediaStreamTrack", "MediaStreamTrackEvent", @@ -555,7 +558,12 @@ export const globalsInBrowser = [ "queueMicrotask", "RadioNodeList", "Range", + "ReadableByteStreamController", "ReadableStream", + "ReadableStreamBYOBReader", + "ReadableStreamBYOBRequest", + "ReadableStreamDefaultController", + "ReadableStreamDefaultReader", "registerProcessor", "RemotePlayback", "removeEventListener", @@ -729,7 +737,9 @@ export const globalsInBrowser = [ "TaskAttributionTiming", "Text", "TextDecoder", + "TextDecoderStream", "TextEncoder", + "TextEncoderStream", "TextEvent", "TextMetrics", "TextTrack", @@ -737,6 +747,7 @@ export const globalsInBrowser = [ "TextTrackCueList", "TextTrackList", "TimeRanges", + "ToggleEvent", "toolbar", "top", "Touch", @@ -744,6 +755,7 @@ export const globalsInBrowser = [ "TouchList", "TrackEvent", "TransformStream", + "TransformStreamDefaultController", "TransitionEvent", "TreeWalker", "UIEvent", @@ -778,6 +790,8 @@ export const globalsInBrowser = [ "Window", "Worker", "WritableStream", + "WritableStreamDefaultController", + "WritableStreamDefaultWriter", "XMLDocument", "XMLHttpRequest", "XMLHttpRequestEventTarget", @@ -786,6 +800,30 @@ export const globalsInBrowser = [ "XPathEvaluator", "XPathExpression", "XPathResult", + "XRAnchor", + "XRBoundedReferenceSpace", + "XRCPUDepthInformation", + "XRDepthInformation", + "XRFrame", + "XRInputSource", + "XRInputSourceArray", + "XRInputSourceEvent", + "XRInputSourcesChangeEvent", + "XRPose", + "XRReferenceSpace", + "XRReferenceSpaceEvent", + "XRRenderState", + "XRRigidTransform", + "XRSession", + "XRSessionEvent", + "XRSpace", + "XRSystem", + "XRView", + "XRViewerPose", + "XRViewport", + "XRWebGLBinding", + "XRWebGLDepthInformation", + "XRWebGLLayer", "XSLTProcessor" ]; \ No newline at end of file diff --git a/packages/sandbox/src/patchers/dynamicAppend/common.ts b/packages/sandbox/src/patchers/dynamicAppend/common.ts index 115d30936..6462bea71 100644 --- a/packages/sandbox/src/patchers/dynamicAppend/common.ts +++ b/packages/sandbox/src/patchers/dynamicAppend/common.ts @@ -160,7 +160,6 @@ export function getOverwrittenAppendChildOrInsertBefore( const transpiledStyleSheetElement = nodeTransformer(stylesheetElement, { fetch, sandbox, - rawNode: stylesheetElement, }); const stylesheetTargetDetached = !document.contains(this); @@ -196,7 +195,6 @@ export function getOverwrittenAppendChildOrInsertBefore( let transformerOpts: AssetsTranspilerOpts = { fetch, sandbox, - rawNode: scriptElement, }; let queueSyncScript: () => void; diff --git a/packages/shared/src/assets-transpilers/script.ts b/packages/shared/src/assets-transpilers/script.ts index 740e7e1cc..7ee2512b4 100644 --- a/packages/shared/src/assets-transpilers/script.ts +++ b/packages/shared/src/assets-transpilers/script.ts @@ -52,10 +52,7 @@ export const preTranspile = ( } if (isValidJavaScriptType(type) && sandbox) { - const rawNode = opts.rawNode as HTMLScriptElement; - const scriptNode = script.textContent ? script : rawNode.childNodes[0]; - - const code = scriptNode.textContent; + const code = script.textContent; if (code) { return { mode: Mode.INLINE_CODE_IN_SANDBOX, @@ -152,11 +149,8 @@ export default function transpileScript( } case Mode.INLINE_CODE_IN_SANDBOX: { - const rawNode = opts.rawNode as HTMLScriptElement; - const scriptNode = script.textContent ? script : rawNode.childNodes[0]; const { code } = result; - - scriptNode.textContent = sandbox!.makeEvaluateFactory(code); + script.textContent = sandbox!.makeEvaluateFactory(code); // mark the script have consumed script.dataset.consumed = 'true'; diff --git a/packages/shared/src/assets-transpilers/types.ts b/packages/shared/src/assets-transpilers/types.ts index 4a8d8d543..ee3be9707 100644 --- a/packages/shared/src/assets-transpilers/types.ts +++ b/packages/shared/src/assets-transpilers/types.ts @@ -13,7 +13,7 @@ export type BaseTranspilerOpts = BaseLoaderOpts & { }; }; -export type AssetsTranspilerOpts = BaseTranspilerOpts & { rawNode: Node }; +export type AssetsTranspilerOpts = BaseTranspilerOpts; export type NodeTransformer = (node: T, opts: Omit) => T;