From 1b0b7ae7c904401893be5a63eb5a4466b9d3e6b9 Mon Sep 17 00:00:00 2001 From: "Node.js GitHub Bot" Date: Sun, 2 Aug 2026 06:56:28 -0400 Subject: [PATCH 01/11] tools: bump nixpkgs pins - nixpkgs-unstable to bcdf747749ad31ab043d6341a18699a8b9b62ef0 - nixpkgs-26.05-darwin to 329c3d2af6d1b618705150ea39f72c15eb4e613e PR-URL: https://github.com/nodejs/node/pull/64747 Reviewed-By: Aviv Keller Reviewed-By: Colin Ihrig Reviewed-By: Antoine du Hamel --- tools/nix/pkgs-26.05.nix | 4 ++-- tools/nix/pkgs.nix | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/nix/pkgs-26.05.nix b/tools/nix/pkgs-26.05.nix index e0697c7a99b9..7a1167a798d1 100644 --- a/tools/nix/pkgs-26.05.nix +++ b/tools/nix/pkgs-26.05.nix @@ -1,10 +1,10 @@ arg: let repo = "https://github.com/NixOS/nixpkgs"; - rev = "fc51889f81924f15fba77a3c0b79cfb3f78fe0d4"; + rev = "329c3d2af6d1b618705150ea39f72c15eb4e613e"; nixpkgs = import (builtins.fetchTarball { url = "${repo}/archive/${rev}.tar.gz"; - sha256 = "16397a8zmfj9gygm0yj4fhp9sj6hw954k246jyzsi0xpgwdzr76h"; + sha256 = "0hkr1j8mm50gpxd55y85vq85bxxww8rhwf6mkvkrg0qw21dmvlmd"; }) arg; in # Unstable channel no longer supports Intel architecture for macOS. We can use the 26.05 channel diff --git a/tools/nix/pkgs.nix b/tools/nix/pkgs.nix index 54fde3a51b80..9b999f68c29c 100644 --- a/tools/nix/pkgs.nix +++ b/tools/nix/pkgs.nix @@ -1,10 +1,10 @@ arg: let repo = "https://github.com/NixOS/nixpkgs"; - rev = "20535e48e12c86043b577b8518234ff5dbb26957"; + rev = "bcdf747749ad31ab043d6341a18699a8b9b62ef0"; nixpkgs = import (builtins.fetchTarball { url = "${repo}/archive/${rev}.tar.gz"; - sha256 = "1dmdschkpmhjp67rhsig7k2qhgd918j5g30s6yxmjljqsxh2vlh9"; + sha256 = "10vv47y0b3k3aq2l52rqd5qzk50a7jbdcamd8rwc0g02mm6blxn8"; }) arg; in # Unstable channel no longer supports Intel architecture for macOS. We can use the 26.05 channel From 93b1088401399ac4c975ccc93944674b388ba80d Mon Sep 17 00:00:00 2001 From: "Node.js GitHub Bot" Date: Sun, 2 Aug 2026 06:56:37 -0400 Subject: [PATCH 02/11] crypto: update root certificates to NSS 3.125 This is the certdata.txt[0] from NSS 3.125. This is the version of NSS that shipped in Firefox 153.0 on 2026-07-21. Certificates removed: - Entrust Root Certification Authority - SecureSign Root CA12 [0] https://raw.githubusercontent.com/nss-dev/nss/refs/tags/NSS_3_125_RTM/lib/ckfw/builtins/certdata.txt PR-URL: https://github.com/nodejs/node/pull/64746 Reviewed-By: Antoine du Hamel Reviewed-By: Luigi Pinca Reviewed-By: Yagiz Nizipli Reviewed-By: Colin Ihrig --- src/node_root_certs.h | 47 ----- tools/certdata.txt | 481 +++++++++++++++--------------------------- 2 files changed, 170 insertions(+), 358 deletions(-) diff --git a/src/node_root_certs.h b/src/node_root_certs.h index 53ac2034c8a8..48d2fc5cb7d1 100644 --- a/src/node_root_certs.h +++ b/src/node_root_certs.h @@ -1,31 +1,5 @@ #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS -/* Entrust Root Certification Authority */ -"-----BEGIN CERTIFICATE-----\n" -"MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMCVVMxFjAU\n" -"BgNVBAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0Lm5ldC9DUFMgaXMg\n" -"aW5jb3Jwb3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMWKGMpIDIwMDYgRW50cnVzdCwg\n" -"SW5jLjEtMCsGA1UEAxMkRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4X\n" -"DTA2MTEyNzIwMjM0MloXDTI2MTEyNzIwNTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQK\n" -"Ew1FbnRydXN0LCBJbmMuMTkwNwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29y\n" -"cG9yYXRlZCBieSByZWZlcmVuY2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4x\n" -"LTArBgNVBAMTJEVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJ\n" -"KoZIhvcNAQEBBQADggEPADCCAQoCggEBALaVtkNC+sZtKm9I35RMOVcF7sN5EUFoNu3s/poB\n" -"j6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYszA9u3g3s+IIRe7bJWKKf44LlAcTfFy0cOlypo\n" -"wCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOwwCj0Yzfv9KlmaI5UXLEWeH25DeW0MXJj+\n" -"SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGIrb68j6xSlkuqUY3kEzEZ6E5Nn9uss2rV\n" -"vDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi94DkZfs0Nw4pgHBNrziGLp5/V6+eF67rHMsoIV+2\n" -"HNjnogQi+dPa2MsCAwEAAaOBsDCBrTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB\n" -"/zArBgNVHRAEJDAigA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1MzQyWjAfBgNVHSME\n" -"GDAWgBRokORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DHhmak8fdLQ/uE\n" -"vW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUAA4IBAQCT\n" -"1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9tO1KzKtvn1ISMY/YP\n" -"yyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6ZuaAGAT/3B+XxFNSRuzFVJ7yVTa\n" -"v52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE\n" -"2jTSW3iDVuycNsMm4hH2Z0kdkquM++v/eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPc\n" -"j2A781q0tHuu2guQOHXvgR1m0vdXcDazv/wor3ElhVsT/h5/WrQ8\n" -"-----END CERTIFICATE-----", - /* COMODO ECC Certification Authority */ "-----BEGIN CERTIFICATE-----\n" "MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTELMAkGA1UE\n" @@ -2641,27 +2615,6 @@ "Jsas7a5wFsWqynKKTbDPAYsDP27X\n" "-----END CERTIFICATE-----", -/* SecureSign Root CA12 */ -"-----BEGIN CERTIFICATE-----\n" -"MIIDcjCCAlqgAwIBAgIUZvnHwa/swlG07VOX5uaCwysckBYwDQYJKoZIhvcNAQELBQAwUTEL\n" -"MAkGA1UEBhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28uLCBMdGQuMR0wGwYD\n" -"VQQDExRTZWN1cmVTaWduIFJvb3QgQ0ExMjAeFw0yMDA0MDgwNTM2NDZaFw00MDA0MDgwNTM2\n" -"NDZaMFExCzAJBgNVBAYTAkpQMSMwIQYDVQQKExpDeWJlcnRydXN0IEphcGFuIENvLiwgTHRk\n" -"LjEdMBsGA1UEAxMUU2VjdXJlU2lnbiBSb290IENBMTIwggEiMA0GCSqGSIb3DQEBAQUAA4IB\n" -"DwAwggEKAoIBAQC6OcE3emhFKxS06+QT61d1I02PJC0W6K6OyX2kVzsqdiUzg2zqMoqUm048\n" -"luT9Ub+ZyZN+v/mtp7JIKwccJ/VMvHASd6SFVLX9kHrko+RRWAPNEHl57muTH2SOa2SroxPj\n" -"cf59q5zdJ1M3s6oYwlkm7Fsf0uZlfO+TvdhYXAvA42VvPMfKWeP+bl+sg779XSVOKik71gur\n" -"FzJ4pOE+lEa+Ym6b3kaosRbnhW70CEBFEaCeVESE99g2zvVQR9wsMJvuwPWW0v4JhscGWa5P\n" -"ro4RmHvzC1KqYiaqId+OJTN5lxZJjfU+1UefNzFJM3IFTQy2VYzxV4+Kh9GtxRESOaCtAgMB\n" -"AAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRXNPN0\n" -"zwRL1SXm8UC2LEzZLemgrTANBgkqhkiG9w0BAQsFAAOCAQEAPrvbFxbS8hQBICw4g0utvsqF\n" -"epq2m2um4fylOqyttCg6r9cBg0krY6LdmmQOmFxv3Y67ilQiLUoT865AQ9tPkbeGGuwAtEGB\n" -"pE/6aouIs3YIcipJQMPTw4WJmBClnW8Zt7vPemVV2zfrPIpyMpcemik+rY3moxtt9XUa5rBo\n" -"uVui7mlHJzWhhpmA8zNL4WukJsPvdFlseqJkth5Ew1DgDzk9qTPxpfPSvWKErI4cqc1avTc7\n" -"bgoitPQV55FYxTpE05Uo2cBl6XLK0A+9H7MV2anjpEcJnuDLN/v9vZfVvhgaaaI5gdka9at/\n" -"yOPiZwud9AzqVN/Ssq+xIvEg37xEHA==\n" -"-----END CERTIFICATE-----", - /* SecureSign Root CA14 */ "-----BEGIN CERTIFICATE-----\n" "MIIFcjCCA1qgAwIBAgIUZNtaDCBO6Ncpd8hQJ6JaJ90t8sswDQYJKoZIhvcNAQEMBQAwUTEL\n" diff --git a/tools/certdata.txt b/tools/certdata.txt index 97b118f68797..fafc33ddeea5 100644 --- a/tools/certdata.txt +++ b/tools/certdata.txt @@ -371,179 +371,6 @@ CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE -# -# Certificate "Entrust Root Certification Authority" -# -# Issuer: CN=Entrust Root Certification Authority,OU="(c) 2006 Entrust, Inc.",OU=www.entrust.net/CPS is incorporated by reference,O="Entrust, Inc.",C=US -# Serial Number: 1164660820 (0x456b5054) -# Subject: CN=Entrust Root Certification Authority,OU="(c) 2006 Entrust, Inc.",OU=www.entrust.net/CPS is incorporated by reference,O="Entrust, Inc.",C=US -# Not Valid Before: Mon Nov 27 20:23:42 2006 -# Not Valid After : Fri Nov 27 20:53:42 2026 -# Fingerprint (SHA-256): 73:C1:76:43:4F:1B:C6:D5:AD:F4:5B:0E:76:E7:27:28:7C:8D:E5:76:16:C1:E6:E6:14:1A:2B:2C:BC:7D:8E:4C -# Fingerprint (SHA1): B3:1E:B1:B7:40:E3:6C:84:02:DA:DC:37:D4:4D:F5:D4:67:49:52:F9 -CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE -CKA_TOKEN CK_BBOOL CK_TRUE -CKA_PRIVATE CK_BBOOL CK_FALSE -CKA_MODIFIABLE CK_BBOOL CK_FALSE -CKA_LABEL UTF8 "Entrust Root Certification Authority" -CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509 -CKA_SUBJECT MULTILINE_OCTAL -\060\201\260\061\013\060\011\006\003\125\004\006\023\002\125\123 -\061\026\060\024\006\003\125\004\012\023\015\105\156\164\162\165 -\163\164\054\040\111\156\143\056\061\071\060\067\006\003\125\004 -\013\023\060\167\167\167\056\145\156\164\162\165\163\164\056\156 -\145\164\057\103\120\123\040\151\163\040\151\156\143\157\162\160 -\157\162\141\164\145\144\040\142\171\040\162\145\146\145\162\145 -\156\143\145\061\037\060\035\006\003\125\004\013\023\026\050\143 -\051\040\062\060\060\066\040\105\156\164\162\165\163\164\054\040 -\111\156\143\056\061\055\060\053\006\003\125\004\003\023\044\105 -\156\164\162\165\163\164\040\122\157\157\164\040\103\145\162\164 -\151\146\151\143\141\164\151\157\156\040\101\165\164\150\157\162 -\151\164\171 -END -CKA_ID UTF8 "0" -CKA_ISSUER MULTILINE_OCTAL -\060\201\260\061\013\060\011\006\003\125\004\006\023\002\125\123 -\061\026\060\024\006\003\125\004\012\023\015\105\156\164\162\165 -\163\164\054\040\111\156\143\056\061\071\060\067\006\003\125\004 -\013\023\060\167\167\167\056\145\156\164\162\165\163\164\056\156 -\145\164\057\103\120\123\040\151\163\040\151\156\143\157\162\160 -\157\162\141\164\145\144\040\142\171\040\162\145\146\145\162\145 -\156\143\145\061\037\060\035\006\003\125\004\013\023\026\050\143 -\051\040\062\060\060\066\040\105\156\164\162\165\163\164\054\040 -\111\156\143\056\061\055\060\053\006\003\125\004\003\023\044\105 -\156\164\162\165\163\164\040\122\157\157\164\040\103\145\162\164 -\151\146\151\143\141\164\151\157\156\040\101\165\164\150\157\162 -\151\164\171 -END -CKA_SERIAL_NUMBER MULTILINE_OCTAL -\002\004\105\153\120\124 -END -CKA_VALUE MULTILINE_OCTAL -\060\202\004\221\060\202\003\171\240\003\002\001\002\002\004\105 -\153\120\124\060\015\006\011\052\206\110\206\367\015\001\001\005 -\005\000\060\201\260\061\013\060\011\006\003\125\004\006\023\002 -\125\123\061\026\060\024\006\003\125\004\012\023\015\105\156\164 -\162\165\163\164\054\040\111\156\143\056\061\071\060\067\006\003 -\125\004\013\023\060\167\167\167\056\145\156\164\162\165\163\164 -\056\156\145\164\057\103\120\123\040\151\163\040\151\156\143\157 -\162\160\157\162\141\164\145\144\040\142\171\040\162\145\146\145 -\162\145\156\143\145\061\037\060\035\006\003\125\004\013\023\026 -\050\143\051\040\062\060\060\066\040\105\156\164\162\165\163\164 -\054\040\111\156\143\056\061\055\060\053\006\003\125\004\003\023 -\044\105\156\164\162\165\163\164\040\122\157\157\164\040\103\145 -\162\164\151\146\151\143\141\164\151\157\156\040\101\165\164\150 -\157\162\151\164\171\060\036\027\015\060\066\061\061\062\067\062 -\060\062\063\064\062\132\027\015\062\066\061\061\062\067\062\060 -\065\063\064\062\132\060\201\260\061\013\060\011\006\003\125\004 -\006\023\002\125\123\061\026\060\024\006\003\125\004\012\023\015 -\105\156\164\162\165\163\164\054\040\111\156\143\056\061\071\060 -\067\006\003\125\004\013\023\060\167\167\167\056\145\156\164\162 -\165\163\164\056\156\145\164\057\103\120\123\040\151\163\040\151 -\156\143\157\162\160\157\162\141\164\145\144\040\142\171\040\162 -\145\146\145\162\145\156\143\145\061\037\060\035\006\003\125\004 -\013\023\026\050\143\051\040\062\060\060\066\040\105\156\164\162 -\165\163\164\054\040\111\156\143\056\061\055\060\053\006\003\125 -\004\003\023\044\105\156\164\162\165\163\164\040\122\157\157\164 -\040\103\145\162\164\151\146\151\143\141\164\151\157\156\040\101 -\165\164\150\157\162\151\164\171\060\202\001\042\060\015\006\011 -\052\206\110\206\367\015\001\001\001\005\000\003\202\001\017\000 -\060\202\001\012\002\202\001\001\000\266\225\266\103\102\372\306 -\155\052\157\110\337\224\114\071\127\005\356\303\171\021\101\150 -\066\355\354\376\232\001\217\241\070\050\374\367\020\106\146\056 -\115\036\032\261\032\116\306\321\300\225\210\260\311\377\061\213 -\063\003\333\267\203\173\076\040\204\136\355\262\126\050\247\370 -\340\271\100\161\067\305\313\107\016\227\052\150\300\042\225\142 -\025\333\107\331\365\320\053\377\202\113\311\255\076\336\114\333 -\220\200\120\077\011\212\204\000\354\060\012\075\030\315\373\375 -\052\131\232\043\225\027\054\105\236\037\156\103\171\155\014\134 -\230\376\110\247\305\043\107\134\136\375\156\347\036\264\366\150 -\105\321\206\203\133\242\212\215\261\343\051\200\376\045\161\210 -\255\276\274\217\254\122\226\113\252\121\215\344\023\061\031\350 -\116\115\237\333\254\263\152\325\274\071\124\161\312\172\172\177 -\220\335\175\035\200\331\201\273\131\046\302\021\376\346\223\342 -\367\200\344\145\373\064\067\016\051\200\160\115\257\070\206\056 -\236\177\127\257\236\027\256\353\034\313\050\041\137\266\034\330 -\347\242\004\042\371\323\332\330\313\002\003\001\000\001\243\201 -\260\060\201\255\060\016\006\003\125\035\017\001\001\377\004\004 -\003\002\001\006\060\017\006\003\125\035\023\001\001\377\004\005 -\060\003\001\001\377\060\053\006\003\125\035\020\004\044\060\042 -\200\017\062\060\060\066\061\061\062\067\062\060\062\063\064\062 -\132\201\017\062\060\062\066\061\061\062\067\062\060\065\063\064 -\062\132\060\037\006\003\125\035\043\004\030\060\026\200\024\150 -\220\344\147\244\246\123\200\307\206\146\244\361\367\113\103\373 -\204\275\155\060\035\006\003\125\035\016\004\026\004\024\150\220 -\344\147\244\246\123\200\307\206\146\244\361\367\113\103\373\204 -\275\155\060\035\006\011\052\206\110\206\366\175\007\101\000\004 -\020\060\016\033\010\126\067\056\061\072\064\056\060\003\002\004 -\220\060\015\006\011\052\206\110\206\367\015\001\001\005\005\000 -\003\202\001\001\000\223\324\060\260\327\003\040\052\320\371\143 -\350\221\014\005\040\251\137\031\312\173\162\116\324\261\333\320 -\226\373\124\132\031\054\014\010\367\262\274\205\250\235\177\155 -\073\122\263\052\333\347\324\204\214\143\366\017\313\046\001\221 -\120\154\364\137\024\342\223\164\300\023\236\060\072\120\343\264 -\140\305\034\360\042\104\215\161\107\254\310\032\311\351\233\232 -\000\140\023\377\160\176\137\021\115\111\033\263\025\122\173\311 -\124\332\277\235\225\257\153\232\330\236\351\361\344\103\215\342 -\021\104\072\277\257\275\203\102\163\122\213\252\273\247\051\317 -\365\144\034\012\115\321\274\252\254\237\052\320\377\177\177\332 -\175\352\261\355\060\045\301\204\332\064\322\133\170\203\126\354 -\234\066\303\046\342\021\366\147\111\035\222\253\214\373\353\377 -\172\356\205\112\247\120\200\360\247\134\112\224\056\137\005\231 -\074\122\101\340\315\264\143\317\001\103\272\234\203\334\217\140 -\073\363\132\264\264\173\256\332\013\220\070\165\357\201\035\146 -\322\367\127\160\066\263\277\374\050\257\161\045\205\133\023\376 -\036\177\132\264\074 -END -CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE -# For Server Distrust After: Sat Nov 30 23:59:59 2024 -CKA_NSS_SERVER_DISTRUST_AFTER MULTILINE_OCTAL -\062\064\061\061\063\060\062\063\065\071\065\071\132 -END -CKA_NSS_EMAIL_DISTRUST_AFTER CK_BBOOL CK_FALSE - -# Trust for "Entrust Root Certification Authority" -# Issuer: CN=Entrust Root Certification Authority,OU="(c) 2006 Entrust, Inc.",OU=www.entrust.net/CPS is incorporated by reference,O="Entrust, Inc.",C=US -# Serial Number: 1164660820 (0x456b5054) -# Subject: CN=Entrust Root Certification Authority,OU="(c) 2006 Entrust, Inc.",OU=www.entrust.net/CPS is incorporated by reference,O="Entrust, Inc.",C=US -# Not Valid Before: Mon Nov 27 20:23:42 2006 -# Not Valid After : Fri Nov 27 20:53:42 2026 -# Fingerprint (SHA-256): 73:C1:76:43:4F:1B:C6:D5:AD:F4:5B:0E:76:E7:27:28:7C:8D:E5:76:16:C1:E6:E6:14:1A:2B:2C:BC:7D:8E:4C -# Fingerprint (SHA1): B3:1E:B1:B7:40:E3:6C:84:02:DA:DC:37:D4:4D:F5:D4:67:49:52:F9 -CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST -CKA_TOKEN CK_BBOOL CK_TRUE -CKA_PRIVATE CK_BBOOL CK_FALSE -CKA_MODIFIABLE CK_BBOOL CK_FALSE -CKA_LABEL UTF8 "Entrust Root Certification Authority" -CKA_CERT_SHA1_HASH MULTILINE_OCTAL -\263\036\261\267\100\343\154\204\002\332\334\067\324\115\365\324 -\147\111\122\371 -END -CKA_CERT_MD5_HASH MULTILINE_OCTAL -\326\245\303\355\135\335\076\000\301\075\207\222\037\035\077\344 -END -CKA_ISSUER MULTILINE_OCTAL -\060\201\260\061\013\060\011\006\003\125\004\006\023\002\125\123 -\061\026\060\024\006\003\125\004\012\023\015\105\156\164\162\165 -\163\164\054\040\111\156\143\056\061\071\060\067\006\003\125\004 -\013\023\060\167\167\167\056\145\156\164\162\165\163\164\056\156 -\145\164\057\103\120\123\040\151\163\040\151\156\143\157\162\160 -\157\162\141\164\145\144\040\142\171\040\162\145\146\145\162\145 -\156\143\145\061\037\060\035\006\003\125\004\013\023\026\050\143 -\051\040\062\060\060\066\040\105\156\164\162\165\163\164\054\040 -\111\156\143\056\061\055\060\053\006\003\125\004\003\023\044\105 -\156\164\162\165\163\164\040\122\157\157\164\040\103\145\162\164 -\151\146\151\143\141\164\151\157\156\040\101\165\164\150\157\162 -\151\164\171 -END -CKA_SERIAL_NUMBER MULTILINE_OCTAL -\002\004\105\153\120\124 -END -CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR -CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_MUST_VERIFY_TRUST -CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST -CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE - # # Certificate "Certum Root CA" # @@ -21216,7 +21043,7 @@ CKA_SERIAL_NUMBER MULTILINE_OCTAL \261\211\270\161\223\017 END CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR -CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR +CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_MUST_VERIFY_TRUST CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE @@ -21334,7 +21161,7 @@ CKA_SERIAL_NUMBER MULTILINE_OCTAL \313\052\164\025\326\327 END CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR -CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR +CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_MUST_VERIFY_TRUST CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE @@ -22552,142 +22379,6 @@ CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE -# -# Certificate "SecureSign Root CA12" -# -# Issuer: CN=SecureSign Root CA12,O="Cybertrust Japan Co., Ltd.",C=JP -# Serial Number:66:f9:c7:c1:af:ec:c2:51:b4:ed:53:97:e6:e6:82:c3:2b:1c:90:16 -# Subject: CN=SecureSign Root CA12,O="Cybertrust Japan Co., Ltd.",C=JP -# Not Valid Before: Wed Apr 08 05:36:46 2020 -# Not Valid After : Sun Apr 08 05:36:46 2040 -# Fingerprint (SHA-256): 3F:03:4B:B5:70:4D:44:B2:D0:85:45:A0:20:57:DE:93:EB:F3:90:5F:CE:72:1A:CB:C7:30:C0:6D:DA:EE:90:4E -# Fingerprint (SHA1): 7A:22:1E:3D:DE:1B:06:AC:9E:C8:47:70:16:8E:3C:E5:F7:6B:06:F4 -CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE -CKA_TOKEN CK_BBOOL CK_TRUE -CKA_PRIVATE CK_BBOOL CK_FALSE -CKA_MODIFIABLE CK_BBOOL CK_FALSE -CKA_LABEL UTF8 "SecureSign Root CA12" -CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509 -CKA_SUBJECT MULTILINE_OCTAL -\060\121\061\013\060\011\006\003\125\004\006\023\002\112\120\061 -\043\060\041\006\003\125\004\012\023\032\103\171\142\145\162\164 -\162\165\163\164\040\112\141\160\141\156\040\103\157\056\054\040 -\114\164\144\056\061\035\060\033\006\003\125\004\003\023\024\123 -\145\143\165\162\145\123\151\147\156\040\122\157\157\164\040\103 -\101\061\062 -END -CKA_ID UTF8 "0" -CKA_ISSUER MULTILINE_OCTAL -\060\121\061\013\060\011\006\003\125\004\006\023\002\112\120\061 -\043\060\041\006\003\125\004\012\023\032\103\171\142\145\162\164 -\162\165\163\164\040\112\141\160\141\156\040\103\157\056\054\040 -\114\164\144\056\061\035\060\033\006\003\125\004\003\023\024\123 -\145\143\165\162\145\123\151\147\156\040\122\157\157\164\040\103 -\101\061\062 -END -CKA_SERIAL_NUMBER MULTILINE_OCTAL -\002\024\146\371\307\301\257\354\302\121\264\355\123\227\346\346 -\202\303\053\034\220\026 -END -CKA_VALUE MULTILINE_OCTAL -\060\202\003\162\060\202\002\132\240\003\002\001\002\002\024\146 -\371\307\301\257\354\302\121\264\355\123\227\346\346\202\303\053 -\034\220\026\060\015\006\011\052\206\110\206\367\015\001\001\013 -\005\000\060\121\061\013\060\011\006\003\125\004\006\023\002\112 -\120\061\043\060\041\006\003\125\004\012\023\032\103\171\142\145 -\162\164\162\165\163\164\040\112\141\160\141\156\040\103\157\056 -\054\040\114\164\144\056\061\035\060\033\006\003\125\004\003\023 -\024\123\145\143\165\162\145\123\151\147\156\040\122\157\157\164 -\040\103\101\061\062\060\036\027\015\062\060\060\064\060\070\060 -\065\063\066\064\066\132\027\015\064\060\060\064\060\070\060\065 -\063\066\064\066\132\060\121\061\013\060\011\006\003\125\004\006 -\023\002\112\120\061\043\060\041\006\003\125\004\012\023\032\103 -\171\142\145\162\164\162\165\163\164\040\112\141\160\141\156\040 -\103\157\056\054\040\114\164\144\056\061\035\060\033\006\003\125 -\004\003\023\024\123\145\143\165\162\145\123\151\147\156\040\122 -\157\157\164\040\103\101\061\062\060\202\001\042\060\015\006\011 -\052\206\110\206\367\015\001\001\001\005\000\003\202\001\017\000 -\060\202\001\012\002\202\001\001\000\272\071\301\067\172\150\105 -\053\024\264\353\344\023\353\127\165\043\115\217\044\055\026\350 -\256\216\311\175\244\127\073\052\166\045\063\203\154\352\062\212 -\224\233\116\074\226\344\375\121\277\231\311\223\176\277\371\255 -\247\262\110\053\007\034\047\365\114\274\160\022\167\244\205\124 -\265\375\220\172\344\243\344\121\130\003\315\020\171\171\356\153 -\223\037\144\216\153\144\253\243\023\343\161\376\175\253\234\335 -\047\123\067\263\252\030\302\131\046\354\133\037\322\346\145\174 -\357\223\275\330\130\134\013\300\343\145\157\074\307\312\131\343 -\376\156\137\254\203\276\375\135\045\116\052\051\073\326\013\253 -\027\062\170\244\341\076\224\106\276\142\156\233\336\106\250\261 -\026\347\205\156\364\010\100\105\021\240\236\124\104\204\367\330 -\066\316\365\120\107\334\054\060\233\356\300\365\226\322\376\011 -\206\307\006\131\256\117\256\216\021\230\173\363\013\122\252\142 -\046\252\041\337\216\045\063\171\227\026\111\215\365\076\325\107 -\237\067\061\111\063\162\005\115\014\266\125\214\361\127\217\212 -\207\321\255\305\021\022\071\240\255\002\003\001\000\001\243\102 -\060\100\060\017\006\003\125\035\023\001\001\377\004\005\060\003 -\001\001\377\060\016\006\003\125\035\017\001\001\377\004\004\003 -\002\001\006\060\035\006\003\125\035\016\004\026\004\024\127\064 -\363\164\317\004\113\325\045\346\361\100\266\054\114\331\055\351 -\240\255\060\015\006\011\052\206\110\206\367\015\001\001\013\005 -\000\003\202\001\001\000\076\273\333\027\026\322\362\024\001\040 -\054\070\203\113\255\276\312\205\172\232\266\233\153\246\341\374 -\245\072\254\255\264\050\072\257\327\001\203\111\053\143\242\335 -\232\144\016\230\134\157\335\216\273\212\124\042\055\112\023\363 -\256\100\103\333\117\221\267\206\032\354\000\264\101\201\244\117 -\372\152\213\210\263\166\010\162\052\111\100\303\323\303\205\211 -\230\020\245\235\157\031\267\273\317\172\145\125\333\067\353\074 -\212\162\062\227\036\232\051\076\255\215\346\243\033\155\365\165 -\032\346\260\150\271\133\242\356\151\107\047\065\241\206\231\200 -\363\063\113\341\153\244\046\303\357\164\131\154\172\242\144\266 -\036\104\303\120\340\017\071\075\251\063\361\245\363\322\275\142 -\204\254\216\034\251\315\132\275\067\073\156\012\042\264\364\025 -\347\221\130\305\072\104\323\225\050\331\300\145\351\162\312\320 -\017\275\037\263\025\331\251\343\244\107\011\236\340\313\067\373 -\375\275\227\325\276\030\032\151\242\071\201\331\032\365\253\177 -\310\343\342\147\013\235\364\014\352\124\337\322\262\257\261\042 -\361\040\337\274\104\034 -END -CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE -CKA_NSS_SERVER_DISTRUST_AFTER CK_BBOOL CK_FALSE -CKA_NSS_EMAIL_DISTRUST_AFTER CK_BBOOL CK_FALSE - -# Trust for "SecureSign Root CA12" -# Issuer: CN=SecureSign Root CA12,O="Cybertrust Japan Co., Ltd.",C=JP -# Serial Number:66:f9:c7:c1:af:ec:c2:51:b4:ed:53:97:e6:e6:82:c3:2b:1c:90:16 -# Subject: CN=SecureSign Root CA12,O="Cybertrust Japan Co., Ltd.",C=JP -# Not Valid Before: Wed Apr 08 05:36:46 2020 -# Not Valid After : Sun Apr 08 05:36:46 2040 -# Fingerprint (SHA-256): 3F:03:4B:B5:70:4D:44:B2:D0:85:45:A0:20:57:DE:93:EB:F3:90:5F:CE:72:1A:CB:C7:30:C0:6D:DA:EE:90:4E -# Fingerprint (SHA1): 7A:22:1E:3D:DE:1B:06:AC:9E:C8:47:70:16:8E:3C:E5:F7:6B:06:F4 -CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST -CKA_TOKEN CK_BBOOL CK_TRUE -CKA_PRIVATE CK_BBOOL CK_FALSE -CKA_MODIFIABLE CK_BBOOL CK_FALSE -CKA_LABEL UTF8 "SecureSign Root CA12" -CKA_CERT_SHA1_HASH MULTILINE_OCTAL -\172\042\036\075\336\033\006\254\236\310\107\160\026\216\074\345 -\367\153\006\364 -END -CKA_CERT_MD5_HASH MULTILINE_OCTAL -\306\211\312\144\102\233\142\010\111\013\036\177\351\007\075\350 -END -CKA_ISSUER MULTILINE_OCTAL -\060\121\061\013\060\011\006\003\125\004\006\023\002\112\120\061 -\043\060\041\006\003\125\004\012\023\032\103\171\142\145\162\164 -\162\165\163\164\040\112\141\160\141\156\040\103\157\056\054\040 -\114\164\144\056\061\035\060\033\006\003\125\004\003\023\024\123 -\145\143\165\162\145\123\151\147\156\040\122\157\157\164\040\103 -\101\061\062 -END -CKA_SERIAL_NUMBER MULTILINE_OCTAL -\002\024\146\371\307\301\257\354\302\121\264\355\123\227\346\346 -\202\303\053\034\220\026 -END -CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR -CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_MUST_VERIFY_TRUST -CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST -CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE - # # Certificate "SecureSign Root CA14" # @@ -24904,3 +24595,171 @@ CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_MUST_VERIFY_TRUST CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE + +# +# Certificate "SecureSign Root CA16" +# +# Issuer: CN=SecureSign Root CA16,O="Cybertrust Japan Co., Ltd.",C=JP +# Serial Number:54:7b:8d:ab:53:11:00:77:a8:18:03:ae:a1:2b:11:29:ab:42:e0:45 +# Subject: CN=SecureSign Root CA16,O="Cybertrust Japan Co., Ltd.",C=JP +# Not Valid Before: Tue Jul 30 07:08:11 2024 +# Not Valid After : Fri Jul 29 06:55:40 2044 +# Fingerprint (SHA-256): 4C:1C:CD:24:F1:7E:95:0F:C1:85:36:B3:3C:AF:E3:22:93:CF:C3:3E:84:67:B4:1E:1C:69:30:55:D7:F5:13:BF +# Fingerprint (SHA1): D1:79:17:EC:45:E2:A0:CA:D7:74:51:30:10:A4:C6:5C:AA:B3:3C:49 +CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE +CKA_TOKEN CK_BBOOL CK_TRUE +CKA_PRIVATE CK_BBOOL CK_FALSE +CKA_MODIFIABLE CK_BBOOL CK_FALSE +CKA_LABEL UTF8 "SecureSign Root CA16" +CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509 +CKA_SUBJECT MULTILINE_OCTAL +\060\121\061\013\060\011\006\003\125\004\006\023\002\112\120\061 +\043\060\041\006\003\125\004\012\023\032\103\171\142\145\162\164 +\162\165\163\164\040\112\141\160\141\156\040\103\157\056\054\040 +\114\164\144\056\061\035\060\033\006\003\125\004\003\023\024\123 +\145\143\165\162\145\123\151\147\156\040\122\157\157\164\040\103 +\101\061\066 +END +CKA_ID UTF8 "0" +CKA_ISSUER MULTILINE_OCTAL +\060\121\061\013\060\011\006\003\125\004\006\023\002\112\120\061 +\043\060\041\006\003\125\004\012\023\032\103\171\142\145\162\164 +\162\165\163\164\040\112\141\160\141\156\040\103\157\056\054\040 +\114\164\144\056\061\035\060\033\006\003\125\004\003\023\024\123 +\145\143\165\162\145\123\151\147\156\040\122\157\157\164\040\103 +\101\061\066 +END +CKA_SERIAL_NUMBER MULTILINE_OCTAL +\002\024\124\173\215\253\123\021\000\167\250\030\003\256\241\053 +\021\051\253\102\340\105 +END +CKA_VALUE MULTILINE_OCTAL +\060\202\005\162\060\202\003\132\240\003\002\001\002\002\024\124 +\173\215\253\123\021\000\167\250\030\003\256\241\053\021\051\253 +\102\340\105\060\015\006\011\052\206\110\206\367\015\001\001\014 +\005\000\060\121\061\013\060\011\006\003\125\004\006\023\002\112 +\120\061\043\060\041\006\003\125\004\012\023\032\103\171\142\145 +\162\164\162\165\163\164\040\112\141\160\141\156\040\103\157\056 +\054\040\114\164\144\056\061\035\060\033\006\003\125\004\003\023 +\024\123\145\143\165\162\145\123\151\147\156\040\122\157\157\164 +\040\103\101\061\066\060\036\027\015\062\064\060\067\063\060\060 +\067\060\070\061\061\132\027\015\064\064\060\067\062\071\060\066 +\065\065\064\060\132\060\121\061\013\060\011\006\003\125\004\006 +\023\002\112\120\061\043\060\041\006\003\125\004\012\023\032\103 +\171\142\145\162\164\162\165\163\164\040\112\141\160\141\156\040 +\103\157\056\054\040\114\164\144\056\061\035\060\033\006\003\125 +\004\003\023\024\123\145\143\165\162\145\123\151\147\156\040\122 +\157\157\164\040\103\101\061\066\060\202\002\042\060\015\006\011 +\052\206\110\206\367\015\001\001\001\005\000\003\202\002\017\000 +\060\202\002\012\002\202\002\001\000\307\045\037\360\022\266\217 +\261\357\177\076\127\276\107\206\363\342\046\314\016\172\356\163 +\302\366\063\044\352\302\037\156\345\321\232\164\205\224\354\163 +\021\340\141\210\355\133\055\245\327\123\323\266\200\254\260\345 +\126\351\126\152\152\232\215\273\352\335\155\302\164\175\136\365 +\047\333\044\267\125\212\222\133\303\245\020\371\167\103\156\151 +\366\263\346\336\175\165\221\260\215\351\373\140\046\155\011\355 +\376\341\124\331\000\211\271\262\326\205\163\070\046\044\323\111 +\231\306\154\065\366\352\076\057\005\174\052\071\002\351\205\065 +\256\123\052\175\144\147\322\200\256\224\260\243\162\010\064\263 +\143\125\317\230\137\103\062\151\376\253\314\205\213\217\043\343 +\214\207\224\076\236\315\341\213\006\372\171\107\025\251\333\126 +\053\122\363\265\101\063\372\244\334\216\325\255\313\116\226\273 +\261\316\324\253\123\130\274\110\134\264\217\327\146\036\024\041 +\014\065\140\320\164\263\141\220\056\170\272\005\356\120\325\117 +\243\302\360\132\072\256\131\314\175\103\207\240\106\161\154\113 +\216\354\064\200\376\273\164\334\370\273\040\356\242\343\352\352 +\246\230\015\262\334\021\044\141\052\260\142\214\346\144\200\130 +\376\270\034\261\325\223\134\001\356\064\160\363\267\035\324\245 +\146\323\016\131\246\275\004\203\313\321\114\014\246\132\142\040 +\113\204\245\116\073\324\250\362\245\142\143\313\136\265\362\170 +\066\027\026\036\362\073\100\006\136\112\155\336\365\364\255\154 +\214\350\211\157\154\050\060\102\055\027\166\000\145\043\235\324 +\321\350\007\077\041\012\356\266\356\123\265\372\173\355\076\072 +\101\224\155\060\051\271\254\117\357\123\013\005\136\304\236\154 +\000\332\163\350\176\056\353\373\302\270\255\105\120\146\316\115 +\370\116\355\110\275\236\027\120\162\217\263\226\106\037\332\320 +\327\267\072\314\024\134\274\211\263\133\354\214\175\254\242\217 +\233\131\206\016\335\060\304\063\150\010\233\275\111\361\305\375 +\072\166\021\233\327\017\240\100\140\046\342\014\257\211\340\162 +\123\252\203\355\311\073\032\341\117\005\216\070\215\122\201\000 +\075\141\105\021\277\263\254\273\114\263\125\163\245\260\135\034 +\164\137\026\141\051\236\250\002\073\002\003\001\000\001\243\102 +\060\100\060\017\006\003\125\035\023\001\001\377\004\005\060\003 +\001\001\377\060\016\006\003\125\035\017\001\001\377\004\004\003 +\002\001\006\060\035\006\003\125\035\016\004\026\004\024\030\156 +\064\266\333\231\125\144\110\245\206\111\270\236\113\223\367\016 +\053\017\060\015\006\011\052\206\110\206\367\015\001\001\014\005 +\000\003\202\002\001\000\253\202\224\212\011\027\240\274\203\130 +\204\261\263\200\143\044\112\341\121\050\076\370\114\314\140\037 +\341\151\320\203\302\361\356\375\010\326\067\323\026\167\102\273 +\331\250\006\166\160\024\271\271\323\151\353\223\352\342\140\061 +\225\300\141\021\165\353\142\336\201\275\345\012\244\244\247\105 +\053\355\222\340\247\110\273\226\110\056\315\317\066\007\161\270 +\166\132\204\377\321\316\336\151\217\124\111\365\135\223\111\100 +\020\160\152\122\304\264\053\340\002\157\066\317\240\006\137\047 +\067\316\025\356\022\002\000\115\135\234\127\331\267\335\150\246 +\177\034\266\244\251\212\025\377\113\215\301\274\027\034\101\327 +\156\272\124\045\234\055\263\070\161\225\150\027\221\334\214\360 +\130\110\064\036\157\217\345\351\055\101\317\017\222\200\330\314 +\144\252\231\021\176\172\371\062\376\033\042\266\372\055\253\054 +\100\322\374\254\045\265\016\114\016\074\273\050\010\243\223\313 +\332\004\176\260\350\065\312\136\025\106\162\073\333\051\316\255 +\365\157\007\173\232\311\111\054\114\012\022\143\302\256\352\355 +\005\044\317\074\316\146\051\037\327\072\140\144\067\200\052\331 +\173\063\157\363\347\213\256\241\024\316\231\031\345\013\172\274 +\326\137\322\223\021\272\365\207\231\337\041\113\342\117\150\126 +\375\261\165\053\076\113\075\116\173\142\346\131\250\365\044\062 +\311\054\243\356\035\266\365\176\056\055\047\122\011\165\203\260 +\306\106\033\073\265\074\252\140\211\345\315\227\037\261\147\313 +\161\217\144\021\025\352\202\000\343\342\115\326\311\270\225\222 +\105\011\025\236\133\121\343\330\301\015\242\202\232\244\135\151 +\334\105\170\201\127\064\035\264\270\003\061\370\171\250\221\104 +\162\216\343\025\312\001\236\150\370\247\306\104\010\256\164\052 +\226\361\023\141\103\030\321\312\107\227\270\330\270\071\254\111 +\031\320\145\360\241\273\132\200\207\251\142\151\276\053\271\257 +\237\310\001\375\326\373\203\237\214\274\227\052\124\141\222\007 +\310\301\316\256\111\140\056\337\345\053\116\000\072\374\271\106 +\253\164\031\070\145\231\301\367\002\065\122\356\351\335\365\164 +\115\240\160\237\156\266\334\024\013\103\062\330\001\021\007\074 +\215\105\157\101\254\001 +END +CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE +CKA_NSS_SERVER_DISTRUST_AFTER CK_BBOOL CK_FALSE +CKA_NSS_EMAIL_DISTRUST_AFTER CK_BBOOL CK_FALSE + +# Trust for "SecureSign Root CA16" +# Issuer: CN=SecureSign Root CA16,O="Cybertrust Japan Co., Ltd.",C=JP +# Serial Number:54:7b:8d:ab:53:11:00:77:a8:18:03:ae:a1:2b:11:29:ab:42:e0:45 +# Subject: CN=SecureSign Root CA16,O="Cybertrust Japan Co., Ltd.",C=JP +# Not Valid Before: Tue Jul 30 07:08:11 2024 +# Not Valid After : Fri Jul 29 06:55:40 2044 +# Fingerprint (SHA-256): 4C:1C:CD:24:F1:7E:95:0F:C1:85:36:B3:3C:AF:E3:22:93:CF:C3:3E:84:67:B4:1E:1C:69:30:55:D7:F5:13:BF +# Fingerprint (SHA1): D1:79:17:EC:45:E2:A0:CA:D7:74:51:30:10:A4:C6:5C:AA:B3:3C:49 +CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST +CKA_TOKEN CK_BBOOL CK_TRUE +CKA_PRIVATE CK_BBOOL CK_FALSE +CKA_MODIFIABLE CK_BBOOL CK_FALSE +CKA_LABEL UTF8 "SecureSign Root CA16" +CKA_CERT_SHA1_HASH MULTILINE_OCTAL +\321\171\027\354\105\342\240\312\327\164\121\060\020\244\306\134 +\252\263\074\111 +END +CKA_CERT_MD5_HASH MULTILINE_OCTAL +\150\132\170\276\353\165\351\257\156\376\274\220\301\201\062\245 +END +CKA_ISSUER MULTILINE_OCTAL +\060\121\061\013\060\011\006\003\125\004\006\023\002\112\120\061 +\043\060\041\006\003\125\004\012\023\032\103\171\142\145\162\164 +\162\165\163\164\040\112\141\160\141\156\040\103\157\056\054\040 +\114\164\144\056\061\035\060\033\006\003\125\004\003\023\024\123 +\145\143\165\162\145\123\151\147\156\040\122\157\157\164\040\103 +\101\061\066 +END +CKA_SERIAL_NUMBER MULTILINE_OCTAL +\002\024\124\173\215\253\123\021\000\167\250\030\003\256\241\053 +\021\051\253\102\340\105 +END +CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_MUST_VERIFY_TRUST +CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR +CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST +CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE From 4b8cee0d4ee10c18c3c98efb3ca9b627d289a31f Mon Sep 17 00:00:00 2001 From: YspritanHyzygy Date: Sun, 2 Aug 2026 09:15:11 -0400 Subject: [PATCH 03/11] doc: document stream.isDestroyed() `stream.isDestroyed()` has been exported since v19.9.0 but was never documented, while its siblings `isErrored()`, `isReadable()` and `isWritable()` all have entries in `doc/api/stream.md`. Unlike those, `isDestroyed()` rejects Web streams: it returns `null` for anything that is not a Node.js stream. The accepted types are therefore documented as `Readable|Writable|Duplex` rather than also listing `ReadableStream`/`WritableStream`. Refs: https://github.com/nodejs/node/pull/45671 Co-Authored-By: Claude Opus 5 Signed-off-by: YspritanHyzygy PR-URL: https://github.com/nodejs/node/pull/64789 Reviewed-By: Aviv Keller Reviewed-By: Luigi Pinca Reviewed-By: Daeyeon Jeong Reviewed-By: James M Snell --- doc/api/stream.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/doc/api/stream.md b/doc/api/stream.md index 2f7fd7961a73..6a5300c6e0e0 100644 --- a/doc/api/stream.md +++ b/doc/api/stream.md @@ -3120,6 +3120,19 @@ console.log(res); // prints 'HELLOWORLD' For convenience, the [`readable.compose(stream)`][] method is available on {Readable} and {Duplex} streams as a wrapper for this function. +### `stream.isDestroyed(stream)` + + + +* `stream` {Readable|Writable|Duplex} +* Returns: {boolean|null} - Only returns `null` if `stream` is not a valid `Readable`, `Writable` or `Duplex`. + +Returns whether the stream has been destroyed. + ### `stream.isErrored(stream)` + +Type: Runtime + +`net.Server.prototype._listen2` is an undocumented alias for an internal +function that sets up the listening handle. It is kept only so that code +replacing it keeps being called by [`server.listen()`][], and it will be +removed in a future version of Node.js. Use [`server.listen()`][] instead of +calling or overriding `_listen2`. + [DEP0142]: #dep0142-repl_builtinlibs [DEP0156]: #dep0156-aborted-property-and-abort-aborted-event-in-http [NIST SP 800-38D]: https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf @@ -4814,6 +4831,7 @@ successfully before the response closed. [`response.writableEnded`]: http.md#responsewritableended [`response.writableFinished`]: http.md#responsewritablefinished [`script.createCachedData()`]: vm.md#scriptcreatecacheddata +[`server.listen()`]: net.md#serverlisten [`setInterval()`]: timers.md#setintervalcallback-delay-args [`setTimeout()`]: timers.md#settimeoutcallback-delay-args [`socket.bufferSize`]: net.md#socketbuffersize diff --git a/lib/net.js b/lib/net.js index 759249047993..445a7d59f8cb 100644 --- a/lib/net.js +++ b/lib/net.js @@ -133,6 +133,7 @@ const { const { isUint8Array } = require('internal/util/types'); const { queueMicrotask } = require('internal/process/task_queues'); const { + deprecate, guessHandleType, isWindows, kEmptyObject, @@ -2357,7 +2358,27 @@ function setupListenHandle(address, port, addressType, backlog, fd, flags) { this); } -Server.prototype._listen2 = setupListenHandle; // legacy alias +// Legacy alias for `setupListenHandle`, kept around only because it is an +// undocumented monkeypatch point. Nothing in core calls it unless it has been +// overridden, see `callSetupListenHandle`. +const legacyListen2 = deprecate( + setupListenHandle, + 'Server.prototype._listen2 is deprecated. Use Server.prototype.listen() instead.', + 'DEP0208'); +Server.prototype._listen2 = legacyListen2; + +// Set up the listen handle, going through `_listen2` when userland replaced it +// so that the monkeypatch keeps taking effect (DEP0208). Servers that did not +// touch `_listen2` must not trigger the deprecation warning. +function callSetupListenHandle(server, address, port, addressType, backlog, + fd, flags) { + if (server._listen2 !== legacyListen2) { + server._listen2(address, port, addressType, backlog, fd, flags); + return; + } + FunctionPrototypeCall(setupListenHandle, server, address, port, addressType, + backlog, fd, flags); +} // A listening TCP Server can be transferred to another thread, which moves the // underlying listening socket (and its pending accept queue) to that thread's @@ -2431,9 +2452,8 @@ function listenInCluster(server, address, port, addressType, if (cluster.isPrimary || exclusive) { // Will create a new handle - // _listen2 sets up the listened handle, it is still named like this - // to avoid breaking code that wraps this method - server._listen2(address, port, addressType, backlog, fd, flags); + callSetupListenHandle(server, address, port, addressType, backlog, fd, + flags); return; } @@ -2467,9 +2487,8 @@ function listenInCluster(server, address, port, addressType, } // Reuse primary's server handle server._handle = handle; - // _listen2 sets up the listened handle, it is still named like this - // to avoid breaking code that wraps this method - server._listen2(address, port, addressType, backlog, fd, flags); + callSetupListenHandle(server, address, port, addressType, backlog, fd, + flags); } } diff --git a/test/parallel/test-net-listen-handle-in-cluster-2.js b/test/parallel/test-net-listen-handle-in-cluster-2.js index 33d6642e9b93..29e537541805 100644 --- a/test/parallel/test-net-listen-handle-in-cluster-2.js +++ b/test/parallel/test-net-listen-handle-in-cluster-2.js @@ -14,7 +14,8 @@ if (cluster.isPrimary) { const handle = new TCP(TCPConstants.SOCKET); const errno = handle.bind('0.0.0.0', 0); assert.strictEqual(errno, 0); - // Execute _listen2 instead of cluster._getServer in listenInCluster + // Set up the listen handle directly instead of going through + // cluster._getServer in listenInCluster net.createServer().listen(handle, common.mustCall(() => { process.exit(0); })); diff --git a/test/parallel/test-net-server-listen2-deprecation.js b/test/parallel/test-net-server-listen2-deprecation.js new file mode 100644 index 000000000000..7e4e410dc5db --- /dev/null +++ b/test/parallel/test-net-server-listen2-deprecation.js @@ -0,0 +1,27 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const net = require('net'); + +// `Server.prototype._listen2` is a deprecated alias for the internal function +// that sets up the listening handle (DEP0208). + +common.expectWarning( + 'DeprecationWarning', + 'Server.prototype._listen2 is deprecated. Use Server.prototype.listen() instead.', + 'DEP0208'); + +// Listening without touching `_listen2` must not emit the warning. +const server = net.createServer(); +server.listen(0, common.mustCall(() => { + server.close(common.mustCall(() => { + // Calling the alias directly emits the warning. It still sets up the + // handle, so the server ends up listening. + const legacy = net.createServer(); + legacy.on('listening', common.mustCall(() => { + assert.strictEqual(legacy.listening, true); + legacy.close(); + })); + legacy._listen2(null, 0, 4, undefined, undefined, 0); + })); +})); diff --git a/test/parallel/test-net-server-listen2-monkeypatch.js b/test/parallel/test-net-server-listen2-monkeypatch.js new file mode 100644 index 000000000000..3bc0155041de --- /dev/null +++ b/test/parallel/test-net-server-listen2-monkeypatch.js @@ -0,0 +1,25 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const net = require('net'); + +// Overriding the deprecated `Server.prototype._listen2` alias (DEP0208) is +// still honored by `server.listen()`. + +common.expectWarning( + 'DeprecationWarning', + 'Server.prototype._listen2 is deprecated. Use Server.prototype.listen() instead.', + 'DEP0208'); + +const original = net.Server.prototype._listen2; +net.Server.prototype._listen2 = common.mustCall(function(...args) { + assert.strictEqual(this, server); + assert.deepStrictEqual(args, [null, 0, 4, 0, undefined, 0]); + return original.apply(this, args); +}); + +const server = net.createServer(); +server.listen(0, common.mustCall(() => { + net.Server.prototype._listen2 = original; + server.close(); +})); From 19cf50c0f35be523b064ffd8253a0081f6e4abfe Mon Sep 17 00:00:00 2001 From: Chengzhong Wu Date: Wed, 29 Jul 2026 12:35:03 -0400 Subject: [PATCH 06/11] src: fix perfetto build on GetTraceFilePath Signed-off-by: Chengzhong Wu PR-URL: https://github.com/nodejs/node/pull/64721 Fixes: https://github.com/nodejs/diagnostics/issues/654 Refs: https://github.com/nodejs/node/pull/64565 Reviewed-By: Aviv Keller Reviewed-By: Yagiz Nizipli Reviewed-By: James M Snell --- src/node_trace_events.cc | 4 ++-- src/tracing/agent_perfetto.cc | 15 ++------------- src/tracing/node_trace_writer.cc | 23 ++--------------------- src/tracing/node_trace_writer.h | 3 --- src/tracing/trace_event_helper.cc | 24 ++++++++++++++++++++++++ src/tracing/trace_event_helper.h | 7 +++++++ 6 files changed, 37 insertions(+), 39 deletions(-) diff --git a/src/node_trace_events.cc b/src/node_trace_events.cc index 3bd9bd2dff5f..fec72919eb83 100644 --- a/src/node_trace_events.cc +++ b/src/node_trace_events.cc @@ -7,7 +7,7 @@ #include "node_v8_platform-inl.h" #include "permission/permission.h" #include "tracing/agent.h" -#include "tracing/node_trace_writer.h" +#include "tracing/trace_event_helper.h" #include "util-inl.h" #include @@ -90,7 +90,7 @@ void NodeCategorySet::Enable(const FunctionCallbackInfo& args) { THROW_IF_INSUFFICIENT_PERMISSIONS( category_set->env(), permission::PermissionScope::kFileSystemWrite, - tracing::NodeTraceWriter::GetFilePath( + tracing::GetTraceFilePath( per_process::cli_options->trace_event_file_pattern, 1)); auto* agent = tracing::Agent::GetInstance(); agent->StartTracing(per_process::cli_options->trace_event_categories); diff --git a/src/tracing/agent_perfetto.cc b/src/tracing/agent_perfetto.cc index 1b1f3852a634..dc5d5d941d41 100644 --- a/src/tracing/agent_perfetto.cc +++ b/src/tracing/agent_perfetto.cc @@ -6,6 +6,7 @@ #include "env-inl.h" #include "node_options.h" #include "trace_event.h" +#include "trace_event_helper.h" #include "trace_event_perfetto.h" @@ -21,16 +22,6 @@ constexpr uint64_t kReadPeriodMs = 5000; // trace file grows without bound. constexpr uint64_t kMaxFileSizeBytes = 64 * 1024 * 1024; // 64 MiB -void replace_substring(std::string* target, - std::string_view search, - std::string_view insert) { - size_t pos = target->find(search); - for (; pos != std::string::npos; pos = target->find(search, pos)) { - target->replace(pos, search.size(), insert); - pos += insert.size(); - } -} - std::set flatten( const std::unordered_map>& map) { std::set result; @@ -104,9 +95,7 @@ class SimpleWriter : public TraceWriter { ++file_num_; uv_fs_t req; - std::string filepath(log_file_pattern_); - replace_substring(&filepath, "${pid}", std::to_string(uv_os_getpid())); - replace_substring(&filepath, "${rotation}", std::to_string(file_num_)); + std::string filepath = GetTraceFilePath(log_file_pattern_, file_num_); if (fd_ >= 0) { uv_fs_close(loop_, &req, fd_, nullptr); diff --git a/src/tracing/node_trace_writer.cc b/src/tracing/node_trace_writer.cc index 6940df51d0f2..4c711fcd938e 100644 --- a/src/tracing/node_trace_writer.cc +++ b/src/tracing/node_trace_writer.cc @@ -1,4 +1,5 @@ #include "tracing/node_trace_writer.h" +#include "tracing/trace_event_helper.h" #include "util-inl.h" @@ -8,27 +9,9 @@ namespace node { namespace tracing { -void replace_substring(std::string* target, - const std::string& search, - const std::string& insert) { - size_t pos = target->find(search); - for (; pos != std::string::npos; pos = target->find(search, pos)) { - target->replace(pos, search.size(), insert); - pos += insert.size(); - } -} - NodeTraceWriter::NodeTraceWriter(const std::string& log_file_pattern) : log_file_pattern_(log_file_pattern) {} -std::string NodeTraceWriter::GetFilePath(const std::string& log_file_pattern, - int file_num) { - std::string filepath(log_file_pattern); - replace_substring(&filepath, "${pid}", std::to_string(uv_os_getpid())); - replace_substring(&filepath, "${rotation}", std::to_string(file_num)); - return filepath; -} - void NodeTraceWriter::InitializeOnThread(uv_loop_t* loop) { CHECK_NULL(tracing_loop_); tracing_loop_ = loop; @@ -82,9 +65,7 @@ void NodeTraceWriter::OpenNewFileForStreaming() { ++file_num_; uv_fs_t req; - // Evaluate a JS-style template string, it accepts the values ${pid} and - // ${rotation} - std::string filepath(GetFilePath(log_file_pattern_, file_num_)); + std::string filepath = GetTraceFilePath(log_file_pattern_, file_num_); if (fd_ != -1) { CHECK_EQ(uv_fs_close(nullptr, &req, fd_, nullptr), 0); diff --git a/src/tracing/node_trace_writer.h b/src/tracing/node_trace_writer.h index 6138374bf981..02efb2c75a84 100644 --- a/src/tracing/node_trace_writer.h +++ b/src/tracing/node_trace_writer.h @@ -21,9 +21,6 @@ class NodeTraceWriter : public AsyncTraceWriter { explicit NodeTraceWriter(const std::string& log_file_pattern); ~NodeTraceWriter() override; - static std::string GetFilePath(const std::string& log_file_pattern, - int file_num); - void InitializeOnThread(uv_loop_t* loop) override; void AppendTraceEvent(TraceObject* trace_event) override; void Flush(bool blocking) override; diff --git a/src/tracing/trace_event_helper.cc b/src/tracing/trace_event_helper.cc index 9a23b25c1782..8b0b712ebb9c 100644 --- a/src/tracing/trace_event_helper.cc +++ b/src/tracing/trace_event_helper.cc @@ -1,5 +1,9 @@ #include "tracing/trace_event_helper.h" #include "node.h" +#include "uv.h" + +#include +#include namespace node { namespace tracing { @@ -14,6 +18,26 @@ void TraceEventHelper::SetTracingController(v8::TracingController* controller) { g_controller = controller; } +namespace { +void replace_substring(std::string* target, + std::string_view search, + std::string_view insert) { + size_t pos = target->find(search); + for (; pos != std::string::npos; pos = target->find(search, pos)) { + target->replace(pos, search.size(), insert); + pos += insert.size(); + } +} +} // namespace + +std::string GetTraceFilePath(std::string_view log_file_pattern, int file_num) { + // Evaluate a JS-style template string that accepts ${pid} and ${rotation}. + std::string filepath(log_file_pattern); + replace_substring(&filepath, "${pid}", std::to_string(uv_os_getpid())); + replace_substring(&filepath, "${rotation}", std::to_string(file_num)); + return filepath; +} + } // namespace tracing v8::TracingController* GetTracingController() { diff --git a/src/tracing/trace_event_helper.h b/src/tracing/trace_event_helper.h index a4c01a66e70f..8cec89a20429 100644 --- a/src/tracing/trace_event_helper.h +++ b/src/tracing/trace_event_helper.h @@ -5,8 +5,15 @@ #include "v8-platform.h" +#include +#include + namespace node::tracing { +// Expands a trace log file pattern into a concrete path, substituting ${pid} +// and ${rotation}. +std::string GetTraceFilePath(std::string_view log_file_pattern, int file_num); + class TraceEventHelper { public: static v8::TracingController* GetTracingController(); From 699ac6e5a09e42c92bfbcb9f35d6dc7370d31fa9 Mon Sep 17 00:00:00 2001 From: Chengzhong Wu Date: Mon, 27 Jul 2026 14:27:49 -0400 Subject: [PATCH 07/11] src,test: disable trace events tests when perfetto is enabled Signed-off-by: Chengzhong Wu PR-URL: https://github.com/nodejs/node/pull/64721 Fixes: https://github.com/nodejs/diagnostics/issues/654 Refs: https://github.com/nodejs/node/pull/64565 Reviewed-By: Aviv Keller Reviewed-By: Yagiz Nizipli Reviewed-By: James M Snell --- benchmark/misc/trace.js | 4 +-- src/debug_utils.h | 1 + src/tracing/agent_perfetto.cc | 25 +++++++++++++++++++ test/common/index.js | 15 +++++++++++ test/common/index.mjs | 2 ++ .../parallel/test-inspector-tracing-domain.js | 1 + test/parallel/test-module-print-timing.mjs | 3 ++- .../test-permission-fs-write-trace-events.js | 1 + test/parallel/test-trace-events-all.js | 2 ++ test/parallel/test-trace-events-api.js | 2 ++ .../test-trace-events-async-hooks-dynamic.js | 2 ++ .../test-trace-events-async-hooks-worker.js | 2 ++ .../parallel/test-trace-events-async-hooks.js | 2 ++ test/parallel/test-trace-events-binding.js | 2 ++ test/parallel/test-trace-events-bootstrap.js | 2 ++ test/parallel/test-trace-events-console.js | 2 ++ .../test-trace-events-dynamic-enable.js | 1 + .../parallel/test-trace-events-environment.js | 2 ++ .../test-trace-events-file-pattern.js | 2 ++ test/parallel/test-trace-events-fs-async.js | 2 ++ test/parallel/test-trace-events-fs-sync.js | 2 ++ ...race-events-get-category-enabled-buffer.js | 2 ++ test/parallel/test-trace-events-http.js | 2 ++ test/parallel/test-trace-events-metadata.js | 2 ++ .../test-trace-events-net-abstract-socket.js | 1 + test/parallel/test-trace-events-net.js | 2 ++ test/parallel/test-trace-events-none.js | 2 ++ .../test-trace-events-process-exit.js | 2 ++ test/parallel/test-trace-events-promises.js | 2 ++ test/parallel/test-trace-events-threadpool.js | 2 ++ test/parallel/test-trace-events-v8.js | 2 ++ test/parallel/test-trace-events-vm.js | 2 ++ ...-trace-events-worker-metadata-with-name.js | 2 ++ .../test-trace-events-worker-metadata.js | 2 ++ 34 files changed, 99 insertions(+), 3 deletions(-) diff --git a/benchmark/misc/trace.js b/benchmark/misc/trace.js index f30823280435..077b8bff2c29 100644 --- a/benchmark/misc/trace.js +++ b/benchmark/misc/trace.js @@ -14,13 +14,13 @@ const bench = common.createBenchmark(main, { }); const { - TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN: kBeforeEvent, + TRACE_EVENT_PHASE_BEGIN: kBeginEvent, } = common.binding('constants').trace; function doTrace(n, trace) { bench.start(); for (let i = 0; i < n; i++) { - trace(kBeforeEvent, 'foo', 'test', 0, 'test'); + trace(kBeginEvent, 'foo', 'test', 0, 'test'); } bench.end(n); } diff --git a/src/debug_utils.h b/src/debug_utils.h index 52895a474b4e..616f6c03e49a 100644 --- a/src/debug_utils.h +++ b/src/debug_utils.h @@ -61,6 +61,7 @@ void NODE_EXTERN_PRIVATE FWrite(FILE* file, const std::string& str); V(MODULE) \ V(MKSNAPSHOT) \ V(SNAPSHOT_SERDES) \ + V(PERFETTO) \ V(PERMISSION_MODEL) \ V(PLATFORM_MINIMAL) \ V(PLATFORM_VERBOSE) \ diff --git a/src/tracing/agent_perfetto.cc b/src/tracing/agent_perfetto.cc index dc5d5d941d41..289b73e8c0ff 100644 --- a/src/tracing/agent_perfetto.cc +++ b/src/tracing/agent_perfetto.cc @@ -30,6 +30,30 @@ std::set flatten( return result; } +void perfetto_log_callback(perfetto::LogMessageCallbackArgs args) { + const char* level_str = "UNKNOWN"; + switch (args.level) { + case perfetto::base::kLogDebug: + level_str = "DEBUG"; + break; + case perfetto::base::kLogInfo: + level_str = "INFO"; + break; + case perfetto::base::kLogImportant: + level_str = "IMPORTANT"; + break; + case perfetto::base::kLogError: + level_str = "ERROR"; + break; + } + per_process::Debug(DebugCategory::PERFETTO, + "[%s] %s:%d: %s\n", + level_str, + args.filename, + args.line, + args.message); +} + } // namespace // Writes trace chunks to a file, rotating by size. It deliberately uses the @@ -252,6 +276,7 @@ PerfettoTracingAgent::PerfettoTracingAgent() { // Set up the in-process backend that the tracing controller will connect // to. perfetto::TracingInitArgs init_args; + init_args.log_message_callback = perfetto_log_callback; init_args.backends = perfetto::BackendType::kInProcessBackend; perfetto::Tracing::Initialize(init_args); diff --git a/test/common/index.js b/test/common/index.js index ac0c400581c4..e37b354f8259 100755 --- a/test/common/index.js +++ b/test/common/index.js @@ -71,6 +71,7 @@ const hasCrypto = Boolean(process.versions.openssl) && const hasInspector = Boolean(process.features.inspector); const hasSQLite = Boolean(process.versions.sqlite); const hasFFI = Boolean(process.config.variables.node_use_ffi); +const hasPerfetto = Boolean(process.config.variables.v8_use_perfetto); const hasDtls = hasCrypto && !!process.features.dtls; const hasQuic = hasCrypto && !!process.features.quic; @@ -769,6 +770,18 @@ function skipIfFFIMissing() { } } +function skipIfPerfettoEnabled() { + if (hasPerfetto) { + skip('Perfetto is enabled'); + } +} + +function skipIfPerfettoDisabled() { + if (!hasPerfetto) { + skip('Perfetto is disabled'); + } +} + function getArrayBufferViews(buf) { const { buffer, byteOffset, byteLength } = buf; @@ -1047,6 +1060,8 @@ const common = { skipIfInspectorDisabled, skipIfFFIMissing, skipIfSQLiteMissing, + skipIfPerfettoEnabled, + skipIfPerfettoDisabled, spawnPromisified, sleepSync, usesSharedLibrary, diff --git a/test/common/index.mjs b/test/common/index.mjs index 0bece9113a13..108cae290999 100644 --- a/test/common/index.mjs +++ b/test/common/index.mjs @@ -53,6 +53,7 @@ const { skipIfEslintMissing, skipIfInspectorDisabled, skipIfSQLiteMissing, + skipIfPerfettoEnabled, spawnPromisified, sleepSync, } = common; @@ -111,6 +112,7 @@ export { skipIfEslintMissing, skipIfInspectorDisabled, skipIfSQLiteMissing, + skipIfPerfettoEnabled, spawnPromisified, sleepSync, }; diff --git a/test/parallel/test-inspector-tracing-domain.js b/test/parallel/test-inspector-tracing-domain.js index aa31d63a0157..b9e62a483e83 100644 --- a/test/parallel/test-inspector-tracing-domain.js +++ b/test/parallel/test-inspector-tracing-domain.js @@ -3,6 +3,7 @@ const common = require('../common'); common.skipIfInspectorDisabled(); +common.skipIfPerfettoEnabled(); const { isMainThread } = require('worker_threads'); diff --git a/test/parallel/test-module-print-timing.mjs b/test/parallel/test-module-print-timing.mjs index eb957742b2ef..6b0bfee8431b 100644 --- a/test/parallel/test-module-print-timing.mjs +++ b/test/parallel/test-module-print-timing.mjs @@ -1,4 +1,4 @@ -import { isWindows } from '../common/index.mjs'; +import { isWindows, skipIfPerfettoEnabled } from '../common/index.mjs'; import assert from 'node:assert'; import { writeFileSync } from 'node:fs'; import { readFile } from 'node:fs/promises'; @@ -7,6 +7,7 @@ import tmpdir from '../common/tmpdir.js'; import { spawnSyncAndAssert } from '../common/child_process.js'; import fixtures from '../common/fixtures.js'; +skipIfPerfettoEnabled(); tmpdir.refresh(); it('should print the timing information for cjs', () => { diff --git a/test/parallel/test-permission-fs-write-trace-events.js b/test/parallel/test-permission-fs-write-trace-events.js index b2801b84de92..37285c3660d2 100644 --- a/test/parallel/test-permission-fs-write-trace-events.js +++ b/test/parallel/test-permission-fs-write-trace-events.js @@ -5,6 +5,7 @@ const common = require('../common'); const { spawnSyncAndExitWithoutError } = require('../common/child_process'); const { isMainThread } = require('worker_threads'); +common.skipIfPerfettoEnabled(); if (!isMainThread) { common.skip('This test only works on a main thread'); } diff --git a/test/parallel/test-trace-events-all.js b/test/parallel/test-trace-events-all.js index 9b0549eeb8be..107a9ca3a00a 100644 --- a/test/parallel/test-trace-events-all.js +++ b/test/parallel/test-trace-events-all.js @@ -4,6 +4,8 @@ const assert = require('assert'); const cp = require('child_process'); const fs = require('fs'); +common.skipIfPerfettoEnabled(); + const CODE = 'setTimeout(() => { for (let i = 0; i < 100000; i++) { "test" + i } }, 1)'; diff --git a/test/parallel/test-trace-events-api.js b/test/parallel/test-trace-events-api.js index 9bffb3b78c4b..dcbc0ac237e3 100644 --- a/test/parallel/test-trace-events-api.js +++ b/test/parallel/test-trace-events-api.js @@ -4,6 +4,8 @@ const common = require('../common'); const { isMainThread } = require('worker_threads'); +common.skipIfPerfettoEnabled(); + if (!isMainThread) { // https://github.com/nodejs/node/issues/22767 common.skip('This test only works on a main thread'); diff --git a/test/parallel/test-trace-events-async-hooks-dynamic.js b/test/parallel/test-trace-events-async-hooks-dynamic.js index 8144632a7138..b64582633fb0 100644 --- a/test/parallel/test-trace-events-async-hooks-dynamic.js +++ b/test/parallel/test-trace-events-async-hooks-dynamic.js @@ -10,6 +10,8 @@ try { common.skip('missing trace events'); } +common.skipIfPerfettoEnabled(); + const assert = require('assert'); const cp = require('child_process'); const fs = require('fs'); diff --git a/test/parallel/test-trace-events-async-hooks-worker.js b/test/parallel/test-trace-events-async-hooks-worker.js index 5204a50e3e15..f4c56653e280 100644 --- a/test/parallel/test-trace-events-async-hooks-worker.js +++ b/test/parallel/test-trace-events-async-hooks-worker.js @@ -10,6 +10,8 @@ try { common.skip('missing trace events'); } +common.skipIfPerfettoEnabled(); + const assert = require('assert'); const cp = require('child_process'); const fs = require('fs'); diff --git a/test/parallel/test-trace-events-async-hooks.js b/test/parallel/test-trace-events-async-hooks.js index 90d4fbc8b7aa..e81d686c2288 100644 --- a/test/parallel/test-trace-events-async-hooks.js +++ b/test/parallel/test-trace-events-async-hooks.js @@ -5,6 +5,8 @@ const cp = require('child_process'); const fs = require('fs'); const util = require('util'); +common.skipIfPerfettoEnabled(); + const CODE = 'setTimeout(() => { for (let i = 0; i < 100000; i++) { "test" + i } }, 1)'; diff --git a/test/parallel/test-trace-events-binding.js b/test/parallel/test-trace-events-binding.js index 0f1461499408..b4cba883024b 100644 --- a/test/parallel/test-trace-events-binding.js +++ b/test/parallel/test-trace-events-binding.js @@ -4,6 +4,8 @@ const assert = require('assert'); const cp = require('child_process'); const fs = require('fs'); +common.skipIfPerfettoEnabled(); + const CODE = ` const { internalBinding } = require('internal/test/binding'); const { trace } = internalBinding('trace_events'); diff --git a/test/parallel/test-trace-events-bootstrap.js b/test/parallel/test-trace-events-bootstrap.js index 0ad9c33800d7..56a35ee8c759 100644 --- a/test/parallel/test-trace-events-bootstrap.js +++ b/test/parallel/test-trace-events-bootstrap.js @@ -5,6 +5,8 @@ const cp = require('child_process'); const fs = require('fs'); const tmpdir = require('../common/tmpdir'); +common.skipIfPerfettoEnabled(); + const names = [ 'environment', 'nodeStart', diff --git a/test/parallel/test-trace-events-console.js b/test/parallel/test-trace-events-console.js index 745ca77f5b94..4b48695c5688 100644 --- a/test/parallel/test-trace-events-console.js +++ b/test/parallel/test-trace-events-console.js @@ -5,6 +5,8 @@ const cp = require('child_process'); const fs = require('fs'); const tmpdir = require('../common/tmpdir'); +common.skipIfPerfettoEnabled(); + // Tests that node.console trace events for counters and time methods are // emitted as expected. diff --git a/test/parallel/test-trace-events-dynamic-enable.js b/test/parallel/test-trace-events-dynamic-enable.js index bf65f80eef53..af8f9095b00b 100644 --- a/test/parallel/test-trace-events-dynamic-enable.js +++ b/test/parallel/test-trace-events-dynamic-enable.js @@ -4,6 +4,7 @@ const common = require('../common'); common.skipIfInspectorDisabled(); +common.skipIfPerfettoEnabled(); const { isMainThread } = require('worker_threads'); diff --git a/test/parallel/test-trace-events-environment.js b/test/parallel/test-trace-events-environment.js index 13127cb494dd..46de418caf13 100644 --- a/test/parallel/test-trace-events-environment.js +++ b/test/parallel/test-trace-events-environment.js @@ -7,6 +7,8 @@ const cp = require('child_process'); const fs = require('fs'); const tmpdir = require('../common/tmpdir'); +common.skipIfPerfettoEnabled(); + // This tests the emission of node.environment trace events const names = new Set([ diff --git a/test/parallel/test-trace-events-file-pattern.js b/test/parallel/test-trace-events-file-pattern.js index d1b02c2e49c1..3e6e339173f6 100644 --- a/test/parallel/test-trace-events-file-pattern.js +++ b/test/parallel/test-trace-events-file-pattern.js @@ -5,6 +5,8 @@ const assert = require('assert'); const cp = require('child_process'); const fs = require('fs'); +common.skipIfPerfettoEnabled(); + tmpdir.refresh(); const CODE = diff --git a/test/parallel/test-trace-events-fs-async.js b/test/parallel/test-trace-events-fs-async.js index 848d0e5f5588..04149dae2e72 100644 --- a/test/parallel/test-trace-events-fs-async.js +++ b/test/parallel/test-trace-events-fs-async.js @@ -5,6 +5,8 @@ const cp = require('child_process'); const fs = require('fs'); const util = require('util'); +common.skipIfPerfettoEnabled(); + const tests = { __proto__: null }; let gid = 1; diff --git a/test/parallel/test-trace-events-fs-sync.js b/test/parallel/test-trace-events-fs-sync.js index a8a6aa11c765..800d1a83b64f 100644 --- a/test/parallel/test-trace-events-fs-sync.js +++ b/test/parallel/test-trace-events-fs-sync.js @@ -5,6 +5,8 @@ const cp = require('child_process'); const fs = require('fs'); const util = require('util'); +common.skipIfPerfettoEnabled(); + const tests = { __proto__: null }; let gid = 1; diff --git a/test/parallel/test-trace-events-get-category-enabled-buffer.js b/test/parallel/test-trace-events-get-category-enabled-buffer.js index 3017b8e6dc87..79d2a1cf30da 100644 --- a/test/parallel/test-trace-events-get-category-enabled-buffer.js +++ b/test/parallel/test-trace-events-get-category-enabled-buffer.js @@ -10,6 +10,8 @@ try { common.skip('missing trace events'); } +common.skipIfPerfettoEnabled(); + const { createTracing, getEnabledCategories } = require('trace_events'); const assert = require('assert'); diff --git a/test/parallel/test-trace-events-http.js b/test/parallel/test-trace-events-http.js index 07a6b28fa5b2..47ac4dff9b33 100644 --- a/test/parallel/test-trace-events-http.js +++ b/test/parallel/test-trace-events-http.js @@ -5,6 +5,8 @@ const cp = require('child_process'); const fs = require('fs'); const tmpdir = require('../common/tmpdir'); +common.skipIfPerfettoEnabled(); + const CODE = ` const http = require('http'); const server = http.createServer((req, res) => { diff --git a/test/parallel/test-trace-events-metadata.js b/test/parallel/test-trace-events-metadata.js index 3a86698e1f7d..d92615fb94ec 100644 --- a/test/parallel/test-trace-events-metadata.js +++ b/test/parallel/test-trace-events-metadata.js @@ -4,6 +4,8 @@ const assert = require('assert'); const cp = require('child_process'); const fs = require('fs'); +common.skipIfPerfettoEnabled(); + const CODE = 'setTimeout(() => { for (let i = 0; i < 100000; i++) { "test" + i } }, 1);' + 'process.title = "foo"'; diff --git a/test/parallel/test-trace-events-net-abstract-socket.js b/test/parallel/test-trace-events-net-abstract-socket.js index d2e1546743c9..9505fb214ad4 100644 --- a/test/parallel/test-trace-events-net-abstract-socket.js +++ b/test/parallel/test-trace-events-net-abstract-socket.js @@ -6,6 +6,7 @@ const fs = require('fs'); const tmpdir = require('../common/tmpdir'); if (!common.isLinux) common.skip(); +common.skipIfPerfettoEnabled(); const CODE = ` const net = require('net'); diff --git a/test/parallel/test-trace-events-net.js b/test/parallel/test-trace-events-net.js index a1a93b19080b..98a5167f957c 100644 --- a/test/parallel/test-trace-events-net.js +++ b/test/parallel/test-trace-events-net.js @@ -5,6 +5,8 @@ const cp = require('child_process'); const fs = require('fs'); const tmpdir = require('../common/tmpdir'); +common.skipIfPerfettoEnabled(); + const CODE = ` const net = require('net'); const socket = net.connect('${common.PIPE}'); diff --git a/test/parallel/test-trace-events-none.js b/test/parallel/test-trace-events-none.js index 53121ac7df05..641787b3b56d 100644 --- a/test/parallel/test-trace-events-none.js +++ b/test/parallel/test-trace-events-none.js @@ -4,6 +4,8 @@ const assert = require('assert'); const cp = require('child_process'); const fs = require('fs'); +common.skipIfPerfettoEnabled(); + const CODE = 'setTimeout(() => { for (let i = 0; i < 100000; i++) { "test" + i } }, 1)'; diff --git a/test/parallel/test-trace-events-process-exit.js b/test/parallel/test-trace-events-process-exit.js index fc81c1eb7ce4..c4066809f3f2 100644 --- a/test/parallel/test-trace-events-process-exit.js +++ b/test/parallel/test-trace-events-process-exit.js @@ -4,6 +4,8 @@ const assert = require('assert'); const cp = require('child_process'); const fs = require('fs'); +common.skipIfPerfettoEnabled(); + const tmpdir = require('../common/tmpdir'); tmpdir.refresh(); const FILE_NAME = tmpdir.resolve('node_trace.1.log'); diff --git a/test/parallel/test-trace-events-promises.js b/test/parallel/test-trace-events-promises.js index 91e3c4fcda71..4626ed9f08a3 100644 --- a/test/parallel/test-trace-events-promises.js +++ b/test/parallel/test-trace-events-promises.js @@ -5,6 +5,8 @@ const cp = require('child_process'); const fs = require('fs'); const tmpdir = require('../common/tmpdir'); +common.skipIfPerfettoEnabled(); + if (process.argv[2] === 'child') { const p = Promise.reject(1); // Handled later Promise.reject(2); // Unhandled diff --git a/test/parallel/test-trace-events-threadpool.js b/test/parallel/test-trace-events-threadpool.js index 52d5a65c6035..36d3b306d0e5 100644 --- a/test/parallel/test-trace-events-threadpool.js +++ b/test/parallel/test-trace-events-threadpool.js @@ -6,6 +6,8 @@ const fs = require('fs'); const tmpdir = require('../common/tmpdir'); const { scheduler } = require('timers/promises'); +common.skipIfPerfettoEnabled(); + if (!common.hasCrypto) common.skip('missing crypto'); diff --git a/test/parallel/test-trace-events-v8.js b/test/parallel/test-trace-events-v8.js index f3724ce6df44..f71c4a057afe 100644 --- a/test/parallel/test-trace-events-v8.js +++ b/test/parallel/test-trace-events-v8.js @@ -4,6 +4,8 @@ const assert = require('assert'); const cp = require('child_process'); const fs = require('fs'); +common.skipIfPerfettoEnabled(); + const CODE = 'setTimeout(() => { for (let i = 0; i < 100000; i++) { "test" + i } }, 1)'; diff --git a/test/parallel/test-trace-events-vm.js b/test/parallel/test-trace-events-vm.js index d85a2cefd645..d2156245ab5d 100644 --- a/test/parallel/test-trace-events-vm.js +++ b/test/parallel/test-trace-events-vm.js @@ -5,6 +5,8 @@ const cp = require('child_process'); const fs = require('fs'); const tmpdir = require('../common/tmpdir'); +common.skipIfPerfettoEnabled(); + const names = [ 'ContextifyScript::New', 'RunInContext', diff --git a/test/parallel/test-trace-events-worker-metadata-with-name.js b/test/parallel/test-trace-events-worker-metadata-with-name.js index bf6e1005aa45..0140d08a5f01 100644 --- a/test/parallel/test-trace-events-worker-metadata-with-name.js +++ b/test/parallel/test-trace-events-worker-metadata-with-name.js @@ -5,6 +5,8 @@ const cp = require('child_process'); const fs = require('fs'); const { isMainThread } = require('worker_threads'); +common.skipIfPerfettoEnabled(); + if (isMainThread) { const CODE = 'const { Worker } = require(\'worker_threads\'); ' + `new Worker(${JSON.stringify(__filename)}, { name: 'foo' })`; diff --git a/test/parallel/test-trace-events-worker-metadata.js b/test/parallel/test-trace-events-worker-metadata.js index 844b3769ce20..2e6c20255ce7 100644 --- a/test/parallel/test-trace-events-worker-metadata.js +++ b/test/parallel/test-trace-events-worker-metadata.js @@ -5,6 +5,8 @@ const cp = require('child_process'); const fs = require('fs'); const { isMainThread } = require('worker_threads'); +common.skipIfPerfettoEnabled(); + if (isMainThread) { const CODE = 'const { Worker } = require(\'worker_threads\'); ' + `new Worker(${JSON.stringify(__filename)})`; From 1255833b3ff267ede3ad4a84f8831b950c2413e6 Mon Sep 17 00:00:00 2001 From: Chengzhong Wu Date: Tue, 28 Jul 2026 17:05:29 -0400 Subject: [PATCH 08/11] build: fix v8_use_perfetto source scraping Signed-off-by: Chengzhong Wu PR-URL: https://github.com/nodejs/node/pull/64721 Fixes: https://github.com/nodejs/diagnostics/issues/654 Refs: https://github.com/nodejs/node/pull/64565 Reviewed-By: Aviv Keller Reviewed-By: Yagiz Nizipli Reviewed-By: James M Snell --- tools/v8_gypfiles/v8.gyp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/v8_gypfiles/v8.gyp b/tools/v8_gypfiles/v8.gyp index 94a5435fca65..32fc99e2af9f 100644 --- a/tools/v8_gypfiles/v8.gyp +++ b/tools/v8_gypfiles/v8.gyp @@ -1740,10 +1740,10 @@ }], ['v8_use_perfetto==1', { 'sources!': [ - ' Date: Fri, 24 Jul 2026 14:31:21 -0400 Subject: [PATCH 09/11] build: run perfetto build and test on GHA Signed-off-by: Chengzhong Wu PR-URL: https://github.com/nodejs/node/pull/64721 Fixes: https://github.com/nodejs/diagnostics/issues/654 Refs: https://github.com/nodejs/node/pull/64565 Reviewed-By: Aviv Keller Reviewed-By: Yagiz Nizipli Reviewed-By: James M Snell --- .github/workflows/test-shared.yml | 5 ++++- shell.nix | 4 +++- tools/nix/v8.nix | 3 +++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test-shared.yml b/.github/workflows/test-shared.yml index 3638aa51371f..077e9e21a981 100644 --- a/.github/workflows/test-shared.yml +++ b/.github/workflows/test-shared.yml @@ -141,6 +141,8 @@ jobs: include: - runner: ubuntu-24.04 system: x86_64-linux + # Exercise the trace-event code against a perfetto-enabled V8. + perfetto: true # built separately in build-aarch64-linux-v8 # - runner: ubuntu-24.04-arm # system: aarch64-linux @@ -148,13 +150,14 @@ jobs: system: x86_64-darwin - runner: macos-latest system: aarch64-darwin - name: '${{ matrix.system }}: with shared libraries' + name: '${{ matrix.system }}: with shared libraries${{ matrix.perfetto && '' and perfetto'' || '''' }}' uses: ./.github/workflows/build-shared.yml with: runner: ${{ matrix.runner }} with-sccache: ${{ github.base_ref == 'main' || github.ref_name == 'main' }} extra-nix-flags: | --arg useSeparateDerivationForV8 true \ + ${{ matrix.perfetto && '--arg withPerfetto true \' || '\' }} ${{ endsWith(matrix.system, '-darwin') && '--arg withAmaro false --arg withLief false --arg withSQLite false --arg withFFI false --arg extraConfigFlags ''["--without-inspector" "--without-node-options"]'' \' || '\' }} secrets: CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }} diff --git a/shell.nix b/shell.nix index 8a873741072e..b97bcac5d7a8 100644 --- a/shell.nix +++ b/shell.nix @@ -19,6 +19,7 @@ withFFI ? true, withSSL ? true, withTemporal ? false, + withPerfetto ? false, sharedLibDeps ? ( import ./tools/nix/sharedLibDeps.nix { inherit @@ -67,7 +68,8 @@ let ) "--v8-${if withTemporal then "enable" else "disable"}-temporal-support" ] - ++ pkgs.lib.optional (withTemporal && useSharedTemporal) "--shared-temporal_capi"; + ++ pkgs.lib.optional (withTemporal && useSharedTemporal) "--shared-temporal_capi" + ++ pkgs.lib.optional withPerfetto "--with-perfetto"; in pkgs.mkShell { inherit nativeBuildInputs; diff --git a/tools/nix/v8.nix b/tools/nix/v8.nix index 3f050b9a8f5e..90dadd336c8d 100644 --- a/tools/nix/v8.nix +++ b/tools/nix/v8.nix @@ -44,6 +44,9 @@ let ../../tools/v8_gypfiles/toolchain.gypi ../../tools/v8_gypfiles/v8.gyp ] + ++ lib.optionals (builtins.elem "--with-perfetto" configureFlags) [ + ../../deps/perfetto + ] ++ lib.optionals (icu != null) [ ../../tools/icu/icu_versions.json ../../tools/icu/icu-system.gyp From 7c6bce0fea70faac00f0bf00a47e621e483f4849 Mon Sep 17 00:00:00 2001 From: Soul Lee Date: Sun, 2 Aug 2026 23:31:14 +0900 Subject: [PATCH 10/11] doc: add missing float32/float64 FFI type names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `ToFFIType()` accepts `float32` and `float64` as aliases for `float` and `double`, and both names already appear in the `ffi.types` constants list further down the same page, but they were missing from the list of supported type names. Also split `char` onto its own line. Unlike `u8`, `uint8` and `bool`, which always map to `ffi_type_uint8`, `char` maps to either `ffi_type_sint8` or `ffi_type_uint8` depending on the platform C ABI, as the paragraph below the list already explains. Signed-off-by: Soul Lee PR-URL: https://github.com/nodejs/node/pull/64874 Refs: https://github.com/nodejs/node/pull/62892 Refs: https://github.com/nodejs/node/issues/64848 Reviewed-By: René Reviewed-By: Paolo Insogna Reviewed-By: Ulises Gascón --- doc/api/ffi.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/doc/api/ffi.md b/doc/api/ffi.md index 94dc9e42f03d..db040d78ba5e 100644 --- a/doc/api/ffi.md +++ b/doc/api/ffi.md @@ -62,16 +62,17 @@ FFI signatures use string type names. Supported type names: * `void` +* `char` * `i8`, `int8` -* `u8`, `uint8`, `bool`, `char` +* `u8`, `uint8`, `bool` * `i16`, `int16` * `u16`, `uint16` * `i32`, `int32` * `u32`, `uint32` * `i64`, `int64` * `u64`, `uint64` -* `f32`, `float` -* `f64`, `double` +* `f32`, `float`, `float32` +* `f64`, `double`, `float64` * `pointer`, `ptr` * `string`, `str` * `buffer` From c55eb4acb18e2a3b7f996b2253723f0936bde263 Mon Sep 17 00:00:00 2001 From: Trivikram Kamat <16024985+trivikr@users.noreply.github.com> Date: Sun, 2 Aug 2026 07:54:42 -0700 Subject: [PATCH 11/11] ffi: reject fast calls after library close Optimized Fast API calls bypass InvokeFunction and can jump directly to a symbol after DynamicLibrary::close() unloads its library. Check the function's closed state in the AArch64 and SysV x64 trampolines before entering the target. If the library is closed, schedule ERR_FFI_LIBRARY_CLOSED and return without calling the symbol. Keep the JavaScript guard on platforms without a native trampoline guard and for signatures that already require argument conversion or validation. This keeps raw scalar fast calls close to their original performance on supported platforms. Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com> Assisted-by: codex:gpt-5.6-sol PR-URL: https://github.com/nodejs/node/pull/64860 Fixes: https://github.com/nodejs/node/issues/64854 Reviewed-By: Paolo Insogna Reviewed-By: Matteo Collina Reviewed-By: James M Snell --- lib/ffi.js | 22 +++++++++++++ lib/internal/errors.js | 1 + lib/internal/ffi/fast-api.js | 37 +++++++++++++++++++--- src/ffi/fast.cc | 32 +++++++++++++++++-- src/ffi/fast.h | 24 +++++++++++---- src/ffi/platforms/arm64.cc | 35 ++++++++++++++++++--- src/ffi/platforms/loong64.cc | 6 ++-- src/ffi/platforms/ppc64.cc | 8 ++--- src/ffi/platforms/riscv64.cc | 6 ++-- src/ffi/platforms/s390x.cc | 6 ++-- src/ffi/platforms/x64.cc | 46 ++++++++++++++++++++++++---- src/node_ffi.cc | 12 +++++--- test/ffi/test-ffi-dynamic-library.js | 23 +++++++++++++- 13 files changed, 217 insertions(+), 41 deletions(-) diff --git a/lib/ffi.js b/lib/ffi.js index 01c330953ac8..cde6cca7a86e 100644 --- a/lib/ffi.js +++ b/lib/ffi.js @@ -68,6 +68,7 @@ const { } = require('internal/ffi-shared-buffer'); const { + markFastLibraryClosed, wrapWithRawPointerConversions, } = require('internal/ffi/fast-api'); @@ -100,6 +101,27 @@ function wrapFFIFunction(rawFn, owner) { const rawGetFunction = DynamicLibrary.prototype.getFunction; const rawGetFunctions = DynamicLibrary.prototype.getFunctions; +const rawClose = DynamicLibrary.prototype.close; + +function close() { + const result = FunctionPrototypeCall(rawClose, this); + markFastLibraryClosed(this); + return result; +} + +ObjectDefineProperty(DynamicLibrary.prototype, 'close', { + __proto__: null, + configurable: true, + value: close, + writable: true, +}); + +ObjectDefineProperty(DynamicLibrary.prototype, SymbolDispose, { + __proto__: null, + configurable: true, + value: close, + writable: true, +}); DynamicLibrary.prototype.getFunction = function getFunction(name, signature) { const raw = FunctionPrototypeCall(rawGetFunction, this, name, signature); diff --git a/lib/internal/errors.js b/lib/internal/errors.js index 93498488ce56..438bde842d8b 100644 --- a/lib/internal/errors.js +++ b/lib/internal/errors.js @@ -1234,6 +1234,7 @@ E('ERR_FEATURE_UNAVAILABLE_ON_PLATFORM', 'The feature %s is unavailable on the current platform' + ', which is being used to run Node.js', TypeError); +E('ERR_FFI_LIBRARY_CLOSED', 'Library is closed', Error); E('ERR_FS_CP_DIR_TO_NON_DIR', 'Cannot overwrite non-directory with directory', SystemError); E('ERR_FS_CP_EEXIST', 'Target already exists', SystemError); diff --git a/lib/internal/ffi/fast-api.js b/lib/internal/ffi/fast-api.js index ebfaed92b27d..44e4c3a04e0f 100644 --- a/lib/internal/ffi/fast-api.js +++ b/lib/internal/ffi/fast-api.js @@ -5,6 +5,7 @@ const { NumberIsInteger, ObjectDefineProperty, ReflectApply, + SafeWeakMap, StringPrototypeIncludes, TypeError, } = primordials; @@ -25,9 +26,16 @@ const { kFastBufferInvoke, } = internalBinding('ffi'); +const { + codes: { + ERR_FFI_LIBRARY_CLOSED, + }, +} = require('internal/errors'); + const U64_MAX = 0xFFFFFFFFFFFFFFFFn; const I64_MAX = 0x7FFFFFFFFFFFFFFFn; const I64_MIN = -0x8000000000000000n; +const fastLibraryStates = new SafeWeakMap(); // These ranges mirror ToFFIArgument in src/ffi/types.cc. V8's Fast API // exposes narrow integers as 32-bit values and uses truncating BigInt @@ -202,7 +210,20 @@ function inheritMetadata(wrapper, rawFn, nargs) { return wrapper; } -function wrapWithRawPointerConversions(rawFn, argumentTypes, _owner) { +function markFastLibraryClosed(owner) { + const state = fastLibraryStates.get(owner); + if (state !== undefined) { + state.closed = true; + } +} + +function throwIfFastLibraryClosed(state) { + if (state.closed) { + throw new ERR_FFI_LIBRARY_CLOSED(); + } +} + +function wrapWithRawPointerConversions(rawFn, argumentTypes, owner) { if (rawFn === undefined || rawFn === null) { return rawFn; } @@ -213,11 +234,14 @@ function wrapWithRawPointerConversions(rawFn, argumentTypes, _owner) { return rawFn; } - const indexes = getFastArgumentIndexes(argumentTypes); - if (indexes === null) { - return rawFn; + let state = fastLibraryStates.get(owner); + if (state === undefined) { + state = { __proto__: null, closed: false }; + fastLibraryStates.set(owner, state); } + const indexes = getFastArgumentIndexes(argumentTypes) ?? []; + const stringState = { __proto__: null, buffers: [], @@ -233,6 +257,7 @@ function wrapWithRawPointerConversions(rawFn, argumentTypes, _owner) { const fastBufferInvoke = needsPointerLikeConversion(t0) ? rawFn[kFastBufferInvoke] : undefined; wrapper = function(a0) { + throwIfFastLibraryClosed(state); if (arguments.length !== 1) { throwFFIArgCountError(1, arguments.length); } @@ -262,6 +287,7 @@ function wrapWithRawPointerConversions(rawFn, argumentTypes, _owner) { const t0 = argumentTypes[0]; const t1 = argumentTypes[1]; wrapper = function(a0, a1) { + throwIfFastLibraryClosed(state); if (arguments.length !== 2) { throwFFIArgCountError(2, arguments.length); } @@ -283,6 +309,7 @@ function wrapWithRawPointerConversions(rawFn, argumentTypes, _owner) { const t1 = argumentTypes[1]; const t2 = argumentTypes[2]; wrapper = function(a0, a1, a2) { + throwIfFastLibraryClosed(state); if (arguments.length !== 3) { throwFFIArgCountError(3, arguments.length); } @@ -300,6 +327,7 @@ function wrapWithRawPointerConversions(rawFn, argumentTypes, _owner) { }; } else { wrapper = function(...args) { + throwIfFastLibraryClosed(state); if (args.length !== nargs) { throwFFIArgCountError(nargs, args.length); } @@ -332,5 +360,6 @@ module.exports = { convertPointerArg, hasPointerMemoryArg, hasStringPointerArg, + markFastLibraryClosed, wrapWithRawPointerConversions, }; diff --git a/src/ffi/fast.cc b/src/ffi/fast.cc index ea98bf8aa4f1..ca9a5715724b 100644 --- a/src/ffi/fast.cc +++ b/src/ffi/fast.cc @@ -241,12 +241,26 @@ extern "C" uintptr_t node_ffi_fast_buffer_data(v8::Local value, v8::Isolate* isolate = options != nullptr ? options->isolate : nullptr; if (isolate != nullptr) { + // No HandleScope is active during a Fast API call, so open one before + // creating the error object. + v8::HandleScope scope(isolate); THROW_ERR_INVALID_ARG_VALUE( isolate, "Argument %u must be a buffer or an ArrayBuffer", index); } return kInvalidBuffer; } +extern "C" void node_ffi_fast_library_closed(v8::Isolate* isolate) { + if (isolate != nullptr) { + // Fast API calls do not enter a HandleScope, and the generated trampolines + // call this helper directly. Building the error object allocates handles, + // so open a scope here. The scheduled exception lives on the isolate and + // outlives the scope. + v8::HandleScope scope(isolate); + THROW_ERR_FFI_LIBRARY_CLOSED(isolate); + } +} + FastFFIMetadata::~FastFFIMetadata() { // Metadata owns executable memory through `trampoline`; releasing it here // ties code lifetime to the V8 function's weak FFIFunctionInfo cleanup. @@ -265,7 +279,18 @@ bool IsFastCallSupported() { #endif } -std::unique_ptr CreateFastFFIMetadata(const FFIFunction& fn) { +bool IsFastLibraryGuardSupported() { +#if defined(__aarch64__) || defined(_M_ARM64) || \ + (defined(__x86_64__) && !defined(_WIN32)) + return true; +#else + return false; +#endif +} + +std::unique_ptr CreateFastFFIMetadata(const FFIFunction& fn, + const bool* closed, + v8::Isolate* isolate) { // Bail early if executable memory allocation doesn't work on this process // (missing MAP_JIT entitlement, hardened runtime, SELinux execmem, etc.). // The self-test runs once and caches the result. @@ -299,6 +324,7 @@ std::unique_ptr CreateFastFFIMetadata(const FFIFunction& fn) { std::vector args; args.reserve(fn.arg_type_names.size()); bool needs_bigint = NeedsBigIntRepresentation(result); + const bool guards_library = IsFastLibraryGuardSupported(); bool needs_callback_options = false; // Normalize public argument names into FastFFIType values while collecting // signature-wide flags required by V8 CFunctionInfo. @@ -320,8 +346,9 @@ std::unique_ptr CreateFastFFIMetadata(const FFIFunction& fn) { // The platform-specific trampoline is the executable entrypoint V8 calls. // If the platform rejects the signature, the whole fast metadata object is // discarded and the caller chooses another invocation path. + FastFFITrampolineConfig config{fn.ptr, closed, isolate}; if (!node_ffi_create_fast_trampoline( - fn.ptr, args.data(), args.size(), result, &metadata->trampoline)) { + config, args.data(), args.size(), result, &metadata->trampoline)) { return nullptr; } @@ -348,6 +375,7 @@ std::unique_ptr CreateFastFFIMetadata(const FFIFunction& fn) { : CFunctionInfo::Int64Representation::kNumber); metadata->c_function = v8::CFunction(metadata->trampoline.code, metadata->c_function_info.get()); + metadata->guards_library = guards_library; return metadata; } diff --git a/src/ffi/fast.h b/src/ffi/fast.h index b85191aade13..7aced6a7cc54 100644 --- a/src/ffi/fast.h +++ b/src/ffi/fast.h @@ -36,6 +36,12 @@ struct FastFFITrampoline { size_t size = 0; }; +struct FastFFITrampolineConfig { + void* target; + const bool* closed; + v8::Isolate* isolate; +}; + struct FastFFIMetadata { FastFFIMetadata() = default; ~FastFFIMetadata(); @@ -47,6 +53,7 @@ struct FastFFIMetadata { std::vector arg_info; std::unique_ptr c_function_info; v8::CFunction c_function; + bool guards_library = false; }; // Public detection queries. @@ -56,6 +63,7 @@ struct FastFFIMetadata { // of any particular signature — if this returns false, no signature can // use the fast-call path. bool IsFastCallSupported(); +bool IsFastLibraryGuardSupported(); bool SignatureNeedsRawPointerConversions(const FFIFunction& fn); bool SignatureNeedsFastIntegerValidation(const FFIFunction& fn); @@ -65,7 +73,9 @@ std::shared_ptr CloneWithRawPointerArgNames( const std::shared_ptr& fn); std::shared_ptr CloneWithFastBufferArgNames( const std::shared_ptr& fn); -std::unique_ptr CreateFastFFIMetadata(const FFIFunction& fn); +std::unique_ptr CreateFastFFIMetadata(const FFIFunction& fn, + const bool* closed, + v8::Isolate* isolate); } // namespace node::ffi @@ -73,11 +83,13 @@ extern "C" { uintptr_t node_ffi_fast_buffer_data(v8::Local value, v8::FastApiCallbackOptions* options, uint32_t index); -bool node_ffi_create_fast_trampoline(void* target, - const node::ffi::FastFFIType* args, - size_t argc, - node::ffi::FastFFIType result, - node::ffi::FastFFITrampoline* out); +void node_ffi_fast_library_closed(v8::Isolate* isolate); +bool node_ffi_create_fast_trampoline( + const node::ffi::FastFFITrampolineConfig& config, + const node::ffi::FastFFIType* args, + size_t argc, + node::ffi::FastFFIType result, + node::ffi::FastFFITrampoline* out); void node_ffi_free_fast_trampoline(node::ffi::FastFFITrampoline* trampoline); } diff --git a/src/ffi/platforms/arm64.cc b/src/ffi/platforms/arm64.cc index a3132966b560..df215ecafed3 100644 --- a/src/ffi/platforms/arm64.cc +++ b/src/ffi/platforms/arm64.cc @@ -81,6 +81,14 @@ uint32_t LdrXSp(unsigned reg, unsigned offset) { return 0xf94003e0 | ((offset / 8) << 10) | reg; } +uint32_t LdrbW(unsigned dst, unsigned base) { + return 0x39400000 | (base << 5) | dst; +} + +uint32_t CbzW(unsigned reg, unsigned instruction_offset) { + return 0x34000000 | ((instruction_offset & 0x7ffff) << 5) | reg; +} + uint32_t MovzW(unsigned dst, uint16_t value) { // Load a small immediate into a W register. The buffer helper's argument // index is uint32_t, but current Fast API signatures are capped well below @@ -213,14 +221,15 @@ bool ProtectCode(void* code, size_t code_size) { } // namespace extern "C" bool node_ffi_create_fast_trampoline( - void* target, + const node::ffi::FastFFITrampolineConfig& config, const node::ffi::FastFFIType* args, size_t argc, node::ffi::FastFFIType result, node::ffi::FastFFITrampoline* out) { // Null inputs mean the caller cannot safely create executable code for this // signature. Report rejection so the generic FFI path can be used instead. - if (target == nullptr || out == nullptr) { + if (config.target == nullptr || config.closed == nullptr || + config.isolate == nullptr || out == nullptr) { return false; } @@ -275,6 +284,24 @@ extern "C" bool node_ffi_create_fast_trampoline( // call can return through this generated trampoline safely. *cursor++ = kStpFpLrPreIndex; + // Fast calls bypass DynamicLibrary::InvokeFunction, so check the stable + // FFIFunction::closed flag before touching the target address. The open + // branch is the hot path. On close, schedule the standard JS exception and + // return; V8 checks for pending exceptions after Fast API calls. + EmitLoadX16(&cursor, reinterpret_cast(config.closed)); + *cursor++ = LdrbW(17, 16); + uint32_t* open_branch = cursor++; + EmitLoadX16(&cursor, reinterpret_cast(config.isolate)); + *cursor++ = MovX(0, 16); + EmitLoadX16( + &cursor, reinterpret_cast(node_ffi_fast_library_closed)); + *cursor++ = kBlrX16; + *cursor++ = MovX(0, 31); + *cursor++ = kLdpFpLrPostIndex; + *cursor++ = kRet; + *open_branch = + CbzW(17, static_cast(cursor - open_branch)); + if (has_buffer_args) { // Buffer conversion calls a C++ helper before the target call, so spill all // incoming GP registers that may be clobbered by that helper. @@ -361,7 +388,7 @@ extern "C" bool node_ffi_create_fast_trampoline( // Tail of the trampoline: load the actual library symbol address and call it // with arguments now arranged according to the native ABI. - EmitLoadX16(&cursor, reinterpret_cast(target)); + EmitLoadX16(&cursor, reinterpret_cast(config.target)); *cursor++ = kBlrX16; if (has_buffer_args) { @@ -414,7 +441,7 @@ extern "C" void node_ffi_free_fast_trampoline( !(defined(__riscv) && __riscv_xlen == 64) && !defined(__s390x__) extern "C" bool node_ffi_create_fast_trampoline( - void* target, + const node::ffi::FastFFITrampolineConfig& config, const node::ffi::FastFFIType* args, size_t argc, node::ffi::FastFFIType result, diff --git a/src/ffi/platforms/loong64.cc b/src/ffi/platforms/loong64.cc index 6bc90358cfca..dda579b6c63f 100644 --- a/src/ffi/platforms/loong64.cc +++ b/src/ffi/platforms/loong64.cc @@ -74,12 +74,12 @@ void FreeCode(void* code, size_t code_size) { } // namespace extern "C" bool node_ffi_create_fast_trampoline( - void* target, + const node::ffi::FastFFITrampolineConfig& config, const node::ffi::FastFFIType* args, size_t argc, node::ffi::FastFFIType result, node::ffi::FastFFITrampoline* out) { - if (target == nullptr || out == nullptr || IsNarrowType(result)) { + if (config.target == nullptr || out == nullptr || IsNarrowType(result)) { return false; } @@ -126,7 +126,7 @@ extern "C" bool node_ffi_create_fast_trampoline( Emit32(&cursor, LdD(12, 12, 16)); // ld.d t0, t0, literal Emit32(&cursor, Jirl(0, 12, 0)); // jr t0 Emit32(&cursor, Or(0, 0, 0)); // nop; align literal to 8 bytes - Emit64(&cursor, reinterpret_cast(target)); + Emit64(&cursor, reinterpret_cast(config.target)); const size_t written = reinterpret_cast(cursor) - static_cast(code); diff --git a/src/ffi/platforms/ppc64.cc b/src/ffi/platforms/ppc64.cc index 78cd91440561..52808abac894 100644 --- a/src/ffi/platforms/ppc64.cc +++ b/src/ffi/platforms/ppc64.cc @@ -86,12 +86,12 @@ void FreeCode(void* code, size_t code_size) { } // namespace extern "C" bool node_ffi_create_fast_trampoline( - void* target, + const node::ffi::FastFFITrampolineConfig& config, const node::ffi::FastFFIType* args, size_t argc, node::ffi::FastFFIType result, node::ffi::FastFFITrampoline* out) { - if (target == nullptr || out == nullptr || IsNarrowType(result)) { + if (config.target == nullptr || out == nullptr || IsNarrowType(result)) { return false; } @@ -149,7 +149,7 @@ extern "C" bool node_ffi_create_fast_trampoline( if (gp_count % 2 == 0) { Emit32(&cursor, 0x60000000); // nop; align literal to 8 bytes } - Emit64(&cursor, reinterpret_cast(target)); + Emit64(&cursor, reinterpret_cast(config.target)); const size_t written = reinterpret_cast(cursor) - static_cast(code); @@ -179,7 +179,7 @@ extern "C" void node_ffi_free_fast_trampoline( #else extern "C" bool node_ffi_create_fast_trampoline( - void* target, + const node::ffi::FastFFITrampolineConfig& config, const node::ffi::FastFFIType* args, size_t argc, node::ffi::FastFFIType result, diff --git a/src/ffi/platforms/riscv64.cc b/src/ffi/platforms/riscv64.cc index 0497f38619a8..841b0db85f68 100644 --- a/src/ffi/platforms/riscv64.cc +++ b/src/ffi/platforms/riscv64.cc @@ -75,12 +75,12 @@ void FreeCode(void* code, size_t code_size) { } // namespace extern "C" bool node_ffi_create_fast_trampoline( - void* target, + const node::ffi::FastFFITrampolineConfig& config, const node::ffi::FastFFIType* args, size_t argc, node::ffi::FastFFIType result, node::ffi::FastFFITrampoline* out) { - if (target == nullptr || out == nullptr || IsNarrowType(result)) { + if (config.target == nullptr || out == nullptr || IsNarrowType(result)) { return false; } @@ -127,7 +127,7 @@ extern "C" bool node_ffi_create_fast_trampoline( Emit32(&cursor, Ld(5, 5, 16)); // ld t0, literal(t0) Emit32(&cursor, Jalr(0, 5, 0)); // jr t0 Emit32(&cursor, Addi(0, 0, 0)); // nop; align literal to 8 bytes - Emit64(&cursor, reinterpret_cast(target)); + Emit64(&cursor, reinterpret_cast(config.target)); const size_t written = reinterpret_cast(cursor) - static_cast(code); diff --git a/src/ffi/platforms/s390x.cc b/src/ffi/platforms/s390x.cc index dd8606de82bc..5ec44d9e486d 100644 --- a/src/ffi/platforms/s390x.cc +++ b/src/ffi/platforms/s390x.cc @@ -86,12 +86,12 @@ void FreeCode(void* code, size_t code_size) { } // namespace extern "C" bool node_ffi_create_fast_trampoline( - void* target, + const node::ffi::FastFFITrampolineConfig& config, const node::ffi::FastFFIType* args, size_t argc, node::ffi::FastFFIType result, node::ffi::FastFFITrampoline* out) { - if (target == nullptr || out == nullptr || IsNarrowType(result)) { + if (config.target == nullptr || out == nullptr || IsNarrowType(result)) { return false; } @@ -136,7 +136,7 @@ extern "C" bool node_ffi_create_fast_trampoline( // Load the target address from the literal pool into r1 and tail-branch. Emit48(&cursor, Lgrl(1, 4)); // lgrl r1, literal Emit16(&cursor, Br(1)); // br r1 - Emit64(&cursor, reinterpret_cast(target)); + Emit64(&cursor, reinterpret_cast(config.target)); const size_t written = cursor - static_cast(code); __builtin___clear_cache(static_cast(code), diff --git a/src/ffi/platforms/x64.cc b/src/ffi/platforms/x64.cc index 51de3c5452f3..e105eabc13db 100644 --- a/src/ffi/platforms/x64.cc +++ b/src/ffi/platforms/x64.cc @@ -211,6 +211,15 @@ void EmitCmp(uint8_t** cursor, unsigned lhs, unsigned rhs) { EmitModRM(cursor, rhs, lhs); } +void EmitCmpBytePtrZero(uint8_t** cursor, unsigned base) { + // cmp byte ptr [base], 0. The closed flag is a stable bool owned by the + // FFIFunction kept alive by this trampoline's FunctionTemplate data. + EmitRex(cursor, false, 7, base); + Emit8(cursor, 0x80); + Emit8(cursor, (7 << 3) | (base & 7)); + Emit8(cursor, 0); +} + void EmitXorEax(uint8_t** cursor) { // Return nullptr/zero after the helper has already scheduled the JS exception. Emit8(cursor, 0x31); @@ -327,14 +336,15 @@ void* AllocateCodeNear(uintptr_t target_address, size_t code_size) { } // namespace extern "C" bool node_ffi_create_fast_trampoline( - void* target, + const node::ffi::FastFFITrampolineConfig& config, const node::ffi::FastFFIType* args, size_t argc, node::ffi::FastFFIType result, node::ffi::FastFFITrampoline* out) { // Null inputs mean the caller cannot safely create executable code for this // signature. Report rejection so the generic FFI path can be used instead. - if (target == nullptr || out == nullptr) { + if (config.target == nullptr || config.closed == nullptr || + config.isolate == nullptr || out == nullptr) { return false; } @@ -377,13 +387,36 @@ extern "C" bool node_ffi_create_fast_trampoline( // Generate into writable anonymous memory first; the page is made executable // only after the instruction stream is complete and the instruction cache is // synchronized. - const uintptr_t target_address = reinterpret_cast(target); + const uintptr_t target_address = + reinterpret_cast(config.target); void* code = AllocateCodeNear(target_address, kCodeSize); if (code == MAP_FAILED) { return false; } uint8_t* cursor = static_cast(code); + + EmitMovImm64(&cursor, kR11, reinterpret_cast(config.closed)); + EmitCmpBytePtrZero(&cursor, kR11); + uint8_t* open_branch = cursor; + Emit8(&cursor, 0x74); // je open + Emit8(&cursor, 0); + + // The closed path is cold. Align the stack, pass the isolate to the helper, + // and return after it schedules ERR_FFI_LIBRARY_CLOSED. V8 checks for + // pending exceptions immediately after the Fast API call. + EmitPushRbp(&cursor); + EmitMovImm64(&cursor, kRdi, reinterpret_cast(config.isolate)); + EmitMovImm64( + &cursor, + kR11, + reinterpret_cast(node_ffi_fast_library_closed)); + EmitCall(&cursor, kR11); + EmitXorEax(&cursor); + EmitPopRbp(&cursor); + EmitRet(&cursor); + open_branch[1] = static_cast(cursor - (open_branch + 2)); + const bool tail_call = !has_buffer_args && !NeedsNarrow(result); if (!tail_call) { EmitPushRbp(&cursor); @@ -689,12 +722,12 @@ void FreeCode(void* code, size_t code_size) { } // namespace extern "C" bool node_ffi_create_fast_trampoline( - void* target, + const node::ffi::FastFFITrampolineConfig& config, const node::ffi::FastFFIType* args, size_t argc, node::ffi::FastFFIType result, node::ffi::FastFFITrampoline* out) { - if (target == nullptr || out == nullptr || argc > 3) { + if (config.target == nullptr || out == nullptr || argc > 3) { return false; } @@ -724,7 +757,8 @@ extern "C" bool node_ffi_create_fast_trampoline( } } - EmitMovImm64(&cursor, kR11, reinterpret_cast(target)); + EmitMovImm64( + &cursor, kR11, reinterpret_cast(config.target)); if (tail_call) { // The caller already provided Win64 shadow space for the trampoline; after // the receiver-slot shuffle, the target can reuse the same stack shape. diff --git a/src/node_ffi.cc b/src/node_ffi.cc index b05d09270126..17b4c13c4552 100644 --- a/src/node_ffi.cc +++ b/src/node_ffi.cc @@ -250,15 +250,16 @@ MaybeLocal DynamicLibrary::CreateFunction( // signature, fall back to SharedBuffer for supported scalar shapes, then to // the generic libffi invoker. std::shared_ptr fast_fn = CloneWithRawPointerArgNames(fn); - info->fast_metadata = CreateFastFFIMetadata(*fast_fn); + info->fast_metadata = CreateFastFFIMetadata(*fast_fn, &fn->closed, isolate); bool use_fast_api = info->fast_metadata != nullptr; bool use_sb = !use_fast_api && IsSBEligibleSignature(*fn); bool has_ptr_args = use_sb && SignatureHasPointerArgs(*fn); - // Fast API signatures that need JS-side argument conversion or range checks - // use a wrapper with the native type names attached as hidden metadata. + // Signatures that need JS-side conversion or validation use a wrapper, as + // do all fast signatures on platforms without a native library guard. bool needs_fast_argument_wrapper = use_fast_api && (SignatureNeedsRawPointerConversions(*fn) || - SignatureNeedsFastIntegerValidation(*fn)); + SignatureNeedsFastIntegerValidation(*fn) || + !info->fast_metadata->guards_library); // A single pointer-like parameter can get a separate Buffer-aware Fast API // entrypoint so Buffer calls avoid JS pointer extraction. bool needs_fast_buffer_invoke = @@ -407,7 +408,8 @@ MaybeLocal DynamicLibrary::CreateFunction( // argument is Buffer/ArrayBuffer-backed memory. std::shared_ptr fast_buffer_fn = CloneWithFastBufferArgNames(fn); - info->fast_buffer_metadata = CreateFastFFIMetadata(*fast_buffer_fn); + info->fast_buffer_metadata = + CreateFastFFIMetadata(*fast_buffer_fn, &fn->closed, isolate); if (info->fast_buffer_metadata != nullptr) { // Store the secondary invoker on the primary raw function under a hidden // Symbol. Keeping it separate avoids overloading SharedBuffer slow-path diff --git a/test/ffi/test-ffi-dynamic-library.js b/test/ffi/test-ffi-dynamic-library.js index 88897be6eaec..2a6aa4129e95 100644 --- a/test/ffi/test-ffi-dynamic-library.js +++ b/test/ffi/test-ffi-dynamic-library.js @@ -1,4 +1,4 @@ -// Flags: --experimental-ffi --expose-gc +// Flags: --experimental-ffi --expose-gc --allow-natives-syntax 'use strict'; const common = require('../common'); common.skipIfFFIMissing(); @@ -209,6 +209,27 @@ test('closed libraries reject subsequent operations', () => { assert.throws(() => lib.getSymbol('add_i32'), /Library is closed/); }); +test('optimized fast calls reject calls after the library is closed', () => { + const { lib, functions } = ffi.dlopen(libraryPath, { + multiply_f64: fixtureSymbols.multiply_f64, + }); + + function hot(a, b) { + return functions.multiply_f64(a, b); + } + + eval('%PrepareFunctionForOptimization(hot)'); + assert.strictEqual(hot(2, 3), 6); + eval('%OptimizeFunctionOnNextCall(hot)'); + assert.strictEqual(hot(2, 3), 6); + + lib.close(); + assert.throws(() => hot(2, 3), { + code: 'ERR_FFI_LIBRARY_CLOSED', + message: 'Library is closed', + }); +}); + test('DynamicLibrary supports Symbol.dispose', () => { const lib = new ffi.DynamicLibrary(libraryPath); const addI32 = lib.getFunction('add_i32', fixtureSymbols.add_i32);