visaljs 0.0.9 → 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 +3745 -890
- package/node/include/js_node.h +12 -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 +405 -94
- 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/http_chars.ts +22 -0
- 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 +30 -14
- 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 +79 -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_buffer.h +185 -0
- package/runtime/include/js_builtins.h +58 -0
- package/runtime/include/js_crypto.h +11 -0
- package/runtime/include/js_exception.h +3 -0
- package/runtime/include/js_function.h +1 -1
- package/runtime/include/js_gc.h +13 -10
- package/runtime/include/js_jobs.h +2 -0
- package/runtime/include/js_object.h +79 -3
- package/runtime/include/js_ops.h +27 -0
- package/runtime/include/js_runtime.h +1 -0
- package/runtime/include/js_web.h +0 -3
- package/runtime/include/jscontext.h +8 -0
- package/runtime/src/builtins.c +17 -4
- 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/function.c +37 -10
- package/runtime/src/gc.c +76 -93
- package/runtime/src/inspect.c +18 -1
- package/runtime/src/iterator.c +5 -1
- package/runtime/src/jobs.c +37 -22
- package/runtime/src/object.c +91 -8
- package/runtime/src/os.c +16 -6
- package/runtime/src/os.h +2 -0
- package/runtime/src/process.c +97 -10
- package/runtime/src/typedarray.c +23 -0
package/runtime/src/crypto_tls.c
CHANGED
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
#include <openssl/err.h>
|
|
21
21
|
#include <openssl/evp.h>
|
|
22
22
|
#include <openssl/pem.h>
|
|
23
|
+
#include <openssl/pkcs8.h>
|
|
23
24
|
#include <openssl/ssl.h>
|
|
24
25
|
#include <openssl/x509.h>
|
|
25
26
|
|
|
@@ -263,27 +264,33 @@ PRIMITIVE(js_tls_context_set_cert) {
|
|
|
263
264
|
return js_int32(0);
|
|
264
265
|
}
|
|
265
266
|
|
|
266
|
-
/*
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
JSKeyData *k = js_key_data(ARG(1));
|
|
271
|
-
if (!o || !k) return js_throw_type_error(ctx, "tlsContextSetKey: a context and a key expected");
|
|
272
|
-
if (k->type != JS_KEY_PRIVATE) return js_int32(1);
|
|
267
|
+
/* A key (handle) as BoringSSL's, from its PKCS#8 or SPKI DER, or NULL for one BoringSSL can't use */
|
|
268
|
+
static EVP_PKEY *pkey_of(const JSKeyData *k) {
|
|
269
|
+
bool private = k->type == JS_KEY_PRIVATE;
|
|
270
|
+
if (!private && k->type != JS_KEY_PUBLIC) return NULL;
|
|
273
271
|
JSBytesOut der = { 0 };
|
|
274
|
-
if (js_key_export_der(k, JS_KEY_ENC_PKCS8, &der) != 0) {
|
|
272
|
+
if (js_key_export_der(k, private ? JS_KEY_ENC_PKCS8 : JS_KEY_ENC_SPKI, &der) != 0) {
|
|
275
273
|
free(der.p);
|
|
276
|
-
return
|
|
274
|
+
return NULL;
|
|
277
275
|
}
|
|
278
276
|
CBS cbs;
|
|
279
277
|
CBS_init(&cbs, der.p, der.n);
|
|
280
|
-
EVP_PKEY *pkey = EVP_parse_private_key(&cbs);
|
|
278
|
+
EVP_PKEY *pkey = private ? EVP_parse_private_key(&cbs) : EVP_parse_public_key(&cbs);
|
|
281
279
|
memset(der.p, 0, der.n);
|
|
282
280
|
free(der.p);
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
281
|
+
ERR_clear_error();
|
|
282
|
+
return pkey;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/* tlsContextSetKey(context, key handle) → 0 | 1 a key TLS can't use | 2 not the certificate's key */
|
|
286
|
+
PRIMITIVE(js_tls_context_set_key) {
|
|
287
|
+
UNUSED_ARGS;
|
|
288
|
+
TlsContextObject *o = context_arg(ARG(0));
|
|
289
|
+
JSKeyData *k = js_key_data(ARG(1));
|
|
290
|
+
if (!o || !k) return js_throw_type_error(ctx, "tlsContextSetKey: a context and a key expected");
|
|
291
|
+
if (k->type != JS_KEY_PRIVATE) return js_int32(1);
|
|
292
|
+
EVP_PKEY *pkey = pkey_of(k);
|
|
293
|
+
if (!pkey) return js_int32(1);
|
|
287
294
|
int ok = SSL_CTX_use_PrivateKey(o->ctx, pkey);
|
|
288
295
|
EVP_PKEY_free(pkey);
|
|
289
296
|
ERR_clear_error();
|
|
@@ -291,6 +298,195 @@ PRIMITIVE(js_tls_context_set_key) {
|
|
|
291
298
|
return js_int32(0);
|
|
292
299
|
}
|
|
293
300
|
|
|
301
|
+
/* tlsContextAddCredential(context, [der, …], key handle) → 0 | 1 a key TLS can't use | 2 not the
|
|
302
|
+
* certificate's key: one of a server's identities (a chain, leaf first, and its key), which
|
|
303
|
+
* BoringSSL chooses among by what the client accepts, as OpenSSL does by key type */
|
|
304
|
+
PRIMITIVE(js_tls_context_add_credential) {
|
|
305
|
+
UNUSED_ARGS;
|
|
306
|
+
TlsContextObject *o = context_arg(ARG(0));
|
|
307
|
+
JSKeyData *k = js_key_data(ARG(2));
|
|
308
|
+
if (!o || !js_is_array(ARG(1)) || !k) return js_throw_type_error(ctx, "tlsContextAddCredential: a context, certificates and a key expected");
|
|
309
|
+
uint32_t n = js_array_length(js_as_object(ARG(1)));
|
|
310
|
+
if (n == 0 || n > 16) return js_throw_type_error(ctx, "tlsContextAddCredential: 1 to 16 certificates expected");
|
|
311
|
+
CRYPTO_BUFFER *certs[16] = { 0 };
|
|
312
|
+
int result = 0;
|
|
313
|
+
for (uint32_t i = 0; i < n && result == 0; i++) {
|
|
314
|
+
const uint8_t *p;
|
|
315
|
+
size_t len;
|
|
316
|
+
if (!bytes_arg(js_get_value(ctx, ARG(1), js_index_key(i)), &p, &len) || !(certs[i] = CRYPTO_BUFFER_new(p, len, NULL))) result = 1;
|
|
317
|
+
}
|
|
318
|
+
EVP_PKEY *pkey = result == 0 && k->type == JS_KEY_PRIVATE ? pkey_of(k) : NULL;
|
|
319
|
+
SSL_CREDENTIAL *cred = SSL_CREDENTIAL_new_x509();
|
|
320
|
+
if (result == 0 && (!pkey || !cred)) result = 1;
|
|
321
|
+
if (result == 0 && !SSL_CREDENTIAL_set1_cert_chain(cred, certs, n)) result = 1;
|
|
322
|
+
if (result == 0 && !SSL_CREDENTIAL_set1_private_key(cred, pkey)) result = 2;
|
|
323
|
+
if (result == 0 && !SSL_CTX_add1_credential(o->ctx, cred)) result = 1;
|
|
324
|
+
SSL_CREDENTIAL_free(cred);
|
|
325
|
+
EVP_PKEY_free(pkey);
|
|
326
|
+
for (uint32_t i = 0; i < n; i++) CRYPTO_BUFFER_free(certs[i]);
|
|
327
|
+
ERR_clear_error();
|
|
328
|
+
return js_int32(result);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/* tlsContextAllowPartialChain(context): a trusted intermediate ends a chain, as a root does
|
|
332
|
+
* (allowPartialTrustChain); on the context's parameters, as its store may be the shared roots' */
|
|
333
|
+
PRIMITIVE(js_tls_context_allow_partial_chain) {
|
|
334
|
+
UNUSED_ARGS;
|
|
335
|
+
TlsContextObject *o = context_arg(ARG(0));
|
|
336
|
+
if (!o) return js_throw_type_error(ctx, "tlsContextAllowPartialChain: a context expected");
|
|
337
|
+
X509_VERIFY_PARAM_set_flags(SSL_CTX_get0_param(o->ctx), X509_V_FLAG_PARTIAL_CHAIN);
|
|
338
|
+
return JS_UNDEFINED;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/* tlsContextTicketKeys(context, keys | null) → the 48 bytes the context's session tickets are
|
|
342
|
+
* encrypted with (after setting them to `keys`) */
|
|
343
|
+
PRIMITIVE(js_tls_context_ticket_keys) {
|
|
344
|
+
UNUSED_ARGS;
|
|
345
|
+
TlsContextObject *o = context_arg(ARG(0));
|
|
346
|
+
if (!o) return js_throw_type_error(ctx, "tlsContextTicketKeys: a context expected");
|
|
347
|
+
const uint8_t *p;
|
|
348
|
+
size_t n;
|
|
349
|
+
if (bytes_arg(ARG(1), &p, &n)) {
|
|
350
|
+
if (n != 48 || !SSL_CTX_set_tlsext_ticket_keys(o->ctx, p, n)) return js_throw_type_error(ctx, "tlsContextTicketKeys: 48 bytes expected");
|
|
351
|
+
}
|
|
352
|
+
uint8_t keys[48];
|
|
353
|
+
SSL_CTX_get_tlsext_ticket_keys(o->ctx, keys, sizeof keys);
|
|
354
|
+
return js_new_buffer_from_bytes(ctx, keys, sizeof keys);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/* tlsContextSetSessions(context, timeout | null, sessionIdContext | null): how long a session can
|
|
358
|
+
* be resumed (seconds), and the context its id is valid in */
|
|
359
|
+
PRIMITIVE(js_tls_context_set_sessions) {
|
|
360
|
+
UNUSED_ARGS;
|
|
361
|
+
TlsContextObject *o = context_arg(ARG(0));
|
|
362
|
+
if (!o) return js_throw_type_error(ctx, "tlsContextSetSessions: a context expected");
|
|
363
|
+
if (js_is_number(ARG(1))) SSL_CTX_set_timeout(o->ctx, (uint32_t)js_as_number(ARG(1)));
|
|
364
|
+
char *sid = string_dup(ctx, ARG(2));
|
|
365
|
+
if (sid) {
|
|
366
|
+
/* OpenSSL's limit, which Node passes through */
|
|
367
|
+
size_t n = strlen(sid);
|
|
368
|
+
SSL_CTX_set_session_id_context(o->ctx, (const uint8_t *)sid, n > SSL_MAX_SID_CTX_LENGTH ? SSL_MAX_SID_CTX_LENGTH : n);
|
|
369
|
+
free(sid);
|
|
370
|
+
}
|
|
371
|
+
return JS_UNDEFINED;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/* tlsPkcs12(der, password | null) → [private key (PKCS#8 DER) | null, certificate (DER) | null,
|
|
375
|
+
* [the other certificates' DER, …]] | the reason it can't be read (OpenSSL's words) */
|
|
376
|
+
PRIMITIVE(js_tls_pkcs12) {
|
|
377
|
+
UNUSED_ARGS;
|
|
378
|
+
const uint8_t *p;
|
|
379
|
+
size_t n;
|
|
380
|
+
if (!bytes_arg(ARG(0), &p, &n)) return js_throw_type_error(ctx, "tlsPkcs12: bytes expected");
|
|
381
|
+
char *password = string_dup(ctx, ARG(1));
|
|
382
|
+
PKCS12 *p12 = d2i_PKCS12(NULL, &p, (long)n);
|
|
383
|
+
EVP_PKEY *pkey = NULL;
|
|
384
|
+
X509 *cert = NULL;
|
|
385
|
+
STACK_OF(X509) *others = NULL;
|
|
386
|
+
bool ok = p12 && PKCS12_parse(p12, password, &pkey, &cert, &others);
|
|
387
|
+
if (password) {
|
|
388
|
+
memset(password, 0, strlen(password));
|
|
389
|
+
free(password);
|
|
390
|
+
}
|
|
391
|
+
PKCS12_free(p12);
|
|
392
|
+
if (!ok) {
|
|
393
|
+
const char *reason = ERR_reason_error_string(ERR_peek_last_error());
|
|
394
|
+
ERR_clear_error();
|
|
395
|
+
return js_new_string_cstr(ctx, reason ? reason : "Unknown error");
|
|
396
|
+
}
|
|
397
|
+
JSValue parts[3] = { JS_NULL, JS_NULL, JS_NULL };
|
|
398
|
+
if (pkey) {
|
|
399
|
+
CBB cbb;
|
|
400
|
+
uint8_t *der;
|
|
401
|
+
size_t len;
|
|
402
|
+
if (CBB_init(&cbb, 0) && EVP_marshal_private_key(&cbb, pkey) && CBB_finish(&cbb, &der, &len)) {
|
|
403
|
+
parts[0] = js_new_buffer_from_bytes(ctx, der, len);
|
|
404
|
+
OPENSSL_cleanse(der, len);
|
|
405
|
+
OPENSSL_free(der);
|
|
406
|
+
} else {
|
|
407
|
+
CBB_cleanup(&cbb);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
uint8_t *der = NULL;
|
|
411
|
+
int len;
|
|
412
|
+
if (cert && (len = i2d_X509(cert, &der)) > 0) parts[1] = js_new_buffer_from_bytes(ctx, der, (size_t)len);
|
|
413
|
+
OPENSSL_free(der);
|
|
414
|
+
size_t count = others ? sk_X509_num(others) : 0;
|
|
415
|
+
parts[2] = js_new_array(ctx, 0);
|
|
416
|
+
for (size_t i = 0; i < count; i++) {
|
|
417
|
+
der = NULL;
|
|
418
|
+
if ((len = i2d_X509(sk_X509_value(others, i), &der)) > 0 &&
|
|
419
|
+
js_array_append(ctx, parts[2], js_new_buffer_from_bytes(ctx, der, (size_t)len)) < 0) {
|
|
420
|
+
OPENSSL_free(der);
|
|
421
|
+
parts[2] = JS_EXCEPTION;
|
|
422
|
+
break;
|
|
423
|
+
}
|
|
424
|
+
OPENSSL_free(der);
|
|
425
|
+
}
|
|
426
|
+
EVP_PKEY_free(pkey);
|
|
427
|
+
X509_free(cert);
|
|
428
|
+
sk_X509_pop_free(others, X509_free);
|
|
429
|
+
ERR_clear_error();
|
|
430
|
+
return js_is_exception(parts[2]) ? JS_EXCEPTION : js_new_array_from(ctx, parts, 3);
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
/* ---- Certificates (crypto.X509Certificate's checks, as OpenSSL's) ---------------------------------- */
|
|
434
|
+
|
|
435
|
+
/* x509Check(der, kind, value, flags) → the name matched (kind 0: a host, 1: an email address,
|
|
436
|
+
* 2: an IP address) or undefined; flags are X509_CHECK_FLAG_*'s */
|
|
437
|
+
PRIMITIVE(js_x509_check) {
|
|
438
|
+
UNUSED_ARGS;
|
|
439
|
+
X509 *x = x509_arg(ARG(0));
|
|
440
|
+
char *value = string_dup(ctx, ARG(2));
|
|
441
|
+
if (!x || !value || !js_is_number(ARG(1))) {
|
|
442
|
+
X509_free(x);
|
|
443
|
+
free(value);
|
|
444
|
+
ERR_clear_error();
|
|
445
|
+
return js_throw_type_error(ctx, "x509Check: a certificate, a kind and a value expected");
|
|
446
|
+
}
|
|
447
|
+
unsigned flags = js_is_number(ARG(3)) ? (unsigned)js_as_number(ARG(3)) : 0;
|
|
448
|
+
size_t n = strlen(value);
|
|
449
|
+
char *peer = NULL;
|
|
450
|
+
int r;
|
|
451
|
+
switch ((int)js_as_number(ARG(1))) {
|
|
452
|
+
case 0: r = X509_check_host(x, value, n, flags, &peer); break;
|
|
453
|
+
case 1: r = X509_check_email(x, value, n, flags); break;
|
|
454
|
+
default: r = X509_check_ip_asc(x, value, flags); break;
|
|
455
|
+
}
|
|
456
|
+
JSValue out = JS_UNDEFINED;
|
|
457
|
+
if (r == 1) out = js_new_string_utf8(ctx, peer ? peer : value, strlen(peer ? peer : value));
|
|
458
|
+
OPENSSL_free(peer);
|
|
459
|
+
free(value);
|
|
460
|
+
X509_free(x);
|
|
461
|
+
ERR_clear_error();
|
|
462
|
+
return out;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
/* x509CheckIssued(der, issuerDer) → whether the issuer's name, key identifier and key usage fit (X509_check_issued) */
|
|
466
|
+
PRIMITIVE(js_x509_check_issued) {
|
|
467
|
+
UNUSED_ARGS;
|
|
468
|
+
X509 *x = x509_arg(ARG(0)), *issuer = x509_arg(ARG(1));
|
|
469
|
+
bool ok = x && issuer && X509_check_issued(issuer, x) == X509_V_OK;
|
|
470
|
+
X509_free(x);
|
|
471
|
+
X509_free(issuer);
|
|
472
|
+
ERR_clear_error();
|
|
473
|
+
return js_bool(ok);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/* x509CheckKey(der, key handle) → for a public key, whether it signed the certificate; for a
|
|
477
|
+
* private one, whether it is the certificate's */
|
|
478
|
+
PRIMITIVE(js_x509_check_key) {
|
|
479
|
+
UNUSED_ARGS;
|
|
480
|
+
X509 *x = x509_arg(ARG(0));
|
|
481
|
+
JSKeyData *k = js_key_data(ARG(1));
|
|
482
|
+
EVP_PKEY *pkey = k ? pkey_of(k) : NULL;
|
|
483
|
+
bool ok = x && pkey && (k->type == JS_KEY_PRIVATE ? X509_check_private_key(x, pkey) : X509_verify(x, pkey)) == 1;
|
|
484
|
+
EVP_PKEY_free(pkey);
|
|
485
|
+
X509_free(x);
|
|
486
|
+
ERR_clear_error();
|
|
487
|
+
return js_bool(ok);
|
|
488
|
+
}
|
|
489
|
+
|
|
294
490
|
/* ---- Connections -------------------------------------------------------------------------------- */
|
|
295
491
|
|
|
296
492
|
typedef struct TlsConnData {
|
|
@@ -301,10 +497,13 @@ typedef struct TlsConnData {
|
|
|
301
497
|
uint32_t handshakes;
|
|
302
498
|
bool in_handshake;
|
|
303
499
|
SSL_SESSION *new_session; /* the last session (or ticket) the peer gave: tlsRun reports it once */
|
|
500
|
+
SSL_SESSION *offered_session; /* a client's, to resume */
|
|
304
501
|
bool session_reported;
|
|
305
502
|
uint8_t *alpn; /* a server's protocols, in the wire format */
|
|
306
503
|
size_t alpn_len;
|
|
307
504
|
bool alpn_strict;
|
|
505
|
+
bool keylog_on;
|
|
506
|
+
JSBytesOut keylog; /* NSS key log lines since tlsRun last reported them */
|
|
308
507
|
} TlsConnData;
|
|
309
508
|
|
|
310
509
|
typedef struct TlsConnObject {
|
|
@@ -346,7 +545,9 @@ static void conn_finalize(JSRuntime *rt, JSCell *cell) {
|
|
|
346
545
|
if (!d) return;
|
|
347
546
|
SSL_free(d->ssl); /* and its BIOs */
|
|
348
547
|
SSL_SESSION_free(d->new_session);
|
|
548
|
+
SSL_SESSION_free(d->offered_session);
|
|
349
549
|
free(d->alpn);
|
|
550
|
+
free(d->keylog.p);
|
|
350
551
|
free(d);
|
|
351
552
|
}
|
|
352
553
|
|
|
@@ -419,7 +620,7 @@ PRIMITIVE(js_tls_new) {
|
|
|
419
620
|
if (bytes_arg(ARG(4), &sp, &spn)) {
|
|
420
621
|
SSL_SESSION *s = SSL_SESSION_from_bytes(sp, spn, cx->ctx);
|
|
421
622
|
if (s) SSL_set_session(d->ssl, s);
|
|
422
|
-
|
|
623
|
+
d->offered_session = s; /* the reference from_bytes gave */
|
|
423
624
|
}
|
|
424
625
|
}
|
|
425
626
|
ERR_clear_error();
|
|
@@ -437,7 +638,8 @@ static bool fatal(int e) {
|
|
|
437
638
|
|
|
438
639
|
/* tlsRun(connection, records | null, data | null) → [records out | null, data received | null,
|
|
439
640
|
* bytes of `data` taken, state (1 established, 2 failed, 4 the peer's close_notify, 8 a new
|
|
440
|
-
* session to report), error ([library, reason, name] | 0), handshakes finished
|
|
641
|
+
* session to report), error ([library, reason, name] | 0), handshakes finished, key log lines |
|
|
642
|
+
* null]: feeds the
|
|
441
643
|
* engine what it was given and runs it until it can't go on. `data` is taken once the handshake
|
|
442
644
|
* is done (and not during a renegotiation); what isn't is given again later. */
|
|
443
645
|
PRIMITIVE(js_tls_run) {
|
|
@@ -515,16 +717,18 @@ PRIMITIVE(js_tls_run) {
|
|
|
515
717
|
d->session_reported = true;
|
|
516
718
|
state |= TLS_NEW_SESSION;
|
|
517
719
|
}
|
|
720
|
+
JSValue keylog = bytes_or_null(ctx, &d->keylog);
|
|
721
|
+
d->keylog = (JSBytesOut){ 0 };
|
|
518
722
|
JSBytesOut out = { 0 };
|
|
519
723
|
const uint8_t *p;
|
|
520
724
|
size_t n;
|
|
521
725
|
if (BIO_mem_contents(d->out, &p, &n) && n) out_append(&out, p, n);
|
|
522
726
|
BIO_reset(d->out);
|
|
523
727
|
ERR_clear_error();
|
|
524
|
-
JSValue items[
|
|
728
|
+
JSValue items[7] = { JS_NULL, JS_NULL, js_number((double)taken), js_int32(state), err, js_number(d->handshakes), keylog };
|
|
525
729
|
items[0] = bytes_or_null(ctx, &out);
|
|
526
730
|
items[1] = bytes_or_null(ctx, &app);
|
|
527
|
-
return js_new_array_from(ctx, items,
|
|
731
|
+
return js_new_array_from(ctx, items, 7);
|
|
528
732
|
}
|
|
529
733
|
|
|
530
734
|
/* tlsShutdown(connection) → the records to send | null: our close_notify; reading goes on until
|
|
@@ -605,8 +809,9 @@ PRIMITIVE(js_tls_session) {
|
|
|
605
809
|
UNUSED_ARGS;
|
|
606
810
|
TlsConnData *d = conn_arg(ARG(0));
|
|
607
811
|
if (!d || !d->established) return JS_UNDEFINED;
|
|
812
|
+
/* OpenSSL's, which Node returns: a TLS 1.3 session before its tickets too (it won't resume) */
|
|
608
813
|
SSL_SESSION *s = d->new_session ? d->new_session : SSL_get_session(d->ssl);
|
|
609
|
-
if (!s
|
|
814
|
+
if (!s) return JS_UNDEFINED;
|
|
610
815
|
uint8_t *p;
|
|
611
816
|
size_t n;
|
|
612
817
|
if (!SSL_SESSION_to_bytes(s, &p, &n)) {
|
|
@@ -618,6 +823,21 @@ PRIMITIVE(js_tls_session) {
|
|
|
618
823
|
return v;
|
|
619
824
|
}
|
|
620
825
|
|
|
826
|
+
/* tlsTicket(connection) → Buffer | undefined: the session ticket a client was given */
|
|
827
|
+
PRIMITIVE(js_tls_ticket) {
|
|
828
|
+
UNUSED_ARGS;
|
|
829
|
+
TlsConnData *d = conn_arg(ARG(0));
|
|
830
|
+
if (!d) return JS_UNDEFINED;
|
|
831
|
+
/* resumed, a TLS 1.3 session is a copy without the ticket: the one offered had it */
|
|
832
|
+
SSL_SESSION *s = d->new_session ? d->new_session
|
|
833
|
+
: SSL_session_reused(d->ssl) && d->offered_session ? d->offered_session : SSL_get_session(d->ssl);
|
|
834
|
+
const uint8_t *p;
|
|
835
|
+
size_t n;
|
|
836
|
+
if (!s || !SSL_SESSION_has_ticket(s)) return JS_UNDEFINED;
|
|
837
|
+
SSL_SESSION_get0_ticket(s, &p, &n);
|
|
838
|
+
return js_new_buffer_from_bytes(ctx, p, n);
|
|
839
|
+
}
|
|
840
|
+
|
|
621
841
|
/* tlsExportKeyingMaterial(connection, length, label, context | undefined) → Buffer | null (RFC 5705) */
|
|
622
842
|
PRIMITIVE(js_tls_export_keying_material) {
|
|
623
843
|
UNUSED_ARGS;
|
|
@@ -670,9 +890,35 @@ PRIMITIVE(js_tls_ciphers) {
|
|
|
670
890
|
|
|
671
891
|
/* tlsSetNoRenegotiation(connection): a server's requests to renegotiate are refused (BoringSSL
|
|
672
892
|
* renegotiates only as a client, when a server asks; it never starts one) */
|
|
893
|
+
static void on_keylog(const SSL *ssl, const char *line) {
|
|
894
|
+
TlsConnData *d = SSL_get_app_data(ssl);
|
|
895
|
+
if (!d || !d->keylog_on) return;
|
|
896
|
+
out_append(&d->keylog, line, strlen(line));
|
|
897
|
+
out_append(&d->keylog, "\n", 1);
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
/* tlsEnableKeylog(connection): its key log lines come with tlsRun's results (the 'keylog' event) */
|
|
901
|
+
PRIMITIVE(js_tls_enable_keylog) {
|
|
902
|
+
UNUSED_ARGS;
|
|
903
|
+
TlsConnData *d = conn_arg(ARG(0));
|
|
904
|
+
if (!d) return JS_UNDEFINED;
|
|
905
|
+
d->keylog_on = true;
|
|
906
|
+
/* the context's: BoringSSL forms the lines only for a context that has a callback */
|
|
907
|
+
SSL_CTX_set_keylog_callback(SSL_get_SSL_CTX(d->ssl), on_keylog);
|
|
908
|
+
return JS_UNDEFINED;
|
|
909
|
+
}
|
|
910
|
+
|
|
673
911
|
PRIMITIVE(js_tls_set_no_renegotiation) {
|
|
674
912
|
UNUSED_ARGS;
|
|
675
913
|
TlsConnData *d = conn_arg(ARG(0));
|
|
676
914
|
if (d && !d->server) SSL_set_renegotiate_mode(d->ssl, ssl_renegotiate_never);
|
|
677
915
|
return JS_UNDEFINED;
|
|
678
916
|
}
|
|
917
|
+
|
|
918
|
+
/* tlsSetMaxSendFragment(connection, size): the largest record's plaintext (512 to 16384) */
|
|
919
|
+
PRIMITIVE(js_tls_set_max_send_fragment) {
|
|
920
|
+
UNUSED_ARGS;
|
|
921
|
+
TlsConnData *d = conn_arg(ARG(0));
|
|
922
|
+
if (d && js_is_number(ARG(1))) SSL_set_max_send_fragment(d->ssl, (size_t)js_as_number(ARG(1)));
|
|
923
|
+
return JS_UNDEFINED;
|
|
924
|
+
}
|
package/runtime/src/function.c
CHANGED
|
@@ -222,10 +222,38 @@ JSValue js_get_prototype_from_constructor(JSContext *ctx, JSValue new_target, JS
|
|
|
222
222
|
return realm ? realm->intrinsics[fallback] : JS_EXCEPTION;
|
|
223
223
|
}
|
|
224
224
|
|
|
225
|
+
/* The root shape of the objects `new f` makes, with at least `slots` inline slots: kept on f, and
|
|
226
|
+
* grown by learn_instance_slots to what its instances end up holding. */
|
|
227
|
+
static JSShape *instance_root(JSContext *ctx, JSFunction *f, JSValue proto, uint16_t slots) {
|
|
228
|
+
JSShape *s = f->instance_shape;
|
|
229
|
+
if (JS_UNLIKELY(!s || !js_same_bits(s->proto, proto) || s->inline_cap < slots)) {
|
|
230
|
+
s = js_shape_root(ctx, &js_class_object, proto, slots);
|
|
231
|
+
js_store_ptr(ctx, &f->obj.cell, &f->instance_shape, s);
|
|
232
|
+
}
|
|
233
|
+
return s;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/* Slack tracking: when the constructors (a class's and its bases') left `v` with more properties
|
|
237
|
+
* than its root shape has inline slots, the next instances get room for them all. A derived
|
|
238
|
+
* class's `this` is made by its base, which can't count its subclasses' properties; the rest
|
|
239
|
+
* would sit out of line, where an inline cache's hit isn't inlined. */
|
|
240
|
+
static void learn_instance_slots(JSContext *ctx, JSFunction *f, JSValue v) {
|
|
241
|
+
JSShape *root = f->instance_shape;
|
|
242
|
+
if (!root || !js_is_object(v)) return;
|
|
243
|
+
JSShape *s = js_as_object(v)->shape;
|
|
244
|
+
if (JS_LIKELY(s->prop_count <= root->inline_cap || root->inline_cap >= JS_MAX_INLINE_SLOTS)) return;
|
|
245
|
+
JSShape *r = s;
|
|
246
|
+
while (r->parent) r = r->parent;
|
|
247
|
+
if (r != root) return; /* not made from it: an object the constructor returned, or a dictionary */
|
|
248
|
+
JSShape *grown = js_shape_root(ctx, &js_class_object, root->proto, (uint16_t)(s->prop_count < JS_MAX_INLINE_SLOTS ? s->prop_count : JS_MAX_INLINE_SLOTS));
|
|
249
|
+
js_store_ptr(ctx, &f->obj.cell, &f->instance_shape, grown);
|
|
250
|
+
}
|
|
251
|
+
|
|
225
252
|
JSValue js_create_from_constructor(JSContext *ctx, JSValue new_target, JSIntrinsic fallback) {
|
|
226
253
|
JSValue proto = js_get_prototype_from_constructor(ctx, new_target, fallback);
|
|
227
254
|
if (js_is_exception(proto)) return JS_EXCEPTION;
|
|
228
|
-
return js_new_object_proto(ctx, proto, JS_DEFAULT_INLINE_SLOTS);
|
|
255
|
+
if (!js_is_function(new_target)) return js_new_object_proto(ctx, proto, JS_DEFAULT_INLINE_SLOTS);
|
|
256
|
+
return js_object_value(js_alloc_object(ctx, JS_CELL_OBJECT, instance_root(ctx, js_as_function(new_target), proto, JS_DEFAULT_INLINE_SLOTS)));
|
|
229
257
|
}
|
|
230
258
|
|
|
231
259
|
JSValue js_new_instance(JSContext *ctx, JSValue fv, uint16_t slots, JSPropCache *ic) {
|
|
@@ -234,26 +262,25 @@ JSValue js_new_instance(JSContext *ctx, JSValue fv, uint16_t slots, JSPropCache
|
|
|
234
262
|
: js_get_prop(ctx, fv, JS_ATOM(prototype), ic);
|
|
235
263
|
if (js_is_exception(proto)) return JS_EXCEPTION;
|
|
236
264
|
if (!js_is_object(proto)) proto = ctx->intrinsics[JS_INTRINSIC_OBJECT_PROTOTYPE]; /* OrdinaryCreateFromConstructor's fallback */
|
|
237
|
-
|
|
238
|
-
JSShape *s = f->instance_shape;
|
|
239
|
-
if (JS_UNLIKELY(!s || !js_same_bits(s->proto, proto) || s->inline_cap != slots)) {
|
|
240
|
-
s = js_shape_root(ctx, &js_class_object, proto, slots);
|
|
241
|
-
js_store_ptr(ctx, &f->obj.cell, &f->instance_shape, s);
|
|
242
|
-
}
|
|
243
|
-
return js_object_value(js_alloc_object(ctx, JS_CELL_OBJECT, s));
|
|
265
|
+
return js_object_value(js_alloc_object(ctx, JS_CELL_OBJECT, instance_root(ctx, js_as_function(fv), proto, slots)));
|
|
244
266
|
}
|
|
245
267
|
|
|
246
268
|
JSValue js_construct(JSContext *ctx, JSValue f, uint32_t argc, const JSValue *argv, JSValue new_target, const char *callee_text) {
|
|
247
269
|
if (JS_UNLIKELY(!js_is_constructor(f))) return not_callable(ctx, f, callee_text, "constructor");
|
|
248
270
|
JSFunction *fn = js_as_function(f);
|
|
271
|
+
bool outermost = js_is_undefined(new_target) || js_same_bits(new_target, f); /* not a super() */
|
|
249
272
|
if (js_is_undefined(new_target)) new_target = f;
|
|
250
|
-
if (!(fn->flags & JS_FN_ORDINARY)) /* builtins create their own object; a derived constructor gets it from super() */
|
|
251
|
-
|
|
273
|
+
if (!(fn->flags & JS_FN_ORDINARY)) { /* builtins create their own object; a derived constructor gets it from super() */
|
|
274
|
+
JSValue r = fn->entry(fn->flags & JS_FN_PROXY ? ctx : fn->realm, f, JS_UNDEFINED, argc, argv, new_target);
|
|
275
|
+
if (outermost && (fn->flags & JS_FN_DERIVED) && !js_is_exception(r)) learn_instance_slots(ctx, fn, r);
|
|
276
|
+
return r;
|
|
277
|
+
}
|
|
252
278
|
/* [[Construct]] of an ordinary function (§10.2.2): this = a new object; an object result wins */
|
|
253
279
|
JSValue this_val = js_create_from_constructor(fn->realm, new_target, JS_INTRINSIC_OBJECT_PROTOTYPE);
|
|
254
280
|
if (js_is_exception(this_val)) return JS_EXCEPTION;
|
|
255
281
|
JSValue r = fn->entry(fn->realm, f, this_val, argc, argv, new_target);
|
|
256
282
|
if (js_is_exception(r)) return JS_EXCEPTION;
|
|
283
|
+
if (outermost) learn_instance_slots(ctx, fn, this_val);
|
|
257
284
|
return js_is_object(r) ? r : this_val;
|
|
258
285
|
}
|
|
259
286
|
|