visaljs 0.0.10 → 0.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -4
- package/THIRD_PARTY_LICENSES +31 -1
- package/cli.js +962 -68
- package/node/include/js_node.h +11 -1
- package/node/prelude/_http_common.js +29 -0
- package/node/prelude/async_hooks.js +50 -11
- package/node/prelude/child_process.js +31 -4
- package/node/prelude/console.js +311 -143
- package/node/prelude/crypto.js +6 -4
- package/node/prelude/dgram.js +1169 -0
- package/node/prelude/diagnostics_channel.js +3 -1
- package/node/prelude/dns.js +250 -45
- package/node/prelude/dns_promises.js +8 -2
- package/node/prelude/fs_promises.js +9 -1
- package/node/prelude/http.js +395 -86
- package/node/prelude/https.js +13 -4
- package/node/prelude/internal/console_class.js +7 -0
- package/node/prelude/internal/console_global.js +25 -0
- package/node/prelude/internal/crypto/key_encryption.js +217 -0
- package/node/prelude/internal/crypto/keys.js +161 -26
- package/node/prelude/internal/crypto/random.js +24 -0
- package/node/prelude/internal/crypto/util.js +2 -1
- package/node/prelude/internal/crypto_x509.js +161 -0
- package/node/prelude/internal/dns_classes.js +6 -0
- package/node/prelude/internal/dns_resolver.js +371 -0
- package/node/prelude/internal/errors.js +9 -0
- package/node/prelude/internal/events_on.js +82 -37
- package/node/prelude/internal/features.js +8 -4
- package/node/prelude/internal/fs_filehandle.js +10 -4
- package/node/prelude/internal/perf_histogram.js +1 -1
- package/node/prelude/internal/process_more.js +32 -17
- package/node/prelude/internal/process_signals.js +8 -2
- package/node/prelude/internal/punycode.ts +163 -0
- package/node/prelude/internal/readline.js +648 -274
- package/node/prelude/internal/readline_editor.js +1240 -0
- package/node/prelude/internal/string_width.js +43 -0
- package/node/prelude/internal/tls/common.js +145 -33
- package/node/prelude/internal/tls/wrap.js +182 -49
- package/node/prelude/internal/tls/x509.js +4 -1
- package/node/prelude/internal/udp.js +177 -0
- package/node/prelude/net.js +13 -1
- package/node/prelude/os.js +24 -6
- package/node/prelude/perf_hooks.js +37 -2
- package/node/prelude/punycode.js +2 -130
- package/node/prelude/readline.js +113 -4
- package/node/prelude/readline_promises.js +56 -32
- package/node/prelude/tls.js +21 -4
- package/node/prelude/util.js +3 -16
- package/node/src/host_dns.c +623 -0
- package/node/src/host_http.c +12 -0
- package/node/src/host_net.c +46 -0
- package/node/src/host_os.c +1 -6
- package/node/src/host_sys.c +70 -0
- package/node/src/host_udp.c +418 -0
- package/node/third_party/c-ares/LICENSE.md +24 -0
- package/node/third_party/c-ares/config/darwin/ares_config.h +573 -0
- package/node/third_party/c-ares/config/freebsd/ares_config.h +573 -0
- package/node/third_party/c-ares/config/linux/ares_config.h +573 -0
- package/node/third_party/c-ares/config/openbsd/ares_config.h +583 -0
- package/node/third_party/c-ares/include/ares.h +1237 -0
- package/node/third_party/c-ares/include/ares_build.h +202 -0
- package/node/third_party/c-ares/include/ares_dns.h +127 -0
- package/node/third_party/c-ares/include/ares_dns_record.h +1119 -0
- package/node/third_party/c-ares/include/ares_nameser.h +510 -0
- package/node/third_party/c-ares/include/ares_version.h +47 -0
- package/node/third_party/c-ares/src/lib/ares_addrinfo2hostent.c +305 -0
- package/node/third_party/c-ares/src/lib/ares_addrinfo_localhost.c +245 -0
- package/node/third_party/c-ares/src/lib/ares_android.c +496 -0
- package/node/third_party/c-ares/src/lib/ares_android.h +38 -0
- package/node/third_party/c-ares/src/lib/ares_cancel.c +87 -0
- package/node/third_party/c-ares/src/lib/ares_close_sockets.c +137 -0
- package/node/third_party/c-ares/src/lib/ares_conn.c +511 -0
- package/node/third_party/c-ares/src/lib/ares_conn.h +202 -0
- package/node/third_party/c-ares/src/lib/ares_cookie.c +461 -0
- package/node/third_party/c-ares/src/lib/ares_data.c +168 -0
- package/node/third_party/c-ares/src/lib/ares_data.h +92 -0
- package/node/third_party/c-ares/src/lib/ares_destroy.c +159 -0
- package/node/third_party/c-ares/src/lib/ares_free_hostent.c +54 -0
- package/node/third_party/c-ares/src/lib/ares_free_string.c +33 -0
- package/node/third_party/c-ares/src/lib/ares_freeaddrinfo.c +67 -0
- package/node/third_party/c-ares/src/lib/ares_getaddrinfo.c +806 -0
- package/node/third_party/c-ares/src/lib/ares_getenv.c +38 -0
- package/node/third_party/c-ares/src/lib/ares_getenv.h +34 -0
- package/node/third_party/c-ares/src/lib/ares_gethostbyaddr.c +229 -0
- package/node/third_party/c-ares/src/lib/ares_gethostbyname.c +341 -0
- package/node/third_party/c-ares/src/lib/ares_getnameinfo.c +437 -0
- package/node/third_party/c-ares/src/lib/ares_hosts_file.c +960 -0
- package/node/third_party/c-ares/src/lib/ares_inet_net_pton.h +31 -0
- package/node/third_party/c-ares/src/lib/ares_init.c +631 -0
- package/node/third_party/c-ares/src/lib/ares_ipv6.h +115 -0
- package/node/third_party/c-ares/src/lib/ares_library_init.c +190 -0
- package/node/third_party/c-ares/src/lib/ares_metrics.c +261 -0
- package/node/third_party/c-ares/src/lib/ares_options.c +492 -0
- package/node/third_party/c-ares/src/lib/ares_parse_into_addrinfo.c +179 -0
- package/node/third_party/c-ares/src/lib/ares_private.h +648 -0
- package/node/third_party/c-ares/src/lib/ares_process.c +1649 -0
- package/node/third_party/c-ares/src/lib/ares_qcache.c +442 -0
- package/node/third_party/c-ares/src/lib/ares_query.c +151 -0
- package/node/third_party/c-ares/src/lib/ares_search.c +623 -0
- package/node/third_party/c-ares/src/lib/ares_send.c +300 -0
- package/node/third_party/c-ares/src/lib/ares_set_socket_functions.c +590 -0
- package/node/third_party/c-ares/src/lib/ares_setup.h +224 -0
- package/node/third_party/c-ares/src/lib/ares_socket.c +427 -0
- package/node/third_party/c-ares/src/lib/ares_socket.h +163 -0
- package/node/third_party/c-ares/src/lib/ares_sortaddrinfo.c +447 -0
- package/node/third_party/c-ares/src/lib/ares_strerror.c +91 -0
- package/node/third_party/c-ares/src/lib/ares_sysconfig.c +642 -0
- package/node/third_party/c-ares/src/lib/ares_sysconfig_files.c +851 -0
- package/node/third_party/c-ares/src/lib/ares_sysconfig_mac.c +373 -0
- package/node/third_party/c-ares/src/lib/ares_sysconfig_win.c +673 -0
- package/node/third_party/c-ares/src/lib/ares_timeout.c +162 -0
- package/node/third_party/c-ares/src/lib/ares_update_servers.c +1376 -0
- package/node/third_party/c-ares/src/lib/ares_version.c +36 -0
- package/node/third_party/c-ares/src/lib/config-dos.h +114 -0
- package/node/third_party/c-ares/src/lib/config-win32.h +396 -0
- package/node/third_party/c-ares/src/lib/dsa/ares_array.c +409 -0
- package/node/third_party/c-ares/src/lib/dsa/ares_htable.c +451 -0
- package/node/third_party/c-ares/src/lib/dsa/ares_htable.h +174 -0
- package/node/third_party/c-ares/src/lib/dsa/ares_htable_asvp.c +224 -0
- package/node/third_party/c-ares/src/lib/dsa/ares_htable_dict.c +230 -0
- package/node/third_party/c-ares/src/lib/dsa/ares_htable_strvp.c +210 -0
- package/node/third_party/c-ares/src/lib/dsa/ares_htable_szvp.c +188 -0
- package/node/third_party/c-ares/src/lib/dsa/ares_htable_vpstr.c +186 -0
- package/node/third_party/c-ares/src/lib/dsa/ares_htable_vpvp.c +194 -0
- package/node/third_party/c-ares/src/lib/dsa/ares_llist.c +385 -0
- package/node/third_party/c-ares/src/lib/dsa/ares_slist.c +479 -0
- package/node/third_party/c-ares/src/lib/dsa/ares_slist.h +207 -0
- package/node/third_party/c-ares/src/lib/event/ares_event.h +191 -0
- package/node/third_party/c-ares/src/lib/event/ares_event_configchg.c +746 -0
- package/node/third_party/c-ares/src/lib/event/ares_event_epoll.c +192 -0
- package/node/third_party/c-ares/src/lib/event/ares_event_kqueue.c +248 -0
- package/node/third_party/c-ares/src/lib/event/ares_event_poll.c +140 -0
- package/node/third_party/c-ares/src/lib/event/ares_event_select.c +159 -0
- package/node/third_party/c-ares/src/lib/event/ares_event_thread.c +575 -0
- package/node/third_party/c-ares/src/lib/event/ares_event_wake_pipe.c +172 -0
- package/node/third_party/c-ares/src/lib/event/ares_event_win32.c +981 -0
- package/node/third_party/c-ares/src/lib/event/ares_event_win32.h +161 -0
- package/node/third_party/c-ares/src/lib/include/ares_array.h +276 -0
- package/node/third_party/c-ares/src/lib/include/ares_buf.h +732 -0
- package/node/third_party/c-ares/src/lib/include/ares_htable_asvp.h +130 -0
- package/node/third_party/c-ares/src/lib/include/ares_htable_dict.h +123 -0
- package/node/third_party/c-ares/src/lib/include/ares_htable_strvp.h +130 -0
- package/node/third_party/c-ares/src/lib/include/ares_htable_szvp.h +118 -0
- package/node/third_party/c-ares/src/lib/include/ares_htable_vpstr.h +111 -0
- package/node/third_party/c-ares/src/lib/include/ares_htable_vpvp.h +128 -0
- package/node/third_party/c-ares/src/lib/include/ares_llist.h +239 -0
- package/node/third_party/c-ares/src/lib/include/ares_mem.h +41 -0
- package/node/third_party/c-ares/src/lib/include/ares_str.h +261 -0
- package/node/third_party/c-ares/src/lib/inet_net_pton.c +451 -0
- package/node/third_party/c-ares/src/lib/inet_ntop.c +219 -0
- package/node/third_party/c-ares/src/lib/legacy/ares_create_query.c +78 -0
- package/node/third_party/c-ares/src/lib/legacy/ares_expand_name.c +99 -0
- package/node/third_party/c-ares/src/lib/legacy/ares_expand_string.c +107 -0
- package/node/third_party/c-ares/src/lib/legacy/ares_fds.c +80 -0
- package/node/third_party/c-ares/src/lib/legacy/ares_getsock.c +85 -0
- package/node/third_party/c-ares/src/lib/legacy/ares_parse_a_reply.c +107 -0
- package/node/third_party/c-ares/src/lib/legacy/ares_parse_aaaa_reply.c +109 -0
- package/node/third_party/c-ares/src/lib/legacy/ares_parse_caa_reply.c +137 -0
- package/node/third_party/c-ares/src/lib/legacy/ares_parse_mx_reply.c +110 -0
- package/node/third_party/c-ares/src/lib/legacy/ares_parse_naptr_reply.c +132 -0
- package/node/third_party/c-ares/src/lib/legacy/ares_parse_ns_reply.c +154 -0
- package/node/third_party/c-ares/src/lib/legacy/ares_parse_ptr_reply.c +213 -0
- package/node/third_party/c-ares/src/lib/legacy/ares_parse_soa_reply.c +115 -0
- package/node/third_party/c-ares/src/lib/legacy/ares_parse_srv_reply.c +114 -0
- package/node/third_party/c-ares/src/lib/legacy/ares_parse_txt_reply.c +144 -0
- package/node/third_party/c-ares/src/lib/legacy/ares_parse_uri_reply.c +113 -0
- package/node/third_party/c-ares/src/lib/record/ares_dns_mapping.c +982 -0
- package/node/third_party/c-ares/src/lib/record/ares_dns_multistring.c +309 -0
- package/node/third_party/c-ares/src/lib/record/ares_dns_multistring.h +72 -0
- package/node/third_party/c-ares/src/lib/record/ares_dns_name.c +736 -0
- package/node/third_party/c-ares/src/lib/record/ares_dns_parse.c +1360 -0
- package/node/third_party/c-ares/src/lib/record/ares_dns_private.h +273 -0
- package/node/third_party/c-ares/src/lib/record/ares_dns_record.c +1701 -0
- package/node/third_party/c-ares/src/lib/record/ares_dns_write.c +1229 -0
- package/node/third_party/c-ares/src/lib/str/ares_buf.c +1510 -0
- package/node/third_party/c-ares/src/lib/str/ares_str.c +562 -0
- package/node/third_party/c-ares/src/lib/str/ares_strsplit.c +90 -0
- package/node/third_party/c-ares/src/lib/str/ares_strsplit.h +51 -0
- package/node/third_party/c-ares/src/lib/thirdparty/apple/dnsinfo.h +122 -0
- package/node/third_party/c-ares/src/lib/util/ares_iface_ips.c +640 -0
- package/node/third_party/c-ares/src/lib/util/ares_iface_ips.h +140 -0
- package/node/third_party/c-ares/src/lib/util/ares_math.c +167 -0
- package/node/third_party/c-ares/src/lib/util/ares_math.h +58 -0
- package/node/third_party/c-ares/src/lib/util/ares_rand.c +389 -0
- package/node/third_party/c-ares/src/lib/util/ares_rand.h +36 -0
- package/node/third_party/c-ares/src/lib/util/ares_threads.c +613 -0
- package/node/third_party/c-ares/src/lib/util/ares_threads.h +60 -0
- package/node/third_party/c-ares/src/lib/util/ares_time.h +49 -0
- package/node/third_party/c-ares/src/lib/util/ares_timeval.c +95 -0
- package/node/third_party/c-ares/src/lib/util/ares_uri.c +1627 -0
- package/node/third_party/c-ares/src/lib/util/ares_uri.h +252 -0
- package/node/third_party/c-ares/src/lib/windows_port.c +29 -0
- package/package.json +1 -1
- package/prebuilt/darwin-arm64/cares-a6286c65ca9374a3.a +0 -0
- package/prebuilt/darwin-x64/cares-a6286c65ca9374a3.a +0 -0
- package/prebuilt/linux-arm64/cares-4ba05ac8e948af8e.a +0 -0
- package/prebuilt/linux-arm64-musl/cares-4ba05ac8e948af8e.a +0 -0
- package/prebuilt/linux-x64/cares-4ba05ac8e948af8e.a +0 -0
- package/prebuilt/linux-x64-musl/cares-4ba05ac8e948af8e.a +0 -0
- package/prebuilt/win32-x64/boringssl-ce573858472b7fc9.a +0 -0
- package/prebuilt/win32-x64/brotli-20d86a61f30baeb3.a +0 -0
- package/prebuilt/win32-x64/cares-49c9ec95162b912d.a +0 -0
- package/prebuilt/win32-x64/uv-b11bae65d7fced82.a +0 -0
- package/prebuilt/win32-x64/zlib-4ce2317a4c3f5fb5.a +0 -0
- package/prebuilt/win32-x64/zstd-015315ac7c784c73.a +0 -0
- package/runtime/include/js_builtins.h +5 -0
- package/runtime/include/js_crypto.h +11 -0
- package/runtime/include/js_gc.h +13 -10
- package/runtime/include/js_jobs.h +2 -0
- package/runtime/include/js_object.h +58 -0
- package/runtime/include/jscontext.h +1 -0
- package/runtime/src/crypto_internal.h +1 -0
- package/runtime/src/crypto_subtle.c +66 -7
- package/runtime/src/crypto_tls.c +265 -19
- package/runtime/src/gc.c +73 -92
- package/runtime/src/inspect.c +18 -1
- package/runtime/src/jobs.c +37 -22
- package/runtime/src/object.c +49 -2
- package/runtime/src/os.c +16 -6
- package/runtime/src/os.h +2 -0
- package/runtime/src/process.c +97 -10
package/runtime/src/gc.c
CHANGED
|
@@ -658,8 +658,8 @@ static JSCell *alloc_large(JSContext *ctx, size_t size) {
|
|
|
658
658
|
b->is_large = 1;
|
|
659
659
|
uint8_t shift = 9; /* cards of 512 bytes, or more for a very large object */
|
|
660
660
|
while ((size + ((size_t)1 << shift) - 1) >> shift > JS_LARGE_CARDS) shift++;
|
|
661
|
-
b->
|
|
662
|
-
b->
|
|
661
|
+
b->card_shift = shift;
|
|
662
|
+
b->large_alloc = 1;
|
|
663
663
|
|
|
664
664
|
if (h->large_count == h->large_cap) {
|
|
665
665
|
h->large_cap = h->large_cap ? h->large_cap * 2 : 16;
|
|
@@ -811,13 +811,12 @@ static void push_remembered(JSHeap *h, JSCell *c) {
|
|
|
811
811
|
* next stores of young cells mark their own cards. */
|
|
812
812
|
static void mark_cards(JSHeap *h, JSCell *c, const void *from, size_t bytes) {
|
|
813
813
|
JSBlock *b = js_block_of(c);
|
|
814
|
-
unsigned shift = b->
|
|
814
|
+
unsigned shift = b->card_shift;
|
|
815
815
|
size_t size = b->cell_size, off = (size_t)((const char *)from - (const char *)c);
|
|
816
816
|
if (!from || (const char *)from < (const char *)c || off >= size) off = 0, bytes = size;
|
|
817
817
|
if (!bytes) bytes = 1;
|
|
818
818
|
size_t last = (off + bytes - 1 < size ? off + bytes - 1 : size - 1) >> shift;
|
|
819
|
-
|
|
820
|
-
for (size_t k = off >> shift; k <= last; k++) cards[k / 64] |= UINT64_C(1) << (k % 64);
|
|
819
|
+
for (size_t k = off >> shift; k <= last; k++) b->cards[k / 64] |= UINT64_C(1) << (k % 64);
|
|
821
820
|
if (!b->remembered) {
|
|
822
821
|
b->remembered = 1;
|
|
823
822
|
push_remembered(h, c);
|
|
@@ -918,6 +917,10 @@ static bool verify_edge(const JSTracer *trc, const JSCell *c) {
|
|
|
918
917
|
/* Kinds that hold no cells: marked, never pushed or visited. */
|
|
919
918
|
static const bool leaf_kind[JS_CELL_KIND_COUNT] = { [JS_CELL_STR_FLAT] = true, [JS_CELL_BIGINT] = true };
|
|
920
919
|
|
|
920
|
+
static bool has_children(const JSCell *c) {
|
|
921
|
+
return !leaf_kind[c->kind] && !(c->kind == JS_CELL_HOST && !((const JSHostCell *)c)->cls->visit);
|
|
922
|
+
}
|
|
923
|
+
|
|
921
924
|
static JS_NOINLINE void grow_stack(JSTracer *trc) {
|
|
922
925
|
trc->cap = trc->cap ? trc->cap * 2 : 4096;
|
|
923
926
|
trc->stack = xrealloc(trc->stack, trc->cap * sizeof *trc->stack);
|
|
@@ -939,6 +942,18 @@ static inline void push(JSTracer *trc, JSCell *c) {
|
|
|
939
942
|
trc->stack[trc->sp++] = c;
|
|
940
943
|
}
|
|
941
944
|
|
|
945
|
+
/* Sets heap cell `c`'s mark bit. Returns whether it was clear: this marker marked it, and it's old
|
|
946
|
+
* from now on. In a young collection every old cell's already is. */
|
|
947
|
+
static inline bool mark_bit(JSTracer *trc, JSCell *c) {
|
|
948
|
+
JSBlock *b = js_block_of(c);
|
|
949
|
+
uint32_t i = cell_index(b, c);
|
|
950
|
+
if (!set_mark(trc, &b->mark_bits[i / 64], UINT64_C(1) << (i % 64))) return false;
|
|
951
|
+
c->gc = b->is_large ? JS_GC_OLD_LARGE : JS_GC_OLD;
|
|
952
|
+
trc->marked++;
|
|
953
|
+
trc->marked_bytes += b->is_large ? b->map_size : b->cell_size;
|
|
954
|
+
return true;
|
|
955
|
+
}
|
|
956
|
+
|
|
942
957
|
/* Marks `c`, and pushes it if it holds cells. Its header is read here, the first touch of the
|
|
943
958
|
* cell: trace_cell prefetched it. */
|
|
944
959
|
static inline void mark(JSTracer *trc, JSCell *c) {
|
|
@@ -947,14 +962,7 @@ static inline void mark(JSTracer *trc, JSCell *c) {
|
|
|
947
962
|
#else
|
|
948
963
|
if (js_cell_is_static(c)) return;
|
|
949
964
|
#endif
|
|
950
|
-
|
|
951
|
-
uint32_t i = cell_index(b, c);
|
|
952
|
-
if (!set_mark(trc, &b->mark_bits[i / 64], UINT64_C(1) << (i % 64))) return; /* in a young collection, every old cell is */
|
|
953
|
-
c->gc = b->is_large ? JS_GC_OLD_LARGE : JS_GC_OLD; /* it survives: old from now on */
|
|
954
|
-
trc->marked++;
|
|
955
|
-
trc->marked_bytes += b->is_large ? b->map_size : b->cell_size;
|
|
956
|
-
if (leaf_kind[c->kind] || (c->kind == JS_CELL_HOST && !((JSHostCell *)c)->cls->visit)) return;
|
|
957
|
-
push(trc, c);
|
|
965
|
+
if (mark_bit(trc, c) && has_children(c)) push(trc, c);
|
|
958
966
|
}
|
|
959
967
|
|
|
960
968
|
/* The marking barrier's: marked now, and on the marker's stack to be visited. */
|
|
@@ -1011,13 +1019,7 @@ static inline void mark_ool(JSTracer *trc, JSValueArray *a) {
|
|
|
1011
1019
|
}
|
|
1012
1020
|
if (verify_edge(trc, c)) return;
|
|
1013
1021
|
#endif
|
|
1014
|
-
|
|
1015
|
-
uint32_t i = cell_index(b, c);
|
|
1016
|
-
if (set_mark(trc, &b->mark_bits[i / 64], UINT64_C(1) << (i % 64))) {
|
|
1017
|
-
c->gc = b->is_large ? JS_GC_OLD_LARGE : JS_GC_OLD;
|
|
1018
|
-
trc->marked++;
|
|
1019
|
-
trc->marked_bytes += b->is_large ? b->map_size : b->cell_size;
|
|
1020
|
-
}
|
|
1022
|
+
mark_bit(trc, c);
|
|
1021
1023
|
for (uint32_t k = 0; k < c->aux; k++) trace_value(trc, a->values[k]);
|
|
1022
1024
|
}
|
|
1023
1025
|
|
|
@@ -1115,6 +1117,11 @@ static void add_task(JSMarkPool *p, JSCell *c, size_t from, size_t to) {
|
|
|
1115
1117
|
atomic_store_int(&p->news, p->news + 1);
|
|
1116
1118
|
}
|
|
1117
1119
|
|
|
1120
|
+
/* Bytes [from, to) of `c` as tasks of MARK_CHUNK bytes at most. */
|
|
1121
|
+
static void add_chunk_tasks(JSMarkPool *p, JSCell *c, size_t from, size_t to) {
|
|
1122
|
+
for (; from < to; from += MARK_CHUNK) add_task(p, c, from, to - from > MARK_CHUNK ? from + MARK_CHUNK : to);
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1118
1125
|
static void give_packet(JSTracer *trc, JSMarkPool *p) {
|
|
1119
1126
|
size_t n = (trc->sp - trc->base) / 2;
|
|
1120
1127
|
if (n > PACKET) n = PACKET;
|
|
@@ -1199,10 +1206,8 @@ static size_t splittable_bytes(const JSCell *c) {
|
|
|
1199
1206
|
/* A large cell met while marking with others: its chunks but the first become tasks, for
|
|
1200
1207
|
* whoever is free; this marker visits the first. */
|
|
1201
1208
|
static void split_cell(JSTracer *trc, JSMarkPool *p, JSCell *c) {
|
|
1202
|
-
size_t size = js_block_of(c)->cell_size;
|
|
1203
1209
|
js_os_lock(p->lock);
|
|
1204
|
-
|
|
1205
|
-
add_task(p, c, from, size - from > MARK_CHUNK ? from + MARK_CHUNK : size);
|
|
1210
|
+
add_chunk_tasks(p, c, MARK_CHUNK, js_block_of(c)->cell_size);
|
|
1206
1211
|
js_os_cond_broadcast(p->work);
|
|
1207
1212
|
js_os_unlock(p->lock);
|
|
1208
1213
|
#ifdef JS_GC_VERIFY
|
|
@@ -1373,10 +1378,6 @@ static void drain(JSTracer *trc) {
|
|
|
1373
1378
|
#endif
|
|
1374
1379
|
}
|
|
1375
1380
|
|
|
1376
|
-
static bool has_children(const JSCell *c) {
|
|
1377
|
-
return !leaf_kind[c->kind] && !(c->kind == JS_CELL_HOST && !((const JSHostCell *)c)->cls->visit);
|
|
1378
|
-
}
|
|
1379
|
-
|
|
1380
1381
|
/* The slots of `slots[0..n)` (at byte `base` of their cell) in bytes [from, to) of it. */
|
|
1381
1382
|
static void trace_slots_in(JSTracer *trc, const JSValue *slots, size_t n, size_t base, size_t from, size_t to) {
|
|
1382
1383
|
size_t first = from <= base ? 0 : (from - base) / sizeof(JSValue);
|
|
@@ -1416,43 +1417,50 @@ static bool visit_range(JSTracer *trc, JSCell *c, size_t from, size_t to) {
|
|
|
1416
1417
|
return false;
|
|
1417
1418
|
}
|
|
1418
1419
|
|
|
1420
|
+
/* Whether visit_range can visit part of `c`, not the whole cell whatever the range. */
|
|
1421
|
+
static bool visits_part(const JSCell *c) {
|
|
1422
|
+
if (c->kind == JS_CELL_HOST) return ((const JSHostCell *)c)->cls->visit_range != NULL;
|
|
1423
|
+
return splittable_bytes(c) != 0;
|
|
1424
|
+
}
|
|
1425
|
+
|
|
1426
|
+
static bool card_marked(const JSBlock *b, size_t k) { return (b->cards[k / 64] >> (k % 64)) & 1; }
|
|
1427
|
+
|
|
1428
|
+
/* The next run of large `b`'s cards from card *k that are marked (`marked`) or not: bytes
|
|
1429
|
+
* [*from, *to) of its cell. Returns false when there's none left. */
|
|
1430
|
+
static bool next_card_run(const JSBlock *b, bool marked, size_t *k, size_t *from, size_t *to) {
|
|
1431
|
+
unsigned shift = b->card_shift;
|
|
1432
|
+
size_t n = (b->cell_size + ((size_t)1 << shift) - 1) >> shift;
|
|
1433
|
+
while (*k < n && card_marked(b, *k) != marked) (*k)++;
|
|
1434
|
+
if (*k == n) return false;
|
|
1435
|
+
size_t end = *k + 1;
|
|
1436
|
+
while (end < n && card_marked(b, end) == marked) end++;
|
|
1437
|
+
*from = *k << shift;
|
|
1438
|
+
*to = end << shift < b->cell_size ? end << shift : b->cell_size;
|
|
1439
|
+
*k = end;
|
|
1440
|
+
return true;
|
|
1441
|
+
}
|
|
1442
|
+
|
|
1443
|
+
static void forget_cards(JSBlock *b) {
|
|
1444
|
+
memset(b->cards, 0, sizeof b->cards);
|
|
1445
|
+
b->remembered = 0;
|
|
1446
|
+
}
|
|
1447
|
+
|
|
1419
1448
|
/* A remembered large cell: visits its marked cards, a run of them at a time (`marked`), or, for
|
|
1420
1449
|
* the barrier verifier, the others; then, when visiting the marked ones, forgets them. */
|
|
1421
1450
|
static void visit_cards(JSTracer *trc, JSCell *c, bool marked) {
|
|
1422
1451
|
JSBlock *b = js_block_of(c);
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
size_t n = (b->cell_size + ((size_t)1 << shift) - 1) >> shift;
|
|
1426
|
-
for (size_t k = 0; k < n;) {
|
|
1427
|
-
if ((bool)((cards[k / 64] >> (k % 64)) & 1) != marked) {
|
|
1428
|
-
k++;
|
|
1429
|
-
continue;
|
|
1430
|
-
}
|
|
1431
|
-
size_t end = k + 1;
|
|
1432
|
-
while (end < n && (bool)((cards[end / 64] >> (end % 64)) & 1) == marked) end++;
|
|
1452
|
+
size_t from, to;
|
|
1453
|
+
for (size_t k = 0; next_card_run(b, marked, &k, &from, &to);) {
|
|
1433
1454
|
#ifdef JS_GC_VERIFY
|
|
1434
1455
|
trc->visiting = c;
|
|
1435
1456
|
#endif
|
|
1436
|
-
|
|
1437
|
-
if (!visit_range(trc, c, k << shift, to) && !marked) return; /* inexact: can't check part */
|
|
1438
|
-
k = end;
|
|
1439
|
-
}
|
|
1440
|
-
if (marked) {
|
|
1441
|
-
memset(cards, 0, JS_LARGE_CARDS / 8);
|
|
1442
|
-
b->remembered = 0;
|
|
1457
|
+
if (!visit_range(trc, c, from, to) && !marked) return; /* inexact: can't check part */
|
|
1443
1458
|
}
|
|
1459
|
+
if (marked) forget_cards(b);
|
|
1444
1460
|
}
|
|
1445
1461
|
|
|
1446
1462
|
/* ---- Incremental marking: slices ---------------------------------------- */
|
|
1447
1463
|
|
|
1448
|
-
/* A large cell is visited this much at a time in a slice, when its kind's range visit is exact. */
|
|
1449
|
-
|
|
1450
|
-
static bool visits_in_chunks(const JSCell *c) {
|
|
1451
|
-
if (!js_block_of(c)->is_large || js_block_of(c)->cell_size <= MARK_CHUNK) return false;
|
|
1452
|
-
return c->kind == JS_CELL_VALUE_ARRAY || c->kind == JS_CELL_ENV ||
|
|
1453
|
-
(c->kind == JS_CELL_ELEMENTS && ((const JSElements *)c)->kind == JS_ELEMENTS_DENSE);
|
|
1454
|
-
}
|
|
1455
|
-
|
|
1456
1464
|
/* The next chunk of the partly visited cell. Returns the bytes it covered. */
|
|
1457
1465
|
static size_t visit_chunk(JSTracer *trc) {
|
|
1458
1466
|
JSCell *c = trc->partial;
|
|
@@ -1489,7 +1497,7 @@ static bool drain_some(JSTracer *trc, size_t budget) {
|
|
|
1489
1497
|
}
|
|
1490
1498
|
if (!trc->sp) break;
|
|
1491
1499
|
JSCell *c = trc->stack[--trc->sp];
|
|
1492
|
-
if (
|
|
1500
|
+
if (splittable_bytes(c) > MARK_CHUNK) {
|
|
1493
1501
|
trc->partial = c;
|
|
1494
1502
|
trc->partial_from = 0;
|
|
1495
1503
|
continue;
|
|
@@ -1508,56 +1516,32 @@ static void drain_all(JSTracer *trc) {
|
|
|
1508
1516
|
drain(trc);
|
|
1509
1517
|
}
|
|
1510
1518
|
|
|
1511
|
-
/* A young collection's other roots: the old cells a store gave a young cell. They're marked
|
|
1512
|
-
* already, so they're pushed to be visited, dead or alive: a remembered cell that died since keeps
|
|
1513
|
-
* its young cells until the next collection, so nothing it points to is freed under it (a stale
|
|
1514
|
-
* stack word could still find it). Each becomes plain old again. */
|
|
1515
1519
|
/* Below this much in marked cards, a young collection visits them itself. */
|
|
1516
1520
|
#define PARALLEL_CARDS ((size_t)256 << 10)
|
|
1517
1521
|
|
|
1518
|
-
static bool exact_range(const JSCell *c) {
|
|
1519
|
-
switch (c->kind) {
|
|
1520
|
-
case JS_CELL_VALUE_ARRAY: case JS_CELL_ENV: return true;
|
|
1521
|
-
case JS_CELL_ELEMENTS: return ((const JSElements *)c)->kind == JS_ELEMENTS_DENSE;
|
|
1522
|
-
case JS_CELL_HOST: return ((const JSHostCell *)c)->cls->visit_range != NULL;
|
|
1523
|
-
default: return false;
|
|
1524
|
-
}
|
|
1525
|
-
}
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
1522
|
/* Large `c`'s marked card runs, as tasks of MARK_CHUNK bytes at most (the whole cell, once, for a
|
|
1529
1523
|
* kind that can't visit part of it); then its cards are forgotten. Returns the tasks' bytes. */
|
|
1530
1524
|
static size_t card_tasks(JSMarkPool *p, JSCell *c) {
|
|
1531
1525
|
JSBlock *b = js_block_of(c);
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
size_t n = (b->cell_size + ((size_t)1 << shift) - 1) >> shift, bytes = 0;
|
|
1535
|
-
if (!exact_range(c)) {
|
|
1526
|
+
size_t bytes = 0, from, to;
|
|
1527
|
+
if (!visits_part(c)) {
|
|
1536
1528
|
add_task(p, c, 0, b->cell_size);
|
|
1537
1529
|
bytes = b->cell_size;
|
|
1538
1530
|
} else {
|
|
1539
|
-
for (size_t k = 0; k
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
continue;
|
|
1543
|
-
}
|
|
1544
|
-
size_t end = k + 1;
|
|
1545
|
-
while (end < n && ((cards[end / 64] >> (end % 64)) & 1)) end++;
|
|
1546
|
-
size_t to = end << shift < b->cell_size ? end << shift : b->cell_size;
|
|
1547
|
-
for (size_t from = k << shift; from < to; from += MARK_CHUNK) {
|
|
1548
|
-
add_task(p, c, from, to - from > MARK_CHUNK ? from + MARK_CHUNK : to);
|
|
1549
|
-
bytes += to - from > MARK_CHUNK ? MARK_CHUNK : to - from;
|
|
1550
|
-
}
|
|
1551
|
-
k = end;
|
|
1531
|
+
for (size_t k = 0; next_card_run(b, true, &k, &from, &to);) {
|
|
1532
|
+
add_chunk_tasks(p, c, from, to);
|
|
1533
|
+
bytes += to - from;
|
|
1552
1534
|
}
|
|
1553
1535
|
}
|
|
1554
|
-
|
|
1555
|
-
b->remembered = 0;
|
|
1536
|
+
forget_cards(b);
|
|
1556
1537
|
return bytes;
|
|
1557
1538
|
}
|
|
1558
1539
|
|
|
1559
|
-
/* A young collection's other roots: the
|
|
1560
|
-
*
|
|
1540
|
+
/* A young collection's other roots: the old cells a store gave a young cell. They're marked
|
|
1541
|
+
* already, so they're pushed to be visited, dead or alive: a remembered cell that died since keeps
|
|
1542
|
+
* its young cells until the next collection, so nothing it points to is freed under it (a stale
|
|
1543
|
+
* stack word could still find it). Each becomes plain old again. With helpers, large cells' marked
|
|
1544
|
+
* cards become tasks that every marker takes a share of (drain), when there are enough of them. */
|
|
1561
1545
|
static void mark_remembered(JSHeap *h, JSTracer *trc) {
|
|
1562
1546
|
JSMarkPool *p = h->gc_helpers ? mark_pool(h) : NULL;
|
|
1563
1547
|
size_t task_bytes = 0;
|
|
@@ -1588,10 +1572,7 @@ static void mark_remembered(JSHeap *h, JSTracer *trc) {
|
|
|
1588
1572
|
static void forget_remembered(JSHeap *h) {
|
|
1589
1573
|
for (size_t i = 0; i < h->remembered_count; i++) {
|
|
1590
1574
|
JSCell *c = h->remembered[i];
|
|
1591
|
-
if (c->gc
|
|
1592
|
-
JSBlock *b = js_block_of(c);
|
|
1593
|
-
memset(js_large_cards(b), 0, JS_LARGE_CARDS / 8);
|
|
1594
|
-
b->remembered = 0;
|
|
1575
|
+
if (c->gc == JS_GC_OLD_LARGE) forget_cards(js_block_of(c)); /* the others: JS_GC_OLD again when they're marked */
|
|
1595
1576
|
}
|
|
1596
1577
|
h->remembered_count = 0;
|
|
1597
1578
|
}
|
package/runtime/src/inspect.c
CHANGED
|
@@ -438,6 +438,23 @@ static JSValue get_constructor_name(Insp *ip, JSValue obj, double recurse) {
|
|
|
438
438
|
}
|
|
439
439
|
|
|
440
440
|
/* getPrefix: "Foo ", "Foo [Tag] ", "[Object: null prototype] " */
|
|
441
|
+
/* Node's getPrefix: the constructor's name already shows the tag when it contains it, at its end
|
|
442
|
+
* or before a character that isn't lowercase (SecretKeyObject shows KeyObject; Foox doesn't show Foo) */
|
|
443
|
+
static bool names_tag(JSContext *ctx, JSValue constructor, JSValue tag) {
|
|
444
|
+
JSStrView c = js_string_view(ctx, constructor), t = js_string_view(ctx, tag);
|
|
445
|
+
if (t.length == 0 || t.length > c.length) return false;
|
|
446
|
+
for (uint32_t pos = 0; pos + t.length <= c.length; pos++) { /* the first occurrence decides, as indexOf */
|
|
447
|
+
uint32_t i = 0;
|
|
448
|
+
while (i < t.length && js_view_at(c, pos + i) == js_view_at(t, i)) i++;
|
|
449
|
+
if (i < t.length) continue;
|
|
450
|
+
uint32_t end = pos + t.length;
|
|
451
|
+
if (end == c.length) return true;
|
|
452
|
+
uint32_t next = js_view_at(c, end);
|
|
453
|
+
return next >= 'A' && next <= 'Z'; /* Node: not equal to its own lowercase (ASCII here) */
|
|
454
|
+
}
|
|
455
|
+
return false;
|
|
456
|
+
}
|
|
457
|
+
|
|
441
458
|
static void put_prefix(Builder *b, JSContext *ctx, JSValue constructor, JSValue tag, const char *fallback, const char *size) {
|
|
442
459
|
bool has_tag = js_string_length(tag) != 0;
|
|
443
460
|
if (js_is_null(constructor)) {
|
|
@@ -455,7 +472,7 @@ static void put_prefix(Builder *b, JSContext *ctx, JSValue constructor, JSValue
|
|
|
455
472
|
}
|
|
456
473
|
put_str(b, ctx, constructor);
|
|
457
474
|
put_ascii(b, size);
|
|
458
|
-
if (has_tag && !
|
|
475
|
+
if (has_tag && !names_tag(ctx, constructor, tag)) {
|
|
459
476
|
put_ascii(b, " [");
|
|
460
477
|
put_str(b, ctx, tag);
|
|
461
478
|
put_ascii(b, "]");
|
package/runtime/src/jobs.c
CHANGED
|
@@ -17,8 +17,7 @@
|
|
|
17
17
|
|
|
18
18
|
/* ---- The queue -------------------------------------------------------------------- */
|
|
19
19
|
|
|
20
|
-
void
|
|
21
|
-
JSJobQueue *q = &ctx->rt->jobs;
|
|
20
|
+
static void enqueue(JSContext *ctx, JSJobQueue *q, const JSJob *job) {
|
|
22
21
|
if (q->count == q->cap) { /* grow, unwrapping the ring: no allocation of cells, so no GC */
|
|
23
22
|
size_t cap = q->cap ? q->cap * 2 : 64;
|
|
24
23
|
JSJob *items = malloc(cap * sizeof *items);
|
|
@@ -36,6 +35,14 @@ void js_enqueue_microtask(JSContext *ctx, const JSJob *job) {
|
|
|
36
35
|
q->count++;
|
|
37
36
|
}
|
|
38
37
|
|
|
38
|
+
void js_enqueue_microtask(JSContext *ctx, const JSJob *job) {
|
|
39
|
+
enqueue(ctx, &ctx->rt->jobs, job);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
void js_enqueue_tick(JSContext *ctx, const JSJob *job) {
|
|
43
|
+
enqueue(ctx, &ctx->rt->ticks, job);
|
|
44
|
+
}
|
|
45
|
+
|
|
39
46
|
/* ---- The async context --------------------------------------------------------------- */
|
|
40
47
|
|
|
41
48
|
JSValue js_async_context(JSContext *ctx) { return ctx->rt->async_context; }
|
|
@@ -144,25 +151,31 @@ static int process_rejections(JSContext *ctx) {
|
|
|
144
151
|
|
|
145
152
|
/* ---- The checkpoint -------------------------------------------------------------- */
|
|
146
153
|
|
|
154
|
+
/* Runs every job in `q`, the ones queued meanwhile too: 0, or -1 after an uncaught error (reported) */
|
|
155
|
+
static int drain(JSJobQueue *q) {
|
|
156
|
+
while (q->count) {
|
|
157
|
+
JSJob job = q->items[q->head]; /* on the C stack: the conservative scan keeps it alive */
|
|
158
|
+
q->head = (q->head + 1) % q->cap;
|
|
159
|
+
q->count--;
|
|
160
|
+
if (run_job(&job) < 0 && js_report_uncaught(job.realm)) return -1; /* handled: the next job runs */
|
|
161
|
+
}
|
|
162
|
+
return 0;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/* Node's processTicksAndRejections: the ticks, then the microtasks (a tick a microtask queues
|
|
166
|
+
* waits for them all), again while there are ticks; the rejections only then, so a handler a
|
|
167
|
+
* tick adds is in time */
|
|
147
168
|
int js_run_microtasks(JSContext *ctx) {
|
|
148
169
|
JSRuntime *rt = ctx->rt;
|
|
149
170
|
if (rt->in_checkpoint) return 0;
|
|
150
171
|
rt->in_checkpoint = 1;
|
|
151
|
-
JSJobQueue *q = &rt->jobs;
|
|
152
172
|
int status = 0;
|
|
153
|
-
do {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
q->head = (q->head + 1) % q->cap;
|
|
157
|
-
q->count--;
|
|
158
|
-
if (run_job(&job) < 0 && js_report_uncaught(job.realm)) { /* handled: the next job runs */
|
|
159
|
-
status = -1;
|
|
160
|
-
break;
|
|
161
|
-
}
|
|
162
|
-
}
|
|
173
|
+
do {
|
|
174
|
+
status = drain(&rt->ticks);
|
|
175
|
+
if (status == 0) status = drain(&rt->jobs);
|
|
163
176
|
js_clear_kept_objects(rt); /* the end of the job: WeakRef targets may go now */
|
|
164
|
-
if (status == 0) status = process_rejections(ctx);
|
|
165
|
-
} while (status == 0 && (
|
|
177
|
+
if (status == 0 && rt->ticks.count == 0) status = process_rejections(ctx);
|
|
178
|
+
} while (status == 0 && (rt->ticks.count || rt->jobs.count || rt->handled_late.count));
|
|
166
179
|
rt->in_checkpoint = 0;
|
|
167
180
|
return status;
|
|
168
181
|
}
|
|
@@ -170,13 +183,14 @@ int js_run_microtasks(JSContext *ctx) {
|
|
|
170
183
|
/* ---- GC and teardown (gc.c) ----------------------------------------------------- */
|
|
171
184
|
|
|
172
185
|
void js_jobs_trace(JSRuntime *rt, JSTracer *trc) {
|
|
173
|
-
JSJobQueue *q = &rt->jobs;
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
186
|
+
for (JSJobQueue *q = &rt->jobs; q; q = q == &rt->jobs ? &rt->ticks : NULL) {
|
|
187
|
+
for (size_t i = 0; i < q->count; i++) {
|
|
188
|
+
JSJob *j = &q->items[(q->head + i) % q->cap];
|
|
189
|
+
js_trace_value(trc, j->a);
|
|
190
|
+
js_trace_value(trc, j->b);
|
|
191
|
+
js_trace_value(trc, j->c);
|
|
192
|
+
js_trace_value(trc, j->context);
|
|
193
|
+
}
|
|
180
194
|
}
|
|
181
195
|
for (size_t i = 0; i < rt->rejections.count; i++) js_trace_value(trc, rt->rejections.items[i]);
|
|
182
196
|
for (size_t i = 0; i < rt->handled_late.count; i++) js_trace_value(trc, rt->handled_late.items[i]);
|
|
@@ -189,6 +203,7 @@ void js_jobs_trace(JSRuntime *rt, JSTracer *trc) {
|
|
|
189
203
|
|
|
190
204
|
void js_jobs_free(JSRuntime *rt) {
|
|
191
205
|
free(rt->jobs.items);
|
|
206
|
+
free(rt->ticks.items);
|
|
192
207
|
free(rt->rejections.items);
|
|
193
208
|
free(rt->handled_late.items);
|
|
194
209
|
free(rt->timers.heap);
|
package/runtime/src/object.c
CHANGED
|
@@ -544,7 +544,8 @@ int js_ordinary_set(JSContext *ctx, JSObject *o, JSValue key, JSValue v, JSValue
|
|
|
544
544
|
/* not for classes that intercept indices (mapped arguments); arrays only guard length */
|
|
545
545
|
bool plain = !o->shape->cls->define_own_property || o->shape->cls == &js_class_array;
|
|
546
546
|
if (plain && js_elements_try_store(ctx, o, js_key_index(key), v)) return 1;
|
|
547
|
-
} else if (js_is_object(receiver) && js_as_object(receiver) == o
|
|
547
|
+
} else if (js_is_object(receiver) && js_as_object(receiver) == o &&
|
|
548
|
+
(!o->shape->cls->define_own_property || o->shape->cls == &js_class_array)) { /* a class that intercepts writes (process.env) sees each */
|
|
548
549
|
uint8_t attrs;
|
|
549
550
|
int32_t slot = find_own(o, key, &attrs);
|
|
550
551
|
if (slot >= 0 && (attrs & (JS_PROP_WRITABLE | JS_PROP_ACCESSOR)) == JS_PROP_WRITABLE) {
|
|
@@ -744,6 +745,51 @@ int js_array_push(JSContext *ctx, JSObject *a, JSValue v) {
|
|
|
744
745
|
return js_define_own_property(ctx, a, js_index_key(len), &d, true);
|
|
745
746
|
}
|
|
746
747
|
|
|
748
|
+
static const char *const SARRAY_KINDS[] = { "number", "string", "boolean" };
|
|
749
|
+
|
|
750
|
+
static JSValue sarray_not_array(JSContext *ctx, int kind) {
|
|
751
|
+
return js_throw_type_error(ctx, "A %s[] of static code isn't an array", SARRAY_KINDS[kind]);
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
static JSValue sarray_out_of_range(JSContext *ctx, int64_t i, uint32_t len) {
|
|
755
|
+
if (i < 0) return js_throw_range_error(ctx, "Invalid array index for length %u", len);
|
|
756
|
+
return js_throw_range_error(ctx, "Index %lld is out of range for length %u", (long long)i, len);
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
JSValue js_sarray_get_slow(JSContext *ctx, JSValue arr, int64_t i, int kind) {
|
|
760
|
+
if (!js_is_array(arr)) return sarray_not_array(ctx, kind);
|
|
761
|
+
uint32_t len = js_array_length(js_as_object(arr));
|
|
762
|
+
if (i < 0 || i >= len) return sarray_out_of_range(ctx, i, len);
|
|
763
|
+
/* a hole, a sparse store: the element as JavaScript reads it, which may be of another kind */
|
|
764
|
+
JSValue v = js_get_elem(ctx, arr, js_number((double)i));
|
|
765
|
+
if (js_is_exception(v) || js_sarray_is(v, kind)) return v;
|
|
766
|
+
return js_throw_type_error(ctx, "Element %lld of a %s[] isn't a %s", (long long)i, SARRAY_KINDS[kind], SARRAY_KINDS[kind]);
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
int js_sarray_set_slow(JSContext *ctx, JSValue arr, int64_t i, JSValue v, int kind) {
|
|
770
|
+
JSValue error = !js_is_array(arr) ? sarray_not_array(ctx, kind)
|
|
771
|
+
: !js_sarray_is(v, kind) ? js_throw_type_error(ctx, "A %s[]'s element can't be another type", SARRAY_KINDS[kind])
|
|
772
|
+
: JS_UNDEFINED;
|
|
773
|
+
if (js_is_exception(error)) return -1;
|
|
774
|
+
uint32_t len = js_array_length(js_as_object(arr));
|
|
775
|
+
if (i == len) return js_array_push(ctx, js_as_object(arr), v);
|
|
776
|
+
if (i < 0 || i > len) {
|
|
777
|
+
js_discard(sarray_out_of_range(ctx, i, len));
|
|
778
|
+
return -1;
|
|
779
|
+
}
|
|
780
|
+
return js_set_elem(ctx, arr, js_number((double)i), v, true);
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
JSValue js_sarray_length_slow(JSContext *ctx, JSValue arr) {
|
|
784
|
+
if (!js_is_array(arr)) return sarray_not_array(ctx, JS_SARRAY_NUMBER);
|
|
785
|
+
return js_throw_range_error(ctx, "A static array's length is below 2^31");
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
JSValue js_sarray_push_slow(JSContext *ctx, JSValue arr, JSValue v, int kind) {
|
|
789
|
+
if (js_sarray_set_slow(ctx, arr, js_is_array(arr) ? js_array_length(js_as_object(arr)) : 0, v, kind) < 0) return JS_EXCEPTION;
|
|
790
|
+
return js_sarray_length(ctx, arr);
|
|
791
|
+
}
|
|
792
|
+
|
|
747
793
|
int js_array_append(JSContext *ctx, JSValue arr, JSValue v) {
|
|
748
794
|
JSObject *a = js_as_object(arr);
|
|
749
795
|
if (!js_is_empty(v)) return js_array_push(ctx, a, v);
|
|
@@ -1083,7 +1129,8 @@ int js_set_prop_slow(JSContext *ctx, JSValue obj, JSValue key, JSValue v, bool s
|
|
|
1083
1129
|
lookup(ctx, o, key, &l);
|
|
1084
1130
|
JSShape *before = o->shape;
|
|
1085
1131
|
bool cacheable = l.cacheable && !l.exotic;
|
|
1086
|
-
|
|
1132
|
+
bool intercepts = before->cls->define_own_property && before->cls != &js_class_array;
|
|
1133
|
+
if (cacheable && !intercepts && l.holder == o && (l.attrs & (JS_PROP_WRITABLE | JS_PROP_ACCESSOR)) == JS_PROP_WRITABLE) {
|
|
1087
1134
|
JSPropCache c = with_fast_path((JSPropCache){ .kind = JS_IC_OWN, .slot = (uint32_t)l.slot, .shape = before });
|
|
1088
1135
|
*ic = c;
|
|
1089
1136
|
m->key = key;
|
package/runtime/src/os.c
CHANGED
|
@@ -151,6 +151,10 @@ const char *js_os_timezone_id(void) {
|
|
|
151
151
|
return tz && *tz ? tz : ""; /* Windows zone names aren't IANA ids: the offset fallback */
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
+
void js_os_timezone_changed(void) {
|
|
155
|
+
_tzset();
|
|
156
|
+
}
|
|
157
|
+
|
|
154
158
|
|
|
155
159
|
double js_os_thread_cpu_ms(void) {
|
|
156
160
|
FILETIME created, exited, kernel, user;
|
|
@@ -331,11 +335,18 @@ double js_os_time_ms(void) {
|
|
|
331
335
|
return (double)ts.tv_sec * 1000.0 + (double)(ts.tv_nsec / 1000000);
|
|
332
336
|
}
|
|
333
337
|
|
|
338
|
+
static bool tz_initialized, tz_id_done;
|
|
339
|
+
|
|
340
|
+
void js_os_timezone_changed(void) {
|
|
341
|
+
tzset();
|
|
342
|
+
tz_initialized = true;
|
|
343
|
+
tz_id_done = false;
|
|
344
|
+
}
|
|
345
|
+
|
|
334
346
|
int32_t js_os_local_offset(int64_t seconds, bool *dst) {
|
|
335
|
-
|
|
336
|
-
if (!initialized) {
|
|
347
|
+
if (!tz_initialized) {
|
|
337
348
|
tzset();
|
|
338
|
-
|
|
349
|
+
tz_initialized = true;
|
|
339
350
|
}
|
|
340
351
|
time_t t = (time_t)seconds;
|
|
341
352
|
struct tm tm;
|
|
@@ -351,9 +362,8 @@ int32_t js_os_local_offset(int64_t seconds, bool *dst) {
|
|
|
351
362
|
* points. */
|
|
352
363
|
const char *js_os_timezone_id(void) {
|
|
353
364
|
static char id[512];
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
done = true;
|
|
365
|
+
if (tz_id_done) return id;
|
|
366
|
+
tz_id_done = true;
|
|
357
367
|
const char *tz = getenv("TZ");
|
|
358
368
|
char path[512] = "";
|
|
359
369
|
if (tz && *tz) {
|
package/runtime/src/os.h
CHANGED
|
@@ -56,5 +56,7 @@ size_t js_os_peak_rss(void);
|
|
|
56
56
|
double js_os_time_ms(void);
|
|
57
57
|
int32_t js_os_local_offset(int64_t seconds, bool *dst);
|
|
58
58
|
const char *js_os_timezone_id(void);
|
|
59
|
+
/* TZ changed (process.env.TZ): local time and the zone's id are looked up again. */
|
|
60
|
+
void js_os_timezone_changed(void);
|
|
59
61
|
|
|
60
62
|
#endif /* JS_OS_H */
|