Skip to content

Commit abe9fbf

Browse files
author
huangchenbj
committed
fix: do not execute javascript if the micro-app has been unmounted
1 parent d7946f4 commit abe9fbf

File tree

3 files changed

+23
-2
lines changed

3 files changed

+23
-2
lines changed

src/create_app.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ export default class CreateApp implements AppInterface {
7878
public isPrefetch: boolean
7979
public isPrerender: boolean
8080
public prefetchLevel?: number
81+
public mountIdentifier?: symbol
8182
public fiber = false
8283
public routerMode: string
8384
public attrs?: Record<string, string>
@@ -287,6 +288,7 @@ export default class CreateApp implements AppInterface {
287288
this.routerMode = routerMode
288289

289290
const dispatchBeforeMount = () => {
291+
this.mountIdentifier = Symbol('mountIdentifier')
290292
dispatchLifecyclesEvent(
291293
this.container,
292294
this.name,
@@ -493,6 +495,8 @@ export default class CreateApp implements AppInterface {
493495
unmountcb?: CallableFunction,
494496
umdHookUnmountResult?: unknown,
495497
): void {
498+
this.mountIdentifier = undefined
499+
496500
// dispatch state event to micro app
497501
dispatchCustomEventToMicroApp(this, 'statechange', {
498502
appState: appStates.UNMOUNT

src/source/scripts.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -320,11 +320,21 @@ export function fetchScriptsFromHtml (
320320

321321
const fiberScriptTasks: fiberTasks = app.isPrefetch || app.fiber ? [] : null
322322

323+
const startIdentifier = app.mountIdentifier
324+
323325
if (fetchScriptPromise.length) {
324326
promiseStream<string>(fetchScriptPromise, (res: {data: string, index: number}) => {
327+
const address = fetchScriptPromiseInfo[res.index][0]
328+
const scriptInfo = fetchScriptPromiseInfo[res.index][1]
329+
const currIdentifier = app.mountIdentifier
330+
if (startIdentifier !== currIdentifier) {
331+
scriptInfo.code = res.data
332+
// app has been unmounted, old sandbox is not valid anymore. should not execute script
333+
throw new Error('app has been unmounted, abort loading script')
334+
}
325335
injectFiberTask(fiberScriptTasks, () => fetchScriptSuccess(
326-
fetchScriptPromiseInfo[res.index][0],
327-
fetchScriptPromiseInfo[res.index][1],
336+
address,
337+
scriptInfo,
328338
res.data,
329339
app,
330340
))
@@ -578,8 +588,14 @@ export function runDynamicRemoteScript (
578588
if (scriptInfo.code || isTypeModule(app, scriptInfo)) {
579589
defer(runDynamicScript)
580590
} else {
591+
const startIdentifier = app.mountIdentifier
581592
fetchSource(address, app.name).then((code: string) => {
593+
const currIdentifier = app.mountIdentifier
582594
scriptInfo.code = code
595+
if (startIdentifier !== currIdentifier) {
596+
// app has been unmounted, old sandbox is not valid anymore. should not execute script
597+
throw new Error('app has been unmounted, abort loading script')
598+
}
583599
runDynamicScript()
584600
}).catch((err) => {
585601
logError(err, app.name)

typings/global.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ declare module '@micro-app/types' {
190190
isPrerender: boolean
191191
isReloading?: boolean
192192
prefetchLevel?: number
193+
mountIdentifier?: symbol // used to identify if the app has been unmounted between async calls
193194
// defaultPage: string // default page when mount
194195
// baseroute: string // route prefix, default is ''
195196
// hiddenRouter: boolean // hide router info of child from browser url

0 commit comments

Comments
 (0)