MIRROR: javascript for ๐Ÿœ's, a tiny runtime with big ambitions
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

implement Set.prototype union, intersection, difference, symmetricDifference, isSubsetOf, isSupersetOf, and isDisjointFrom

+497 -15
+7 -7
examples/results.txt
··· 1430 1430 compat-table/es2025/Iterator.prototype.toArray.js: OK 1431 1431 compat-table/es2025/Promise.try.js: OK 1432 1432 compat-table/es2025/RegExp.escape.js: OK 1433 - compat-table/es2025/Set.prototype.difference.js: TypeError: undefined is not a function 1434 - compat-table/es2025/Set.prototype.intersection.js: TypeError: undefined is not a function 1435 - compat-table/es2025/Set.prototype.isDisjointFrom.js: TypeError: undefined is not a function 1436 - compat-table/es2025/Set.prototype.isSubsetOf.js: TypeError: undefined is not a function 1437 - compat-table/es2025/Set.prototype.isSupersetOf.js: TypeError: undefined is not a function 1438 - compat-table/es2025/Set.prototype.symmetricDifference.js: TypeError: undefined is not a function 1439 - compat-table/es2025/Set.prototype.union.js: TypeError: undefined is not a function 1433 + compat-table/es2025/Set.prototype.difference.js: OK 1434 + compat-table/es2025/Set.prototype.intersection.js: OK 1435 + compat-table/es2025/Set.prototype.isDisjointFrom.js: OK 1436 + compat-table/es2025/Set.prototype.isSubsetOf.js: OK 1437 + compat-table/es2025/Set.prototype.isSupersetOf.js: OK 1438 + compat-table/es2025/Set.prototype.symmetricDifference.js: OK 1439 + compat-table/es2025/Set.prototype.union.js: OK 1440 1440 compat-table/es2025/regex.duplicate-named-groups.js: OK 1441 1441 compat-table/es2025/regex.pattern-modifiers.i.js: OK 1442 1442 compat-table/es2025/regex.pattern-modifiers.m.js: OK
+86
examples/spec/set.js
··· 41 41 42 42 test('set delete nonexistent', set.delete('nonexistent'), false); 43 43 44 + const setLike = { 45 + size: 2, 46 + has(value) { 47 + return value === 2 || value === 3; 48 + }, 49 + keys() { 50 + return [2, 3][Symbol.iterator](); 51 + } 52 + }; 53 + 54 + test('set union accepts set-like object', [...new Set([1, 2]).union(setLike)].join(','), '1,2,3'); 55 + test('set intersection accepts set-like object', [...new Set([1, 2]).intersection(setLike)].join(','), '2'); 56 + test('set difference accepts set-like object', [...new Set([1, 2]).difference(setLike)].join(','), '1'); 57 + test('set isSubsetOf accepts set-like object', new Set([2]).isSubsetOf(setLike), true); 58 + 59 + const duplicateKeysSetLike = { 60 + size: 3, 61 + has(value) { 62 + return value === 2 || value === 3; 63 + }, 64 + keys() { 65 + return [2, 3, 3][Symbol.iterator](); 66 + } 67 + }; 68 + 69 + test('set symmetricDifference ignores duplicate set-like keys', [...new Set([1, 2]).symmetricDifference(duplicateKeysSetLike)].join(','), '1,3'); 70 + 71 + const directIteratorSetLike = { 72 + size: 2, 73 + has(value) { 74 + return value === 2 || value === 4; 75 + }, 76 + keys() { 77 + const values = [2, 4]; 78 + let index = 0; 79 + return { 80 + next() { 81 + return index < values.length ? { value: values[index++], done: false } : { done: true }; 82 + } 83 + }; 84 + } 85 + }; 86 + 87 + test('set union accepts direct keys iterator', [...new Set([1, 2]).union(directIteratorSetLike)].join(','), '1,2,4'); 88 + 89 + let closedKeysIterator = false; 90 + const nonSubsetSetLike = { 91 + size: 1, 92 + has() { 93 + return false; 94 + }, 95 + keys() { 96 + return { 97 + next() { 98 + return { value: 2, done: false }; 99 + }, 100 + return() { 101 + closedKeysIterator = true; 102 + return {}; 103 + } 104 + }; 105 + } 106 + }; 107 + 108 + test('set isSupersetOf closes keys iterator on early false', new Set([1]).isSupersetOf(nonSubsetSetLike), false); 109 + test('set isSupersetOf called keys iterator return', closedKeysIterator, true); 110 + 111 + const getSetRecordOrder = []; 112 + try { 113 + new Set().union({ 114 + get size() { 115 + getSetRecordOrder.push('size'); 116 + return NaN; 117 + }, 118 + get has() { 119 + getSetRecordOrder.push('has'); 120 + return () => true; 121 + }, 122 + keys() { 123 + return [][Symbol.iterator](); 124 + } 125 + }); 126 + } catch (e) {} 127 + 128 + test('set GetSetRecord rejects NaN size before reading has', getSetRecordOrder.join(','), 'size'); 129 + 44 130 summary();
+404 -8
src/modules/collections.c
··· 637 637 return js_mkerr(js, "forEach requires a callback function"); 638 638 639 639 ant_value_t callback = args[0]; 640 + if (set_ptr && *set_ptr) { 641 + set_entry_t *entry, *tmp; 640 642 641 - if (set_ptr && *set_ptr) { 643 + HASH_ITER(hh, *set_ptr, entry, tmp) { 644 + ant_value_t call_args[3] = { entry->value, entry->value, this_val }; 645 + ant_value_t result = sv_vm_call(js->vm, js, callback, js_mkundef(), call_args, 3, NULL, false); 646 + if (is_err(result)) return result; 647 + }} 648 + 649 + return js_mkundef(); 650 + } 651 + 652 + static ant_value_t make_set_result(ant_t *js, set_entry_t ***out_set) { 653 + ant_value_t set_obj = js_mkobj(js); 654 + if (is_err(set_obj)) return set_obj; 655 + js_obj_ptr(set_obj)->type_tag = T_SET; 656 + 657 + ant_value_t set_proto = js_get_ctor_proto(js, "Set", 3); 658 + if (is_special_object(set_proto)) js_set_proto_init(set_obj, set_proto); 659 + 660 + set_entry_t **set_head = ant_calloc(sizeof(set_entry_t *)); 661 + if (!set_head) return js_mkerr(js, "out of memory"); 662 + *set_head = NULL; 663 + 664 + js_set_slot(set_obj, SLOT_DATA, ANT_PTR(set_head)); 665 + if (out_set) *out_set = set_head; 666 + 667 + return set_obj; 668 + } 669 + 670 + static bool set_result_add(ant_t *js, ant_value_t set_obj, set_entry_t **set_ptr, ant_value_t value) { 671 + if (!set_store_entry(js, set_ptr, value)) return false; 672 + ant_object_t *obj = js_obj_ptr(set_obj); 673 + if (obj) gc_write_barrier(js, obj, value); 674 + return true; 675 + } 676 + 677 + static void set_result_delete(ant_t *js, set_entry_t **set_ptr, ant_value_t value) { 678 + set_entry_t *entry = set_find_entry(js, set_ptr, value); 679 + if (!entry) return; 680 + HASH_DEL(*set_ptr, entry); 681 + free(entry->key); 682 + free(entry); 683 + } 684 + 685 + typedef struct { 686 + ant_value_t obj; 687 + ant_value_t has; 688 + ant_value_t keys; 689 + double size; 690 + } set_record_t; 691 + 692 + typedef ant_value_t (*set_key_cb)( 693 + ant_t *js, 694 + ant_value_t value, 695 + void *ctx, 696 + bool *stop 697 + ); 698 + 699 + static ant_value_t get_set_record(ant_t *js, ant_value_t value, const char *method, set_record_t *out) { 700 + if (!is_object_type(value)) 701 + return js_mkerr_typed(js, JS_ERR_TYPE, "Set.%s() requires a set-like object", method); 702 + 703 + ant_value_t size = js_getprop_fallback(js, value, "size"); 704 + if (is_err(size)) return size; 705 + 706 + if (vtype(size) == T_BIGINT || vtype(size) == T_SYMBOL) 707 + return js_mkerr_typed(js, JS_ERR_TYPE, "Set.%s() requires a numeric size", method); 708 + double num_size = js_to_number(js, size); 709 + if (isnan(num_size)) 710 + return js_mkerr_typed(js, JS_ERR_TYPE, "Set.%s() requires a numeric size", method); 711 + double int_size = (num_size == 0.0 || !isfinite(num_size)) 712 + ? num_size 713 + : (num_size < 0 ? -floor(-num_size) : floor(num_size)); 714 + if (int_size < 0) 715 + return js_mkerr_typed(js, JS_ERR_RANGE, "Set.%s() requires a non-negative size", method); 716 + 717 + ant_value_t has = js_getprop_fallback(js, value, "has"); 718 + if (is_err(has)) return has; 719 + if (!is_callable(has)) 720 + return js_mkerr_typed(js, JS_ERR_TYPE, "Set.%s() requires a callable has method", method); 721 + 722 + ant_value_t keys = js_getprop_fallback(js, value, "keys"); 723 + if (is_err(keys)) return keys; 724 + if (!is_callable(keys)) 725 + return js_mkerr_typed(js, JS_ERR_TYPE, "Set.%s() requires a callable keys method", method); 726 + 727 + out->obj = value; 728 + out->has = has; 729 + out->keys = keys; 730 + out->size = int_size; 731 + 732 + return js_mkundef(); 733 + } 734 + 735 + static ant_value_t set_record_has(ant_t *js, set_record_t *record, ant_value_t value, bool *out) { 736 + ant_value_t result = sv_vm_call(js->vm, js, record->has, record->obj, &value, 1, NULL, false); 737 + if (is_err(result)) return result; 738 + *out = js_truthy(js, result); 739 + return js_mkundef(); 740 + } 741 + 742 + static ant_value_t set_record_close_keys_iterator(ant_t *js, ant_value_t iterator) { 743 + ant_value_t return_fn = js_getprop_fallback(js, iterator, "return"); 744 + if (is_err(return_fn)) return return_fn; 745 + if (!is_callable(return_fn)) return js_mkundef(); 746 + return sv_vm_call(js->vm, js, return_fn, iterator, NULL, 0, NULL, false); 747 + } 748 + 749 + static ant_value_t set_record_for_each_key(ant_t *js, set_record_t *record, set_key_cb cb, void *ctx) { 750 + ant_value_t iterator = sv_vm_call(js->vm, js, record->keys, record->obj, NULL, 0, NULL, false); 751 + if (is_err(iterator)) return iterator; 752 + if (!is_object_type(iterator)) 753 + return js_mkerr_typed(js, JS_ERR_TYPE, "Set keys() result is not an iterator"); 754 + 755 + ant_value_t next_fn = js_getprop_fallback(js, iterator, "next"); 756 + if (is_err(next_fn)) return next_fn; 757 + if (!is_callable(next_fn)) 758 + return js_mkerr_typed(js, JS_ERR_TYPE, "Set keys() iterator has no callable next method"); 759 + 760 + while (true) { 761 + ant_value_t next = sv_vm_call(js->vm, js, next_fn, iterator, NULL, 0, NULL, false); 762 + if (is_err(next)) return next; 763 + if (!is_object_type(next)) 764 + return js_mkerr_typed(js, JS_ERR_TYPE, "Set keys() iterator result is not an object"); 765 + 766 + ant_value_t done = js_getprop_fallback(js, next, "done"); 767 + if (is_err(done)) return done; 768 + if (js_truthy(js, done)) return js_mkundef(); 769 + 770 + ant_value_t value = js_getprop_fallback(js, next, "value"); 771 + if (is_err(value)) return value; 772 + 773 + bool stop = false; 774 + ant_value_t result = cb(js, value, ctx, &stop); 775 + if (is_err(result)) { 776 + ant_value_t close_result = set_record_close_keys_iterator(js, iterator); 777 + return is_err(close_result) ? close_result : result; 778 + } 779 + if (stop) { 780 + ant_value_t close_result = set_record_close_keys_iterator(js, iterator); 781 + return is_err(close_result) ? close_result : js_mkundef(); 782 + } 783 + } 784 + } 785 + 786 + typedef struct { 787 + ant_value_t out; 788 + set_entry_t **out_set; 789 + } set_build_ctx_t; 790 + 791 + static ant_value_t set_add_key_cb(ant_t *js, ant_value_t value, void *ctx, bool *stop) { 792 + set_build_ctx_t *build = (set_build_ctx_t *)ctx; 793 + if (!set_result_add(js, build->out, build->out_set, value)) 794 + return js_mkerr(js, "out of memory"); 795 + return js_mkundef(); 796 + } 797 + 798 + static ant_value_t set_union(ant_t *js, ant_value_t *args, int nargs) { 799 + set_entry_t **this_set = get_set_from_obj(js->this_val); 800 + if (!this_set) return js_mkerr_typed(js, JS_ERR_TYPE, "Invalid Set object"); 801 + if (nargs < 1) return js_mkerr_typed(js, JS_ERR_TYPE, "Set.union() requires a set-like object"); 802 + 803 + set_record_t other; 804 + ant_value_t rec = get_set_record(js, args[0], "union", &other); 805 + if (is_err(rec)) return rec; 806 + 807 + set_entry_t **out_set = NULL; 808 + ant_value_t out = make_set_result(js, &out_set); 809 + if (is_err(out)) return out; 810 + set_build_ctx_t build = { out, out_set }; 811 + 812 + set_entry_t *entry, *tmp; 813 + HASH_ITER(hh, *this_set, entry, tmp) 814 + if (!set_result_add(js, out, out_set, entry->value)) return js_mkerr(js, "out of memory"); 815 + ant_value_t result = set_record_for_each_key(js, &other, set_add_key_cb, &build); 816 + 817 + return is_err(result) ? result : out; 818 + } 819 + 820 + typedef struct { 821 + ant_value_t out; 822 + set_entry_t **out_set; 823 + set_entry_t **this_set; 824 + } set_compare_build_ctx_t; 825 + 826 + static ant_value_t set_intersection_key_cb(ant_t *js, ant_value_t value, void *ctx, bool *stop) { 827 + set_compare_build_ctx_t *build = (set_compare_build_ctx_t *)ctx; 828 + if ( 829 + set_find_entry(js, build->this_set, value) && 830 + !set_result_add(js, build->out, build->out_set, value) 831 + ) return js_mkerr(js, "out of memory"); 832 + return js_mkundef(); 833 + } 834 + 835 + static ant_value_t set_intersection(ant_t *js, ant_value_t *args, int nargs) { 836 + set_entry_t **this_set = get_set_from_obj(js->this_val); 837 + if (!this_set) return js_mkerr_typed(js, JS_ERR_TYPE, "Invalid Set object"); 838 + if (nargs < 1) return js_mkerr_typed(js, JS_ERR_TYPE, "Set.intersection() requires a set-like object"); 839 + 840 + set_record_t other; 841 + ant_value_t rec = get_set_record(js, args[0], "intersection", &other); 842 + if (is_err(rec)) return rec; 843 + 844 + set_entry_t **out_set = NULL; 845 + ant_value_t out = make_set_result(js, &out_set); 846 + if (is_err(out)) return out; 847 + 848 + double this_size = (double)HASH_COUNT(*this_set); 849 + if (this_size <= other.size) { 642 850 set_entry_t *entry, *tmp; 643 - HASH_ITER(hh, *set_ptr, entry, tmp) { 644 - ant_value_t call_args[3] = { entry->value, entry->value, this_val }; 645 - ant_value_t result = sv_vm_call(js->vm, js, callback, js_mkundef(), call_args, 3, NULL, false); 851 + HASH_ITER(hh, *this_set, entry, tmp) { 852 + bool has = false; 853 + ant_value_t result = set_record_has(js, &other, entry->value, &has); 854 + if (is_err(result)) return result; 855 + if (has && !set_result_add(js, out, out_set, entry->value)) return js_mkerr(js, "out of memory"); 856 + } 857 + return out; 858 + } 859 + 860 + set_compare_build_ctx_t build = { out, out_set, this_set }; 861 + ant_value_t result = set_record_for_each_key(js, &other, set_intersection_key_cb, &build); 862 + 863 + return is_err(result) ? result : out; 864 + } 865 + 866 + typedef struct { 867 + set_record_t *other; 868 + ant_value_t out; 869 + set_entry_t **out_set; 870 + } set_difference_ctx_t; 871 + 872 + static ant_value_t set_difference_key_cb(ant_t *js, ant_value_t value, void *ctx) { 873 + set_difference_ctx_t *build = (set_difference_ctx_t *)ctx; 874 + bool has = false; 875 + ant_value_t result = set_record_has(js, build->other, value, &has); 876 + if (is_err(result)) return result; 877 + if (!has && !set_result_add(js, build->out, build->out_set, value)) return js_mkerr(js, "out of memory"); 878 + return js_mkundef(); 879 + } 880 + 881 + static ant_value_t set_delete_key_cb(ant_t *js, ant_value_t value, void *ctx, bool *stop) { 882 + set_build_ctx_t *build = (set_build_ctx_t *)ctx; 883 + set_result_delete(js, build->out_set, value); 884 + return js_mkundef(); 885 + } 886 + 887 + static ant_value_t set_difference(ant_t *js, ant_value_t *args, int nargs) { 888 + set_entry_t **this_set = get_set_from_obj(js->this_val); 889 + if (!this_set) return js_mkerr_typed(js, JS_ERR_TYPE, "Invalid Set object"); 890 + if (nargs < 1) return js_mkerr_typed(js, JS_ERR_TYPE, "Set.difference() requires a set-like object"); 891 + 892 + set_record_t other; 893 + ant_value_t rec = get_set_record(js, args[0], "difference", &other); 894 + if (is_err(rec)) return rec; 895 + 896 + set_entry_t **out_set = NULL; 897 + ant_value_t out = make_set_result(js, &out_set); 898 + if (is_err(out)) return out; 899 + 900 + set_entry_t *entry, *tmp; 901 + if ((double)HASH_COUNT(*this_set) <= other.size) { 902 + set_difference_ctx_t diff = { &other, out, out_set }; 903 + HASH_ITER(hh, *this_set, entry, tmp) { 904 + ant_value_t result = set_difference_key_cb(js, entry->value, &diff); 646 905 if (is_err(result)) return result; 647 906 } 907 + return out; 648 908 } 909 + 910 + HASH_ITER(hh, *this_set, entry, tmp) { 911 + if (!set_result_add(js, out, out_set, entry->value)) return js_mkerr(js, "out of memory"); 912 + } 913 + 914 + set_build_ctx_t build = { out, out_set }; 915 + ant_value_t result = set_record_for_each_key(js, &other, set_delete_key_cb, &build); 649 916 917 + return is_err(result) ? result : out; 918 + } 919 + 920 + typedef struct { 921 + ant_value_t out; 922 + set_entry_t **out_set; 923 + set_entry_t **this_set; 924 + } set_symdiff_ctx_t; 925 + 926 + static ant_value_t set_symmetric_difference_key_cb(ant_t *js, ant_value_t value, void *ctx, bool *stop) { 927 + set_symdiff_ctx_t *build = (set_symdiff_ctx_t *)ctx; 928 + if (set_find_entry(js, build->this_set, value)) { 929 + set_result_delete(js, build->out_set, value); 930 + } else if (!set_find_entry(js, build->out_set, value)) 931 + if (!set_result_add(js, build->out, build->out_set, value)) return js_mkerr(js, "out of memory"); 650 932 return js_mkundef(); 651 933 } 652 934 935 + static ant_value_t set_symmetricDifference(ant_t *js, ant_value_t *args, int nargs) { 936 + set_entry_t **this_set = get_set_from_obj(js->this_val); 937 + if (!this_set) return js_mkerr_typed(js, JS_ERR_TYPE, "Invalid Set object"); 938 + if (nargs < 1) return js_mkerr_typed(js, JS_ERR_TYPE, "Set.symmetricDifference() requires a set-like object"); 939 + 940 + set_record_t other; 941 + ant_value_t rec = get_set_record(js, args[0], "symmetricDifference", &other); 942 + if (is_err(rec)) return rec; 943 + 944 + set_entry_t **out_set = NULL; 945 + ant_value_t out = make_set_result(js, &out_set); 946 + if (is_err(out)) return out; 947 + 948 + set_entry_t *entry, *tmp; 949 + HASH_ITER(hh, *this_set, entry, tmp) { 950 + if (!set_result_add(js, out, out_set, entry->value)) return js_mkerr(js, "out of memory"); 951 + } 952 + set_symdiff_ctx_t build = { out, out_set, this_set }; 953 + ant_value_t result = set_record_for_each_key(js, &other, set_symmetric_difference_key_cb, &build); 954 + return is_err(result) ? result : out; 955 + } 956 + 957 + static ant_value_t set_isSubsetOf(ant_t *js, ant_value_t *args, int nargs) { 958 + set_entry_t **this_set = get_set_from_obj(js->this_val); 959 + if (!this_set) return js_mkerr_typed(js, JS_ERR_TYPE, "Invalid Set object"); 960 + if (nargs < 1) return js_mkerr_typed(js, JS_ERR_TYPE, "Set.isSubsetOf() requires a set-like object"); 961 + 962 + set_record_t other; 963 + ant_value_t rec = get_set_record(js, args[0], "isSubsetOf", &other); 964 + 965 + if (is_err(rec)) return rec; 966 + if ((double)HASH_COUNT(*this_set) > other.size) return js_false; 967 + 968 + set_entry_t *entry, *tmp; 969 + HASH_ITER(hh, *this_set, entry, tmp) { 970 + bool has = false; 971 + ant_value_t result = set_record_has(js, &other, entry->value, &has); 972 + if (is_err(result)) return result; 973 + if (!has) return js_false; 974 + } 975 + return js_true; 976 + } 977 + 978 + typedef struct { 979 + set_entry_t **this_set; 980 + bool result; 981 + } set_predicate_ctx_t; 982 + 983 + static ant_value_t set_superset_key_cb(ant_t *js, ant_value_t value, void *ctx, bool *stop) { 984 + set_predicate_ctx_t *pred = (set_predicate_ctx_t *)ctx; 985 + if (!set_find_entry(js, pred->this_set, value)) { 986 + pred->result = false; 987 + *stop = true; 988 + } 989 + return js_mkundef(); 990 + } 991 + 992 + static ant_value_t set_isSupersetOf(ant_t *js, ant_value_t *args, int nargs) { 993 + set_entry_t **this_set = get_set_from_obj(js->this_val); 994 + if (!this_set) return js_mkerr_typed(js, JS_ERR_TYPE, "Invalid Set object"); 995 + if (nargs < 1) return js_mkerr_typed(js, JS_ERR_TYPE, "Set.isSupersetOf() requires a set-like object"); 996 + 997 + set_record_t other; 998 + ant_value_t rec = get_set_record(js, args[0], "isSupersetOf", &other); 999 + if (is_err(rec)) return rec; 1000 + if ((double)HASH_COUNT(*this_set) < other.size) return js_false; 1001 + 1002 + set_predicate_ctx_t pred = { this_set, true }; 1003 + ant_value_t result = set_record_for_each_key(js, &other, set_superset_key_cb, &pred); 1004 + if (is_err(result)) return result; 1005 + return js_bool(pred.result); 1006 + } 1007 + 1008 + static ant_value_t set_disjoint_key_cb(ant_t *js, ant_value_t value, void *ctx, bool *stop) { 1009 + set_predicate_ctx_t *pred = (set_predicate_ctx_t *)ctx; 1010 + if (set_find_entry(js, pred->this_set, value)) { 1011 + pred->result = false; 1012 + *stop = true; 1013 + } 1014 + return js_mkundef(); 1015 + } 1016 + 1017 + static ant_value_t set_isDisjointFrom(ant_t *js, ant_value_t *args, int nargs) { 1018 + set_entry_t **this_set = get_set_from_obj(js->this_val); 1019 + if (!this_set) return js_mkerr_typed(js, JS_ERR_TYPE, "Invalid Set object"); 1020 + if (nargs < 1) return js_mkerr_typed(js, JS_ERR_TYPE, "Set.isDisjointFrom() requires a set-like object"); 1021 + 1022 + set_record_t other; 1023 + ant_value_t rec = get_set_record(js, args[0], "isDisjointFrom", &other); 1024 + if (is_err(rec)) return rec; 1025 + 1026 + if ((double)HASH_COUNT(*this_set) <= other.size) { 1027 + set_entry_t *entry, *tmp; 1028 + HASH_ITER(hh, *this_set, entry, tmp) { 1029 + bool has = false; 1030 + ant_value_t result = set_record_has(js, &other, entry->value, &has); 1031 + if (is_err(result)) return result; 1032 + if (has) return js_false; 1033 + } 1034 + return js_true; 1035 + } 1036 + 1037 + set_predicate_ctx_t pred = { this_set, true }; 1038 + ant_value_t result = set_record_for_each_key(js, &other, set_disjoint_key_cb, &pred); 1039 + if (is_err(result)) return result; 1040 + 1041 + return js_bool(pred.result); 1042 + } 1043 + 653 1044 static ant_value_t weakmap_set(ant_t *js, ant_value_t *args, int nargs) { 654 1045 if (nargs < 2) return js_mkerr(js, "WeakMap.set() requires 2 arguments"); 655 1046 ··· 661 1052 return js_mkerr(js, "WeakMap key must be an object"); 662 1053 663 1054 ant_value_t key_obj = args[0]; 664 - 665 1055 weakmap_entry_t *entry; 666 1056 HASH_FIND(hh, *wm_ptr, &key_obj, sizeof(ant_value_t), entry); 667 - if (entry) { 668 - entry->value = args[1]; 669 - } else { 1057 + 1058 + if (entry) entry->value = args[1]; else { 670 1059 entry = ant_calloc(sizeof(weakmap_entry_t)); 671 1060 if (!entry) return js_mkerr(js, "out of memory"); 672 1061 entry->key_obj = key_obj; ··· 1115 1504 js_set_exact(js, set_proto, "keys", js_get(js, set_proto, "values")); 1116 1505 js_set(js, set_proto, "entries", js_mkfun(set_entries)); 1117 1506 js_set(js, set_proto, "forEach", js_mkfun(set_forEach)); 1507 + js_set(js, set_proto, "union", js_mkfun(set_union)); 1508 + js_set(js, set_proto, "intersection", js_mkfun(set_intersection)); 1509 + js_set(js, set_proto, "difference", js_mkfun(set_difference)); 1510 + js_set(js, set_proto, "symmetricDifference", js_mkfun(set_symmetricDifference)); 1511 + js_set(js, set_proto, "isSubsetOf", js_mkfun(set_isSubsetOf)); 1512 + js_set(js, set_proto, "isSupersetOf", js_mkfun(set_isSupersetOf)); 1513 + js_set(js, set_proto, "isDisjointFrom", js_mkfun(set_isDisjointFrom)); 1118 1514 js_set_sym(js, set_proto, iter_sym, js_get(js, set_proto, "values")); 1119 1515 js_set_sym(js, set_proto, tag_sym, js_mkstr(js, "Set", 3)); 1120 1516