@@ -9,18 +9,18 @@ export namespace Entry {
9
9
config ?: any
10
10
disabled ?: boolean | null
11
11
intercept ?: Dict | null
12
- isolate ?: Dict < true | string >
12
+ isolate ?: Dict < true | string > | null
13
13
when ?: any
14
14
}
15
15
}
16
16
17
- function swap < T extends { } > ( target : T , source ?: T | null ) : T {
18
- const result = { ...target }
19
- for ( const key in result ) {
20
- delete target [ key ]
17
+ function swap < T extends { } > ( target : T , source ?: T | null ) {
18
+ for ( const key of Reflect . ownKeys ( target ) ) {
19
+ Reflect . deleteProperty ( target , key )
20
+ }
21
+ for ( const key of Reflect . ownKeys ( source || { } ) ) {
22
+ Reflect . defineProperty ( target , key , Reflect . getOwnPropertyDescriptor ( source ! , key ) ! )
21
23
}
22
- Object . assign ( target , source )
23
- return result
24
24
}
25
25
26
26
function takeEntries ( object : { } , keys : string [ ] ) {
@@ -62,30 +62,18 @@ export class Entry {
62
62
}
63
63
}
64
64
65
- patch ( ctx ?: Context , legacy ?: Entry . Options ) {
66
- ctx ??= this . parent . extend ( {
67
- [ Context . intercept ] : Object . create ( this . parent [ Context . intercept ] ) ,
68
- [ Context . isolate ] : Object . create ( this . parent [ Context . isolate ] ) ,
69
- } )
70
- ctx . emit ( 'loader/patch' , this , legacy )
71
- swap ( ctx [ Context . intercept ] , this . options . intercept )
72
-
65
+ patch ( ctx : Context , ref : Context = ctx ) {
73
66
// part 1: prepare isolate map
74
- const newMap : Dict < symbol > = Object . create ( Object . getPrototypeOf ( ctx [ Context . isolate ] ) )
67
+ const newMap : Dict < symbol > = Object . create ( Object . getPrototypeOf ( ref [ Context . isolate ] ) )
75
68
for ( const [ key , label ] of Object . entries ( this . options . isolate ?? { } ) ) {
76
69
const realm = this . resolveRealm ( label )
77
70
newMap [ key ] = ( this . loader . realms [ realm ] ??= Object . create ( null ) ) [ key ] ??= Symbol ( `${ key } ${ realm } ` )
78
71
}
79
- for ( const [ key , label ] of Object . entries ( legacy ?. isolate ?? { } ) ) {
80
- if ( this . options . isolate ?. [ key ] === label ) continue
81
- const name = this . resolveRealm ( label )
82
- this . loader . _clearRealm ( key , name )
83
- }
84
72
85
73
// part 2: generate service diff
86
74
const diff : [ string , symbol , symbol , symbol , symbol ] [ ] = [ ]
87
75
const oldMap = ctx [ Context . isolate ]
88
- for ( const key in { ...oldMap , ...newMap } ) {
76
+ for ( const key in { ...oldMap , ...newMap , ... this . loader . delims } ) {
89
77
if ( newMap [ key ] === oldMap [ key ] ) continue
90
78
const delim = this . loader . delims [ key ] ??= Symbol ( key )
91
79
ctx [ delim ] = Symbol ( `${ key } #${ this . options . id } ` )
@@ -114,8 +102,14 @@ export class Entry {
114
102
}
115
103
116
104
// part 3.2: update service impl, prevent double update
117
- this . fork ?. update ( this . options . config )
118
- swap ( ctx [ Context . isolate ] , newMap )
105
+ swap ( ctx [ Context . intercept ] , this . options . intercept )
106
+ if ( ctx === ref ) {
107
+ this . fork ?. update ( this . options . config )
108
+ swap ( ctx [ Context . isolate ] , newMap )
109
+ } else {
110
+ Object . setPrototypeOf ( ctx , Object . getPrototypeOf ( ref ) )
111
+ swap ( ctx , ref )
112
+ }
119
113
for ( const [ , symbol1 , symbol2 , flag1 , flag2 ] of diff ) {
120
114
if ( flag1 === flag2 && ctx [ symbol1 ] && ! ctx [ symbol2 ] ) {
121
115
ctx . root [ symbol2 ] = ctx . root [ symbol1 ]
@@ -139,7 +133,13 @@ export class Entry {
139
133
delete ctx [ this . loader . delims [ key ] ]
140
134
}
141
135
}
142
- return ctx
136
+ }
137
+
138
+ createContext ( ) {
139
+ return this . parent . extend ( {
140
+ [ Context . intercept ] : Object . create ( this . parent [ Context . intercept ] ) ,
141
+ [ Context . isolate ] : Object . create ( this . parent [ Context . isolate ] ) ,
142
+ } )
143
143
}
144
144
145
145
async update ( parent : Context , options : Entry . Options ) {
@@ -150,12 +150,18 @@ export class Entry {
150
150
this . stop ( )
151
151
} else if ( this . fork ) {
152
152
this . isUpdate = true
153
- this . patch ( this . fork . parent , legacy )
153
+ for ( const [ key , label ] of Object . entries ( legacy . isolate ?? { } ) ) {
154
+ if ( this . options . isolate ?. [ key ] === label ) continue
155
+ const name = this . resolveRealm ( label )
156
+ this . loader . _clearRealm ( key , name )
157
+ }
158
+ this . patch ( this . fork . parent )
154
159
} else {
155
160
this . parent . emit ( 'loader/entry' , 'apply' , this )
156
161
const plugin = await this . loader . resolve ( this . options . name )
157
162
if ( ! plugin ) return
158
- const ctx = this . patch ( )
163
+ const ctx = this . createContext ( )
164
+ this . patch ( ctx )
159
165
this . fork = ctx . plugin ( plugin , this . options . config )
160
166
this . fork . entry = this
161
167
}
0 commit comments