Set.js (13359B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 // ES2017 draft rev 0e10c9f29fca1385980c08a7d5e7bb3eb775e2e4 6 // 23.2.1.1 Set, steps 6-8 7 function SetConstructorInit(iterable) { 8 var set = this; 9 10 // Step 6.a. 11 var adder = set.add; 12 13 // Step 6.b. 14 if (!IsCallable(adder)) { 15 ThrowTypeError(JSMSG_NOT_FUNCTION, typeof adder); 16 } 17 18 // Steps 6.c-8. 19 for (var nextValue of allowContentIter(iterable)) { 20 callContentFunction(adder, set, nextValue); 21 } 22 } 23 24 // ES2018 draft rev f83aa38282c2a60c6916ebc410bfdf105a0f6a54 25 // 23.2.3.6 Set.prototype.forEach ( callbackfn [ , thisArg ] ) 26 function SetForEach(callbackfn, thisArg = undefined) { 27 // Step 1. 28 var S = this; 29 30 // Steps 2-3. 31 if (!IsObject(S) || (S = GuardToSetObject(S)) === null) { 32 return callFunction( 33 CallSetMethodIfWrapped, 34 this, 35 callbackfn, 36 thisArg, 37 "SetForEach" 38 ); 39 } 40 41 // Step 4. 42 if (!IsCallable(callbackfn)) { 43 ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, callbackfn)); 44 } 45 46 // Steps 5-8. 47 var values = callFunction(std_Set_values, S); 48 49 // Inlined: SetIteratorNext 50 var setIterationResult = globalSetIterationResult; 51 52 while (true) { 53 var done = GetNextSetEntryForIterator(values, setIterationResult); 54 if (done) { 55 break; 56 } 57 58 var value = setIterationResult[0]; 59 setIterationResult[0] = null; 60 61 callContentFunction(callbackfn, thisArg, value, value, S); 62 } 63 } 64 65 // ES6 final draft 23.2.2.2. 66 // Uncloned functions with `$` prefix are allocated as extended function 67 // to store the original name in `SetCanonicalName`. 68 function $SetSpecies() { 69 // Step 1. 70 return this; 71 } 72 SetCanonicalName($SetSpecies, "get [Symbol.species]"); 73 74 var globalSetIterationResult = CreateSetIterationResult(); 75 76 function SetIteratorNext() { 77 // Step 1. 78 var O = this; 79 80 // Steps 2-3. 81 if (!IsObject(O) || (O = GuardToSetIterator(O)) === null) { 82 return callFunction( 83 CallSetIteratorMethodIfWrapped, 84 this, 85 "SetIteratorNext" 86 ); 87 } 88 89 // Steps 4-5 (implemented in GetNextSetEntryForIterator). 90 // Steps 8-9 (omitted). 91 92 var setIterationResult = globalSetIterationResult; 93 94 var retVal = { value: undefined, done: true }; 95 96 // Steps 10.a, 11. 97 var done = GetNextSetEntryForIterator(O, setIterationResult); 98 if (!done) { 99 // Steps 10.b-c (omitted). 100 101 // Step 6. 102 var itemKind = UnsafeGetInt32FromReservedSlot(O, MAP_SET_ITERATOR_SLOT_ITEM_KIND); 103 104 var result; 105 if (itemKind === ITEM_KIND_VALUE) { 106 // Step 10.d.i. 107 result = setIterationResult[0]; 108 } else { 109 // Step 10.d.ii. 110 assert(itemKind === ITEM_KIND_KEY_AND_VALUE, itemKind); 111 result = [setIterationResult[0], setIterationResult[0]]; 112 } 113 114 setIterationResult[0] = null; 115 retVal.value = result; 116 retVal.done = false; 117 } 118 119 // Steps 7, 10.d, 12. 120 return retVal; 121 } 122 123 // GetSetRecord ( obj ) 124 // 125 // https://tc39.es/proposal-set-methods/#sec-getsetrecord 126 function GetSetRecord(obj) { 127 // Step 1. 128 if (!IsObject(obj)) { 129 ThrowTypeError(JSMSG_OBJECT_REQUIRED, obj === null ? "null" : typeof obj); 130 } 131 132 // Step 2. 133 var rawSize = obj.size; 134 135 // Step 3. 136 var numSize = +rawSize; 137 138 // Steps 4-5. 139 if (numSize !== numSize) { 140 if (rawSize === undefined) { 141 ThrowTypeError(JSMSG_UNEXPECTED_TYPE, "size", "undefined"); 142 } else { 143 ThrowTypeError(JSMSG_UNEXPECTED_TYPE, "size", "NaN"); 144 } 145 } 146 147 // Step 6. 148 var intSize = ToInteger(numSize); 149 150 // Step 7. 151 if (intSize < 0) { 152 ThrowRangeError(JSMSG_SET_NEGATIVE_SIZE); 153 } 154 155 // Step 8. 156 var has = obj.has; 157 158 // Step 9. 159 if (!IsCallable(has)) { 160 ThrowTypeError(JSMSG_PROPERTY_NOT_CALLABLE, "has"); 161 } 162 163 // Step 10. 164 var keys = obj.keys; 165 166 // Step 11. 167 if (!IsCallable(keys)) { 168 ThrowTypeError(JSMSG_PROPERTY_NOT_CALLABLE, "keys"); 169 } 170 171 // Step 12. 172 return { set: obj, size: intSize, has, keys }; 173 } 174 175 // 7.4.2 GetIteratorFromMethod ( obj, method ) 176 // 177 // ES2024 draft rev a103b287cd19bdc51c7a3d8d7c1431b1506a74e2 178 function GetIteratorFromMethod(setRec) { 179 // Step 1. 180 var keysIter = callContentFunction(setRec.keys, setRec.set); 181 182 // Step 2. 183 if (!IsObject(keysIter)) { 184 ThrowTypeError( 185 JSMSG_OBJECT_REQUIRED, 186 keysIter === null ? "null" : typeof keysIter 187 ); 188 } 189 190 // Step 3. (Implemented in caller.) 191 192 // Step 4. 193 return keysIter; 194 } 195 196 // Set.prototype.union ( other ) 197 // 198 // https://tc39.es/proposal-set-methods/#sec-set.prototype.union 199 function SetUnion(other) { 200 // Step 1. 201 var O = this; 202 203 // Step 2. 204 if (!IsObject(O) || (O = GuardToSetObject(O)) === null) { 205 return callFunction(CallSetMethodIfWrapped, this, other, "SetUnion"); 206 } 207 208 // Step 3. 209 var otherRec = GetSetRecord(other); 210 211 // Step 4. 212 var keysIter = GetIteratorFromMethod(otherRec); 213 var keysIterNext = keysIter.next; 214 215 // Steps 5 and 8-9. (Reordered) 216 var result = SetCopy(O); 217 218 // Steps 6-7. 219 for (var nextValue of allowContentIterWithNext(keysIter, keysIterNext)) { 220 // Step 7.a and 7.b.i. (Implicit through for-of loop) 221 222 // Steps 7.b.ii-iii. (Implicit through std_Set_add) 223 224 // Step 7.b.iii.1. 225 callFunction(std_Set_add, result, nextValue); 226 } 227 228 // Step 10. 229 return result; 230 } 231 232 // Set.prototype.intersection ( other ) 233 // 234 // https://tc39.es/proposal-set-methods/#sec-set.prototype.intersection 235 function SetIntersection(other) { 236 // Step 1. 237 var O = this; 238 239 // Step 2. 240 if (!IsObject(O) || (O = GuardToSetObject(O)) === null) { 241 return callFunction(CallSetMethodIfWrapped, this, other, "SetIntersection"); 242 } 243 244 // Step 3. 245 var otherRec = GetSetRecord(other); 246 247 // Steps 4 and 8-9. (Reordered) 248 var Set = GetBuiltinConstructor("Set"); 249 var result = new Set(); 250 251 // Step 5. 252 var thisSize = callFunction(std_Set_size, O); 253 254 // Steps 6-7. 255 if (thisSize <= otherRec.size) { 256 // Steps 6.a-b. 257 var values = callFunction(std_Set_values, O); 258 var setIterationResult = globalSetIterationResult; 259 while (true) { 260 var done = GetNextSetEntryForIterator(values, setIterationResult); 261 if (done) { 262 break; 263 } 264 265 var value = setIterationResult[0]; 266 setIterationResult[0] = null; 267 268 // Steps 6.b.i-ii. (Implicit through SetIterator) 269 270 // Steps 6.b.iii.1-2. 271 if (callContentFunction(otherRec.has, otherRec.set, value)) { 272 // Steps 6.b.iii.2.a-b. (Implicit through std_Set_add) 273 274 // Step 6.b.iii.2.c.i. 275 callFunction(std_Set_add, result, value); 276 } 277 278 // Steps 6.b.iii.3-4. (Implicit through SetIterator) 279 } 280 } else { 281 // Step 7.a. 282 var keysIter = GetIteratorFromMethod(otherRec); 283 284 // Steps 7.b-c. 285 for (var nextValue of allowContentIterWithNext(keysIter, keysIter.next)) { 286 // Step 7.c.i and 7.c.ii.1. (Implicit through for-of loop) 287 288 // Steps 7.c.ii.2-4. (Implicit through std_Set_add) 289 290 // Steps 7.c.ii.5-6. 291 if (callFunction(std_Set_has, O, nextValue)) { 292 callFunction(std_Set_add, result, nextValue); 293 } 294 } 295 } 296 297 // Step 10. 298 return result; 299 } 300 301 // Set.prototype.difference ( other ) 302 // 303 // https://tc39.es/proposal-set-methods/#sec-set.prototype.difference 304 function SetDifference(other) { 305 // Step 1. 306 var O = this; 307 308 // Step 2. 309 if (!IsObject(O) || (O = GuardToSetObject(O)) === null) { 310 return callFunction(CallSetMethodIfWrapped, this, other, "SetDifference"); 311 } 312 313 // Step 3. 314 var otherRec = GetSetRecord(other); 315 316 // Steps 4 and 8-9. (Reordered) 317 var result = SetCopy(O); 318 319 // Step 5. 320 var thisSize = callFunction(std_Set_size, O); 321 322 // Steps 6-7. 323 if (thisSize <= otherRec.size) { 324 // Steps 6.a-b. 325 var values = callFunction(std_Set_values, result); 326 var setIterationResult = globalSetIterationResult; 327 while (true) { 328 var done = GetNextSetEntryForIterator(values, setIterationResult); 329 if (done) { 330 break; 331 } 332 333 var value = setIterationResult[0]; 334 setIterationResult[0] = null; 335 336 // Steps 6.b.i-ii. (Implicit through SetIterator) 337 338 // Steps 6.b.iii.1-2. 339 if (callContentFunction(otherRec.has, otherRec.set, value)) { 340 callFunction(std_Set_delete, result, value); 341 } 342 } 343 } else { 344 // Step 7.a. 345 var keysIter = GetIteratorFromMethod(otherRec); 346 347 // Steps 7.b-c. 348 for (var nextValue of allowContentIterWithNext(keysIter, keysIter.next)) { 349 // Step 7.c.i and 7.c.ii.1. (Implicit through for-of loop) 350 351 // Steps 7.c.ii.2-3. 352 callFunction(std_Set_delete, result, nextValue); 353 } 354 } 355 356 // Step 10. 357 return result; 358 } 359 360 // Set.prototype.symmetricDifference ( other ) 361 // 362 // https://tc39.es/proposal-set-methods/#sec-set.prototype.symmetricdifference 363 function SetSymmetricDifference(other) { 364 // Step 1. 365 var O = this; 366 367 // Step 2. 368 if (!IsObject(O) || (O = GuardToSetObject(O)) === null) { 369 return callFunction( 370 CallSetMethodIfWrapped, 371 this, 372 other, 373 "SetSymmetricDifference" 374 ); 375 } 376 377 // Step 3. 378 var otherRec = GetSetRecord(other); 379 380 // Step 4. 381 var keysIter = GetIteratorFromMethod(otherRec); 382 var keysIterNext = keysIter.next; 383 384 // Steps 5 and 8-9. (Reordered) 385 var result = SetCopy(O); 386 387 // Steps 6-7. 388 for (var nextValue of allowContentIterWithNext(keysIter, keysIterNext)) { 389 // Step 7.a and 7.b.i. (Implicit through for-of loop) 390 391 // Steps 7.b.ii-iii. (Implicit through std_Set_has) 392 393 // Steps 7.b.iv-v. 394 if (callFunction(std_Set_has, O, nextValue)) { 395 // Step 7.b.iv.1. 396 callFunction(std_Set_delete, result, nextValue); 397 } else { 398 // Step 7.b.v.1. 399 callFunction(std_Set_add, result, nextValue); 400 } 401 } 402 403 // Step 10. 404 return result; 405 } 406 407 // Set.prototype.isSubsetOf ( other ) 408 // 409 // https://tc39.es/proposal-set-methods/#sec-set.prototype.issubsetof 410 function SetIsSubsetOf(other) { 411 // Step 1. 412 var O = this; 413 414 // Step 2. 415 if (!IsObject(O) || (O = GuardToSetObject(O)) === null) { 416 return callFunction(CallSetMethodIfWrapped, this, other, "SetIsSubsetOf"); 417 } 418 419 // Step 3. 420 var otherRec = GetSetRecord(other); 421 422 // Step 4. 423 var thisSize = callFunction(std_Set_size, O); 424 425 // Step 5. 426 if (thisSize > otherRec.size) { 427 return false; 428 } 429 430 // Steps 6-7. 431 var values = callFunction(std_Set_values, O); 432 var setIterationResult = globalSetIterationResult; 433 while (true) { 434 var done = GetNextSetEntryForIterator(values, setIterationResult); 435 if (done) { 436 break; 437 } 438 439 var value = setIterationResult[0]; 440 setIterationResult[0] = null; 441 442 // Steps 7.a-b. (Implicit through SetIterator) 443 444 // Steps 7.c-d. 445 if (!callContentFunction(otherRec.has, otherRec.set, value)) { 446 return false; 447 } 448 449 // Steps 7.e-f. (Implicit through SetIterator) 450 } 451 452 // Step 7. 453 return true; 454 } 455 456 // Set.prototype.isSupersetOf ( other ) 457 // 458 // https://tc39.es/proposal-set-methods/#sec-set.prototype.issupersetof 459 function SetIsSupersetOf(other) { 460 // Step 1. 461 var O = this; 462 463 // Step 2. 464 if (!IsObject(O) || (O = GuardToSetObject(O)) === null) { 465 return callFunction(CallSetMethodIfWrapped, this, other, "SetIsSupersetOf"); 466 } 467 468 // Step 3. 469 var otherRec = GetSetRecord(other); 470 471 // Step 4. 472 var thisSize = callFunction(std_Set_size, O); 473 474 // Step 5. 475 if (thisSize < otherRec.size) { 476 return false; 477 } 478 479 // Step 6. 480 var keysIter = GetIteratorFromMethod(otherRec); 481 482 // Steps 7-8. 483 for (var nextValue of allowContentIterWithNext(keysIter, keysIter.next)) { 484 // Step 8.a and 8.b.i. (Implicit through for-of loop) 485 486 // Step 8.b.ii. 487 if (!callFunction(std_Set_has, O, nextValue)) { 488 // Step 8.b.ii.1. (Implicit through for-of loop) 489 490 // Step 8.b.ii.2. 491 return false; 492 } 493 } 494 495 // Step 9. 496 return true; 497 } 498 499 // Set.prototype.isDisjointFrom ( other ) 500 // 501 // https://tc39.es/proposal-set-methods/#sec-set.prototype.isdisjointfrom 502 function SetIsDisjointFrom(other) { 503 // Step 1. 504 var O = this; 505 506 // Step 2. 507 if (!IsObject(O) || (O = GuardToSetObject(O)) === null) { 508 return callFunction( 509 CallSetMethodIfWrapped, 510 this, 511 other, 512 "SetIsDisjointFrom" 513 ); 514 } 515 516 // Step 3. 517 var otherRec = GetSetRecord(other); 518 519 // Step 4. 520 var thisSize = callFunction(std_Set_size, O); 521 522 // Steps 5-6. 523 if (thisSize <= otherRec.size) { 524 // Steps 5.a-b. 525 var values = callFunction(std_Set_values, O); 526 var setIterationResult = globalSetIterationResult; 527 while (true) { 528 var done = GetNextSetEntryForIterator(values, setIterationResult); 529 if (done) { 530 break; 531 } 532 533 var value = setIterationResult[0]; 534 setIterationResult[0] = null; 535 536 // Step 5.b.i-ii. (Implicit through SetIterator) 537 538 // Steps 5.b.iii.1-2. 539 if (callContentFunction(otherRec.has, otherRec.set, value)) { 540 return false; 541 } 542 543 // Steps 5.b.iii.3-4. (Implicit through SetIterator) 544 } 545 } else { 546 // Step 6.a. 547 var keysIter = GetIteratorFromMethod(otherRec); 548 549 // Steps 6.b-c. 550 for (var nextValue of allowContentIterWithNext(keysIter, keysIter.next)) { 551 // Step 6.c.i and 6.c.ii.1. (Implicit through for-of loop) 552 553 // Step 6.c.ii.2. 554 if (callFunction(std_Set_has, O, nextValue)) { 555 // Step 6.c.ii.2.a. (Implicit through for-of loop) 556 557 // Step 6.c.ii.2.b. 558 return false; 559 } 560 } 561 } 562 563 // Step 7. 564 return true; 565 }