| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2,6 +2,7 @@ | |||
| 2 | 2 | ||
| 3 | 3 | const { | |
| 4 | 4 | Array, | |
| 5 | + ArrayIsArray, | ||
| 5 | 6 | ArrayPrototypeJoin, | |
| 6 | 7 | ArrayPrototypeMap, | |
| 7 | 8 | ArrayPrototypePush, | |
@@ -157,52 +158,74 @@ function isURLSearchParams(self) { | |||
| 157 | 158 | } | |
| 158 | 159 | ||
| 159 | 160 | class URLSearchParams { | |
| 161 | + [searchParams] = []; | ||
| 162 | + | ||
| 163 | + // "associated url object" | ||
| 164 | + [context] = null; | ||
| 165 | + | ||
| 160 | 166 | // URL Standard says the default value is '', but as undefined and '' have | |
| 161 | 167 | // the same result, undefined is used to prevent unnecessary parsing. | |
| 162 | 168 | // Default parameter is necessary to keep URLSearchParams.length === 0 in | |
| 163 | 169 | // accordance with Web IDL spec. | |
| 164 | 170 | constructor(init = undefined) { | |
| 165 | - if (init === null || init === undefined) { | ||
| 166 | - this[searchParams] = []; | ||
| 171 | + if (init == null) { | ||
| 172 | + // Do nothing | ||
| 167 | 173 | } else if (typeof init === 'object' || typeof init === 'function') { | |
| 168 | 174 | const method = init[SymbolIterator]; | |
| 169 | 175 | if (method === this[SymbolIterator]) { | |
| 170 | 176 | // While the spec does not have this branch, we can use it as a | |
| 171 | 177 | // shortcut to avoid having to go through the costly generic iterator. | |
| 172 | 178 | const childParams = init[searchParams]; | |
| 173 | 179 | this[searchParams] = childParams.slice(); | |
| 174 | - } else if (method !== null && method !== undefined) { | ||
| 180 | + } else if (method != null) { | ||
| 181 | + // Sequence<sequence<USVString>> | ||
| 175 | 182 | if (typeof method !== 'function') { | |
| 176 | 183 | throw new ERR_ARG_NOT_ITERABLE('Query pairs'); | |
| 177 | 184 | } | |
| 178 | 185 | ||
| 179 | - // Sequence<sequence<USVString>> | ||
| 180 | - // Note: per spec we have to first exhaust the lists then process them | ||
| 181 | - const pairs = []; | ||
| 186 | + // The following implementationd differs from the URL specification: | ||
| 187 | + // Sequences must first be converted from ECMAScript objects before | ||
| 188 | + // and operations are done on them, and the operation of converting | ||
| 189 | + // the sequences would first exhaust the iterators. If the iterator | ||
| 190 | + // returns something invalid in the middle, whether it would be called | ||
| 191 | + // after that would be an observable change to the users. | ||
| 192 | + // Exhausting the iterator and later converting them to USVString comes | ||
| 193 | + // with a significant cost (~40-80%). In order optimize URLSearchParams | ||
| 194 | + // creation duration, Node.js merges the iteration and converting | ||
| 195 | + // iterations into a single iteration. | ||
| 182 | 196 | for (const pair of init) { | |
| 183 | - if ((typeof pair !== 'object' && typeof pair !== 'function') || | ||
| 184 | - pair === null || | ||
| 185 | - typeof pair[SymbolIterator] !== 'function') { | ||
| 197 | + if (pair == null) { | ||
| 186 | 198 | throw new ERR_INVALID_TUPLE('Each query pair', '[name, value]'); | |
| 187 | - } | ||
| 188 | - const convertedPair = []; | ||
| 189 | - for (const element of pair) | ||
| 190 | - ArrayPrototypePush(convertedPair, toUSVString(element)); | ||
| 191 | - ArrayPrototypePush(pairs, convertedPair); | ||
| 192 | - } | ||
| 199 | + } else if (ArrayIsArray(pair)) { | ||
| 200 | + // If innerSequence's size is not 2, then throw a TypeError. | ||
| 201 | + if (pair.length !== 2) { | ||
| 202 | + throw new ERR_INVALID_TUPLE('Each query pair', '[name, value]'); | ||
| 203 | + } | ||
| 204 | + // Append (innerSequence[0], innerSequence[1]) to querys list. | ||
| 205 | + ArrayPrototypePush(this[searchParams], toUSVString(pair[0]), toUSVString(pair[1])); | ||
| 206 | + } else { | ||
| 207 | + if (((typeof pair !== 'object' && typeof pair !== 'function') || | ||
| 208 | + typeof pair[SymbolIterator] !== 'function')) { | ||
| 209 | + throw new ERR_INVALID_TUPLE('Each query pair', '[name, value]'); | ||
| 210 | + } | ||
| 193 | 211 | ||
| 194 | - this[searchParams] = []; | ||
| 195 | - for (const pair of pairs) { | ||
| 196 | - if (pair.length !== 2) { | ||
| 197 | - throw new ERR_INVALID_TUPLE('Each query pair', '[name, value]'); | ||
| 212 | + let length = 0; | ||
| 213 | + | ||
| 214 | + for (const element of pair) { | ||
| 215 | + length++; | ||
| 216 | + ArrayPrototypePush(this[searchParams], toUSVString(element)); | ||
| 217 | + } | ||
| 218 | + | ||
| 219 | + // If innerSequence's size is not 2, then throw a TypeError. | ||
| 220 | + if (length !== 2) { | ||
| 221 | + throw new ERR_INVALID_TUPLE('Each query pair', '[name, value]'); | ||
| 222 | + } | ||
| 198 | 223 | } | |
| 199 | - ArrayPrototypePush(this[searchParams], pair[0], pair[1]); | ||
| 200 | 224 | } | |
| 201 | 225 | } else { | |
| 202 | 226 | // Record<USVString, USVString> | |
| 203 | 227 | // Need to use reflection APIs for full spec compliance. | |
| 204 | 228 | const visited = {}; | |
| 205 | - this[searchParams] = []; | ||
| 206 | 229 | const keys = ReflectOwnKeys(init); | |
| 207 | 230 | for (let i = 0; i < keys.length; i++) { | |
| 208 | 231 | const key = keys[i]; | |
@@ -224,13 +247,10 @@ class URLSearchParams { | |||
| 224 | 247 | } | |
| 225 | 248 | } | |
| 226 | 249 | } else { | |
| 227 | - // USVString | ||
| 250 | + // https://url.spec.whatwg.org/#dom-urlsearchparams-urlsearchparams | ||
| 228 | 251 | init = toUSVString(init); | |
| 229 | 252 | initSearchParams(this, init); | |
| 230 | 253 | } | |
| 231 | - | ||
| 232 | - // "associated url object" | ||
| 233 | - this[context] = null; | ||
| 234 | 254 | } | |
| 235 | 255 | ||
| 236 | 256 | [inspect.custom](recurseTimes, ctx) { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -47,6 +47,10 @@ function makeIterableFunc(array) { | |||
| 47 | 47 | assert.throws(() => new URLSearchParams([null]), tupleError); | |
| 48 | 48 | assert.throws(() => new URLSearchParams([{ [Symbol.iterator]: 42 }]), | |
| 49 | 49 | tupleError); | |
| 50 | + | ||
| 51 | + assert.throws(() => new URLSearchParams( | ||
| 52 | + makeIterableFunc([['key', 'val', 'val2']]) | ||
| 53 | + ), tupleError); | ||
| 50 | 54 | } | |
| 51 | 55 | ||
| 52 | 56 | { | |
| Back | FazBrowse Home | New Git URL |
0 commit comments