1
1
'use strict' ;
2
2
3
3
const {
4
- SafeMap ,
5
- SafeWeakMap ,
4
+ Map ,
5
+ MapPrototype ,
6
6
Object,
7
7
RegExpPrototype,
8
+ SafeMap,
8
9
uncurryThis
9
10
} = primordials ;
10
11
const {
@@ -21,16 +22,13 @@ const debug = require('internal/util/debuglog').debuglog('policy');
21
22
const SRI = require ( 'internal/policy/sri' ) ;
22
23
const crypto = require ( 'crypto' ) ;
23
24
const { Buffer } = require ( 'buffer' ) ;
24
- const { URL } = require ( 'url' ) ;
25
+ const { URL } = require ( 'internal/ url' ) ;
25
26
const { createHash, timingSafeEqual } = crypto ;
26
27
const HashUpdate = uncurryThis ( crypto . Hash . prototype . update ) ;
27
28
const HashDigest = uncurryThis ( crypto . Hash . prototype . digest ) ;
28
29
const BufferEquals = uncurryThis ( Buffer . prototype . equals ) ;
29
30
const BufferToString = uncurryThis ( Buffer . prototype . toString ) ;
30
31
const { entries } = Object ;
31
- const kIntegrities = new SafeWeakMap ( ) ;
32
- const kDependencies = new SafeWeakMap ( ) ;
33
- const kReactions = new SafeWeakMap ( ) ;
34
32
const kRelativeURLStringPattern = / ^ \. { 0 , 2 } \/ / ;
35
33
const { getOptionValue } = require ( 'internal/options' ) ;
36
34
const shouldAbortOnUncaughtException =
@@ -54,13 +52,12 @@ function REACTION_LOG(error) {
54
52
}
55
53
56
54
class Manifest {
55
+ #integrities = new SafeMap ( ) ;
56
+ #dependencies = new SafeMap ( ) ;
57
+ #reaction = null ;
57
58
constructor ( obj , manifestURL ) {
58
- const integrities = {
59
- __proto__ : null ,
60
- } ;
61
- const dependencies = {
62
- __proto__ : null ,
63
- } ;
59
+ const integrities = this . #integrities;
60
+ const dependencies = this . #dependencies;
64
61
let reaction = REACTION_THROW ;
65
62
66
63
if ( obj . onerror ) {
@@ -75,23 +72,33 @@ class Manifest {
75
72
}
76
73
}
77
74
78
- kReactions . set ( this , reaction ) ;
75
+ this . #reaction = reaction ;
79
76
const manifestEntries = entries ( obj . resources ) ;
80
77
78
+ const parsedURLs = new SafeMap ( ) ;
81
79
for ( var i = 0 ; i < manifestEntries . length ; i ++ ) {
82
- let url = manifestEntries [ i ] [ 0 ] ;
83
- const originalURL = url ;
84
- if ( RegExpPrototype . test ( kRelativeURLStringPattern , url ) ) {
85
- url = new URL ( url , manifestURL ) . href ;
80
+ let resourceHREF = manifestEntries [ i ] [ 0 ] ;
81
+ const originalHREF = resourceHREF ;
82
+ let resourceURL ;
83
+ if ( parsedURLs . has ( resourceHREF ) ) {
84
+ resourceURL = parsedURLs . get ( resourceHREF ) ;
85
+ resourceHREF = resourceURL . href ;
86
+ } else if (
87
+ RegExpPrototype . test ( kRelativeURLStringPattern , resourceHREF )
88
+ ) {
89
+ resourceURL = new URL ( resourceHREF , manifestURL ) ;
90
+ resourceHREF = resourceURL . href ;
91
+ parsedURLs . set ( originalHREF , resourceURL ) ;
92
+ parsedURLs . set ( resourceHREF , resourceURL ) ;
86
93
}
87
94
let integrity = manifestEntries [ i ] [ 1 ] . integrity ;
88
95
if ( ! integrity ) integrity = null ;
89
96
if ( integrity != null ) {
90
- debug ( `Manifest contains integrity for url ${ originalURL } ` ) ;
97
+ debug ( `Manifest contains integrity for url ${ originalHREF } ` ) ;
91
98
if ( typeof integrity === 'string' ) {
92
99
const sri = Object . freeze ( SRI . parse ( integrity ) ) ;
93
- if ( url in integrities ) {
94
- const old = integrities [ url ] ;
100
+ if ( integrities . has ( resourceHREF ) ) {
101
+ const old = integrities . get ( resourceHREF ) ;
95
102
let mismatch = false ;
96
103
97
104
if ( old . length !== sri . length ) {
@@ -112,14 +119,16 @@ class Manifest {
112
119
}
113
120
114
121
if ( mismatch ) {
115
- throw new ERR_MANIFEST_INTEGRITY_MISMATCH ( url ) ;
122
+ throw new ERR_MANIFEST_INTEGRITY_MISMATCH ( resourceURL ) ;
116
123
}
117
124
}
118
- integrities [ url ] = sri ;
125
+ integrities . set ( resourceHREF , sri ) ;
119
126
} else if ( integrity === true ) {
120
- integrities [ url ] = true ;
127
+ integrities . set ( resourceHREF , true ) ;
121
128
} else {
122
- throw new ERR_MANIFEST_INVALID_RESOURCE_FIELD ( url , 'integrity' ) ;
129
+ throw new ERR_MANIFEST_INVALID_RESOURCE_FIELD (
130
+ resourceHREF ,
131
+ 'integrity' ) ;
123
132
}
124
133
}
125
134
@@ -128,50 +137,72 @@ class Manifest {
128
137
dependencyMap = { } ;
129
138
}
130
139
if ( typeof dependencyMap === 'object' && ! Array . isArray ( dependencyMap ) ) {
131
- dependencies [ url ] = new SafeMap ( Object . entries ( dependencyMap ) . map (
132
- ( [ from , to ] ) => {
140
+ /**
141
+ * @returns {true | URL }
142
+ */
143
+ const dependencyRedirectList = ( toSpecifier ) => {
144
+ if ( toSpecifier in dependencyMap !== true ) {
145
+ return null ;
146
+ } else {
147
+ const to = dependencyMap [ toSpecifier ] ;
133
148
if ( to === true ) {
134
- return [ from , to ] ;
149
+ return true ;
135
150
}
136
- if ( canBeRequiredByUsers ( to ) ) {
137
- return [ from , `node:${ to } ` ] ;
151
+ if ( parsedURLs . has ( to ) ) {
152
+ return parsedURLs . get ( to ) ;
153
+ } else if ( canBeRequiredByUsers ( to ) ) {
154
+ const href = `node:${ to } ` ;
155
+ const resolvedURL = new URL ( href ) ;
156
+ parsedURLs . set ( to , resolvedURL ) ;
157
+ parsedURLs . set ( href , resolvedURL ) ;
158
+ return resolvedURL ;
138
159
} else if ( RegExpPrototype . test ( kRelativeURLStringPattern , to ) ) {
139
- return [ from , new URL ( to , manifestURL ) . href ] ;
160
+ const resolvedURL = new URL ( to , manifestURL ) ;
161
+ const href = resourceURL . href ;
162
+ parsedURLs . set ( to , resolvedURL ) ;
163
+ parsedURLs . set ( href , resolvedURL ) ;
164
+ return resolvedURL ;
140
165
}
141
- return [ from , new URL ( to ) . href ] ;
142
- } )
143
- ) ;
166
+ const resolvedURL = new URL ( to ) ;
167
+ const href = resourceURL . href ;
168
+ parsedURLs . set ( to , resolvedURL ) ;
169
+ parsedURLs . set ( href , resolvedURL ) ;
170
+ return resolvedURL ;
171
+ }
172
+ } ;
173
+ dependencies . set ( resourceHREF , dependencyRedirectList ) ;
144
174
} else if ( dependencyMap === true ) {
145
- dependencies [ url ] = true ;
175
+ const arbitraryDependencies = ( ) => true ;
176
+ dependencies . set ( resourceHREF , arbitraryDependencies ) ;
146
177
} else {
147
- throw new ERR_MANIFEST_INVALID_RESOURCE_FIELD ( url , 'dependencies' ) ;
178
+ throw new ERR_MANIFEST_INVALID_RESOURCE_FIELD (
179
+ resourceHREF ,
180
+ 'dependencies' ) ;
148
181
}
149
182
}
150
- Object . freeze ( integrities ) ;
151
- kIntegrities . set ( this , integrities ) ;
152
- Object . freeze ( dependencies ) ;
153
- kDependencies . set ( this , dependencies ) ;
154
183
Object . freeze ( this ) ;
155
184
}
156
185
157
- getRedirects ( requester ) {
158
- const dependencies = kDependencies . get ( this ) ;
159
- if ( dependencies && requester in dependencies ) {
186
+ getRedirector ( requester ) {
187
+ requester = `${ requester } ` ;
188
+ const dependencies = this . #dependencies;
189
+ if ( dependencies . has ( requester ) ) {
160
190
return {
161
- map : dependencies [ requester ] ,
162
- reaction : kReactions . get ( this )
191
+ resolve : ( to ) => dependencies . get ( requester ) ( ` ${ to } ` ) ,
192
+ reaction : this . #reaction
163
193
} ;
164
194
}
165
195
return null ;
166
196
}
167
197
168
198
assertIntegrity ( url , content ) {
169
- debug ( `Checking integrity of ${ url } ` ) ;
170
- const integrities = kIntegrities . get ( this ) ;
171
- const realIntegrities = new SafeMap ( ) ;
199
+ const href = `${ url } ` ;
200
+ debug ( `Checking integrity of ${ href } ` ) ;
201
+ const integrities = this . #integrities;
202
+ const realIntegrities = new Map ( ) ;
172
203
173
- if ( integrities && url in integrities ) {
174
- const integrityEntries = integrities [ url ] ;
204
+ if ( integrities . has ( href ) ) {
205
+ const integrityEntries = integrities . get ( href ) ;
175
206
if ( integrityEntries === true ) return true ;
176
207
// Avoid clobbered Symbol.iterator
177
208
for ( var i = 0 ; i < integrityEntries . length ; i ++ ) {
@@ -186,11 +217,15 @@ class Manifest {
186
217
timingSafeEqual ( digest , expected ) ) {
187
218
return true ;
188
219
}
189
- realIntegrities . set ( algorithm , BufferToString ( digest , 'base64' ) ) ;
220
+ MapPrototype . set (
221
+ realIntegrities ,
222
+ algorithm ,
223
+ BufferToString ( digest , 'base64' )
224
+ ) ;
190
225
}
191
226
}
192
227
const error = new ERR_MANIFEST_ASSERT_INTEGRITY ( url , realIntegrities ) ;
193
- kReactions . get ( this ) ( error ) ;
228
+ this . #reaction ( error ) ;
194
229
}
195
230
}
196
231
0 commit comments