@php-wasm/web 3.0.35 → 3.0.37

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../../../../packages/php-wasm/web/src/lib/get-php-loader-module.ts","../../../../packages/php-wasm/web/src/lib/tls/utils.ts","../../../../packages/php-wasm/web/src/lib/tls/extensions/types.ts","../../../../packages/php-wasm/web/src/lib/tls/extensions/0_server_name.ts","../../../../packages/php-wasm/web/src/lib/tls/cipher-suites.ts","../../../../packages/php-wasm/web/src/lib/tls/extensions/10_supported_groups.ts","../../../../packages/php-wasm/web/src/lib/tls/extensions/11_ec_point_formats.ts","../../../../packages/php-wasm/web/src/lib/tls/extensions/13_signature_algorithms.ts","../../../../packages/php-wasm/web/src/lib/tls/extensions/parse-extensions.ts","../../../../packages/php-wasm/web/src/lib/tls/1_2/prf.ts","../../../../packages/php-wasm/web/src/lib/tls/1_2/types.ts","../../../../packages/php-wasm/web/src/lib/tls/1_2/connection.ts","../../../../packages/php-wasm/web/src/lib/tls/certificates.ts","../../../../packages/php-wasm/web/src/lib/firewall-interference-error.ts","../../../../packages/php-wasm/web/src/lib/fetch-with-cors-proxy.ts","../../../../packages/php-wasm/web/src/lib/chunked-decoder.ts","../../../../packages/php-wasm/web/src/lib/tcp-over-fetch-websocket.ts","../../../../packages/php-wasm/web/src/lib/extensions/intl/get-intl-extension-module.ts","../../../../packages/php-wasm/web/src/lib/extensions/intl/with-intl.ts","../../../../packages/php-wasm/web/src/lib/load-runtime.ts","../../../../packages/php-wasm/web/src/lib/setup-post-message-relay.ts","../../../../packages/php-wasm/web/src/lib/worker-thread/spawn-php-worker-thread.ts","../../../../packages/php-wasm/web/src/lib/directory-handle-mount.ts"],"sourcesContent":["import type { PHPLoaderModule, SupportedPHPVersion } from '@php-wasm/universal';\nimport { LatestSupportedPHPVersion } from '@php-wasm/universal';\n\n/**\n * Loads the PHP loader module for the given PHP version.\n *\n * Each PHP version is packaged separately to reduce bundle size.\n * - @php-wasm/web-8-5\n * - @php-wasm/web-8-4\n * - @php-wasm/web-8-3\n * - etc.\n *\n * @param version The PHP version to load.\n * @returns The PHP loader module.\n */\nexport async function getPHPLoaderModule(\n\tversion: SupportedPHPVersion = LatestSupportedPHPVersion\n): Promise<PHPLoaderModule> {\n\tswitch (version) {\n\t\tcase '8.5':\n\t\t\t// @ts-ignore\n\t\t\treturn (await import('@php-wasm/web-8-5')).getPHPLoaderModule();\n\t\tcase '8.4':\n\t\t\t// @ts-ignore\n\t\t\treturn (await import('@php-wasm/web-8-4')).getPHPLoaderModule();\n\t\tcase '8.3':\n\t\t\t// @ts-ignore\n\t\t\treturn (await import('@php-wasm/web-8-3')).getPHPLoaderModule();\n\t\tcase '8.2':\n\t\t\t// @ts-ignore\n\t\t\treturn (await import('@php-wasm/web-8-2')).getPHPLoaderModule();\n\t\tcase '8.1':\n\t\t\t// @ts-ignore\n\t\t\treturn (await import('@php-wasm/web-8-1')).getPHPLoaderModule();\n\t\tcase '8.0':\n\t\t\t// @ts-ignore\n\t\t\treturn (await import('@php-wasm/web-8-0')).getPHPLoaderModule();\n\t\tcase '7.4':\n\t\t\t// @ts-ignore\n\t\t\treturn (await import('@php-wasm/web-7-4')).getPHPLoaderModule();\n\t\tcase '7.3':\n\t\t\t// @ts-ignore\n\t\t\treturn (await import('@php-wasm/web-7-3')).getPHPLoaderModule();\n\t\tcase '7.2':\n\t\t\t// @ts-ignore\n\t\t\treturn (await import('@php-wasm/web-7-2')).getPHPLoaderModule();\n\t}\n\tthrow new Error(`Unsupported PHP version ${version}`);\n}\n","export function flipObject(obj: Record<any, any>) {\n\treturn Object.fromEntries(Object.entries(obj).map(([k, v]) => [v, k]));\n}\n\nexport function as2Bytes(value: number): Uint8Array {\n\treturn new Uint8Array([(value >> 8) & 0xff, value & 0xff]);\n}\n\nexport function as3Bytes(value: number): Uint8Array {\n\treturn new Uint8Array([\n\t\t(value >> 16) & 0xff,\n\t\t(value >> 8) & 0xff,\n\t\tvalue & 0xff,\n\t]);\n}\n\nexport function as8Bytes(value: number): Uint8Array {\n\tconst buffer = new ArrayBuffer(8);\n\tconst view = new DataView(buffer);\n\tview.setBigUint64(0, BigInt(value), false); // false for big-endian\n\treturn new Uint8Array(buffer);\n}\nexport class ArrayBufferReader {\n\tprivate view: DataView;\n\toffset = 0;\n\tprivate buffer: ArrayBuffer;\n\n\tconstructor(buffer: ArrayBuffer) {\n\t\tthis.buffer = buffer;\n\t\tthis.view = new DataView(buffer);\n\t}\n\n\treadUint8(): number {\n\t\tconst value = this.view.getUint8(this.offset);\n\t\tthis.offset += 1;\n\t\treturn value;\n\t}\n\treadUint16(): number {\n\t\tconst value = this.view.getUint16(this.offset);\n\t\tthis.offset += 2;\n\t\treturn value;\n\t}\n\treadUint32(): number {\n\t\tconst value = this.view.getUint32(this.offset);\n\t\tthis.offset += 4;\n\t\treturn value;\n\t}\n\treadUint8Array(length: number): Uint8Array {\n\t\tconst value = this.buffer.slice(this.offset, this.offset + length);\n\t\tthis.offset += length;\n\t\treturn new Uint8Array(value);\n\t}\n\n\tisFinished() {\n\t\treturn this.offset >= this.buffer.byteLength;\n\t}\n}\n\nexport class ArrayBufferWriter {\n\tbuffer: ArrayBuffer;\n\tview: DataView;\n\tuint8Array: Uint8Array;\n\n\tprivate offset = 0;\n\n\tconstructor(length: number) {\n\t\tthis.buffer = new ArrayBuffer(length);\n\t\tthis.uint8Array = new Uint8Array(this.buffer);\n\t\tthis.view = new DataView(this.buffer);\n\t}\n\n\twriteUint8(value: number) {\n\t\tthis.view.setUint8(this.offset, value);\n\t\tthis.offset += 1;\n\t}\n\n\twriteUint16(value: number) {\n\t\tthis.view.setUint16(this.offset, value);\n\t\tthis.offset += 2;\n\t}\n\n\twriteUint32(value: number) {\n\t\tthis.view.setUint32(this.offset, value);\n\t\tthis.offset += 4;\n\t}\n\n\twriteUint8Array(value: Uint8Array) {\n\t\tthis.uint8Array.set(value, this.offset);\n\t\tthis.offset += value.length;\n\t}\n}\n","/**\n * IANA maintains a list of TLS extensions here:\n * https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml\n */\nexport const ExtensionTypes = {\n\tserver_name: 0,\n\tmax_fragment_length: 1,\n\tclient_certificate_url: 2,\n\ttrusted_ca_keys: 3,\n\ttruncated_hmac: 4,\n\tstatus_request: 5,\n\tuser_mapping: 6,\n\tclient_authz: 7,\n\tserver_authz: 8,\n\tcert_type: 9,\n\tsupported_groups: 10,\n\tec_point_formats: 11,\n\tsrp: 12,\n\tsignature_algorithms: 13,\n\tuse_srtp: 14,\n\theartbeat: 15,\n\tapplication_layer_protocol_negotiation: 16,\n\tstatus_request_v2: 17,\n\tsigned_certificate_timestamp: 18,\n\tclient_certificate_type: 19,\n\tserver_certificate_type: 20,\n\tpadding: 21,\n\tencrypt_then_mac: 22,\n\textended_master_secret: 23,\n\ttoken_binding: 24,\n\tcached_info: 25,\n\ttls_its: 26,\n\tcompress_certificate: 27,\n\trecord_size_limit: 28,\n\tpwd_protect: 29,\n\tpwo_clear: 30,\n\tpassword_salt: 31,\n\tticket_pinning: 32,\n\ttls_cert_with_extern_psk: 33,\n\tdelegated_credential: 34,\n\tsession_ticket: 35,\n\tTLMSP: 36,\n\tTLMSP_proxying: 37,\n\tTLMSP_delegate: 38,\n\tsupported_ekt_ciphers: 39,\n\tpre_shared_key: 41,\n\tearly_data: 42,\n\tsupported_versions: 43,\n\tcookie: 44,\n\tpsk_key_exchange_modes: 45,\n\treserved: 46,\n\tcertificate_authorities: 47,\n\toid_filters: 48,\n\tpost_handshake_auth: 49,\n\tsignature_algorithms_cert: 50,\n\tkey_share: 51,\n\ttransparency_info: 52,\n\tconnection_id: 54,\n} as const;\n\nimport { flipObject } from '../utils';\n\nexport type ExtensionType = keyof typeof ExtensionTypes;\n\nexport const ExtensionNames = flipObject(ExtensionTypes);\nexport type ExtensionName = keyof typeof ExtensionNames;\n","/**\n * TLS server_name extension\n * https://www.rfc-editor.org/rfc/rfc6066.html\n */\n\nimport { ArrayBufferWriter } from '../utils';\nimport { ExtensionTypes } from './types';\nimport { flipObject } from '../utils';\n\nexport interface ServerNameList {\n\tserver_name_list: ServerName[];\n}\n\nexport interface ServerName {\n\tname_type: typeof ServerNameTypes;\n\tname: {\n\t\thost_name: string;\n\t};\n}\n\nexport const ServerNameTypes = {\n\thost_name: 0,\n} as const;\nexport type ServerNameType =\n\t(typeof ServerNameTypes)[keyof typeof ServerNameTypes];\nexport const ServerNameNames = flipObject(ServerNameTypes);\n\nexport class ServerNameExtension {\n\tstatic decodeFromClient(data: Uint8Array): ServerNameList {\n\t\tconst view = new DataView(data.buffer);\n\t\tlet offset = 0;\n\n\t\tconst listLength = view.getUint16(offset);\n\t\toffset += 2;\n\n\t\tconst serverNameList: ServerName[] = [];\n\n\t\twhile (offset < listLength + 2) {\n\t\t\tconst nameType = data[offset] as ServerNameType;\n\t\t\toffset += 1;\n\n\t\t\tconst valueLength = view.getUint16(offset);\n\t\t\toffset += 2;\n\n\t\t\tconst value = data.slice(offset, offset + valueLength);\n\t\t\toffset += valueLength;\n\n\t\t\tswitch (nameType) {\n\t\t\t\tcase ServerNameTypes.host_name:\n\t\t\t\t\tserverNameList.push({\n\t\t\t\t\t\tname_type: ServerNameNames[nameType],\n\t\t\t\t\t\tname: {\n\t\t\t\t\t\t\thost_name: new TextDecoder().decode(value),\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tthrow new Error(`Unsupported name type ${nameType}`);\n\t\t\t}\n\t\t}\n\n\t\treturn { server_name_list: serverNameList };\n\t}\n\n\t/**\n\t * Encode the server_name extension\n\t *\n\t * +------------------------------------+\n\t * | Extension Type (server_name) [2B] |\n\t * | 0x00 0x00 |\n\t * +------------------------------------+\n\t * | Extension Length [2B] |\n\t * | 0x00 0x00 |\n\t * +------------------------------------+\n\t */\n\tstatic encodeForClient(serverNames?: ServerNameList) {\n\t\tif (serverNames?.server_name_list.length) {\n\t\t\tthrow new Error(\n\t\t\t\t'Encoding non-empty lists for ClientHello is not supported yet. ' +\n\t\t\t\t\t'Only empty lists meant for ServerHello are supported today.'\n\t\t\t);\n\t\t}\n\n\t\tconst writer = new ArrayBufferWriter(4);\n\t\twriter.writeUint16(ExtensionTypes.server_name);\n\t\t// Zero body length encoded using two bytes\n\t\twriter.writeUint16(0);\n\t\treturn writer.uint8Array;\n\t}\n}\n","import { flipObject } from './utils';\n\n/**\n * TLS1 cipher suites sourced from OpenSSL:\n *\n * https://github.com/openssl/openssl/blob/36254fda37fe169e136079404a3c32aeea35cbd4/include/openssl/tls1.h#L371\n */\nexport const CipherSuites = {\n\tTLS1_CK_PSK_WITH_RC4_128_SHA: 0x008a,\n\tTLS1_CK_PSK_WITH_3DES_EDE_CBC_SHA: 0x008b,\n\tTLS1_CK_PSK_WITH_AES_128_CBC_SHA: 0x008c,\n\tTLS1_CK_PSK_WITH_AES_256_CBC_SHA: 0x008d,\n\tTLS1_CK_DHE_PSK_WITH_RC4_128_SHA: 0x008e,\n\tTLS1_CK_DHE_PSK_WITH_3DES_EDE_CBC_SHA: 0x008f,\n\tTLS1_CK_DHE_PSK_WITH_AES_128_CBC_SHA: 0x0090,\n\tTLS1_CK_DHE_PSK_WITH_AES_256_CBC_SHA: 0x0091,\n\tTLS1_CK_RSA_PSK_WITH_RC4_128_SHA: 0x0092,\n\tTLS1_CK_RSA_PSK_WITH_3DES_EDE_CBC_SHA: 0x0093,\n\tTLS1_CK_RSA_PSK_WITH_AES_128_CBC_SHA: 0x0094,\n\tTLS1_CK_RSA_PSK_WITH_AES_256_CBC_SHA: 0x0095,\n\tTLS1_CK_PSK_WITH_AES_128_GCM_SHA256: 0x00a8,\n\tTLS1_CK_PSK_WITH_AES_256_GCM_SHA384: 0x00a9,\n\tTLS1_CK_DHE_PSK_WITH_AES_128_GCM_SHA256: 0x00aa,\n\tTLS1_CK_DHE_PSK_WITH_AES_256_GCM_SHA384: 0x00ab,\n\tTLS1_CK_RSA_PSK_WITH_AES_128_GCM_SHA256: 0x00ac,\n\tTLS1_CK_RSA_PSK_WITH_AES_256_GCM_SHA384: 0x00ad,\n\tTLS1_CK_PSK_WITH_AES_128_CBC_SHA256: 0x00ae,\n\tTLS1_CK_PSK_WITH_AES_256_CBC_SHA384: 0x00af,\n\tTLS1_CK_PSK_WITH_NULL_SHA256: 0x00b0,\n\tTLS1_CK_PSK_WITH_NULL_SHA384: 0x00b1,\n\tTLS1_CK_DHE_PSK_WITH_AES_128_CBC_SHA256: 0x00b2,\n\tTLS1_CK_DHE_PSK_WITH_AES_256_CBC_SHA384: 0x00b3,\n\tTLS1_CK_DHE_PSK_WITH_NULL_SHA256: 0x00b4,\n\tTLS1_CK_DHE_PSK_WITH_NULL_SHA384: 0x00b5,\n\tTLS1_CK_RSA_PSK_WITH_AES_128_CBC_SHA256: 0x00b6,\n\tTLS1_CK_RSA_PSK_WITH_AES_256_CBC_SHA384: 0x00b7,\n\tTLS1_CK_RSA_PSK_WITH_NULL_SHA256: 0x00b8,\n\tTLS1_CK_RSA_PSK_WITH_NULL_SHA384: 0x00b9,\n\tTLS1_CK_PSK_WITH_NULL_SHA: 0x002c,\n\tTLS1_CK_DHE_PSK_WITH_NULL_SHA: 0x002d,\n\tTLS1_CK_RSA_PSK_WITH_NULL_SHA: 0x002e,\n\tTLS1_CK_RSA_WITH_AES_128_SHA: 0x002f,\n\tTLS1_CK_DH_DSS_WITH_AES_128_SHA: 0x0030,\n\tTLS1_CK_DH_RSA_WITH_AES_128_SHA: 0x0031,\n\tTLS1_CK_DHE_DSS_WITH_AES_128_SHA: 0x0032,\n\tTLS1_CK_DHE_RSA_WITH_AES_128_SHA: 0x0033,\n\tTLS1_CK_ADH_WITH_AES_128_SHA: 0x0034,\n\tTLS1_CK_RSA_WITH_AES_256_SHA: 0x0035,\n\tTLS1_CK_DH_DSS_WITH_AES_256_SHA: 0x0036,\n\tTLS1_CK_DH_RSA_WITH_AES_256_SHA: 0x0037,\n\tTLS1_CK_DHE_DSS_WITH_AES_256_SHA: 0x0038,\n\tTLS1_CK_DHE_RSA_WITH_AES_256_SHA: 0x0039,\n\tTLS1_CK_ADH_WITH_AES_256_SHA: 0x003a,\n\tTLS1_CK_RSA_WITH_NULL_SHA256: 0x003b,\n\tTLS1_CK_RSA_WITH_AES_128_SHA256: 0x003c,\n\tTLS1_CK_RSA_WITH_AES_256_SHA256: 0x003d,\n\tTLS1_CK_DH_DSS_WITH_AES_128_SHA256: 0x003e,\n\tTLS1_CK_DH_RSA_WITH_AES_128_SHA256: 0x003f,\n\tTLS1_CK_DHE_DSS_WITH_AES_128_SHA256: 0x0040,\n\tTLS1_CK_RSA_WITH_CAMELLIA_128_CBC_SHA: 0x0041,\n\tTLS1_CK_DH_DSS_WITH_CAMELLIA_128_CBC_SHA: 0x0042,\n\tTLS1_CK_DH_RSA_WITH_CAMELLIA_128_CBC_SHA: 0x0043,\n\tTLS1_CK_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA: 0x0044,\n\tTLS1_CK_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA: 0x0045,\n\tTLS1_CK_ADH_WITH_CAMELLIA_128_CBC_SHA: 0x0046,\n\tTLS1_CK_DHE_RSA_WITH_AES_128_SHA256: 0x0067,\n\tTLS1_CK_DH_DSS_WITH_AES_256_SHA256: 0x0068,\n\tTLS1_CK_DH_RSA_WITH_AES_256_SHA256: 0x0069,\n\tTLS1_CK_DHE_DSS_WITH_AES_256_SHA256: 0x006a,\n\tTLS1_CK_DHE_RSA_WITH_AES_256_SHA256: 0x006b,\n\tTLS1_CK_ADH_WITH_AES_128_SHA256: 0x006c,\n\tTLS1_CK_ADH_WITH_AES_256_SHA256: 0x006d,\n\tTLS1_CK_RSA_WITH_CAMELLIA_256_CBC_SHA: 0x0084,\n\tTLS1_CK_DH_DSS_WITH_CAMELLIA_256_CBC_SHA: 0x0085,\n\tTLS1_CK_DH_RSA_WITH_CAMELLIA_256_CBC_SHA: 0x0086,\n\tTLS1_CK_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA: 0x0087,\n\tTLS1_CK_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA: 0x0088,\n\tTLS1_CK_ADH_WITH_CAMELLIA_256_CBC_SHA: 0x0089,\n\tTLS1_CK_RSA_WITH_SEED_SHA: 0x0096,\n\tTLS1_CK_DH_DSS_WITH_SEED_SHA: 0x0097,\n\tTLS1_CK_DH_RSA_WITH_SEED_SHA: 0x0098,\n\tTLS1_CK_DHE_DSS_WITH_SEED_SHA: 0x0099,\n\tTLS1_CK_DHE_RSA_WITH_SEED_SHA: 0x009a,\n\tTLS1_CK_ADH_WITH_SEED_SHA: 0x009b,\n\tTLS1_CK_RSA_WITH_AES_128_GCM_SHA256: 0x009c,\n\tTLS1_CK_RSA_WITH_AES_256_GCM_SHA384: 0x009d,\n\tTLS1_CK_DHE_RSA_WITH_AES_128_GCM_SHA256: 0x009e,\n\tTLS1_CK_DHE_RSA_WITH_AES_256_GCM_SHA384: 0x009f,\n\tTLS1_CK_DH_RSA_WITH_AES_128_GCM_SHA256: 0x00a0,\n\tTLS1_CK_DH_RSA_WITH_AES_256_GCM_SHA384: 0x00a1,\n\tTLS1_CK_DHE_DSS_WITH_AES_128_GCM_SHA256: 0x00a2,\n\tTLS1_CK_DHE_DSS_WITH_AES_256_GCM_SHA384: 0x00a3,\n\tTLS1_CK_DH_DSS_WITH_AES_128_GCM_SHA256: 0x00a4,\n\tTLS1_CK_DH_DSS_WITH_AES_256_GCM_SHA384: 0x00a5,\n\tTLS1_CK_ADH_WITH_AES_128_GCM_SHA256: 0x00a6,\n\tTLS1_CK_ADH_WITH_AES_256_GCM_SHA384: 0x00a7,\n\tTLS1_CK_RSA_WITH_AES_128_CCM: 0xc09c,\n\tTLS1_CK_RSA_WITH_AES_256_CCM: 0xc09d,\n\tTLS1_CK_DHE_RSA_WITH_AES_128_CCM: 0xc09e,\n\tTLS1_CK_DHE_RSA_WITH_AES_256_CCM: 0xc09f,\n\tTLS1_CK_RSA_WITH_AES_128_CCM_8: 0xc0a0,\n\tTLS1_CK_RSA_WITH_AES_256_CCM_8: 0xc0a1,\n\tTLS1_CK_DHE_RSA_WITH_AES_128_CCM_8: 0xc0a2,\n\tTLS1_CK_DHE_RSA_WITH_AES_256_CCM_8: 0xc0a3,\n\tTLS1_CK_PSK_WITH_AES_128_CCM: 0xc0a4,\n\tTLS1_CK_PSK_WITH_AES_256_CCM: 0xc0a5,\n\tTLS1_CK_DHE_PSK_WITH_AES_128_CCM: 0xc0a6,\n\tTLS1_CK_DHE_PSK_WITH_AES_256_CCM: 0xc0a7,\n\tTLS1_CK_PSK_WITH_AES_128_CCM_8: 0xc0a8,\n\tTLS1_CK_PSK_WITH_AES_256_CCM_8: 0xc0a9,\n\tTLS1_CK_DHE_PSK_WITH_AES_128_CCM_8: 0xc0aa,\n\tTLS1_CK_DHE_PSK_WITH_AES_256_CCM_8: 0xc0ab,\n\tTLS1_CK_ECDHE_ECDSA_WITH_AES_128_CCM: 0xc0ac,\n\tTLS1_CK_ECDHE_ECDSA_WITH_AES_256_CCM: 0xc0ad,\n\tTLS1_CK_ECDHE_ECDSA_WITH_AES_128_CCM_8: 0xc0ae,\n\tTLS1_CK_ECDHE_ECDSA_WITH_AES_256_CCM_8: 0xc0af,\n\tTLS1_CK_RSA_WITH_CAMELLIA_128_CBC_SHA256: 0x00ba,\n\tTLS1_CK_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256: 0x00bb,\n\tTLS1_CK_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256: 0x00bc,\n\tTLS1_CK_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256: 0x00bd,\n\tTLS1_CK_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: 0x00be,\n\tTLS1_CK_ADH_WITH_CAMELLIA_128_CBC_SHA256: 0x00bf,\n\tTLS1_CK_RSA_WITH_CAMELLIA_256_CBC_SHA256: 0x00c0,\n\tTLS1_CK_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256: 0x00c1,\n\tTLS1_CK_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256: 0x00c2,\n\tTLS1_CK_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256: 0x00c3,\n\tTLS1_CK_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256: 0x00c4,\n\tTLS1_CK_ADH_WITH_CAMELLIA_256_CBC_SHA256: 0x00c5,\n\tTLS1_CK_ECDH_ECDSA_WITH_NULL_SHA: 0xc001,\n\tTLS1_CK_ECDH_ECDSA_WITH_RC4_128_SHA: 0xc002,\n\tTLS1_CK_ECDH_ECDSA_WITH_DES_192_CBC3_SHA: 0xc003,\n\tTLS1_CK_ECDH_ECDSA_WITH_AES_128_CBC_SHA: 0xc004,\n\tTLS1_CK_ECDH_ECDSA_WITH_AES_256_CBC_SHA: 0xc005,\n\tTLS1_CK_ECDHE_ECDSA_WITH_NULL_SHA: 0xc006,\n\tTLS1_CK_ECDHE_ECDSA_WITH_RC4_128_SHA: 0xc007,\n\tTLS1_CK_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA: 0xc008,\n\tTLS1_CK_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: 0xc009,\n\tTLS1_CK_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: 0xc00a,\n\tTLS1_CK_ECDH_RSA_WITH_NULL_SHA: 0xc00b,\n\tTLS1_CK_ECDH_RSA_WITH_RC4_128_SHA: 0xc00c,\n\tTLS1_CK_ECDH_RSA_WITH_DES_192_CBC3_SHA: 0xc00d,\n\tTLS1_CK_ECDH_RSA_WITH_AES_128_CBC_SHA: 0xc00e,\n\tTLS1_CK_ECDH_RSA_WITH_AES_256_CBC_SHA: 0xc00f,\n\tTLS1_CK_ECDHE_RSA_WITH_NULL_SHA: 0xc010,\n\tTLS1_CK_ECDHE_RSA_WITH_RC4_128_SHA: 0xc011,\n\tTLS1_CK_ECDHE_RSA_WITH_DES_192_CBC3_SHA: 0xc012,\n\tTLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA: 0xc013,\n\tTLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA: 0xc014,\n\tTLS1_CK_ECDH_anon_WITH_NULL_SHA: 0xc015,\n\tTLS1_CK_ECDH_anon_WITH_RC4_128_SHA: 0xc016,\n\tTLS1_CK_ECDH_anon_WITH_DES_192_CBC3_SHA: 0xc017,\n\tTLS1_CK_ECDH_anon_WITH_AES_128_CBC_SHA: 0xc018,\n\tTLS1_CK_ECDH_anon_WITH_AES_256_CBC_SHA: 0xc019,\n\tTLS1_CK_SRP_SHA_WITH_3DES_EDE_CBC_SHA: 0xc01a,\n\tTLS1_CK_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA: 0xc01b,\n\tTLS1_CK_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA: 0xc01c,\n\tTLS1_CK_SRP_SHA_WITH_AES_128_CBC_SHA: 0xc01d,\n\tTLS1_CK_SRP_SHA_RSA_WITH_AES_128_CBC_SHA: 0xc01e,\n\tTLS1_CK_SRP_SHA_DSS_WITH_AES_128_CBC_SHA: 0xc01f,\n\tTLS1_CK_SRP_SHA_WITH_AES_256_CBC_SHA: 0xc020,\n\tTLS1_CK_SRP_SHA_RSA_WITH_AES_256_CBC_SHA: 0xc021,\n\tTLS1_CK_SRP_SHA_DSS_WITH_AES_256_CBC_SHA: 0xc022,\n\tTLS1_CK_ECDHE_ECDSA_WITH_AES_128_SHA256: 0xc023,\n\tTLS1_CK_ECDHE_ECDSA_WITH_AES_256_SHA384: 0xc024,\n\tTLS1_CK_ECDH_ECDSA_WITH_AES_128_SHA256: 0xc025,\n\tTLS1_CK_ECDH_ECDSA_WITH_AES_256_SHA384: 0xc026,\n\tTLS1_CK_ECDHE_RSA_WITH_AES_128_SHA256: 0xc027,\n\tTLS1_CK_ECDHE_RSA_WITH_AES_256_SHA384: 0xc028,\n\tTLS1_CK_ECDH_RSA_WITH_AES_128_SHA256: 0xc029,\n\tTLS1_CK_ECDH_RSA_WITH_AES_256_SHA384: 0xc02a,\n\tTLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: 0xc02b,\n\tTLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: 0xc02c,\n\tTLS1_CK_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: 0xc02d,\n\tTLS1_CK_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: 0xc02e,\n\tTLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256: 0xc02f,\n\tTLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384: 0xc030,\n\tTLS1_CK_ECDH_RSA_WITH_AES_128_GCM_SHA256: 0xc031,\n\tTLS1_CK_ECDH_RSA_WITH_AES_256_GCM_SHA384: 0xc032,\n\tTLS1_CK_ECDHE_PSK_WITH_RC4_128_SHA: 0xc033,\n\tTLS1_CK_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA: 0xc034,\n\tTLS1_CK_ECDHE_PSK_WITH_AES_128_CBC_SHA: 0xc035,\n\tTLS1_CK_ECDHE_PSK_WITH_AES_256_CBC_SHA: 0xc036,\n\tTLS1_CK_ECDHE_PSK_WITH_AES_128_CBC_SHA256: 0xc037,\n\tTLS1_CK_ECDHE_PSK_WITH_AES_256_CBC_SHA384: 0xc038,\n\tTLS1_CK_ECDHE_PSK_WITH_NULL_SHA: 0xc039,\n\tTLS1_CK_ECDHE_PSK_WITH_NULL_SHA256: 0xc03a,\n\tTLS1_CK_ECDHE_PSK_WITH_NULL_SHA384: 0xc03b,\n\tTLS1_CK_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: 0xc072,\n\tTLS1_CK_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: 0xc073,\n\tTLS1_CK_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: 0xc074,\n\tTLS1_CK_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: 0xc075,\n\tTLS1_CK_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: 0xc076,\n\tTLS1_CK_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384: 0xc077,\n\tTLS1_CK_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256: 0xc078,\n\tTLS1_CK_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384: 0xc079,\n\tTLS1_CK_PSK_WITH_CAMELLIA_128_CBC_SHA256: 0xc094,\n\tTLS1_CK_PSK_WITH_CAMELLIA_256_CBC_SHA384: 0xc095,\n\tTLS1_CK_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256: 0xc096,\n\tTLS1_CK_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384: 0xc097,\n\tTLS1_CK_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256: 0xc098,\n\tTLS1_CK_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384: 0xc099,\n\tTLS1_CK_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256: 0xc09a,\n\tTLS1_CK_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384: 0xc09b,\n\tTLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305: 0xcca8,\n\tTLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305: 0xcca9,\n\tTLS1_CK_DHE_RSA_WITH_CHACHA20_POLY1305: 0xccaa,\n\tTLS1_CK_PSK_WITH_CHACHA20_POLY1305: 0xccab,\n\tTLS1_CK_ECDHE_PSK_WITH_CHACHA20_POLY1305: 0xccac,\n\tTLS1_CK_DHE_PSK_WITH_CHACHA20_POLY1305: 0xccad,\n\tTLS1_CK_RSA_PSK_WITH_CHACHA20_POLY1305: 0xccae,\n} as const;\n\nexport const CipherSuitesNames = flipObject(CipherSuites);\n","/**\n * TLS supported_groups extension\n * https://www.iana.org/go/rfc7919\n * https://www.iana.org/go/rfc8422\n */\n\nimport { ArrayBufferReader, ArrayBufferWriter } from '../utils';\nimport { ExtensionTypes } from './types';\nimport { flipObject } from '../utils';\n\nexport const SupportedGroups = {\n\tsecp256r1: 23,\n\tsecp384r1: 24,\n\tsecp521r1: 25,\n\tx25519: 29,\n\tx448: 30,\n} as const;\nexport const SupportedGroupsNames = flipObject(SupportedGroups);\nexport type SupportedGroup = keyof typeof SupportedGroups;\n\nexport type ParsedSupportedGroups = (keyof typeof SupportedGroups)[];\n\nexport class SupportedGroupsExtension {\n\t/**\n\t * +--------------------------------------------------+\n\t * | Payload Length [2B] |\n\t * +--------------------------------------------------+\n\t * | Supported Groups List Length [2B] |\n\t * +--------------------------------------------------+\n\t * | Supported Group 1 [2B] |\n\t * +--------------------------------------------------+\n\t * | Supported Group 2 [2B] |\n\t * +--------------------------------------------------+\n\t * | ... |\n\t * +--------------------------------------------------+\n\t * | Supported Group n [2B] |\n\t * +--------------------------------------------------+\n\t */\n\tstatic decodeFromClient(data: Uint8Array): ParsedSupportedGroups {\n\t\tconst reader = new ArrayBufferReader(data.buffer);\n\t\t// Skip the length field\n\t\treader.readUint16();\n\t\tconst groups = [];\n\t\twhile (!reader.isFinished()) {\n\t\t\tconst group = reader.readUint16();\n\t\t\tif (!(group in SupportedGroupsNames)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tgroups.push(SupportedGroupsNames[group]);\n\t\t}\n\t\treturn groups;\n\t}\n\n\t/**\n\t * +--------------------------------------------------+\n\t * | Extension Type (supported_groups) [2B] |\n\t * | 0x00 0x0A |\n\t * +--------------------------------------------------+\n\t * | Extension Length [2B] |\n\t * +--------------------------------------------------+\n\t * | Selected Group [2B] |\n\t * +--------------------------------------------------+\n\t */\n\tstatic encodeForClient(group: SupportedGroup): Uint8Array {\n\t\tconst writer = new ArrayBufferWriter(6);\n\t\twriter.writeUint16(ExtensionTypes.supported_groups);\n\t\twriter.writeUint16(2);\n\t\twriter.writeUint16(SupportedGroups[group]);\n\t\treturn writer.uint8Array;\n\t}\n}\n","/**\n * TLS ec_point_formats extension\n * https://www.rfc-editor.org/rfc/rfc4492#section-5.1.2\n */\n\nimport { ArrayBufferReader, ArrayBufferWriter } from '../utils';\nimport { ExtensionTypes } from './types';\nimport { flipObject } from '../utils';\n\nexport const ECPointFormats = {\n\tuncompressed: 0,\n\tansiX962_compressed_prime: 1,\n\tansiX962_compressed_char2: 2,\n} as const;\nexport type ECPointFormat = keyof typeof ECPointFormats;\n\nexport const ECPointFormatNames = flipObject(ECPointFormats);\n\nexport type ParsedECPointFormats = (keyof typeof ECPointFormats)[];\n\nexport class ECPointFormatsExtension {\n\t/**\n\t * +--------------------------------------------------+\n\t * | Payload Length [2B] |\n\t * +--------------------------------------------------+\n\t * | EC Point Formats Length [1B] |\n\t * +--------------------------------------------------+\n\t * | EC Point Format 1 [1B] |\n\t * +--------------------------------------------------+\n\t * | EC Point Format 2 [1B] |\n\t * +--------------------------------------------------+\n\t * | ... |\n\t * +--------------------------------------------------+\n\t * | EC Point Format n [1B] |\n\t * +--------------------------------------------------+\n\t */\n\tstatic decodeFromClient(data: Uint8Array): ParsedECPointFormats {\n\t\tconst reader = new ArrayBufferReader(data.buffer);\n\t\t// Read the EC Point Formats Length\n\t\tconst length = reader.readUint8();\n\t\tconst formats = [];\n\t\tfor (let i = 0; i < length; i++) {\n\t\t\tconst format = reader.readUint8();\n\t\t\tif (format in ECPointFormatNames) {\n\t\t\t\tformats.push(ECPointFormatNames[format]);\n\t\t\t}\n\t\t}\n\t\treturn formats;\n\t}\n\n\t/**\n\t * Encode the ec_point_formats extension\n\t *\n\t * +--------------------------------------------------+\n\t * | Extension Type (ec_point_formats) [2B] |\n\t * | 0x00 0x0B |\n\t * +--------------------------------------------------+\n\t * | Body Length [2B] |\n\t * +--------------------------------------------------+\n\t * | EC Point Format Length [1B] |\n\t * +--------------------------------------------------+\n\t * | EC Point Format [1B] |\n\t * +--------------------------------------------------+\n\t */\n\tstatic encodeForClient(format: ECPointFormat): Uint8Array {\n\t\tconst writer = new ArrayBufferWriter(6);\n\t\twriter.writeUint16(ExtensionTypes.ec_point_formats);\n\t\twriter.writeUint16(2); // Body length\n\t\twriter.writeUint8(1); // EC Point Formats Length\n\t\twriter.writeUint8(ECPointFormats[format]);\n\t\treturn writer.uint8Array;\n\t}\n}\n","/**\n * TLS signature_algorithms extension\n * https://www.rfc-editor.org/rfc/rfc8446.html#page-41\n */\n\nimport { ArrayBufferReader, ArrayBufferWriter } from '../utils';\nimport { ExtensionTypes } from './types';\nimport { flipObject } from '../utils';\nimport { logger } from '@php-wasm/logger';\n\n/**\n * A list of supported signature algorithms,\n * one byte per algorithm.\n */\nexport type SignatureAlgorithms = Uint8Array;\n\n/**\n * Signature algorithms from\n * https://datatracker.ietf.org/doc/html/rfc5246#section-7.4.1.4.1\n */\nexport const SignatureAlgorithms = {\n\tanonymous: 0,\n\trsa: 1,\n\tdsa: 2,\n\tecdsa: 3,\n};\nexport type SignatureAlgorithm = keyof typeof SignatureAlgorithms;\nexport const SignatureAlgorithmsNames = flipObject(SignatureAlgorithms);\n\n/**\n * Hash algorithms from\n * https://datatracker.ietf.org/doc/html/rfc5246#section-7.4.1.4.1\n */\nexport const HashAlgorithms = {\n\tnone: 0,\n\tmd5: 1,\n\tsha1: 2,\n\tsha224: 3,\n\tsha256: 4,\n\tsha384: 5,\n\tsha512: 6,\n};\nexport type HashAlgorithm = keyof typeof HashAlgorithms;\nexport const HashAlgorithmsNames = flipObject(HashAlgorithms);\n\nexport type ParsedSignatureAlgorithm = {\n\thash: HashAlgorithm;\n\talgorithm: SignatureAlgorithm;\n};\n\n/**\n * Handles the signature algorithms extension as defined in\n * https://www.rfc-editor.org/rfc/rfc8446.html#page-41\n */\nexport class SignatureAlgorithmsExtension {\n\t/**\n\t * Binary layout:\n\t *\n\t * +------------------------------------+\n\t * | Payload Length [2B] |\n\t * +------------------------------------+\n\t * | Hash Algorithm 1 [1B] |\n\t * | Signature Algorithm 1 [1B] |\n\t * +------------------------------------+\n\t * | Hash Algorithm 2 [1B] |\n\t * | Signature Algorithm 2 [1B] |\n\t * +------------------------------------+\n\t * | ... |\n\t * +------------------------------------+\n\t */\n\tstatic decodeFromClient(data: Uint8Array): ParsedSignatureAlgorithm[] {\n\t\tconst reader = new ArrayBufferReader(data.buffer);\n\t\treader.readUint16(); // Skip algorithms length\n\t\tconst parsedAlgorithms: ParsedSignatureAlgorithm[] = [];\n\t\twhile (!reader.isFinished()) {\n\t\t\tconst hash = reader.readUint8();\n\t\t\tconst algorithm = reader.readUint8();\n\t\t\tif (!SignatureAlgorithmsNames[algorithm]) {\n\t\t\t\t// Unknown signature algorithm. It's fine, the client just supports\n\t\t\t\t// more algorithms than the server.\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!HashAlgorithmsNames[hash]) {\n\t\t\t\tlogger.warn(`Unknown hash algorithm: ${hash}`);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tparsedAlgorithms.push({\n\t\t\t\talgorithm: SignatureAlgorithmsNames[algorithm],\n\t\t\t\thash: HashAlgorithmsNames[hash],\n\t\t\t});\n\t\t}\n\t\treturn parsedAlgorithms;\n\t}\n\n\t/**\n\t * +--------------------------------------------------+\n\t * | Extension Type (signature_algorithms) [2B] |\n\t * | 0x00 0x0D |\n\t * +--------------------------------------------------+\n\t * | Body Length [2B] |\n\t * +--------------------------------------------------+\n\t * | Hash Algorithm [1B] |\n\t * | Signature Algorithm [1B] |\n\t * +--------------------------------------------------+\n\t */\n\tstatic encodeforClient(\n\t\thash: HashAlgorithm,\n\t\talgorithm: SignatureAlgorithm\n\t): Uint8Array {\n\t\tconst writer = new ArrayBufferWriter(6);\n\t\twriter.writeUint16(ExtensionTypes.signature_algorithms);\n\t\twriter.writeUint16(2);\n\t\twriter.writeUint8(HashAlgorithms[hash]);\n\t\twriter.writeUint8(SignatureAlgorithms[algorithm]);\n\t\treturn writer.uint8Array;\n\t}\n}\n","/**\n * Glue for the implemented TLS extensions\n * For the full list of TLS extensions, see\n * https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml */\nimport { ArrayBufferReader } from '../utils';\nimport type { ServerNameList } from './0_server_name';\nimport { ServerNameExtension } from './0_server_name';\nimport type { ParsedSupportedGroups } from './10_supported_groups';\nimport { SupportedGroupsExtension } from './10_supported_groups';\nimport type { ParsedECPointFormats } from './11_ec_point_formats';\nimport { ECPointFormatsExtension } from './11_ec_point_formats';\nimport type { SignatureAlgorithms } from './13_signature_algorithms';\nimport { SignatureAlgorithmsExtension } from './13_signature_algorithms';\nimport { ExtensionNames } from './types';\n\nexport const TLSExtensionsHandlers = {\n\tserver_name: ServerNameExtension,\n\tsignature_algorithms: SignatureAlgorithmsExtension,\n\tsupported_groups: SupportedGroupsExtension,\n\tec_point_formats: ECPointFormatsExtension,\n} as const;\n\nexport type SupportedTLSExtension = keyof typeof TLSExtensionsHandlers;\n\nexport type ParsedExtension =\n\t| {\n\t\t\ttype: 'server_name';\n\t\t\tdata: ServerNameList;\n\t\t\traw: Uint8Array;\n\t }\n\t| {\n\t\t\ttype: 'signature_algorithms';\n\t\t\tdata: SignatureAlgorithms;\n\t\t\traw: Uint8Array;\n\t }\n\t| {\n\t\t\ttype: 'ec_point_formats';\n\t\t\tdata: ParsedECPointFormats;\n\t\t\traw: Uint8Array;\n\t }\n\t| {\n\t\t\ttype: 'supported_groups';\n\t\t\tdata: ParsedSupportedGroups;\n\t\t\traw: Uint8Array;\n\t };\n\n/**\n * The extensions in a ClientHello message are encoded as follows:\n *\n * struct {\n * ExtensionType extension_type;\n * opaque extension_data<0..2^16-1>;\n * } Extension;\n *\n * The overall extensions structure is:\n *\n * Extension extensions<0..2^16-1>;\n *\n * This means:\n * •\tThere's a 2-byte length field for the entire extensions block.\n * •\tFollowed by zero or more individual extensions.\n *\n * Binary Data Layout\n *\n * +-----------------------------+\n * | Extension 1 Type (2 bytes) |\n * +-----------------------------+\n * | Extension 1 Length (2 bytes)|\n * +-----------------------------+\n * | Extension 1 Data (variable) |\n * +-----------------------------+\n * | Extension 2 Type (2 bytes) |\n * +-----------------------------+\n * | Extension 2 Length (2 bytes)|\n * +-----------------------------+\n * | Extension 2 Data (variable) |\n * +-----------------------------+\n * | ... (more extensions) |\n * +-----------------------------+\n *\n * @param data\n * @returns\n */\nexport function parseClientHelloExtensions(data: Uint8Array) {\n\tconst reader = new ArrayBufferReader(data.buffer);\n\n\tconst parsed: ParsedExtension[] = [];\n\twhile (!reader.isFinished()) {\n\t\tconst initialOffset = reader.offset;\n\t\tconst extensionType = reader.readUint16();\n\t\tconst extensionTypeName = ExtensionNames[extensionType];\n\t\tconst extensionLength = reader.readUint16();\n\t\tconst extensionBytes = reader.readUint8Array(extensionLength);\n\n\t\tif (!(extensionTypeName in TLSExtensionsHandlers)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst handler =\n\t\t\tTLSExtensionsHandlers[\n\t\t\t\textensionTypeName as keyof typeof TLSExtensionsHandlers\n\t\t\t];\n\t\tparsed.push({\n\t\t\ttype: extensionTypeName,\n\t\t\tdata: handler.decodeFromClient(extensionBytes) as any,\n\t\t\traw: data.slice(initialOffset, initialOffset + 4 + extensionLength),\n\t\t});\n\t}\n\n\treturn parsed;\n}\n","import { concatArrayBuffers } from '@php-wasm/util';\n\n/**\n * Implements the TLS 1.2 PRF using HMAC-SHA256.\n *\n * See https://datatracker.ietf.org/doc/html/rfc5246#section-5\n */\nexport async function tls12Prf(\n\tsecret: ArrayBuffer,\n\tlabel: ArrayBuffer,\n\tseed: ArrayBuffer,\n\toutputLength: number\n): Promise<ArrayBuffer> {\n\tconst seedBytes = concatArrayBuffers([label, seed]);\n\n\t// Import the secret as a CryptoKey\n\tconst hmacKey = await crypto.subtle.importKey(\n\t\t'raw',\n\t\tsecret,\n\t\t{ name: 'HMAC', hash: { name: 'SHA-256' } },\n\t\tfalse,\n\t\t['sign']\n\t);\n\n\tlet A = seedBytes; // Initialize A(0) = seedBytes\n\tconst resultBuffers: ArrayBuffer[] = [];\n\n\twhile (concatArrayBuffers(resultBuffers).byteLength < outputLength) {\n\t\t// A(i) = HMAC_hash(secret, A(i-1))\n\t\tA = await hmacSha256(hmacKey, A);\n\n\t\t// Compute HMAC_hash(secret, A(i) + seedBytes)\n\t\tconst hmacInput = concatArrayBuffers([A, seedBytes]);\n\t\tconst fragment = await hmacSha256(hmacKey, hmacInput);\n\n\t\tresultBuffers.push(fragment);\n\t}\n\n\t// Concatenate and trim the result to the desired length\n\tconst fullResult = concatArrayBuffers(resultBuffers);\n\treturn fullResult.slice(0, outputLength);\n}\n\nexport async function hmacSha256(\n\tkey: CryptoKey,\n\tdata: ArrayBuffer\n): Promise<ArrayBuffer> {\n\treturn await crypto.subtle.sign(\n\t\t{ name: 'HMAC', hash: 'SHA-256' },\n\t\tkey,\n\t\tdata\n\t);\n}\n","/**\n * TLS 1.2 Record layer types defined after the structs\n * from the TLS 1.2 RFC.\n * https://datatracker.ietf.org/doc/html/rfc5246#section-6.2\n */\n\nimport type { ParsedExtension } from '../extensions/parse-extensions';\nimport { flipObject } from '../utils';\n\nexport const CompressionMethod = {\n\tNull: 0,\n\tDeflate: 1,\n} as const;\nexport type CompressionMethod =\n\t(typeof CompressionMethod)[keyof typeof CompressionMethod];\n\n/**\n * TLS 1.2 Record layer types defined after the structs\n * from the TLS 1.2 RFC.\n * https://datatracker.ietf.org/doc/html/rfc5246#section-6.2.1\n */\n\nexport interface TLSRecord {\n\ttype: ContentType; // 1 byte\n\tversion: ProtocolVersion; // 2 bytes\n\tlength: number; // 2 bytes\n\tfragment: Uint8Array; // variable length\n}\n\nexport interface ProtocolVersion {\n\tmajor: number;\n\tminor: number;\n}\n\nexport interface GenericStreamCipher {\n\tcontent: Uint8Array;\n\tMAC: Uint8Array;\n}\n\nexport interface GenericBlockCipher {\n\tIV: Uint8Array;\n\tblock_ciphered: BlockCiphered;\n}\n\nexport interface BlockCiphered {\n\tcontent: Uint8Array;\n\tMAC: Uint8Array;\n\tpadding: Uint8Array;\n\tpadding_length: number;\n}\n\nexport interface GenericAEADCipher {\n\tnonce_explicit: Uint8Array;\n\taead_encrypted: Uint8Array;\n}\n\n/**\n * TLS 1.2 Handshake types defined after the structs\n * from the TLS 1.2 RFC.\n * https://datatracker.ietf.org/doc/html/rfc5246#section-7.4\n */\n\nexport type TLSMessage =\n\t| AlertMessage\n\t| HandshakeMessage<any>\n\t| ChangeCipherSpecMessage\n\t| ApplicationDataMessage;\n\nexport interface AlertMessage {\n\ttype: typeof ContentTypes.Alert;\n\tlevel: AlertLevel;\n\tdescription: AlertDescription;\n}\n\nexport const AlertLevels = {\n\tWarning: 1,\n\tFatal: 2,\n} as const;\nexport type AlertLevel = (typeof AlertLevels)[keyof typeof AlertLevels];\nexport const AlertLevelNames = flipObject(AlertLevels);\n\nexport const AlertDescriptions = {\n\tCloseNotify: 0,\n\tUnexpectedMessage: 10,\n\tBadRecordMac: 20,\n\tDecryptionFailed: 21,\n\tRecordOverflow: 22,\n\tDecompressionFailure: 30,\n\tHandshakeFailure: 40,\n\tNoCertificate: 41,\n\tBadCertificate: 42,\n\tUnsupportedCertificate: 43,\n\tCertificateRevoked: 44,\n\tCertificateExpired: 45,\n\tCertificateUnknown: 46,\n\tIllegalParameter: 47,\n\tUnknownCa: 48,\n\tAccessDenied: 49,\n\tDecodeError: 50,\n\tDecryptError: 51,\n\tExportRestriction: 60,\n\tProtocolVersion: 70,\n\tInsufficientSecurity: 71,\n\tInternalError: 80,\n\tUserCanceled: 90,\n\tNoRenegotiation: 100,\n\tUnsupportedExtension: 110,\n} as const;\nexport type AlertDescription =\n\t(typeof AlertDescriptions)[keyof typeof AlertDescriptions];\nexport const AlertDescriptionNames = flipObject(AlertDescriptions);\n\nexport interface ChangeCipherSpecMessage {\n\ttype: typeof ContentTypes.ChangeCipherSpec;\n\tbody: Uint8Array;\n}\n\nexport interface ApplicationDataMessage {\n\ttype: typeof ContentTypes.ApplicationData;\n\tbody: Uint8Array;\n}\n\nexport const ContentTypes = {\n\tChangeCipherSpec: 20,\n\tAlert: 21,\n\tHandshake: 22,\n\tApplicationData: 23,\n} as const;\nexport type ContentType = (typeof ContentTypes)[keyof typeof ContentTypes];\n\nexport const HandshakeType = {\n\tHelloRequest: 0,\n\tClientHello: 1,\n\tServerHello: 2,\n\tCertificate: 11,\n\tServerKeyExchange: 12,\n\tCertificateRequest: 13,\n\tServerHelloDone: 14,\n\tCertificateVerify: 15,\n\tClientKeyExchange: 16,\n\tFinished: 20,\n} as const;\nexport type HandshakeType = (typeof HandshakeType)[keyof typeof HandshakeType];\n\nexport type HandshakeMessageBody =\n\t| HelloRequest\n\t| ClientHello\n\t| ServerHello\n\t| Certificate\n\t| ServerKeyExchange\n\t| CertificateRequest\n\t| ServerHelloDone\n\t| CertificateVerify\n\t| ClientKeyExchange\n\t| Finished;\n\nexport interface HandshakeMessage<Body extends HandshakeMessageBody> {\n\ttype: typeof ContentTypes.Handshake;\n\tmsg_type: HandshakeType; // 1 byte\n\tlength: number; // 2 bytes\n\t// Custom property to hold the raw body of the message\n\tbody: Body;\n}\n\n// Specific Handshake Message Types\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface HelloRequest {} // Empty for TLS 1.2\n\n/**\n * 1 byte\n */\nexport type SessionId = Uint8Array;\nexport interface ClientHello {\n\tclient_version: Uint8Array; // 2 bytes\n\trandom: Uint8Array; // 32 bytes\n\tsession_id: SessionId;\n\tcipher_suites: string[];\n\tcompression_methods: Uint8Array;\n\textensions: ParsedExtension[];\n}\n\nexport interface ServerHello {\n\tserver_version: Uint8Array; // 2 bytes\n\trandom: Uint8Array; // 32 bytes\n\tsession_id: Uint8Array;\n\tcipher_suite: Uint8Array; // 2 bytes\n\tcompression_method: number;\n\textensions?: Uint8Array;\n}\n\nexport interface Certificate {\n\tcertificate_list: Uint8Array[];\n}\n\nexport interface ServerKeyExchange {\n\tparams: Uint8Array;\n\tsigned_params: Uint8Array;\n}\n\n/**\n * ECCurveType from\n * https://datatracker.ietf.org/doc/html/rfc4492#section-5.4\n */\nexport const ECCurveTypes = {\n\t/**\n\t * Indicates the elliptic curve domain parameters are\n\t * conveyed verbosely, and the underlying finite field is a prime\n\t * field.\n\t */\n\tExplicitPrime: 1,\n\t/**\n\t * Indicates the elliptic curve domain parameters are\n\t * conveyed verbosely, and the underlying finite field is a\n\t * characteristic-2 field.\n\t */\n\tExplicitChar2: 2,\n\t/**\n\t * Indicates that a named curve is used. This option\n\t * SHOULD be used when applicable.\n\t */\n\tNamedCurve: 3,\n\t/**\n\t * Values 248 through 255 are reserved for private use.\n\t */\n};\n\n/**\n * Named elliptic curves from\n * https://datatracker.ietf.org/doc/html/rfc4492#section-5.1.1\n */\nexport const ECNamedCurves = {\n\tsect163k1: 1,\n\tsect163r1: 2,\n\tsect163r2: 3,\n\tsect193r1: 4,\n\tsect193r2: 5,\n\tsect233k1: 6,\n\tsect233r1: 7,\n\tsect239k1: 8,\n\tsect283k1: 9,\n\tsect283r1: 10,\n\tsect409k1: 11,\n\tsect409r1: 12,\n\tsecp256k1: 22,\n\tsecp256r1: 23,\n\tsecp384r1: 24,\n\tsecp521r1: 25,\n\tarbitrary_explicit_prime_curves: 0xff01,\n\tarbitrary_explicit_char2_curves: 0xff02,\n};\n\nexport interface CertificateRequest {\n\tcertificate_types: Uint8Array;\n\tsupported_signature_algorithms: Uint8Array;\n\tcertificate_authorities: Uint8Array;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface ServerHelloDone {} // Empty for TLS 1.2\n\nexport interface CertificateVerify {\n\talgorithm: Uint8Array;\n\tsignature: Uint8Array;\n}\n\nexport interface ClientKeyExchange {\n\texchange_keys: Uint8Array;\n}\n\nexport interface Finished {\n\tverify_data: Uint8Array;\n}\n\nexport type SessionKeys = {\n\tmasterSecret: Uint8Array;\n\tclientWriteKey: CryptoKey;\n\tserverWriteKey: CryptoKey;\n\tclientIV: Uint8Array;\n\tserverIV: Uint8Array;\n};\n","import { concatUint8Arrays } from '@php-wasm/util';\n\nimport { ServerNameExtension } from '../extensions/0_server_name';\nimport { CipherSuitesNames } from '../cipher-suites';\nimport { CipherSuites } from '../cipher-suites';\nimport { parseClientHelloExtensions } from '../extensions/parse-extensions';\nimport { ArrayBufferReader, as2Bytes, as3Bytes, as8Bytes } from '../utils';\nimport {\n\tHashAlgorithms,\n\tSignatureAlgorithms,\n} from '../extensions/13_signature_algorithms';\nimport { tls12Prf } from './prf';\nimport type {\n\tSessionKeys,\n\tHandshakeMessage,\n\tClientHello,\n\tClientKeyExchange,\n\tFinished,\n\tApplicationDataMessage,\n\tAlertMessage,\n\tChangeCipherSpecMessage,\n\tTLSMessage,\n\tContentType,\n\tTLSRecord,\n\tHandshakeMessageBody,\n\tHelloRequest,\n} from './types';\nimport {\n\tCompressionMethod,\n\tHandshakeType,\n\tContentTypes,\n\tAlertLevelNames,\n\tAlertDescriptionNames,\n\tECCurveTypes,\n\tECNamedCurves,\n} from './types';\n\nclass TLSConnectionClosed extends Error {}\nconst TLS_Version_1_2 = new Uint8Array([0x03, 0x03]);\n\n/**\n * Reuse the same ECDHE key pair for all connections to\n * save some CPU cycles. We can do this because this TLS\n * implementation is not meant to be secure.\n */\nconst generalEcdheKeyPair = crypto.subtle.generateKey(\n\t{\n\t\tname: 'ECDH',\n\t\tnamedCurve: 'P-256', // Use secp256r1 curve\n\t},\n\ttrue, // Extractable\n\t['deriveKey', 'deriveBits'] // Key usage\n);\n\n/**\n * This isomorphic class implements the server end of\n * the client <-> server TLS 1.2 connection. It has two ends:\n *\n * * Client end, that emits and accepts TLS encrypted data.\n * * Server end, that emits and accepts unencrypted data.\n *\n * The API consumer is responsible for connecting both ends\n * to the appropriate handlers.\n *\n * See https://datatracker.ietf.org/doc/html/rfc5246.\n *\n * ## Warning\n *\n * **WARNING** NEVER USE THIS CODE AS A SERVER-SIDE TLS HANDLER.\n *\n * This code is not secure. It is a minimal subset required\n * to decrypt the TLS traffic from a PHP-wasm worker. Yes,\n * it can speak TLS. No, it won't protect your data.\n *\n * ## Rationale\n *\n * This is useful for running PHP.wasm in web browsers.\n * Function calls such as `file_get_contents(\"https://w.org\")`\n * emit encrypted TLS traffic. With this class, you\n * can decrypt it, serve the requested data, and encrypt\n * the response before passing it back to the PHP.wasm\n * module.\n *\n * ## Implementation details\n *\n * TLS_1_2_Connection implements the minimal subset of TLS 1.2\n * required to exchange encrypted data with PHP.wasm:\n *\n * * TLS Handshake\n * * All TLS 1.2 record types, including messages spanning multiple\n * records and empty records.\n * * Encryption and decryption of application data.\n * * Auto-chunking long data blobs before encrypting them to\n * respect the AES-GCM record size limit.\n *\n * The logic is based on numerous RFCs:\n *\n * * RFC 5246: The TLS Protocol Version 1.2\n * * RFC 8446: TLS 1.3\n * * RFC 6066: TLS Extensions\n * * RFC 4492: Elliptic Curve Cryptography (ECC) Cipher Suites for TLS\n * * RFC 5288: AES Galois Counter Mode (GCM) Cipher Suites for TLS\n * * RFC 6070: PKCS #5: Password-Based Key Derivation Function 2 (PBKDF2) Test Vectors\n *\n * ... and a few others.\n *\n * ## Limitations\n *\n * * Multiple ChangeCipherSpec messages are not supported.\n * * Only uncompressed mode (compression method 0) is supported.\n * * Only the TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256 cipher suite is\n * supported, primarily because `crypto.subtle` supports AES-GCM.\n * For AES-GCM details, see https://datatracker.ietf.org/doc/html/rfc5288.\n */\nexport class TLS_1_2_Connection {\n\t/**\n\t * Sequence number of the last received TLS record.\n\t *\n\t * AES-GCM requires transmitting the sequence number\n\t * in the clear in the additional data to prevent a\n\t * potential attacker from re-transmitting the same\n\t * TLS record in a different context.\n\t */\n\tprivate receivedRecordSequenceNumber = 0;\n\n\t/**\n\t * Sequence number of the last sent TLS record.\n\t *\n\t * AES-GCM requires transmitting the sequence number\n\t * in the clear in the additional data to prevent a\n\t * potential attacker from re-transmitting the same\n\t * TLS record in a different context.\n\t */\n\tprivate sentRecordSequenceNumber = 0;\n\n\t/**\n\t * Encryption keys for this connection derived during\n\t * the TLS handshake.\n\t */\n\tprivate sessionKeys: SessionKeys | undefined;\n\n\t/**\n\t * Whether this connection have been closed.\n\t */\n\tprivate closed = false;\n\n\t/**\n\t * Bytes received from the client but not yet parsed\n\t * as TLS records.\n\t */\n\tprivate receivedBytesBuffer: Uint8Array = new Uint8Array();\n\n\t/**\n\t * TLS records received from the client but not yet\n\t * parsed as TLS messages.\n\t */\n\tprivate receivedTLSRecords: Array<TLSRecord> = [];\n\n\t/**\n\t * TLS messages can span multiple TLS records. This\n\t * map holds partial TLS messages that are still incomplete\n\t * after parsing one or more TLS records.\n\t */\n\tprivate partialTLSMessages: Partial<Record<ContentType, Uint8Array>> = {};\n\n\t/**\n\t * A log of all the exchanged TLS handshake messages.\n\t * This is required to build the Finished message and\n\t * verify the integrity of the handshake.\n\t */\n\tprivate handshakeMessages: Uint8Array[] = [];\n\n\t/**\n\t * Maximum chunk size supported by the cipher suite used\n\t * in this TLS implementation.\n\t */\n\tprivate MAX_CHUNK_SIZE = 1024 * 16;\n\n\t/**\n\t * The client end of the TLS connection.\n\t * This is where the WASM module can write and read the\n\t * encrypted data.\n\t */\n\tclientEnd = {\n\t\t// We don't need to chunk the encrypted data.\n\t\t// OpenSSL already done that for us.\n\t\tupstream: new TransformStream<Uint8Array, Uint8Array>(),\n\t\tdownstream: new TransformStream<Uint8Array, Uint8Array>(),\n\t};\n\n\tprivate clientDownstreamWriter =\n\t\tthis.clientEnd.downstream.writable.getWriter();\n\tprivate clientUpstreamReader = this.clientEnd.upstream.readable.getReader();\n\n\t/**\n\t * The server end of the TLS connection.\n\t * This is where the JavaScript handler can write and read the\n\t * unencrypted data.\n\t */\n\tserverEnd = {\n\t\tupstream: new TransformStream<Uint8Array, Uint8Array>(),\n\t\t/**\n\t\t * Chunk the data before encrypting it. The\n\t\t * TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256 cipher suite\n\t\t * only supports up to 16KB of data per record.\n\t\t *\n\t\t * This will spread some messages across multiple records,\n\t\t * but TLS supports it so that's fine.\n\t\t */\n\t\tdownstream: chunkStream(this.MAX_CHUNK_SIZE),\n\t};\n\n\tprivate serverUpstreamWriter = this.serverEnd.upstream.writable.getWriter();\n\n\tconstructor() {\n\t\t// eslint-disable-next-line @typescript-eslint/no-this-alias\n\t\tconst tlsConnection = this;\n\t\t// Whenever the \"server handler\" produces data, encrypt it\n\t\t// and send it back to the client.\n\t\tthis.serverEnd.downstream.readable\n\t\t\t.pipeTo(\n\t\t\t\tnew WritableStream({\n\t\t\t\t\tasync write(chunk) {\n\t\t\t\t\t\tawait tlsConnection.writeTLSRecord(\n\t\t\t\t\t\t\tContentTypes.ApplicationData,\n\t\t\t\t\t\t\tchunk\n\t\t\t\t\t\t);\n\t\t\t\t\t},\n\t\t\t\t\tasync abort(e) {\n\t\t\t\t\t\ttlsConnection.clientDownstreamWriter.releaseLock();\n\t\t\t\t\t\ttlsConnection.clientEnd.downstream.writable.abort(e);\n\t\t\t\t\t\ttlsConnection.close();\n\t\t\t\t\t},\n\t\t\t\t\tclose() {\n\t\t\t\t\t\ttlsConnection.close();\n\t\t\t\t\t},\n\t\t\t\t})\n\t\t\t)\n\t\t\t.catch(() => {\n\t\t\t\t// Ignore failures arising from stream errors. The caller\n\t\t\t\t// should react to the readable stream erroring out.\n\t\t\t});\n\t}\n\n\t/**\n\t * Marks this connections as closed and closes all the associated\n\t * streams.\n\t */\n\tasync close() {\n\t\tif (this.closed) {\n\t\t\treturn;\n\t\t}\n\t\tthis.closed = true;\n\t\ttry {\n\t\t\tawait this.clientDownstreamWriter.close();\n\t\t} catch {\n\t\t\t// Ignore\n\t\t}\n\t\ttry {\n\t\t\tawait this.clientUpstreamReader.cancel();\n\t\t} catch {\n\t\t\t// Ignore\n\t\t}\n\t\ttry {\n\t\t\tawait this.serverUpstreamWriter.close();\n\t\t} catch {\n\t\t\t// Ignore\n\t\t}\n\t\ttry {\n\t\t\tawait this.clientEnd.upstream.readable.cancel();\n\t\t} catch {\n\t\t\t// Ignore\n\t\t}\n\t\ttry {\n\t\t\tawait this.clientEnd.downstream.writable.close();\n\t\t} catch {\n\t\t\t// Ignore\n\t\t}\n\t}\n\n\t/**\n\t * TLS handshake as per RFC 5246.\n\t *\n\t * https://datatracker.ietf.org/doc/html/rfc5246#section-7.4\n\t */\n\tasync TLSHandshake(\n\t\tcertificatePrivateKey: CryptoKey,\n\t\tcertificatesDER: Uint8Array[]\n\t): Promise<void> {\n\t\t// Step 1: Receive ClientHello\n\t\tconst clientHelloRecord = await this.readNextHandshakeMessage(\n\t\t\tHandshakeType.ClientHello\n\t\t);\n\t\tif (!clientHelloRecord.body.cipher_suites.length) {\n\t\t\tthrow new Error(\n\t\t\t\t'Client did not propose any supported cipher suites.'\n\t\t\t);\n\t\t}\n\n\t\t// Step 2: Choose hashing, encryption etc. and tell the\n\t\t// client about our choices. Also share the certificate\n\t\t// and the encryption keys.\n\t\tconst serverRandom = crypto.getRandomValues(new Uint8Array(32));\n\t\tawait this.writeTLSRecord(\n\t\t\tContentTypes.Handshake,\n\t\t\tMessageEncoder.serverHello(\n\t\t\t\tclientHelloRecord.body,\n\t\t\t\tserverRandom,\n\t\t\t\tCompressionMethod.Null\n\t\t\t)\n\t\t);\n\n\t\tawait this.writeTLSRecord(\n\t\t\tContentTypes.Handshake,\n\t\t\tMessageEncoder.certificate(certificatesDER)\n\t\t);\n\n\t\tconst ecdheKeyPair = await generalEcdheKeyPair;\n\t\tconst clientRandom = clientHelloRecord.body.random;\n\t\tconst serverKeyExchange = await MessageEncoder.ECDHEServerKeyExchange(\n\t\t\tclientRandom,\n\t\t\tserverRandom,\n\t\t\tecdheKeyPair,\n\t\t\tcertificatePrivateKey\n\t\t);\n\t\tawait this.writeTLSRecord(ContentTypes.Handshake, serverKeyExchange);\n\t\tawait this.writeTLSRecord(\n\t\t\tContentTypes.Handshake,\n\t\t\tMessageEncoder.serverHelloDone()\n\t\t);\n\n\t\t// Step 3: Receive the client's response, encryption keys, and\n\t\t// decrypt the first encrypted message.\n\t\tconst clientKeyExchangeRecord = await this.readNextHandshakeMessage(\n\t\t\tHandshakeType.ClientKeyExchange\n\t\t);\n\t\tawait this.readNextMessage(ContentTypes.ChangeCipherSpec);\n\n\t\tthis.sessionKeys = await this.deriveSessionKeys({\n\t\t\tclientRandom,\n\t\t\tserverRandom,\n\t\t\tserverPrivateKey: ecdheKeyPair.privateKey,\n\t\t\tclientPublicKey: await crypto.subtle.importKey(\n\t\t\t\t'raw',\n\t\t\t\tclientKeyExchangeRecord.body.exchange_keys,\n\t\t\t\t{ name: 'ECDH', namedCurve: 'P-256' },\n\t\t\t\tfalse,\n\t\t\t\t[]\n\t\t\t),\n\t\t});\n\n\t\tawait this.readNextHandshakeMessage(HandshakeType.Finished);\n\n\t\t// We're not actually verifying the hash provided by client\n\t\t// as we're not concerned with the client's identity.\n\n\t\tawait this.writeTLSRecord(\n\t\t\tContentTypes.ChangeCipherSpec,\n\t\t\tMessageEncoder.changeCipherSpec()\n\t\t);\n\t\tawait this.writeTLSRecord(\n\t\t\tContentTypes.Handshake,\n\t\t\tawait MessageEncoder.createFinishedMessage(\n\t\t\t\tthis.handshakeMessages,\n\t\t\t\tthis.sessionKeys!.masterSecret\n\t\t\t)\n\t\t);\n\t\t// Clean up the handshake messages as they are no longer needed.\n\t\tthis.handshakeMessages = [];\n\n\t\tthis.pollForClientMessages();\n\t}\n\n\t/**\n\t * Derives the session keys from the random values and the\n\t * pre-master secret – as per RFC 5246.\n\t */\n\tprivate async deriveSessionKeys({\n\t\tclientRandom,\n\t\tserverRandom,\n\t\tserverPrivateKey,\n\t\tclientPublicKey,\n\t}: {\n\t\tclientRandom: Uint8Array;\n\t\tserverRandom: Uint8Array;\n\t\tserverPrivateKey: CryptoKey;\n\t\tclientPublicKey: CryptoKey;\n\t}): Promise<SessionKeys> {\n\t\tconst preMasterSecret = await crypto.subtle.deriveBits(\n\t\t\t{\n\t\t\t\tname: 'ECDH',\n\t\t\t\tpublic: clientPublicKey,\n\t\t\t},\n\t\t\tserverPrivateKey,\n\t\t\t256 // Length of the derived secret (256 bits for P-256)\n\t\t);\n\n\t\tconst masterSecret = new Uint8Array(\n\t\t\tawait tls12Prf(\n\t\t\t\tpreMasterSecret,\n\t\t\t\tnew TextEncoder().encode('master secret'),\n\t\t\t\tconcatUint8Arrays([clientRandom, serverRandom]),\n\t\t\t\t48\n\t\t\t)\n\t\t);\n\n\t\tconst keyBlock = await tls12Prf(\n\t\t\tmasterSecret,\n\t\t\tnew TextEncoder().encode('key expansion'),\n\t\t\tconcatUint8Arrays([serverRandom, clientRandom]),\n\t\t\t// Client key, server key, client IV, server IV\n\t\t\t16 + 16 + 4 + 4\n\t\t);\n\n\t\tconst reader = new ArrayBufferReader(keyBlock);\n\t\tconst clientWriteKey = reader.readUint8Array(16);\n\t\tconst serverWriteKey = reader.readUint8Array(16);\n\t\tconst clientIV = reader.readUint8Array(4);\n\t\tconst serverIV = reader.readUint8Array(4);\n\n\t\treturn {\n\t\t\tmasterSecret,\n\t\t\tclientWriteKey: await crypto.subtle.importKey(\n\t\t\t\t'raw',\n\t\t\t\tclientWriteKey,\n\t\t\t\t{ name: 'AES-GCM' },\n\t\t\t\tfalse,\n\t\t\t\t['encrypt', 'decrypt']\n\t\t\t),\n\t\t\tserverWriteKey: await crypto.subtle.importKey(\n\t\t\t\t'raw',\n\t\t\t\tserverWriteKey,\n\t\t\t\t{ name: 'AES-GCM' },\n\t\t\t\tfalse,\n\t\t\t\t['encrypt', 'decrypt']\n\t\t\t),\n\t\t\tclientIV,\n\t\t\tserverIV,\n\t\t};\n\t}\n\n\tprivate async readNextHandshakeMessage(\n\t\tmessageType: typeof HandshakeType.ClientHello\n\t): Promise<HandshakeMessage<ClientHello>>;\n\tprivate async readNextHandshakeMessage(\n\t\tmessageType: typeof HandshakeType.ClientKeyExchange\n\t): Promise<HandshakeMessage<ClientKeyExchange>>;\n\tprivate async readNextHandshakeMessage(\n\t\tmessageType: typeof HandshakeType.Finished\n\t): Promise<HandshakeMessage<Finished>>;\n\tprivate async readNextHandshakeMessage(\n\t\tmessageType:\n\t\t\t| typeof HandshakeType.ClientHello\n\t\t\t| typeof HandshakeType.ClientKeyExchange\n\t\t\t| typeof HandshakeType.Finished\n\t): Promise<HandshakeMessage<any>> {\n\t\tconst message = await this.readNextMessage(ContentTypes.Handshake);\n\t\tif (message.msg_type !== messageType) {\n\t\t\tthrow new Error(`Expected ${messageType} message`);\n\t\t}\n\t\treturn message;\n\t}\n\n\tprivate async readNextMessage(\n\t\trequestedType: (typeof ContentTypes)['Handshake']\n\t): Promise<HandshakeMessage<any>>;\n\tprivate async readNextMessage(\n\t\trequestedType: (typeof ContentTypes)['ApplicationData']\n\t): Promise<ApplicationDataMessage>;\n\tprivate async readNextMessage(\n\t\trequestedType: (typeof ContentTypes)['Alert']\n\t): Promise<AlertMessage>;\n\tprivate async readNextMessage(\n\t\trequestedType: (typeof ContentTypes)['ChangeCipherSpec']\n\t): Promise<ChangeCipherSpecMessage>;\n\tprivate async readNextMessage<Message extends TLSMessage>(\n\t\trequestedType: ContentType\n\t): Promise<Message> {\n\t\tlet record: TLSRecord;\n\t\tlet accumulatedPayload: false | Uint8Array = false;\n\t\tdo {\n\t\t\trecord = await this.readNextTLSRecord(requestedType);\n\t\t\taccumulatedPayload = await this.accumulateUntilMessageIsComplete(\n\t\t\t\trecord\n\t\t\t);\n\t\t} while (accumulatedPayload === false);\n\n\t\tconst message = TLSDecoder.TLSMessage(\n\t\t\trecord.type,\n\t\t\taccumulatedPayload\n\t\t) as Message;\n\t\tif (record.type === ContentTypes.Handshake) {\n\t\t\tthis.handshakeMessages.push(record.fragment);\n\t\t}\n\t\treturn message;\n\t}\n\n\tprivate async readNextTLSRecord(\n\t\trequestedType: ContentType\n\t): Promise<TLSRecord> {\n\t\twhile (true) {\n\t\t\t// First, check if we have a complete record of the requested type.\n\t\t\tfor (let i = 0; i < this.receivedTLSRecords.length; i++) {\n\t\t\t\tconst record = this.receivedTLSRecords[i];\n\t\t\t\tif (record.type !== requestedType) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tthis.receivedTLSRecords.splice(i, 1);\n\t\t\t\treturn record;\n\t\t\t}\n\n\t\t\t// We don't have a complete record of the requested type yet.\n\t\t\t// Let's read the next TLS record, then.\n\t\t\tconst header = await this.pollBytes(5);\n\t\t\tconst length = (header[3] << 8) | header[4];\n\t\t\tconst type = header[0];\n\t\t\tconst fragment = await this.pollBytes(length);\n\t\t\tconst record = {\n\t\t\t\ttype,\n\t\t\t\tversion: {\n\t\t\t\t\tmajor: header[1],\n\t\t\t\t\tminor: header[2],\n\t\t\t\t},\n\t\t\t\tlength,\n\t\t\t\tfragment:\n\t\t\t\t\tthis.sessionKeys && type !== ContentTypes.ChangeCipherSpec\n\t\t\t\t\t\t? await this.decryptData(type, fragment)\n\t\t\t\t\t\t: fragment,\n\t\t\t} as TLSRecord;\n\n\t\t\tif (record.type === ContentTypes.Alert) {\n\t\t\t\tconst severity = AlertLevelNames[record.fragment[0]];\n\t\t\t\tconst description = AlertDescriptionNames[record.fragment[1]];\n\t\t\t\t/**\n\t\t\t\t * @TODO: Handle TLS warnings, e.g. this one:\n\t\t\t\t *\n\t\t\t\t * close_notify\n\t\t\t\t * Either party may initiate a close by sending a close_notify alert.\n\t\t\t\t * Any data received after a closure alert is ignored.\n\t\t\t\t *\n\t\t\t\t * Unless some other fatal alert has been transmitted, each party is\n\t\t\t\t * required to send a close_notify alert before closing the write side\n\t\t\t\t * of the connection. The other party MUST respond with a close_notify\n\t\t\t\t * alert of its own and close down the connection immediately,\n\t\t\t\t * discarding any pending writes.\n\t\t\t\t */\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`TLS non-warning alert received: ${severity} ${description}`\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.receivedTLSRecords.push(record);\n\t\t}\n\t}\n\n\t/**\n\t * Returns the requested number of bytes from the client.\n\t * Waits for the bytes to arrive if necessary.\n\t */\n\tprivate async pollBytes(length: number) {\n\t\twhile (this.receivedBytesBuffer.length < length) {\n\t\t\tconst { value, done } = await this.clientUpstreamReader.read();\n\t\t\tif (done) {\n\t\t\t\tawait this.close();\n\t\t\t\tthrow new TLSConnectionClosed('TLS connection closed');\n\t\t\t}\n\t\t\tthis.receivedBytesBuffer = concatUint8Arrays([\n\t\t\t\tthis.receivedBytesBuffer,\n\t\t\t\tvalue,\n\t\t\t]);\n\t\t\tif (this.receivedBytesBuffer.length >= length) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t// Patience is the key...\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, 100));\n\t\t}\n\t\tconst requestedBytes = this.receivedBytesBuffer.slice(0, length);\n\t\tthis.receivedBytesBuffer = this.receivedBytesBuffer.slice(length);\n\t\treturn requestedBytes;\n\t}\n\n\t/**\n\t * Listens for all incoming messages and passes them to the\n\t * server handler.\n\t */\n\tprivate async pollForClientMessages() {\n\t\ttry {\n\t\t\twhile (true) {\n\t\t\t\tconst appData = await this.readNextMessage(\n\t\t\t\t\tContentTypes.ApplicationData\n\t\t\t\t);\n\t\t\t\tthis.serverUpstreamWriter.write(appData.body);\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tif (e instanceof TLSConnectionClosed) {\n\t\t\t\t// Connection closed, no more application data to emit.\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthrow e;\n\t\t}\n\t}\n\n\t/**\n\t * Decrypts data in a TLS 1.2-compliant manner using\n\t * the AES-GCM algorithm.\n\t */\n\tprivate async decryptData(\n\t\tcontentType: number,\n\t\tpayload: Uint8Array\n\t): Promise<Uint8Array> {\n\t\tconst implicitIV = this.sessionKeys!.clientIV;\n\t\t// Part of the IV is randomly generated for each record\n\t\t// and prepended in its unencrypted form before the\n\t\t// ciphertext.\n\t\tconst explicitIV = payload.slice(0, 8);\n\t\tconst iv = new Uint8Array([...implicitIV, ...explicitIV]);\n\n\t\tconst decrypted = await crypto.subtle.decrypt(\n\t\t\t{\n\t\t\t\tname: 'AES-GCM',\n\t\t\t\tiv,\n\t\t\t\tadditionalData: new Uint8Array([\n\t\t\t\t\t...as8Bytes(this.receivedRecordSequenceNumber),\n\t\t\t\t\tcontentType,\n\t\t\t\t\t...TLS_Version_1_2,\n\t\t\t\t\t// Payload length without IV and tag\n\t\t\t\t\t...as2Bytes(payload.length - 8 - 16),\n\t\t\t\t]),\n\t\t\t\ttagLength: 128,\n\t\t\t},\n\t\t\tthis.sessionKeys!.clientWriteKey,\n\t\t\t// Payload without the explicit IV\n\t\t\tpayload.slice(8)\n\t\t);\n\t\t++this.receivedRecordSequenceNumber;\n\n\t\treturn new Uint8Array(decrypted);\n\t}\n\n\tprivate async accumulateUntilMessageIsComplete(\n\t\trecord: TLSRecord\n\t): Promise<false | Uint8Array> {\n\t\tthis.partialTLSMessages[record.type] = concatUint8Arrays([\n\t\t\tthis.partialTLSMessages[record.type] || new Uint8Array(),\n\t\t\trecord.fragment,\n\t\t]);\n\t\tconst message = this.partialTLSMessages[record.type]!;\n\t\tswitch (record.type) {\n\t\t\tcase ContentTypes.Handshake: {\n\t\t\t\t// We don't have the message header yet, let's wait for more data.\n\t\t\t\tif (message.length < 4) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tconst length = (message[1] << 8) | message[2];\n\t\t\t\tif (message.length < 3 + length) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase ContentTypes.Alert: {\n\t\t\t\tif (message.length < 2) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase ContentTypes.ChangeCipherSpec:\n\t\t\tcase ContentTypes.ApplicationData:\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthrow new Error(`TLS: Unsupported record type ${record.type}`);\n\t\t}\n\t\tdelete this.partialTLSMessages[record.type];\n\t\treturn message;\n\t}\n\n\t/**\n\t * Passes a TLS record to the client.\n\t *\n\t * Accepts unencrypted data and ensures it gets encrypted\n\t * if needed before sending it to the client. The encryption\n\t * only kicks in after the handshake is complete.\n\t */\n\tprivate async writeTLSRecord(\n\t\tcontentType: number,\n\t\tpayload: Uint8Array\n\t): Promise<void> {\n\t\tif (contentType === ContentTypes.Handshake) {\n\t\t\tthis.handshakeMessages.push(payload);\n\t\t}\n\t\tif (this.sessionKeys && contentType !== ContentTypes.ChangeCipherSpec) {\n\t\t\tpayload = await this.encryptData(contentType, payload);\n\t\t}\n\n\t\tconst version = TLS_Version_1_2;\n\t\tconst length = payload.length;\n\t\tconst header = new Uint8Array(5);\n\t\theader[0] = contentType;\n\t\theader[1] = version[0];\n\t\theader[2] = version[1];\n\t\theader[3] = (length >> 8) & 0xff;\n\t\theader[4] = length & 0xff;\n\n\t\tconst record = concatUint8Arrays([header, payload]);\n\t\tthis.clientDownstreamWriter.write(record);\n\t}\n\n\t/**\n\t * Encrypts data in a TLS 1.2-compliant manner using\n\t * the AES-GCM algorithm.\n\t */\n\tprivate async encryptData(\n\t\tcontentType: number,\n\t\tpayload: Uint8Array\n\t): Promise<Uint8Array> {\n\t\tconst implicitIV = this.sessionKeys!.serverIV;\n\t\t// Part of the IV is randomly generated for each record\n\t\t// and prepended in its unencrypted form before the\n\t\t// ciphertext.\n\t\tconst explicitIV = crypto.getRandomValues(new Uint8Array(8));\n\t\tconst iv = new Uint8Array([...implicitIV, ...explicitIV]);\n\n\t\tconst additionalData = new Uint8Array([\n\t\t\t...as8Bytes(this.sentRecordSequenceNumber),\n\t\t\tcontentType,\n\t\t\t...TLS_Version_1_2,\n\t\t\t// Payload length without IV and tag\n\t\t\t...as2Bytes(payload.length),\n\t\t]);\n\t\tconst ciphertextWithTag = await crypto.subtle.encrypt(\n\t\t\t{\n\t\t\t\tname: 'AES-GCM',\n\t\t\t\tiv,\n\t\t\t\tadditionalData,\n\t\t\t\ttagLength: 128,\n\t\t\t},\n\t\t\tthis.sessionKeys!.serverWriteKey,\n\t\t\tpayload\n\t\t);\n\t\t++this.sentRecordSequenceNumber;\n\n\t\tconst encrypted = concatUint8Arrays([\n\t\t\texplicitIV,\n\t\t\tnew Uint8Array(ciphertextWithTag),\n\t\t]);\n\n\t\treturn encrypted;\n\t}\n}\n\nclass TLSDecoder {\n\tstatic TLSMessage(\n\t\ttype: ContentType,\n\t\taccumulatedPayload: Uint8Array\n\t): TLSMessage {\n\t\tswitch (type) {\n\t\t\tcase ContentTypes.Handshake: {\n\t\t\t\treturn TLSDecoder.clientHandshake(accumulatedPayload);\n\t\t\t}\n\t\t\tcase ContentTypes.Alert: {\n\t\t\t\treturn TLSDecoder.alert(accumulatedPayload);\n\t\t\t}\n\t\t\tcase ContentTypes.ChangeCipherSpec: {\n\t\t\t\treturn TLSDecoder.changeCipherSpec();\n\t\t\t}\n\t\t\tcase ContentTypes.ApplicationData: {\n\t\t\t\treturn TLSDecoder.applicationData(accumulatedPayload);\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\tthrow new Error(`TLS: Unsupported TLS record type ${type}`);\n\t\t}\n\t}\n\n\t/**\n\t * Parses the cipher suites from the server hello message.\n\t *\n\t * The cipher suites are encoded as a list of 2-byte values.\n\t *\n\t * Binary layout:\n\t *\n\t * +----------------------------+\n\t * | Cipher Suites Length | 2 bytes\n\t * +----------------------------+\n\t * | Cipher Suite 1 | 2 bytes\n\t * +----------------------------+\n\t * | Cipher Suite 2 | 2 bytes\n\t * +----------------------------+\n\t * | ... |\n\t * +----------------------------+\n\t * | Cipher Suite n | 2 bytes\n\t * +----------------------------+\n\t *\n\t * The full list of supported cipher suites values is available at:\n\t *\n\t * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-4\n\t */\n\tstatic parseCipherSuites(buffer: ArrayBuffer): string[] {\n\t\tconst reader = new ArrayBufferReader(buffer);\n\t\t// Skip the length of the cipher suites\n\t\treader.readUint16();\n\n\t\tconst cipherSuites = [];\n\t\twhile (!reader.isFinished()) {\n\t\t\tconst suite = reader.readUint16();\n\t\t\tif (!(suite in CipherSuitesNames)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tcipherSuites.push(CipherSuitesNames[suite]);\n\t\t}\n\t\treturn cipherSuites;\n\t}\n\n\tstatic applicationData(message: Uint8Array): ApplicationDataMessage {\n\t\treturn {\n\t\t\ttype: ContentTypes.ApplicationData,\n\t\t\tbody: message,\n\t\t};\n\t}\n\n\tstatic changeCipherSpec(): ChangeCipherSpecMessage {\n\t\treturn {\n\t\t\ttype: ContentTypes.ChangeCipherSpec,\n\t\t\tbody: new Uint8Array(),\n\t\t};\n\t}\n\n\tstatic alert(message: Uint8Array): AlertMessage {\n\t\treturn {\n\t\t\ttype: ContentTypes.Alert,\n\t\t\tlevel: AlertLevelNames[message[0]],\n\t\t\tdescription: AlertDescriptionNames[message[1]],\n\t\t};\n\t}\n\n\tstatic clientHandshake<T extends HandshakeMessageBody>(\n\t\tmessage: Uint8Array\n\t): HandshakeMessage<T> {\n\t\tconst msg_type = message[0];\n\t\tconst length = (message[1] << 16) | (message[2] << 8) | message[3];\n\t\tconst bodyBytes = message.slice(4);\n\t\tlet body: HandshakeMessageBody | undefined = undefined;\n\t\tswitch (msg_type) {\n\t\t\tcase HandshakeType.HelloRequest:\n\t\t\t\tbody = TLSDecoder.clientHelloRequestPayload();\n\t\t\t\tbreak;\n\t\t\tcase HandshakeType.ClientHello:\n\t\t\t\tbody = TLSDecoder.clientHelloPayload(bodyBytes);\n\t\t\t\tbreak;\n\t\t\tcase HandshakeType.ClientKeyExchange:\n\t\t\t\tbody = TLSDecoder.clientKeyExchangePayload(bodyBytes);\n\t\t\t\tbreak;\n\t\t\tcase HandshakeType.Finished:\n\t\t\t\tbody = TLSDecoder.clientFinishedPayload(bodyBytes);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthrow new Error(`Invalid handshake type ${msg_type}`);\n\t\t}\n\t\treturn {\n\t\t\ttype: ContentTypes.Handshake,\n\t\t\tmsg_type,\n\t\t\tlength,\n\t\t\tbody: body as T,\n\t\t};\n\t}\n\n\tstatic clientHelloRequestPayload(): HelloRequest {\n\t\treturn {};\n\t}\n\n\t/**\n\t *\tOffset Size Field\n\t *\t(bytes) (bytes)\n\t *\t+------+------+---------------------------+\n\t *\t| 0000 | 1 | Handshake Type (1 = ClientHello)\n\t *\t+------+------+---------------------------+\n\t *\t| 0001 | 3 | Length of ClientHello\n\t *\t+------+------+---------------------------+\n\t *\t| 0004 | 2 | Protocol Version\n\t *\t+------+------+---------------------------+\n\t *\t| 0006 | 32 | Client Random\n\t *\t| | | (4 bytes timestamp +\n\t *\t| | | 28 bytes random)\n\t *\t+------+------+---------------------------+\n\t *\t| 0038 | 1 | Session ID Length\n\t *\t+------+------+---------------------------+\n\t *\t| 0039 | 0+ | Session ID (variable)\n\t *\t| | | (0-32 bytes)\n\t *\t+------+------+---------------------------+\n\t *\t| 003A*| 2 | Cipher Suites Length\n\t *\t+------+------+---------------------------+\n\t *\t| 003C*| 2+ | Cipher Suites\n\t *\t| | | (2 bytes each)\n\t *\t+------+------+---------------------------+\n\t *\t| xxxx | 1 | Compression Methods Length\n\t *\t+------+------+---------------------------+\n\t *\t| xxxx | 1+ | Compression Methods\n\t *\t| | | (1 byte each)\n\t *\t+------+------+---------------------------+\n\t *\t| xxxx | 2 | Extensions Length\n\t *\t+------+------+---------------------------+\n\t *\t| xxxx | 2 | Extension Type\n\t *\t+------+------+---------------------------+\n\t *\t| xxxx | 2 | Extension Length\n\t *\t+------+------+---------------------------+\n\t *\t| xxxx | v | Extension Data\n\t *\t+------+------+---------------------------+\n\t *\t| | | (Additional extensions...)\n\t *\t+------+------+---------------------------+\n\t */\n\tstatic clientHelloPayload(data: Uint8Array): ClientHello {\n\t\tconst reader = new ArrayBufferReader(data.buffer);\n\t\tconst buff: Partial<ClientHello> = {\n\t\t\tclient_version: reader.readUint8Array(2),\n\t\t\t/**\n\t\t\t * Technically this consists of a GMT timestamp\n\t\t\t * and 28 random bytes, but we don't need to\n\t\t\t * parse this further.\n\t\t\t */\n\t\t\trandom: reader.readUint8Array(32),\n\t\t};\n\t\tconst sessionIdLength = reader.readUint8();\n\t\tbuff.session_id = reader.readUint8Array(sessionIdLength);\n\n\t\tconst cipherSuitesLength = reader.readUint16();\n\t\tbuff.cipher_suites = TLSDecoder.parseCipherSuites(\n\t\t\treader.readUint8Array(cipherSuitesLength).buffer\n\t\t);\n\n\t\tconst compressionMethodsLength = reader.readUint8();\n\t\tbuff.compression_methods = reader.readUint8Array(\n\t\t\tcompressionMethodsLength\n\t\t);\n\n\t\tconst extensionsLength = reader.readUint16();\n\t\tbuff.extensions = parseClientHelloExtensions(\n\t\t\treader.readUint8Array(extensionsLength)\n\t\t);\n\t\treturn buff as ClientHello;\n\t}\n\n\t/**\n\t * Binary layout:\n\t *\n\t *\t+------------------------------------+\n\t *\t| ECDH Client Public Key Length [1B] |\n\t *\t+------------------------------------+\n\t *\t| ECDH Client Public Key [variable]|\n\t *\t+------------------------------------+\n\t */\n\tstatic clientKeyExchangePayload(data: Uint8Array): ClientKeyExchange {\n\t\treturn {\n\t\t\t// Skip the first byte, which is the length of the public key\n\t\t\texchange_keys: data.slice(1, data.length),\n\t\t};\n\t}\n\n\tstatic clientFinishedPayload(data: Uint8Array): Finished {\n\t\treturn {\n\t\t\tverify_data: data,\n\t\t};\n\t}\n}\n\n/**\n * Creates a stream that emits chunks not larger than\n * the specified size.\n */\nfunction chunkStream(chunkSize: number) {\n\treturn new TransformStream({\n\t\ttransform(chunk, controller) {\n\t\t\twhile (chunk.length > 0) {\n\t\t\t\tcontroller.enqueue(chunk.slice(0, chunkSize));\n\t\t\t\tchunk = chunk.slice(chunkSize);\n\t\t\t}\n\t\t},\n\t});\n}\n\nclass MessageEncoder {\n\tstatic certificate(certificatesDER: ArrayBuffer[]): Uint8Array {\n\t\tconst certsBodies: Uint8Array[] = [];\n\t\tfor (const cert of certificatesDER) {\n\t\t\tcertsBodies.push(as3Bytes(cert.byteLength));\n\t\t\tcertsBodies.push(new Uint8Array(cert));\n\t\t}\n\t\tconst certsBody = concatUint8Arrays(certsBodies);\n\t\tconst body = new Uint8Array([\n\t\t\t...as3Bytes(certsBody.byteLength),\n\t\t\t...certsBody,\n\t\t]);\n\t\treturn new Uint8Array([\n\t\t\tHandshakeType.Certificate,\n\t\t\t...as3Bytes(body.length),\n\t\t\t...body,\n\t\t]);\n\t}\n\n\t/*\n\t * Byte layout of the ServerKeyExchange message:\n\t *\n\t * +-----------------------------------+\n\t * | ServerKeyExchange Message |\n\t * +-----------------------------------+\n\t * | Handshake type (1 byte) |\n\t * +-----------------------------------+\n\t * | Length (3 bytes) |\n\t * +-----------------------------------+\n\t * | Curve Type (1 byte) |\n\t * +-----------------------------------+\n\t * | Named Curve (2 bytes) |\n\t * +-----------------------------------+\n\t * | EC Point Format (1 byte) |\n\t * +-----------------------------------+\n\t * | Public Key Length (1 byte) |\n\t * +-----------------------------------+\n\t * | Public Key (variable) |\n\t * +-----------------------------------+\n\t * | Signature Algorithm (2 bytes) |\n\t * +-----------------------------------+\n\t * | Signature Length (2 bytes) |\n\t * +-----------------------------------+\n\t * | Signature (variable) |\n\t * +-----------------------------------+\n\t *\n\t * @param clientRandom - 32 bytes from ClientHello\n\t * @param serverRandom - 32 bytes from ServerHello\n\t * @param ecdheKeyPair - ECDHE key pair\n\t * @param rsaPrivateKey - RSA private key for signing\n\t * @returns\n\t */\n\tstatic async ECDHEServerKeyExchange(\n\t\tclientRandom: Uint8Array,\n\t\tserverRandom: Uint8Array,\n\t\tecdheKeyPair: CryptoKeyPair,\n\t\trsaPrivateKey: CryptoKey\n\t): Promise<Uint8Array> {\n\t\t// 65 bytes (04 followed by x and y coordinates)\n\t\tconst publicKey = new Uint8Array(\n\t\t\tawait crypto.subtle.exportKey('raw', ecdheKeyPair.publicKey)\n\t\t);\n\n\t\t/*\n\t\t * The ServerKeyExchange message is extended as follows.\n\t\t *\n\t\t * select (KeyExchangeAlgorithm) {\n\t\t * case ec_diffie_hellman:\n\t\t * ServerECDHParams params;\n\t\t * Signature signed_params;\n\t\t * } ServerKeyExchange;\n\t\t *\n\t\t * struct {\n\t\t * ECCurveType curve_type;\n\t\t * NamedCurve namedcurve;\n\t\t * ECPoint public;\n\t\t * } ServerECDHParams;\n\t\t */\n\t\tconst params = new Uint8Array([\n\t\t\t// Curve type (1 byte)\n\t\t\tECCurveTypes.NamedCurve,\n\t\t\t// Curve name (2 bytes)\n\t\t\t...as2Bytes(ECNamedCurves.secp256r1),\n\n\t\t\t// Public key length (1 byte)\n\t\t\tpublicKey.byteLength,\n\n\t\t\t// Public key (65 bytes, uncompressed format)\n\t\t\t...publicKey,\n\t\t]);\n\n\t\t/**\n\t\t * signed_params:\n\t\t * A hash of the params, with the signature appropriate to that hash\n\t\t * applied. The private key corresponding to the certified public key\n\t\t * in the server's Certificate message is used for signing.\n\t\t *\n\t\t * Signature = encrypt(SHA(\n\t\t * ClientHello.random + ServerHello.random + ServerECDHParams\n\t\t * ));\n\t\t */\n\t\tconst signedParams = await crypto.subtle.sign(\n\t\t\t{\n\t\t\t\tname: 'RSASSA-PKCS1-v1_5',\n\t\t\t\thash: 'SHA-256',\n\t\t\t},\n\t\t\trsaPrivateKey,\n\t\t\tnew Uint8Array([...clientRandom, ...serverRandom, ...params])\n\t\t);\n\t\tconst signatureBytes = new Uint8Array(signedParams);\n\n\t\t/**\n\t\t * SignatureAlgorithm is \"rsa\" for the ECDHE_RSA key exchange\n\t\t * These cases are defined in TLS [RFC2246].\n\t\t */\n\t\tconst signatureAlgorithm = new Uint8Array([\n\t\t\tHashAlgorithms.sha256,\n\t\t\tSignatureAlgorithms.rsa,\n\t\t]);\n\n\t\t// Step 6: Construct the complete Server Key Exchange message\n\t\tconst body = new Uint8Array([\n\t\t\t...params,\n\t\t\t...signatureAlgorithm,\n\t\t\t...as2Bytes(signatureBytes.length),\n\t\t\t...signatureBytes,\n\t\t]);\n\n\t\treturn new Uint8Array([\n\t\t\tHandshakeType.ServerKeyExchange,\n\t\t\t...as3Bytes(body.length),\n\t\t\t...body,\n\t\t]);\n\t}\n\n\t/**\n\t * +------------------------------------+\n\t * | Content Type (Handshake) [1B] |\n\t * | 0x16 |\n\t * +------------------------------------+\n\t * | Version (TLS 1.2) [2B] |\n\t * | 0x03 0x03 |\n\t * +------------------------------------+\n\t * | Length [2B] |\n\t * +------------------------------------+\n\t * | Handshake Type (ServerHello) [1B] |\n\t * | 0x02 |\n\t * +------------------------------------+\n\t * | Handshake Length [3B] |\n\t * +------------------------------------+\n\t * | Server Version [2B] |\n\t * +------------------------------------+\n\t * | Server Random [32B] |\n\t * +------------------------------------+\n\t * | Session ID Length [1B] |\n\t * +------------------------------------+\n\t * | Session ID [0-32B] |\n\t * +------------------------------------+\n\t * | Cipher Suite [2B] |\n\t * +------------------------------------+\n\t * | Compression Method [1B] |\n\t * +------------------------------------+\n\t * | Extensions Length [2B] |\n\t * +------------------------------------+\n\t * | Extension: ec_point_formats |\n\t * | Type (0x00 0x0B) [2B] |\n\t * | Length [2B] |\n\t * | EC Point Formats Length [1B] |\n\t * | EC Point Format [1B] |\n\t * +------------------------------------+\n\t * | Other Extensions... |\n\t * +------------------------------------+\n\t */\n\tstatic serverHello(\n\t\tclientHello: ClientHello,\n\t\tserverRandom: Uint8Array,\n\t\tcompressionAlgorithm: number\n\t): Uint8Array {\n\t\tconst extensionsParts: Uint8Array[] = clientHello.extensions\n\t\t\t.map((extension) => {\n\t\t\t\tswitch (extension['type']) {\n\t\t\t\t\tcase 'server_name':\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * The server SHALL include an extension of type \"server_name\" in the\n\t\t\t\t\t\t * (extended) server hello. The \"extension_data\" field of this extension\n\t\t\t\t\t\t * SHALL be empty.\n\t\t\t\t\t\t *\n\t\t\t\t\t\t * Source: dfile:///Users/cloudnik/Library/Application%20Support/Dash/User%20Contributed/RFCs/RFCs.docset/Contents/Resources/Documents/rfc6066.html#section-3\n\t\t\t\t\t\t */\n\t\t\t\t\t\treturn ServerNameExtension.encodeForClient();\n\t\t\t\t}\n\t\t\t\treturn undefined;\n\t\t\t})\n\t\t\t.filter((x): x is Uint8Array => x !== undefined);\n\t\tconst extensions = concatUint8Arrays(extensionsParts);\n\n\t\tconst body = new Uint8Array([\n\t\t\t// Version field – 0x03, 0x03 means TLS 1.2\n\t\t\t...TLS_Version_1_2,\n\n\t\t\t...serverRandom,\n\n\t\t\tclientHello.session_id.length,\n\t\t\t...clientHello.session_id,\n\n\t\t\t...as2Bytes(CipherSuites.TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256),\n\n\t\t\tcompressionAlgorithm,\n\n\t\t\t// Extensions length (2 bytes)\n\t\t\t...as2Bytes(extensions.length),\n\n\t\t\t...extensions,\n\t\t]);\n\n\t\treturn new Uint8Array([\n\t\t\tHandshakeType.ServerHello,\n\t\t\t...as3Bytes(body.length),\n\t\t\t...body,\n\t\t]);\n\t}\n\n\tstatic serverHelloDone(): Uint8Array {\n\t\treturn new Uint8Array([HandshakeType.ServerHelloDone, ...as3Bytes(0)]);\n\t}\n\n\t/**\n\t * Server finished message.\n\t * The structure is defined in:\n\t * https://datatracker.ietf.org/doc/html/rfc5246#section-7.4.9\n\t *\n\t * struct {\n\t * opaque verify_data[verify_data_length];\n\t * } Finished;\n\t *\n\t * verify_data\n\t * PRF(master_secret, finished_label, Hash(handshake_messages))\n\t * [0..verify_data_length-1];\n\t *\n\t * finished_label\n\t * For Finished messages sent by the client, the string\n\t * \"client finished\". For Finished messages sent by the server,\n\t * the string \"server finished\".\n\t */\n\tstatic async createFinishedMessage(\n\t\thandshakeMessages: Uint8Array[],\n\t\tmasterSecret: ArrayBuffer\n\t): Promise<Uint8Array> {\n\t\t// Step 1: Compute the hash of the handshake messages\n\t\tconst handshakeHash = await crypto.subtle.digest(\n\t\t\t'SHA-256',\n\t\t\tconcatUint8Arrays(handshakeMessages)\n\t\t);\n\n\t\t// Step 2: Compute the verify_data using the PRF\n\t\tconst verifyData = new Uint8Array(\n\t\t\tawait tls12Prf(\n\t\t\t\tmasterSecret,\n\t\t\t\tnew TextEncoder().encode('server finished'),\n\t\t\t\thandshakeHash,\n\t\t\t\t// verify_data length. TLS 1.2 specifies 12 bytes for verify_data\n\t\t\t\t12\n\t\t\t)\n\t\t);\n\n\t\t// Step 3: Construct the Finished message\n\t\treturn new Uint8Array([\n\t\t\tHandshakeType.Finished,\n\t\t\t...as3Bytes(verifyData.length),\n\t\t\t...verifyData,\n\t\t]);\n\t}\n\n\tstatic changeCipherSpec(): Uint8Array {\n\t\treturn new Uint8Array([0x01]);\n\t}\n}\n","import { concatUint8Arrays } from '@php-wasm/util';\n\n/**\n * Generates an X.509 certificate from the given description.\n *\n * If the issuer key pair is provided, the certificate will be signed\n * using the provided issuer's private key. Otherwise, the certificate\n * will be self-signed.\n *\n * The code below is underdocumented. The following links may provide\n * more clarity about X.509, ASN.1, DER, PEM, and other data formats\n * this module encodes:\n *\n * * https://letsencrypt.org/docs/a-warm-welcome-to-asn1-and-der/\n * * https://dev.to/wayofthepie/structure-of-an-ssl-x-509-certificate-16b\n * * https://www.oss.com/asn1/resources/asn1-made-simple/asn1-quick-reference/asn1-tags.html\n */\nexport function generateCertificate(\n\tdescription: TBSCertificateDescription,\n\tissuerKeyPair?: CryptoKeyPair\n): Promise<GeneratedCertificate> {\n\treturn CertificateGenerator.generateCertificate(description, issuerKeyPair);\n}\n\nexport function certificateToPEM(certificate: Uint8Array): string {\n\treturn `-----BEGIN CERTIFICATE-----\\n${formatPEM(\n\t\tencodeUint8ArrayAsBase64(certificate.buffer)\n\t)}\\n-----END CERTIFICATE-----`;\n}\n\nexport async function privateKeyToPEM(privateKey: CryptoKey): Promise<string> {\n\tconst pkcs8 = await crypto.subtle.exportKey('pkcs8', privateKey);\n\treturn `-----BEGIN PRIVATE KEY-----\\n${formatPEM(\n\t\tencodeUint8ArrayAsBase64(pkcs8)\n\t)}\\n-----END PRIVATE KEY-----`;\n}\n\nclass CertificateGenerator {\n\tstatic async generateCertificate(\n\t\ttbsDescription: TBSCertificateDescription,\n\t\tissuerKeyPair?: CryptoKeyPair\n\t) {\n\t\tconst subjectKeyPair = await crypto.subtle.generateKey(\n\t\t\t{\n\t\t\t\tname: 'RSASSA-PKCS1-v1_5',\n\t\t\t\thash: 'SHA-256',\n\t\t\t\tmodulusLength: 2048,\n\t\t\t\tpublicExponent: new Uint8Array([0x01, 0x00, 0x01]),\n\t\t\t},\n\t\t\ttrue, // extractable\n\t\t\t['sign', 'verify']\n\t\t);\n\t\tconst tbsCertificate = await this.signingRequest(\n\t\t\ttbsDescription,\n\t\t\tsubjectKeyPair.publicKey\n\t\t);\n\t\tconst certificate = await this.sign(\n\t\t\ttbsCertificate,\n\t\t\tissuerKeyPair?.privateKey ?? subjectKeyPair.privateKey\n\t\t);\n\t\treturn {\n\t\t\tkeyPair: subjectKeyPair,\n\t\t\tcertificate,\n\t\t\ttbsCertificate,\n\t\t\ttbsDescription,\n\t\t};\n\t}\n\n\tstatic async sign(\n\t\ttbsCertificate: TBSCertificate,\n\t\tprivateKey: CryptoKey\n\t): Promise<Uint8Array> {\n\t\t// Step 3: Sign the TBSCertificate\n\t\tconst signature = await crypto.subtle.sign(\n\t\t\t{\n\t\t\t\tname: 'RSASSA-PKCS1-v1_5',\n\t\t\t\thash: 'SHA-256',\n\t\t\t},\n\t\t\tprivateKey,\n\t\t\ttbsCertificate.buffer\n\t\t);\n\n\t\t// Step 4: Build the final Certificate sequence\n\t\tconst certificate = ASN1Encoder.sequence([\n\t\t\tnew Uint8Array(tbsCertificate.buffer),\n\t\t\tthis.signatureAlgorithm('sha256WithRSAEncryption'),\n\t\t\tASN1Encoder.bitString(new Uint8Array(signature)),\n\t\t]);\n\t\treturn certificate;\n\t}\n\n\tstatic async signingRequest(\n\t\tdescription: TBSCertificateDescription,\n\t\tsubjectPublicKey: CryptoKey\n\t): Promise<TBSCertificate> {\n\t\tconst extensions: Uint8Array[] = [];\n\t\tif (description.keyUsage) {\n\t\t\textensions.push(this.keyUsage(description.keyUsage));\n\t\t}\n\t\tif (description.extKeyUsage) {\n\t\t\textensions.push(this.extKeyUsage(description.extKeyUsage));\n\t\t}\n\t\tif (description.subjectAltNames) {\n\t\t\textensions.push(this.subjectAltName(description.subjectAltNames));\n\t\t}\n\t\tif (description.nsCertType) {\n\t\t\textensions.push(this.nsCertType(description.nsCertType));\n\t\t}\n\t\tif (description.basicConstraints) {\n\t\t\textensions.push(\n\t\t\t\tthis.basicConstraints(description.basicConstraints)\n\t\t\t);\n\t\t}\n\t\treturn ASN1Encoder.sequence([\n\t\t\tthis.version(description.version),\n\t\t\tthis.serialNumber(description.serialNumber),\n\t\t\tthis.signatureAlgorithm(description.signatureAlgorithm),\n\t\t\tthis.distinguishedName(description.issuer ?? description.subject),\n\t\t\tthis.validity(description.validity),\n\t\t\tthis.distinguishedName(description.subject),\n\t\t\tawait this.subjectPublicKeyInfo(subjectPublicKey),\n\t\t\tthis.extensions(extensions),\n\t\t]);\n\t}\n\n\tprivate static version(version = 0x02) {\n\t\t// [0] EXPLICIT Version: 2 (v3)\n\t\treturn ASN1Encoder.ASN1(\n\t\t\t0xa0,\n\t\t\tASN1Encoder.integer(new Uint8Array([version]))\n\t\t);\n\t}\n\n\tprivate static serialNumber(\n\t\tserialNumber = crypto.getRandomValues(new Uint8Array(4))\n\t) {\n\t\treturn ASN1Encoder.integer(serialNumber);\n\t}\n\n\tprivate static signatureAlgorithm(\n\t\talgorithm: OIDName = 'sha256WithRSAEncryption'\n\t) {\n\t\treturn ASN1Encoder.sequence([\n\t\t\tASN1Encoder.objectIdentifier(oidByName(algorithm)),\n\t\t\tASN1Encoder.null(),\n\t\t]);\n\t}\n\n\tprivate static async subjectPublicKeyInfo(publicKey: CryptoKey) {\n\t\t// ExportKey already returns data in ASN.1 DER format, we don't\n\t\t// need to wrap it in a sequence agin.\n\t\treturn new Uint8Array(await crypto.subtle.exportKey('spki', publicKey));\n\t}\n\n\tprivate static extensions(extensions: Uint8Array[]) {\n\t\treturn ASN1Encoder.ASN1(0xa3, ASN1Encoder.sequence(extensions));\n\t}\n\n\tprivate static distinguishedName(nameInfo: DistinguishedName) {\n\t\tconst values = [];\n\t\tfor (const [oidName, value] of Object.entries(nameInfo)) {\n\t\t\tconst entry = [\n\t\t\t\tASN1Encoder.objectIdentifier(oidByName(oidName as OIDName)),\n\t\t\t];\n\t\t\tswitch (oidName) {\n\t\t\t\tcase 'countryName':\n\t\t\t\t\tentry.push(ASN1Encoder.printableString(value));\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tentry.push(ASN1Encoder.utf8String(value));\n\t\t\t}\n\t\t\tvalues.push(ASN1Encoder.set([ASN1Encoder.sequence(entry)]));\n\t\t}\n\t\treturn ASN1Encoder.sequence(values);\n\t}\n\n\tprivate static validity(validity?: Validity) {\n\t\treturn ASN1Encoder.sequence([\n\t\t\tASN1Encoder.ASN1(\n\t\t\t\tASN1Tags.UTCTime,\n\t\t\t\tnew TextEncoder().encode(\n\t\t\t\t\tformatDateASN1(validity?.notBefore ?? new Date())\n\t\t\t\t)\n\t\t\t),\n\t\t\tASN1Encoder.ASN1(\n\t\t\t\tASN1Tags.UTCTime,\n\t\t\t\tnew TextEncoder().encode(\n\t\t\t\t\tformatDateASN1(\n\t\t\t\t\t\tvalidity?.notAfter ?? addYears(new Date(), 10)\n\t\t\t\t\t)\n\t\t\t\t)\n\t\t\t),\n\t\t]);\n\t}\n\n\tprivate static basicConstraints({\n\t\tca = true,\n\t\tpathLenConstraint = undefined,\n\t}: BasicConstraints) {\n\t\tconst sequence = [ASN1Encoder.boolean(ca)];\n\t\tif (pathLenConstraint !== undefined) {\n\t\t\tsequence.push(\n\t\t\t\tASN1Encoder.integer(new Uint8Array([pathLenConstraint]))\n\t\t\t);\n\t\t}\n\t\treturn ASN1Encoder.sequence([\n\t\t\tASN1Encoder.objectIdentifier(oidByName('basicConstraints')),\n\t\t\tASN1Encoder.octetString(ASN1Encoder.sequence(sequence)),\n\t\t]);\n\t}\n\n\tprivate static keyUsage(keyUsage?: KeyUsage) {\n\t\tconst keyUsageBits = new Uint8Array([0b00000000]);\n\t\tif (keyUsage?.digitalSignature) {\n\t\t\tkeyUsageBits[0] |= 0b00000001;\n\t\t}\n\t\tif (keyUsage?.nonRepudiation) {\n\t\t\tkeyUsageBits[0] |= 0b00000010;\n\t\t}\n\t\tif (keyUsage?.keyEncipherment) {\n\t\t\tkeyUsageBits[0] |= 0b00000100;\n\t\t}\n\t\tif (keyUsage?.dataEncipherment) {\n\t\t\tkeyUsageBits[0] |= 0b00001000;\n\t\t}\n\t\tif (keyUsage?.keyAgreement) {\n\t\t\tkeyUsageBits[0] |= 0b00010000;\n\t\t}\n\t\tif (keyUsage?.keyCertSign) {\n\t\t\tkeyUsageBits[0] |= 0b00100000;\n\t\t}\n\t\tif (keyUsage?.cRLSign) {\n\t\t\tkeyUsageBits[0] |= 0b01000000;\n\t\t}\n\t\tif (keyUsage?.encipherOnly) {\n\t\t\tkeyUsageBits[0] |= 0b10000000;\n\t\t}\n\t\tif (keyUsage?.decipherOnly) {\n\t\t\tkeyUsageBits[0] |= 0b01000000;\n\t\t}\n\t\treturn ASN1Encoder.sequence([\n\t\t\tASN1Encoder.objectIdentifier(oidByName('keyUsage')),\n\t\t\tASN1Encoder.boolean(true), // Critical\n\t\t\tASN1Encoder.octetString(ASN1Encoder.bitString(keyUsageBits)),\n\t\t]);\n\t}\n\n\tprivate static extKeyUsage(extKeyUsage: ExtKeyUsage = {}) {\n\t\treturn ASN1Encoder.sequence([\n\t\t\tASN1Encoder.objectIdentifier(oidByName('extKeyUsage')),\n\t\t\tASN1Encoder.boolean(true), // Critical\n\t\t\tASN1Encoder.octetString(\n\t\t\t\tASN1Encoder.sequence(\n\t\t\t\t\tObject.entries(extKeyUsage).map(([oidName, value]) => {\n\t\t\t\t\t\tif (value) {\n\t\t\t\t\t\t\treturn ASN1Encoder.objectIdentifier(\n\t\t\t\t\t\t\t\toidByName(oidName as OIDName)\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn ASN1Encoder.null();\n\t\t\t\t\t})\n\t\t\t\t)\n\t\t\t),\n\t\t]);\n\t}\n\n\tprivate static nsCertType(nsCertType: NSCertType) {\n\t\tconst bits = new Uint8Array([0x00]);\n\t\tif (nsCertType.client) {\n\t\t\tbits[0] |= 0x01;\n\t\t}\n\t\tif (nsCertType.server) {\n\t\t\tbits[0] |= 0x02;\n\t\t}\n\t\tif (nsCertType.email) {\n\t\t\tbits[0] |= 0x04;\n\t\t}\n\t\tif (nsCertType.objsign) {\n\t\t\tbits[0] |= 0x08;\n\t\t}\n\t\tif (nsCertType.sslCA) {\n\t\t\tbits[0] |= 0x10;\n\t\t}\n\t\tif (nsCertType.emailCA) {\n\t\t\tbits[0] |= 0x20;\n\t\t}\n\t\tif (nsCertType.objCA) {\n\t\t\tbits[0] |= 0x40;\n\t\t}\n\t\treturn ASN1Encoder.sequence([\n\t\t\tASN1Encoder.objectIdentifier(oidByName('nsCertType')),\n\t\t\tASN1Encoder.octetString(bits),\n\t\t]);\n\t}\n\n\tprivate static subjectAltName(altNames: SubjectAltNames) {\n\t\tconst generalNames =\n\t\t\taltNames.dnsNames?.map((name) => {\n\t\t\t\tconst dnsName = ASN1Encoder.ia5String(name);\n\t\t\t\treturn ASN1Encoder.contextSpecific(2, dnsName);\n\t\t\t}) || [];\n\t\tconst ipAddresses =\n\t\t\taltNames.ipAddresses?.map((ip) => {\n\t\t\t\tconst ipAddress = ASN1Encoder.ia5String(ip);\n\t\t\t\treturn ASN1Encoder.contextSpecific(7, ipAddress);\n\t\t\t}) || [];\n\t\tconst sanExtensionValue = ASN1Encoder.octetString(\n\t\t\tASN1Encoder.sequence([...generalNames, ...ipAddresses])\n\t\t);\n\t\treturn ASN1Encoder.sequence([\n\t\t\tASN1Encoder.objectIdentifier(oidByName('subjectAltName')),\n\t\t\tASN1Encoder.boolean(true),\n\t\t\tsanExtensionValue,\n\t\t]);\n\t}\n}\n\n/**\n * OIDs used in X.509 certificates.\n *\n * Source: https://oidref.com/\n */\nconst oids = {\n\t// Algorithm OIDs\n\t'1.2.840.113549.1.1.1': 'rsaEncryption',\n\t'1.2.840.113549.1.1.4': 'md5WithRSAEncryption',\n\t'1.2.840.113549.1.1.5': 'sha1WithRSAEncryption',\n\t'1.2.840.113549.1.1.7': 'RSAES-OAEP',\n\t'1.2.840.113549.1.1.8': 'mgf1',\n\t'1.2.840.113549.1.1.9': 'pSpecified',\n\t'1.2.840.113549.1.1.10': 'RSASSA-PSS',\n\t'1.2.840.113549.1.1.11': 'sha256WithRSAEncryption',\n\t'1.2.840.113549.1.1.12': 'sha384WithRSAEncryption',\n\t'1.2.840.113549.1.1.13': 'sha512WithRSAEncryption',\n\t'1.3.101.112': 'EdDSA25519',\n\t'1.2.840.10040.4.3': 'dsa-with-sha1',\n\t'1.3.14.3.2.7': 'desCBC',\n\t'1.3.14.3.2.26': 'sha1',\n\t'1.3.14.3.2.29': 'sha1WithRSASignature',\n\t'2.16.840.1.101.3.4.2.1': 'sha256',\n\t'2.16.840.1.101.3.4.2.2': 'sha384',\n\t'2.16.840.1.101.3.4.2.3': 'sha512',\n\t'2.16.840.1.101.3.4.2.4': 'sha224',\n\t'2.16.840.1.101.3.4.2.5': 'sha512-224',\n\t'2.16.840.1.101.3.4.2.6': 'sha512-256',\n\t'1.2.840.113549.2.2': 'md2',\n\t'1.2.840.113549.2.5': 'md5',\n\n\t// pkcs#7 content types\n\t'1.2.840.113549.1.7.1': 'data',\n\t'1.2.840.113549.1.7.2': 'signedData',\n\t'1.2.840.113549.1.7.3': 'envelopedData',\n\t'1.2.840.113549.1.7.4': 'signedAndEnvelopedData',\n\t'1.2.840.113549.1.7.5': 'digestedData',\n\t'1.2.840.113549.1.7.6': 'encryptedData',\n\n\t// pkcs#9 oids\n\t'1.2.840.113549.1.9.1': 'emailAddress',\n\t'1.2.840.113549.1.9.2': 'unstructuredName',\n\t'1.2.840.113549.1.9.3': 'contentType',\n\t'1.2.840.113549.1.9.4': 'messageDigest',\n\t'1.2.840.113549.1.9.5': 'signingTime',\n\t'1.2.840.113549.1.9.6': 'counterSignature',\n\t'1.2.840.113549.1.9.7': 'challengePassword',\n\t'1.2.840.113549.1.9.8': 'unstructuredAddress',\n\t'1.2.840.113549.1.9.14': 'extensionRequest',\n\t'1.2.840.113549.1.9.20': 'friendlyName',\n\t'1.2.840.113549.1.9.21': 'localKeyId',\n\t'1.2.840.113549.1.9.22.1': 'x509Certificate',\n\n\t// pkcs#12 safe bags\n\t'1.2.840.113549.1.12.10.1.1': 'keyBag',\n\t'1.2.840.113549.1.12.10.1.2': 'pkcs8ShroudedKeyBag',\n\t'1.2.840.113549.1.12.10.1.3': 'certBag',\n\t'1.2.840.113549.1.12.10.1.4': 'crlBag',\n\t'1.2.840.113549.1.12.10.1.5': 'secretBag',\n\t'1.2.840.113549.1.12.10.1.6': 'safeContentsBag',\n\n\t// password-based-encryption for pkcs#12\n\t'1.2.840.113549.1.5.13': 'pkcs5PBES2',\n\t'1.2.840.113549.1.5.12': 'pkcs5PBKDF2',\n\t'1.2.840.113549.1.12.1.1': 'pbeWithSHAAnd128BitRC4',\n\t'1.2.840.113549.1.12.1.2': 'pbeWithSHAAnd40BitRC4',\n\t'1.2.840.113549.1.12.1.3': 'pbeWithSHAAnd3-KeyTripleDES-CBC',\n\t'1.2.840.113549.1.12.1.4': 'pbeWithSHAAnd2-KeyTripleDES-CBC',\n\t'1.2.840.113549.1.12.1.5': 'pbeWithSHAAnd128BitRC2-CBC',\n\t'1.2.840.113549.1.12.1.6': 'pbewithSHAAnd40BitRC2-CBC',\n\n\t// hmac OIDs\n\t'1.2.840.113549.2.7': 'hmacWithSHA1',\n\t'1.2.840.113549.2.8': 'hmacWithSHA224',\n\t'1.2.840.113549.2.9': 'hmacWithSHA256',\n\t'1.2.840.113549.2.10': 'hmacWithSHA384',\n\t'1.2.840.113549.2.11': 'hmacWithSHA512',\n\n\t// symmetric key algorithm oids\n\t'1.2.840.113549.3.7': 'des-EDE3-CBC',\n\t'2.16.840.1.101.3.4.1.2': 'aes128-CBC',\n\t'2.16.840.1.101.3.4.1.22': 'aes192-CBC',\n\t'2.16.840.1.101.3.4.1.42': 'aes256-CBC',\n\n\t// certificate issuer/subject OIDs\n\t'2.5.4.3': 'commonName',\n\t'2.5.4.4': 'surname',\n\t'2.5.4.5': 'serialNumber',\n\t'2.5.4.6': 'countryName',\n\t'2.5.4.7': 'localityName',\n\t'2.5.4.8': 'stateOrProvinceName',\n\t'2.5.4.9': 'streetAddress',\n\t'2.5.4.10': 'organizationName',\n\t'2.5.4.11': 'organizationalUnitName',\n\t'2.5.4.12': 'title',\n\t'2.5.4.13': 'description',\n\t'2.5.4.15': 'businessCategory',\n\t'2.5.4.17': 'postalCode',\n\t'2.5.4.42': 'givenName',\n\t'1.3.6.1.4.1.311.60.2.1.2':\n\t\t'jurisdictionOfIncorporationStateOrProvinceName',\n\t'1.3.6.1.4.1.311.60.2.1.3': 'jurisdictionOfIncorporationCountryName',\n\n\t// X.509 extension OIDs\n\t'2.16.840.1.113730.1.1': 'nsCertType',\n\t'2.16.840.1.113730.1.13': 'nsComment',\n\t'2.5.29.14': 'subjectKeyIdentifier',\n\t'2.5.29.15': 'keyUsage',\n\t'2.5.29.17': 'subjectAltName',\n\t'2.5.29.18': 'issuerAltName',\n\t'2.5.29.19': 'basicConstraints',\n\t'2.5.29.31': 'cRLDistributionPoints',\n\t'2.5.29.32': 'certificatePolicies',\n\t'2.5.29.35': 'authorityKeyIdentifier',\n\t'2.5.29.37': 'extKeyUsage',\n\n\t// extKeyUsage purposes\n\t'1.3.6.1.4.1.11129.2.4.2': 'timestampList',\n\t'1.3.6.1.5.5.7.1.1': 'authorityInfoAccess',\n\t'1.3.6.1.5.5.7.3.1': 'serverAuth',\n\t'1.3.6.1.5.5.7.3.2': 'clientAuth',\n\t'1.3.6.1.5.5.7.3.3': 'codeSigning',\n\t'1.3.6.1.5.5.7.3.4': 'emailProtection',\n\t'1.3.6.1.5.5.7.3.8': 'timeStamping',\n} as const;\n\nfunction oidByName(requestedName: OIDName): OID {\n\tfor (const [oid, name] of Object.entries(oids)) {\n\t\tif (name === requestedName) {\n\t\t\treturn oid as OID;\n\t\t}\n\t}\n\tthrow new Error(`OID not found for name: ${requestedName}`);\n}\n\nconst constructedBit = 0b00100000;\nconst ASN1Tags = {\n\tEOC: 0,\n\tBoolean: 1,\n\tInteger: 2,\n\tBitString: 3,\n\tOctetString: 4,\n\tNull: 5,\n\tOID: 6,\n\tObjectDescriptor: 7,\n\tExternal: 8,\n\tReal: 9, // float\n\tEnumeration: 10,\n\tPDV: 11,\n\tUtf8String: 12,\n\tRelativeOID: 13,\n\tSequence: 16 | constructedBit,\n\tSet: 17 | constructedBit,\n\tNumericString: 18,\n\tPrintableString: 19,\n\tT61String: 20,\n\tVideotexString: 21,\n\tIA5String: 22,\n\tUTCTime: 23,\n\tGeneralizedTime: 24,\n\tGraphicString: 25,\n\tVisibleString: 26,\n\tGeneralString: 28,\n\tUniversalString: 29,\n\tCharacterString: 30,\n\tBMPString: 31,\n\tConstructor: 32,\n\tContext: 128,\n};\n\nclass ASN1Encoder {\n\t// Helper functions for ASN.1 DER encoding\n\tstatic length_(length: number): Uint8Array {\n\t\tif (length < 0x80) {\n\t\t\t// Short form: single byte length\n\t\t\treturn new Uint8Array([length]);\n\t\t} else {\n\t\t\t// Long form: first byte is 0x80 + number of length bytes\n\t\t\t// Subsequent bytes are the length, big-endian\n\t\t\tlet tempLength = length;\n\t\t\tconst lengthBytesArray: number[] = [];\n\t\t\twhile (tempLength > 0) {\n\t\t\t\tlengthBytesArray.unshift(tempLength & 0xff);\n\t\t\t\ttempLength >>= 8;\n\t\t\t}\n\t\t\tconst numLengthBytes = lengthBytesArray.length;\n\t\t\tconst result = new Uint8Array(1 + numLengthBytes);\n\t\t\tresult[0] = 0x80 | numLengthBytes;\n\t\t\tfor (let i = 0; i < numLengthBytes; i++) {\n\t\t\t\tresult[i + 1] = lengthBytesArray[i];\n\t\t\t}\n\t\t\treturn result;\n\t\t}\n\t}\n\n\tstatic ASN1(tag: number, data: Uint8Array): Uint8Array {\n\t\tconst lengthBytes = ASN1Encoder.length_(data.length);\n\t\tconst result = new Uint8Array(1 + lengthBytes.length + data.length);\n\t\tresult[0] = tag;\n\t\tresult.set(lengthBytes, 1);\n\t\tresult.set(data, 1 + lengthBytes.length);\n\t\treturn result;\n\t}\n\n\tstatic integer(number: Uint8Array): Uint8Array {\n\t\t// Ensure number is positive and first bit is 0\n\t\tif (number[0] > 0x7f) {\n\t\t\tconst extendedNumber = new Uint8Array(number.length + 1);\n\t\t\textendedNumber[0] = 0x00;\n\t\t\textendedNumber.set(number, 1);\n\t\t\tnumber = extendedNumber;\n\t\t}\n\t\treturn ASN1Encoder.ASN1(ASN1Tags.Integer, number);\n\t}\n\n\tstatic bitString(data: Uint8Array): Uint8Array {\n\t\tconst unusedBits = new Uint8Array([0x00]);\n\t\tconst combined = new Uint8Array(unusedBits.length + data.length);\n\t\tcombined.set(unusedBits);\n\t\tcombined.set(data, unusedBits.length);\n\t\treturn ASN1Encoder.ASN1(ASN1Tags.BitString, combined);\n\t}\n\n\tstatic octetString(data: Uint8Array): Uint8Array {\n\t\treturn ASN1Encoder.ASN1(ASN1Tags.OctetString, data);\n\t}\n\n\tstatic null(): Uint8Array {\n\t\treturn ASN1Encoder.ASN1(ASN1Tags.Null, new Uint8Array(0));\n\t}\n\n\tstatic objectIdentifier(oid: string): Uint8Array {\n\t\tconst oidParts = oid.split('.').map(Number);\n\t\tconst firstByte = oidParts[0] * 40 + oidParts[1];\n\t\tconst encodedParts = [firstByte];\n\t\tfor (let i = 2; i < oidParts.length; i++) {\n\t\t\tlet value = oidParts[i];\n\t\t\tconst bytes: number[] = [];\n\t\t\tdo {\n\t\t\t\tbytes.unshift(value & 0x7f);\n\t\t\t\tvalue >>= 7;\n\t\t\t} while (value > 0);\n\t\t\tfor (let j = 0; j < bytes.length - 1; j++) {\n\t\t\t\tbytes[j] |= 0x80;\n\t\t\t}\n\t\t\tencodedParts.push(...bytes);\n\t\t}\n\t\treturn ASN1Encoder.ASN1(ASN1Tags.OID, new Uint8Array(encodedParts));\n\t}\n\n\tstatic utf8String(str: string): Uint8Array {\n\t\tconst utf8Bytes = new TextEncoder().encode(str);\n\t\treturn ASN1Encoder.ASN1(ASN1Tags.Utf8String, utf8Bytes);\n\t}\n\n\tstatic printableString(str: string): Uint8Array {\n\t\tconst utf8Bytes = new TextEncoder().encode(str);\n\t\treturn ASN1Encoder.ASN1(ASN1Tags.PrintableString, utf8Bytes);\n\t}\n\n\tstatic sequence(items: Uint8Array[]): Uint8Array {\n\t\treturn ASN1Encoder.ASN1(ASN1Tags.Sequence, concatUint8Arrays(items));\n\t}\n\n\tstatic set(items: Uint8Array[]): Uint8Array {\n\t\treturn ASN1Encoder.ASN1(ASN1Tags.Set, concatUint8Arrays(items));\n\t}\n\n\tstatic ia5String(str: string): Uint8Array {\n\t\tconst utf8Bytes = new TextEncoder().encode(str);\n\t\treturn ASN1Encoder.ASN1(ASN1Tags.IA5String, utf8Bytes);\n\t}\n\n\tstatic contextSpecific(\n\t\ttagNumber: number,\n\t\tdata: Uint8Array,\n\t\tconstructed = false\n\t): Uint8Array {\n\t\tconst tag = (constructed ? 0xa0 : 0x80) | tagNumber;\n\t\treturn ASN1Encoder.ASN1(tag, data);\n\t}\n\n\tstatic boolean(value: boolean): Uint8Array {\n\t\treturn ASN1Encoder.ASN1(\n\t\t\tASN1Tags.Boolean,\n\t\t\tnew Uint8Array([value ? 0xff : 0x00])\n\t\t);\n\t}\n}\n\nexport interface DistinguishedName {\n\tcountryName?: string;\n\torganizationName?: string;\n\tcommonName?: string;\n\tlocalityName?: string;\n\tstateOrProvinceName?: string;\n\tstreetAddress?: string;\n\tpostalCode?: string;\n\temailAddress?: string;\n\torganizationalUnitName?: string;\n\ttitle?: string;\n\tdescription?: string;\n\tbusinessCategory?: string;\n}\n\nexport type Validity = {\n\tnotBefore: Date;\n\tnotAfter: Date;\n};\n\nexport type OID = keyof typeof oids;\nexport type OIDName = (typeof oids)[OID];\n\nexport interface BasicConstraints {\n\tca: boolean;\n\tpathLenConstraint?: number;\n}\n\nexport interface KeyUsage {\n\tdigitalSignature?: boolean;\n\tnonRepudiation?: boolean;\n\tkeyEncipherment?: boolean;\n\tdataEncipherment?: boolean;\n\tkeyAgreement?: boolean;\n\tkeyCertSign?: boolean;\n\tcRLSign?: boolean;\n\tencipherOnly?: boolean;\n\tdecipherOnly?: boolean;\n}\n\nexport interface ExtKeyUsage {\n\tserverAuth?: boolean;\n\tclientAuth?: boolean;\n\tcodeSigning?: boolean;\n\temailProtection?: boolean;\n\ttimeStamping?: boolean;\n}\n\nexport interface NSCertType {\n\tclient?: boolean;\n\tserver?: boolean;\n\temail?: boolean;\n\tobjsign?: boolean;\n\tsslCA?: boolean;\n\temailCA?: boolean;\n\tobjCA?: boolean;\n}\n\nexport interface SubjectAltNames {\n\tdnsNames?: string[];\n\tipAddresses?: string[];\n}\n\nexport interface TBSCertificateDescription {\n\tversion?: number;\n\tserialNumber?: Uint8Array;\n\tsignatureAlgorithm?: OIDName;\n\tissuer?: DistinguishedName;\n\tvalidity?: Validity;\n\tsubject: DistinguishedName;\n\tbasicConstraints?: BasicConstraints;\n\tkeyUsage?: KeyUsage;\n\textKeyUsage?: ExtKeyUsage;\n\tsubjectAltNames?: SubjectAltNames;\n\tnsCertType?: NSCertType;\n}\nexport type TBSCertificate = Uint8Array;\n\nexport type GeneratedCertificate = {\n\tkeyPair: CryptoKeyPair;\n\tcertificate: Uint8Array;\n\ttbsDescription: TBSCertificateDescription;\n\ttbsCertificate: TBSCertificate;\n};\n\n// Helper functions\nfunction encodeUint8ArrayAsBase64(bytes: ArrayBuffer) {\n\treturn btoa(String.fromCodePoint(...new Uint8Array(bytes)));\n}\n\nfunction formatPEM(pemString: string): string {\n\treturn pemString.match(/.{1,64}/g)?.join('\\n') || pemString;\n}\n\nfunction formatDateASN1(date: Date): string {\n\t// Format date to YYMMDDHHMMSSZ for UTCTime\n\tconst year = date.getUTCFullYear().toString().substr(2);\n\tconst month = padNumber(date.getUTCMonth() + 1);\n\tconst day = padNumber(date.getUTCDate());\n\tconst hours = padNumber(date.getUTCHours());\n\tconst minutes = padNumber(date.getUTCMinutes());\n\tconst seconds = padNumber(date.getUTCSeconds());\n\treturn `${year}${month}${day}${hours}${minutes}${seconds}Z`;\n}\n\nfunction padNumber(num: number): string {\n\treturn num.toString().padStart(2, '0');\n}\n\nfunction addYears(date: Date, years: number): Date {\n\tconst newDate = new Date(date);\n\tnewDate.setUTCFullYear(newDate.getUTCFullYear() + years);\n\treturn newDate;\n}\n","/**\n * Error thrown when a CORS proxy response appears to have been\n * intercepted by a network firewall or corporate proxy.\n *\n * This is detected when a response from the CORS proxy is missing\n * the X-Playground-Cors-Proxy header that legitimate responses include.\n */\nexport class FirewallInterferenceError extends Error {\n\tpublic readonly url: string;\n\tpublic readonly status: number;\n\tpublic readonly statusText: string;\n\n\tconstructor(url: string, status: number, statusText: string) {\n\t\tsuper(\n\t\t\t`Could not fetch ${url} – your network appears to be blocking this request (HTTP ${status}). ` +\n\t\t\t\t`This often happens on school, university, or corporate networks. ` +\n\t\t\t\t`Try switching to a different network or using a VPN.`\n\t\t);\n\t\tthis.name = 'FirewallInterferenceError';\n\t\tthis.url = url;\n\t\tthis.status = status;\n\t\tthis.statusText = statusText;\n\t}\n}\n","import { cloneRequest, teeRequest } from '@php-wasm/web-service-worker';\nimport { FirewallInterferenceError } from './firewall-interference-error';\n\nconst CORS_PROXY_HEADER = 'X-Playground-Cors-Proxy';\n\nexport async function fetchWithCorsProxy(\n\tinput: RequestInfo,\n\tinit?: RequestInit,\n\tcorsProxyUrl?: string,\n\tplaygroundUrl?: string\n): Promise<Response> {\n\tlet requestObject =\n\t\ttypeof input === 'string' ? new Request(input, init) : input;\n\tconst playgroundUrlObj = playgroundUrl ? new URL(playgroundUrl) : null;\n\tlet requestUrlObj = playgroundUrlObj\n\t\t? new URL(requestObject.url, playgroundUrlObj)\n\t\t: new URL(requestObject.url);\n\tif (requestUrlObj.protocol === 'http:') {\n\t\trequestUrlObj.protocol = 'https:';\n\t\tconst httpsUrl = requestUrlObj.toString();\n\t\trequestObject = await cloneRequest(requestObject, { url: httpsUrl });\n\t\trequestUrlObj = new URL(httpsUrl);\n\t}\n\tif (!corsProxyUrl) {\n\t\treturn await fetch(requestObject);\n\t}\n\n\t/**\n\t * Never try to proxy requests to the playground itself. The remote proxy\n\t * won't be able to reach it. At best, it will produce a cryptic error\n\t * message. At worst, it will time out, making the user wait for 30 seconds.\n\t */\n\tif (\n\t\tplaygroundUrlObj &&\n\t\trequestUrlObj.protocol === playgroundUrlObj.protocol &&\n\t\trequestUrlObj.hostname === playgroundUrlObj.hostname &&\n\t\trequestUrlObj.port === playgroundUrlObj.port &&\n\t\trequestUrlObj.pathname.startsWith(playgroundUrlObj.pathname)\n\t) {\n\t\treturn await fetch(requestObject);\n\t}\n\n\t// Tee the request to avoid consuming the request body stream on the initial\n\t// fetch() so that we can retry through the cors proxy.\n\tconst [request1, request2] = await teeRequest(requestObject);\n\n\ttry {\n\t\treturn await fetch(request1);\n\t} catch {\n\t\t// If the developer has explicitly allowed the request to pass the\n\t\t// credentials headers with the X-Cors-Proxy-Allowed-Request-Headers header,\n\t\t// then let's include those credentials in the fetch() request.\n\t\tconst headers = new Headers(request2.headers);\n\t\tconst corsProxyAllowedHeaders =\n\t\t\theaders.get('x-cors-proxy-allowed-request-headers')?.split(',') ||\n\t\t\t[];\n\t\tconst requestIntendsToPassCredentials =\n\t\t\tcorsProxyAllowedHeaders.includes('authorization') ||\n\t\t\tcorsProxyAllowedHeaders.includes('cookie');\n\n\t\tconst newRequest = await cloneRequest(request2, {\n\t\t\turl: `${corsProxyUrl}${requestObject.url}`,\n\t\t\t...(requestIntendsToPassCredentials && { credentials: 'include' }),\n\t\t});\n\n\t\tconst response = await fetch(newRequest, init);\n\n\t\t// Check for firewall interference: if we got a response but it's\n\t\t// missing the CORS proxy identification header, the response likely\n\t\t// came from a network firewall rather than the actual CORS proxy.\n\t\tif (!response.headers.has(CORS_PROXY_HEADER)) {\n\t\t\tthrow new FirewallInterferenceError(\n\t\t\t\trequestObject.url,\n\t\t\t\tresponse.status,\n\t\t\t\tresponse.statusText\n\t\t\t);\n\t\t}\n\n\t\treturn response;\n\t}\n}\n","import { concatUint8Arrays } from '@php-wasm/util';\n\n/**\n * A TransformStream that decodes HTTP chunked transfer encoding.\n * Each chunk starts with the chunk size in hex followed by CRLF,\n * then the chunk data, then CRLF. A chunk size of 0 indicates the end.\n */\nexport class ChunkedDecoderStream extends TransformStream<\n\tUint8Array,\n\tUint8Array\n> {\n\tconstructor() {\n\t\tlet buffer = new Uint8Array(0);\n\t\tlet state:\n\t\t\t| 'SCAN_CHUNK_SIZE'\n\t\t\t| 'SCAN_CHUNK_DATA'\n\t\t\t| 'SCAN_CHUNK_TRAILER'\n\t\t\t| 'SCAN_FINAL_CHUNK' = 'SCAN_CHUNK_SIZE';\n\t\tlet chunkRemainingBytes = 0;\n\n\t\tsuper({\n\t\t\ttransform(chunk, controller) {\n\t\t\t\t// Add new chunk to buffer\n\t\t\t\tbuffer = concatUint8Arrays([buffer, chunk]);\n\n\t\t\t\twhile (buffer.length > 0) {\n\t\t\t\t\tif (state === 'SCAN_CHUNK_SIZE') {\n\t\t\t\t\t\t// Need at least \"0\\r\\n\" (3 bytes)\n\t\t\t\t\t\tif (buffer.length < 3) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Find the chunk size hex digits\n\t\t\t\t\t\tlet chunkBytesNb = 0;\n\t\t\t\t\t\twhile (chunkBytesNb < buffer.length) {\n\t\t\t\t\t\t\tconst byte = buffer[chunkBytesNb];\n\t\t\t\t\t\t\tconst isHexDigit =\n\t\t\t\t\t\t\t\t(byte >= 48 && byte <= 57) || // 0-9\n\t\t\t\t\t\t\t\t(byte >= 97 && byte <= 102) || // a-f\n\t\t\t\t\t\t\t\t(byte >= 65 && byte <= 70); // A-F\n\t\t\t\t\t\t\tif (!isHexDigit) break;\n\t\t\t\t\t\t\tchunkBytesNb++;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (chunkBytesNb === 0) {\n\t\t\t\t\t\t\tthrow new Error('Invalid chunk size format');\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Look for CRLF after chunk size\n\t\t\t\t\t\tif (buffer.length < chunkBytesNb + 2) {\n\t\t\t\t\t\t\t// Not enough data, let's wait for more\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tbuffer[chunkBytesNb] !== 13 || // \\r\n\t\t\t\t\t\t\tbuffer[chunkBytesNb + 1] !== 10 // \\n\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\t'Invalid chunk size format. Expected CRLF after chunk size'\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Parse the chunk size\n\t\t\t\t\t\tconst chunkSizeHex = new TextDecoder().decode(\n\t\t\t\t\t\t\tbuffer.slice(0, chunkBytesNb)\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconst chunkSize = parseInt(chunkSizeHex, 16);\n\n\t\t\t\t\t\t// Remove chunk header from buffer\n\t\t\t\t\t\tbuffer = buffer.slice(chunkBytesNb + 2);\n\n\t\t\t\t\t\tif (chunkSize === 0) {\n\t\t\t\t\t\t\tstate = 'SCAN_FINAL_CHUNK';\n\t\t\t\t\t\t\tcontroller.terminate();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tchunkRemainingBytes = chunkSize;\n\t\t\t\t\t\tstate = 'SCAN_CHUNK_DATA';\n\t\t\t\t\t} else if (state === 'SCAN_CHUNK_DATA') {\n\t\t\t\t\t\tconst bytesToRead = Math.min(\n\t\t\t\t\t\t\tchunkRemainingBytes,\n\t\t\t\t\t\t\tbuffer.length\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconst data = buffer.slice(0, bytesToRead);\n\t\t\t\t\t\tbuffer = buffer.slice(bytesToRead);\n\t\t\t\t\t\tchunkRemainingBytes -= bytesToRead;\n\n\t\t\t\t\t\tcontroller.enqueue(data);\n\n\t\t\t\t\t\tif (chunkRemainingBytes === 0) {\n\t\t\t\t\t\t\tstate = 'SCAN_CHUNK_TRAILER';\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (state === 'SCAN_CHUNK_TRAILER') {\n\t\t\t\t\t\tif (buffer.length < 2) {\n\t\t\t\t\t\t\t// Not enough data, let's wait for more\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (buffer[0] !== 13 || buffer[1] !== 10) {\n\t\t\t\t\t\t\t// \\r\\n\n\t\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\t'Invalid chunk trailer format. Expected CRLF after chunk data'\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbuffer = buffer.slice(2);\n\t\t\t\t\t\tstate = 'SCAN_CHUNK_SIZE';\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\t}\n}\n","/**\n * This is the secret sauce that enables HTTPS requests from PHP\n * via file_get_contents(), curl, and all other networking mechanisms.\n *\n * This is effectively a MITM attack on the PHP instance. The code\n * in this module decrypts the outbound traffic, runs the request\n * using fetch(), and then provides an encrypted response. From\n * PHP's perspective, it is indistinguishable from a direct connection\n * to the right server.\n *\n * ## How does it work?\n *\n * Emscripten can be configured to stream all network traffic through a\n * WebSocket. `@php-wasm/node` and `wp-now` use that to access the internet\n * via a local WebSocket->TCP proxy, but the in-browser version of WordPress\n * Playground exposes no such proxy.\n *\n * This module implements a \"fake\" WebSocket class. Instead of starting a `ws://`\n * connection, it translates the raw HTTP/HTTPS bytes into a `fetch()` call.\n *\n * In case of HTTP, the raw request bytes are parsed into a Request object with\n * a body stream and passes it to `fetch()`. Then, as the response status, headers,\n * and the body arrive, they're stream-encoded as raw response bytes and exposed as\n * incoming WebSocket data.\n *\n * In case of HTTPS, we the raw bytes are first piped through a custom TCPConnection\n * class as follows:\n *\n * 1. We generate a self-signed CA certificate and tell PHP to trust it using the\n * `openssl.cafile` PHP.ini option\n * 2. We create a domain-specific child certificate and sign it with the CA private key.\n * 3. We start accepting raw encrypted bytes, process them as structured TLS records,\n * and perform the TLS handshake.\n * 4. Encrypted tunnel is established\n * * TLSConnection decrypts the encrypted outbound data sent by PHP\n * * TLSConnection encrypts the unencrypted inbound data fed back to PHP\n *\n * From there, the plaintext data is treated by the same HTTP<->fetch() machinery as\n * described in the previous paragraph.\n */\nimport { TLS_1_2_Connection } from './tls/1_2/connection';\nimport type { GeneratedCertificate } from './tls/certificates';\nimport { generateCertificate } from './tls/certificates';\nimport { ContentTypes } from './tls/1_2/types';\nimport { fetchWithCorsProxy } from './fetch-with-cors-proxy';\nimport { ChunkedDecoderStream } from './chunked-decoder';\nimport type { EmscriptenOptions } from '@php-wasm/universal';\nimport { concatUint8Arrays } from '@php-wasm/util';\n\nexport type TCPOverFetchOptions = {\n\tCAroot: GeneratedCertificate;\n\tcorsProxyUrl?: string;\n};\n\n/**\n * Sets up a WebSocket that analyzes the received bytes and, if they look like\n * TLS or HTTP, handles the network transmission using fetch().\n */\nexport const tcpOverFetchWebsocket = (\n\temOptions: EmscriptenOptions,\n\ttcpOptions: TCPOverFetchOptions\n) => {\n\treturn {\n\t\t...emOptions,\n\t\twebsocket: {\n\t\t\turl: (_: any, host: string, port: string) => {\n\t\t\t\tconst query = new URLSearchParams({\n\t\t\t\t\thost,\n\t\t\t\t\tport,\n\t\t\t\t}).toString();\n\t\t\t\treturn `ws://playground.internal/?${query}`;\n\t\t\t},\n\t\t\tsubprotocol: 'binary',\n\t\t\tdecorator: () => {\n\t\t\t\treturn class extends TCPOverFetchWebsocket {\n\t\t\t\t\tconstructor(url: string, wsOptions: string[]) {\n\t\t\t\t\t\tsuper(url, wsOptions, {\n\t\t\t\t\t\t\tCAroot: tcpOptions.CAroot,\n\t\t\t\t\t\t\tcorsProxyUrl: tcpOptions.corsProxyUrl,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t},\n\t\t},\n\t};\n};\n\nexport interface TCPOverFetchWebsocketOptions {\n\tCAroot?: GeneratedCertificate;\n\t/**\n\t * If true, the WebSocket will emit 'message' events with the received bytes\n\t * and the 'close' event when the WebSocket is closed.\n\t *\n\t * If false, the consumer will be responsible for reading the bytes from the\n\t * clientDownstream stream and tracking the closure of that stream.\n\t */\n\toutputType?: 'messages' | 'stream';\n\tcorsProxyUrl?: string;\n}\n\nexport class TCPOverFetchWebsocket {\n\tCONNECTING = 0;\n\tOPEN = 1;\n\tCLOSING = 2;\n\tCLOSED = 3;\n\treadyState = this.CONNECTING;\n\tbinaryType = 'blob';\n\tbufferedAmount = 0;\n\textensions = '';\n\tprotocol = 'ws';\n\thost = '';\n\tport = 0;\n\tlisteners = new Map<string, any>();\n\tCAroot?: GeneratedCertificate;\n\tcorsProxyUrl?: string;\n\n\tclientUpstream = new TransformStream();\n\tclientUpstreamWriter = this.clientUpstream.writable.getWriter();\n\tclientDownstream = new TransformStream();\n\tfetchInitiated = false;\n\tbufferedBytesFromClient: Uint8Array = new Uint8Array(0);\n\n\turl: string;\n\toptions: string[];\n\n\tconstructor(\n\t\turl: string,\n\t\toptions: string[],\n\t\t{\n\t\t\tCAroot,\n\t\t\tcorsProxyUrl,\n\t\t\toutputType = 'messages',\n\t\t}: TCPOverFetchWebsocketOptions = {}\n\t) {\n\t\tthis.url = url;\n\t\tthis.options = options;\n\n\t\tconst wsUrl = new URL(url);\n\t\tthis.host = wsUrl.searchParams.get('host')!;\n\t\tthis.port = parseInt(wsUrl.searchParams.get('port')!, 10);\n\t\tthis.binaryType = 'arraybuffer';\n\n\t\tthis.corsProxyUrl = corsProxyUrl;\n\t\tthis.CAroot = CAroot;\n\t\tif (outputType === 'messages') {\n\t\t\tthis.clientDownstream.readable\n\t\t\t\t.pipeTo(\n\t\t\t\t\tnew WritableStream({\n\t\t\t\t\t\twrite: (chunk) => {\n\t\t\t\t\t\t\t/**\n\t\t\t\t\t\t\t * Emscripten expects the message event to be emitted\n\t\t\t\t\t\t\t * so let's emit it.\n\t\t\t\t\t\t\t */\n\t\t\t\t\t\t\tthis.emit('message', { data: chunk });\n\t\t\t\t\t\t},\n\t\t\t\t\t\tabort: () => {\n\t\t\t\t\t\t\t// We don't know what went wrong and the browser\n\t\t\t\t\t\t\t// won't tell us much either, so let's just pretend\n\t\t\t\t\t\t\t// the server is unreachable.\n\t\t\t\t\t\t\tthis.emit('error', new Error('ECONNREFUSED'));\n\t\t\t\t\t\t\tthis.close();\n\t\t\t\t\t\t},\n\t\t\t\t\t\tclose: () => {\n\t\t\t\t\t\t\tthis.close();\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t)\n\t\t\t\t.catch(() => {\n\t\t\t\t\t// Ignore failures arising from stream errors.\n\t\t\t\t\t// This class communicates problems to the caller\n\t\t\t\t\t// via the 'error' event.\n\t\t\t\t});\n\t\t}\n\t\tthis.readyState = this.OPEN;\n\t\tthis.emit('open');\n\t}\n\n\ton(eventName: string, callback: (e: any) => void) {\n\t\tthis.addEventListener(eventName, callback);\n\t}\n\n\tonce(eventName: string, callback: (e: any) => void) {\n\t\tconst wrapper = (e: any) => {\n\t\t\tcallback(e);\n\t\t\tthis.removeEventListener(eventName, wrapper);\n\t\t};\n\t\tthis.addEventListener(eventName, wrapper);\n\t}\n\n\taddEventListener(eventName: string, callback: (e: any) => void) {\n\t\tif (!this.listeners.has(eventName)) {\n\t\t\tthis.listeners.set(eventName, new Set());\n\t\t}\n\t\tthis.listeners.get(eventName).add(callback);\n\t}\n\n\tremoveListener(eventName: string, callback: (e: any) => void) {\n\t\tthis.removeEventListener(eventName, callback);\n\t}\n\n\tremoveEventListener(eventName: string, callback: (e: any) => void) {\n\t\tconst listeners = this.listeners.get(eventName);\n\t\tif (listeners) {\n\t\t\tlisteners.delete(callback);\n\t\t}\n\t}\n\n\temit(eventName: string, data: any = {}) {\n\t\tif (eventName === 'message') {\n\t\t\tthis.onmessage(data);\n\t\t} else if (eventName === 'close') {\n\t\t\tthis.onclose(data);\n\t\t} else if (eventName === 'error') {\n\t\t\tthis.onerror(data);\n\t\t} else if (eventName === 'open') {\n\t\t\tthis.onopen(data);\n\t\t}\n\t\tconst listeners = this.listeners.get(eventName);\n\t\tif (listeners) {\n\t\t\tfor (const listener of listeners) {\n\t\t\t\tlistener(data);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Default event handlers that can be overridden by the user\n\t// eslint-disable-next-line @typescript-eslint/no-unused-vars\n\tonclose(data: any) {}\n\t// eslint-disable-next-line @typescript-eslint/no-unused-vars\n\tonerror(data: any) {}\n\t// eslint-disable-next-line @typescript-eslint/no-unused-vars\n\tonmessage(data: any) {}\n\t// eslint-disable-next-line @typescript-eslint/no-unused-vars\n\tonopen(data: any) {}\n\n\t/**\n\t * Emscripten calls this method whenever the WASM module\n\t * writes bytes to the TCP socket.\n\t */\n\tsend(data: ArrayBuffer) {\n\t\tif (\n\t\t\tthis.readyState === this.CLOSING ||\n\t\t\tthis.readyState === this.CLOSED\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.clientUpstreamWriter.write(new Uint8Array(data));\n\n\t\tif (this.fetchInitiated) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Guess the protocol type first so we can learn\n\t\t// what to do with the incoming bytes.\n\t\tthis.bufferedBytesFromClient = concatUint8Arrays([\n\t\t\tthis.bufferedBytesFromClient,\n\t\t\tnew Uint8Array(data),\n\t\t]);\n\t\tswitch (guessProtocol(this.port, this.bufferedBytesFromClient)) {\n\t\t\tcase false:\n\t\t\t\t// Not enough data to classify the protocol,\n\t\t\t\t// let's wait for more.\n\t\t\t\treturn;\n\t\t\tcase 'other':\n\t\t\t\tthis.emit('error', new Error('Unsupported protocol'));\n\t\t\t\tthis.close();\n\t\t\t\tbreak;\n\t\t\tcase 'tls':\n\t\t\t\tthis.fetchOverTLS();\n\t\t\t\tthis.fetchInitiated = true;\n\t\t\t\tbreak;\n\t\t\tcase 'http':\n\t\t\t\tthis.fetchOverHTTP();\n\t\t\t\tthis.fetchInitiated = true;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tasync fetchOverTLS() {\n\t\tif (!this.CAroot) {\n\t\t\tthrow new Error(\n\t\t\t\t'TLS protocol is only supported when the TCPOverFetchWebsocket is ' +\n\t\t\t\t\t'instantiated with a CAroot'\n\t\t\t);\n\t\t}\n\t\tconst siteCert = await generateCertificate(\n\t\t\t{\n\t\t\t\tsubject: {\n\t\t\t\t\tcommonName: this.host,\n\t\t\t\t\torganizationName: this.host,\n\t\t\t\t\tcountryName: 'US',\n\t\t\t\t},\n\t\t\t\tissuer: this.CAroot.tbsDescription.subject,\n\t\t\t},\n\t\t\tthis.CAroot.keyPair\n\t\t);\n\n\t\tconst tlsConnection = new TLS_1_2_Connection();\n\n\t\t// Connect this WebSocket's client end to the TLS connection.\n\t\t// Forward the encrypted bytes from the WebSocket to the TLS connection.\n\t\tthis.clientUpstream.readable\n\t\t\t.pipeTo(tlsConnection.clientEnd.upstream.writable)\n\t\t\t.catch(() => {\n\t\t\t\t// Ignore failures arising from pipeTo() errors.\n\t\t\t\t// The caller will observe the clientEnd.downstream.writable stream\n\t\t\t\t// erroring out.\n\t\t\t});\n\n\t\t// Forward the decrypted bytes from the TLS connection to this WebSocket.\n\t\ttlsConnection.clientEnd.downstream.readable\n\t\t\t.pipeTo(this.clientDownstream.writable)\n\t\t\t.catch(() => {\n\t\t\t\t// Ignore failures arising from pipeTo() errors.\n\t\t\t\t// The caller will observe the clientEnd.downstream.writable stream\n\t\t\t\t// erroring out.\n\t\t\t});\n\n\t\t// Perform the TLS handshake\n\t\tawait tlsConnection.TLSHandshake(siteCert.keyPair.privateKey, [\n\t\t\tsiteCert.certificate,\n\t\t\tthis.CAroot.certificate,\n\t\t]);\n\n\t\t// Connect the TLS server end to the fetch() request\n\t\tconst request = await RawBytesFetch.parseHttpRequest(\n\t\t\ttlsConnection.serverEnd.upstream.readable,\n\t\t\tthis.host,\n\t\t\t'https'\n\t\t);\n\t\ttry {\n\t\t\tawait RawBytesFetch.fetchRawResponseBytes(\n\t\t\t\trequest,\n\t\t\t\tthis.corsProxyUrl\n\t\t\t).pipeTo(tlsConnection.serverEnd.downstream.writable);\n\t\t} catch {\n\t\t\t// Ignore errors from fetch()\n\t\t\t// They are handled in the constructor\n\t\t\t// via this.clientDownstream.readable.pipeTo()\n\t\t\t// and if we let the failures they would be logged\n\t\t\t// as an unhandled promise rejection.\n\t\t}\n\t}\n\n\tasync fetchOverHTTP() {\n\t\t// Connect this WebSocket's client end to the fetch() request\n\t\tconst request = await RawBytesFetch.parseHttpRequest(\n\t\t\tthis.clientUpstream.readable,\n\t\t\tthis.host,\n\t\t\t'http'\n\t\t);\n\t\ttry {\n\t\t\tawait RawBytesFetch.fetchRawResponseBytes(\n\t\t\t\trequest,\n\t\t\t\tthis.corsProxyUrl\n\t\t\t).pipeTo(this.clientDownstream.writable);\n\t\t} catch {\n\t\t\t// Ignore errors from fetch()\n\t\t\t// They are handled in the constructor\n\t\t\t// via this.clientDownstream.readable.pipeTo()\n\t\t\t// and if we let the failures they would be logged\n\t\t\t// as an unhandled promise rejection.\n\t\t}\n\t}\n\n\tclose() {\n\t\t/**\n\t\t * Workaround a PHP.wasm issue – if the WebSocket is\n\t\t * closed asynchronously after the last chunk is received,\n\t\t * the PHP.wasm runtime enters an infinite polling loop.\n\t\t *\n\t\t * The root cause of the problem is unclear at the time\n\t\t * of writing this comment. There's a chance it's a regular\n\t\t * POSIX behavior.\n\t\t *\n\t\t * Either way, sending an empty data chunk before closing\n\t\t * the WebSocket resolves the problem.\n\t\t */\n\t\tthis.emit('message', { data: new Uint8Array(0) });\n\n\t\tthis.readyState = this.CLOSING;\n\t\tthis.emit('close');\n\t\tthis.readyState = this.CLOSED;\n\t}\n}\n\nconst HTTP_METHODS = [\n\t'GET',\n\t'POST',\n\t'HEAD',\n\t'PATCH',\n\t'OPTIONS',\n\t'DELETE',\n\t'PUT',\n\t'TRACE',\n];\n\nfunction guessProtocol(port: number, data: Uint8Array) {\n\tif (data.length < 8) {\n\t\t// Not enough data to classify the protocol, let's wait for more.\n\t\treturn false;\n\t}\n\n\t// Assume TLS if we're on the usual HTTPS port and the\n\t// first three bytes look like a TLS handshake record.\n\tconst looksLikeTls =\n\t\tport === 443 &&\n\t\tdata[0] === ContentTypes.Handshake &&\n\t\t// TLS versions between 1.0 and 1.2\n\t\tdata[1] === 0x03 &&\n\t\tdata[2] >= 0x01 &&\n\t\tdata[2] <= 0x03;\n\tif (looksLikeTls) {\n\t\treturn 'tls';\n\t}\n\n\t// Assume HTTP if we're on the usual HTTP port and the\n\t// first starts with an HTTP method and a space.\n\tconst decodedFirstLine = new TextDecoder('latin1', {\n\t\tfatal: true,\n\t}).decode(data);\n\tconst looksLikeHttp = HTTP_METHODS.some((method) =>\n\t\tdecodedFirstLine.startsWith(method + ' ')\n\t);\n\tif (looksLikeHttp) {\n\t\treturn 'http';\n\t}\n\n\treturn 'other';\n}\n\nexport class RawBytesFetch {\n\t/**\n\t * Streams a HTTP response including the status line and headers.\n\t */\n\tstatic fetchRawResponseBytes(request: Request, corsProxyUrl?: string) {\n\t\t// This initially used a TransformStream and piped the response\n\t\t// body to the writable side of the TransformStream.\n\t\t//\n\t\t// Unfortunately, the first response body chunk was not correctly\n\t\t// enqueued so we switched to a customReadableStream.\n\t\treturn new ReadableStream({\n\t\t\tasync start(controller) {\n\t\t\t\tlet response: Response;\n\t\t\t\ttry {\n\t\t\t\t\tresponse = await fetchWithCorsProxy(\n\t\t\t\t\t\trequest,\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t\tcorsProxyUrl\n\t\t\t\t\t);\n\t\t\t\t} catch (error) {\n\t\t\t\t\t/**\n\t\t\t\t\t * Pretend we've got a 400 Bad Request response whenever\n\t\t\t\t\t * the fetch() call fails.\n\t\t\t\t\t *\n\t\t\t\t\t * Just propagating an error and closing a WebSocket does\n\t\t\t\t\t * not make PHP aware the socket closed abruptly. This means\n\t\t\t\t\t * the AsyncHttp\\Client will keep polling the socket indefinitely\n\t\t\t\t\t * until the request times out. This isn't perfect, as we want\n\t\t\t\t\t * to close the socket as soon as possible to avoid, e.g., 10 seconds\n\t\t\t\t\t * of unnecessary waitin for the timeout\n\t\t\t\t\t *\n\t\t\t\t\t * The root cause is unknown and likely related to the low-level\n\t\t\t\t\t * implementation of polling file descriptors. The following\n\t\t\t\t\t * workaround is far from ideal, but it must suffice until we\n\t\t\t\t\t * have a platform-level resolution.\n\t\t\t\t\t */\n\t\t\t\t\tcontroller.enqueue(\n\t\t\t\t\t\tnew TextEncoder().encode(\n\t\t\t\t\t\t\t'HTTP/1.1 400 Bad Request\\r\\nContent-Length: 0\\r\\n\\r\\n'\n\t\t\t\t\t\t)\n\t\t\t\t\t);\n\t\t\t\t\tcontroller.error(error);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tcontroller.enqueue(RawBytesFetch.headersAsBytes(response));\n\t\t\t\tconst reader = response.body?.getReader();\n\t\t\t\tif (!reader) {\n\t\t\t\t\tcontroller.close();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst encoder = new TextEncoder();\n\t\t\t\twhile (true) {\n\t\t\t\t\tconst { done, value } = await reader.read();\n\t\t\t\t\tif (value) {\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * Pass the body stream assuming the response uses\n\t\t\t\t\t\t * chunked transfer encoding.\n\t\t\t\t\t\t *\n\t\t\t\t\t\t * See `headersAsBytes()` for the details.\n\t\t\t\t\t\t */\n\t\t\t\t\t\tcontroller.enqueue(\n\t\t\t\t\t\t\tencoder.encode(`${value.length.toString(16)}\\r\\n`)\n\t\t\t\t\t\t);\n\t\t\t\t\t\tcontroller.enqueue(value);\n\t\t\t\t\t\tcontroller.enqueue(encoder.encode('\\r\\n'));\n\t\t\t\t\t}\n\t\t\t\t\tif (done) {\n\t\t\t\t\t\tcontroller.enqueue(encoder.encode('0\\r\\n\\r\\n'));\n\t\t\t\t\t\tcontroller.close();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\t}\n\n\tprivate static headersAsBytes(response: Response) {\n\t\tconst status = `HTTP/1.1 ${response.status} ${response.statusText}`;\n\n\t\tconst headersObject: Record<string, string> = {};\n\t\tresponse.headers.forEach((value, name) => {\n\t\t\theadersObject[name.toLowerCase()] = value;\n\t\t});\n\n\t\t/**\n\t\t * Best-effort attempt to provide the correct content-length\n\t\t * to the PHP-side request handler.\n\t\t *\n\t\t * Web servers often respond with a combination of Content-Length\n\t\t * and Content-Encoding. For example, a 16kb text file may be compressed\n\t\t * to 4kb with gzip and served with a Content-Encoding of `gzip` and a\n\t\t * Content-Length of 4KB.\n\t\t *\n\t\t * The web browser, however, exposes neither the Content-Encoding header\n\t\t * nor the gzipped data stream. All we have access to is the original\n\t\t * Content-Length value of the gzipped file and a decompressed data stream.\n\t\t *\n\t\t * If we just pass that along to the PHP-side request handler, it would\n\t\t * see a 16KB body stream with a Content-Length of 4KB. It would then\n\t\t * truncate the body stream at 4KB and discard the rest of the data.\n\t\t *\n\t\t * This is not what we want.\n\t\t *\n\t\t * To correct that behavior, we're stripping the Content-Length entirely.\n\t\t * We do that for every single response because we don't have any way\n\t\t * of knowing whether any Content-Encoding was used. Furthermore, we can't\n\t\t * just calculate the correct Content-Length value without consuming the\n\t\t * entire content stream – and we want to pass each data chunk to PHP\n\t\t * as we receive it.\n\t\t *\n\t\t * Instead of a fixed Content-Length, we'll use Content-Encoding: Chunked,\n\t\t * and then provide a per-chunk Content-Length. See fetchRawResponseBytes()\n\t\t * for the details.\n\t\t */\n\t\tdelete headersObject['content-length'];\n\t\theadersObject['transfer-encoding'] = 'chunked';\n\n\t\tconst headers: string[] = [];\n\t\tfor (const [name, value] of Object.entries(headersObject)) {\n\t\t\theaders.push(`${name}: ${value}`);\n\t\t}\n\t\tconst string = [status, ...headers].join('\\r\\n') + '\\r\\n\\r\\n';\n\t\treturn new TextEncoder().encode(string);\n\t}\n\n\t/**\n\t * Parses a raw, streamed HTTP request into a Request object\n\t * with known headers and a readable body stream.\n\t */\n\tstatic async parseHttpRequest(\n\t\trequestBytesStream: ReadableStream<Uint8Array>,\n\t\thost: string,\n\t\tprotocol: 'http' | 'https'\n\t) {\n\t\tlet inputBuffer: Uint8Array = new Uint8Array(0);\n\n\t\tlet requestDataExhausted = false;\n\t\tlet headersEndIndex = -1;\n\t\tconst requestBytesReader = requestBytesStream.getReader();\n\t\twhile (headersEndIndex === -1) {\n\t\t\tconst { done, value } = await requestBytesReader.read();\n\t\t\tif (done) {\n\t\t\t\trequestDataExhausted = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tinputBuffer = concatUint8Arrays([inputBuffer, value]);\n\t\t\t// Find the end of the headers (\\r\\n\\r\\n). This is\n\t\t\t// not optimal as we may end up scanning the same\n\t\t\t// bytes multiple times, but the overhead is negligible\n\t\t\t// and the code is much simpler this way.\n\t\t\theadersEndIndex = findSequenceInBuffer(\n\t\t\t\tinputBuffer,\n\t\t\t\tnew Uint8Array([0x0d, 0x0a, 0x0d, 0x0a])\n\t\t\t);\n\t\t}\n\t\trequestBytesReader.releaseLock();\n\n\t\tconst headersBuffer = inputBuffer.slice(0, headersEndIndex);\n\t\tconst parsedHeaders = RawBytesFetch.parseRequestHeaders(headersBuffer);\n\t\tconst terminationMode =\n\t\t\tparsedHeaders.headers.get('Transfer-Encoding') !== null\n\t\t\t\t? 'chunked'\n\t\t\t\t: 'content-length';\n\t\tconst contentLength =\n\t\t\tparsedHeaders.headers.get('Content-Length') !== null\n\t\t\t\t? parseInt(parsedHeaders.headers.get('Content-Length')!, 10)\n\t\t\t\t: undefined;\n\n\t\tconst bodyBytes = inputBuffer.slice(\n\t\t\theadersEndIndex + 4 /* Skip \\r\\n\\r\\n */\n\t\t);\n\t\tlet outboundBodyStream: ReadableStream<Uint8Array> | undefined;\n\t\tif (parsedHeaders.method !== 'GET') {\n\t\t\tconst requestBytesReader = requestBytesStream.getReader();\n\t\t\tlet seenBytes = bodyBytes.length;\n\t\t\tlet last5Bytes = bodyBytes.slice(-6);\n\t\t\tconst emptyChunk = new TextEncoder().encode('0\\r\\n\\r\\n');\n\t\t\toutboundBodyStream = new ReadableStream<Uint8Array>({\n\t\t\t\tasync start(controller) {\n\t\t\t\t\tif (bodyBytes.length > 0) {\n\t\t\t\t\t\tcontroller.enqueue(bodyBytes);\n\t\t\t\t\t}\n\t\t\t\t\tif (requestDataExhausted) {\n\t\t\t\t\t\tcontroller.close();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tasync pull(controller) {\n\t\t\t\t\tconst { done, value } = await requestBytesReader.read();\n\t\t\t\t\tseenBytes += value?.length || 0;\n\t\t\t\t\tif (value) {\n\t\t\t\t\t\tcontroller.enqueue(value);\n\t\t\t\t\t\tlast5Bytes = concatUint8Arrays([\n\t\t\t\t\t\t\tlast5Bytes,\n\t\t\t\t\t\t\tvalue || new Uint8Array(),\n\t\t\t\t\t\t]).slice(-5);\n\t\t\t\t\t}\n\t\t\t\t\tconst shouldTerminate =\n\t\t\t\t\t\tdone ||\n\t\t\t\t\t\t(terminationMode === 'content-length' &&\n\t\t\t\t\t\t\tcontentLength !== undefined &&\n\t\t\t\t\t\t\tseenBytes >= contentLength) ||\n\t\t\t\t\t\t(terminationMode === 'chunked' &&\n\t\t\t\t\t\t\tlast5Bytes.every(\n\t\t\t\t\t\t\t\t(byte, index) => byte === emptyChunk[index]\n\t\t\t\t\t\t\t));\n\t\t\t\t\tif (shouldTerminate) {\n\t\t\t\t\t\tcontroller.close();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tif (terminationMode === 'chunked') {\n\t\t\t\t// Strip chunked transfer encoding from the request body stream.\n\t\t\t\t// PHP may encode the request body with chunked transfer encoding,\n\t\t\t\t// giving us a stream of chunks with a size line ending in \\r\\n,\n\t\t\t\t// a body chunk, and a chunk trailer ending in \\r\\n.\n\t\t\t\t//\n\t\t\t\t// We must not include the chunk headers and trailers in the\n\t\t\t\t// transmitted data. fetch() trusts us to provide the body stream\n\t\t\t\t// in its original form and will pass treat the chunked encoding\n\t\t\t\t// artifacts as a part of the data to be transmitted to the server.\n\t\t\t\t// This, in turn, means sending over a corrupted request body.\n\t\t\t\t//\n\t\t\t\t// Therefore, let's just strip any chunked encoding-related bytes.\n\t\t\t\toutboundBodyStream = outboundBodyStream.pipeThrough(\n\t\t\t\t\tnew ChunkedDecoderStream()\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t * Prefer the Host header to the host from the URL used in a PHP\n\t\t * function call.\n\t\t *\n\t\t * There are tradeoffs involved in this decision.\n\t\t *\n\t\t * The URL from the PHP function call is the actual network location\n\t\t * the caller intended to reach, e.g. `http://192.168.1.100` or\n\t\t * `http://127.0.0.1`.\n\t\t *\n\t\t * The Host header is what the developer wanted to provide to the\n\t\t * web server, e.g. `wordpress.org` or `localhost`.\n\t\t *\n\t\t * The Host header is not a reliable indication of the target URL.\n\t\t * However, `fetch()` does not support Host spoofing. Furthermore,\n\t\t * a webserver running on 127.0.0.1 may only respond correctly\n\t\t * when it is provided with the Host header `localhost`.\n\t\t *\n\t\t * Prefering the Host header over the host from the PHP function call\n\t\t * is not perfect, but it seems like the lesser of two evils.\n\t\t */\n\t\tconst hostname = parsedHeaders.headers.get('Host') ?? host;\n\t\tconst url = new URL(parsedHeaders.path, protocol + '://' + hostname);\n\n\t\treturn new Request(url.toString(), {\n\t\t\tmethod: parsedHeaders.method,\n\t\t\theaders: parsedHeaders.headers,\n\t\t\tbody: outboundBodyStream,\n\t\t\t// In Node.js, duplex: 'half' is required when\n\t\t\t// the body stream is provided.\n\t\t\t// @ts-expect-error\n\t\t\tduplex: 'half',\n\t\t});\n\t}\n\n\tprivate static parseRequestHeaders(httpRequestBytes: Uint8Array) {\n\t\tconst httpRequest = new TextDecoder().decode(httpRequestBytes);\n\t\tconst statusLineMaybe = httpRequest.split('\\n')[0];\n\t\tconst [method, path] = statusLineMaybe.split(' ');\n\n\t\tconst headers = new Headers();\n\t\tfor (const line of httpRequest.split('\\r\\n').slice(1)) {\n\t\t\tif (line === '') {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tconst [name, value] = line.split(': ');\n\t\t\theaders.set(name, value);\n\t\t}\n\n\t\treturn { method, path, headers };\n\t}\n}\n\nfunction findSequenceInBuffer(\n\tbuffer: Uint8Array,\n\tsequence: Uint8Array\n): number {\n\tconst bufferLength = buffer.length;\n\tconst sequenceLength = sequence.length;\n\tconst lastPossibleIndex = bufferLength - sequenceLength;\n\n\tfor (let i = 0; i <= lastPossibleIndex; i++) {\n\t\tlet found = true;\n\t\tfor (let j = 0; j < sequenceLength; j++) {\n\t\t\tif (buffer[i + j] !== sequence[j]) {\n\t\t\t\tfound = false;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (found) {\n\t\t\treturn i;\n\t\t}\n\t}\n\treturn -1;\n}\n","import { LatestSupportedPHPVersion } from '@php-wasm/universal';\nimport type { SupportedPHPVersion } from '@php-wasm/universal';\n\n/**\n * Returns the path to the intl extension for the specified PHP version.\n *\n * Each PHP version's intl extension is packaged separately. Install the\n * version-specific package you need:\n * - @php-wasm/web-8-5\n * - @php-wasm/web-8-4\n * - etc.\n */\nexport async function getIntlExtensionModule(\n\tversion: SupportedPHPVersion = LatestSupportedPHPVersion\n): Promise<any> {\n\tswitch (version) {\n\t\tcase '8.5':\n\t\t\t// @ts-ignore\n\t\t\treturn (await import('@php-wasm/web-8-5')).getIntlExtensionPath();\n\t\tcase '8.4':\n\t\t\t// @ts-ignore\n\t\t\treturn (await import('@php-wasm/web-8-4')).getIntlExtensionPath();\n\t\tcase '8.3':\n\t\t\t// @ts-ignore\n\t\t\treturn (await import('@php-wasm/web-8-3')).getIntlExtensionPath();\n\t\tcase '8.2':\n\t\t\t// @ts-ignore\n\t\t\treturn (await import('@php-wasm/web-8-2')).getIntlExtensionPath();\n\t\tcase '8.1':\n\t\t\t// @ts-ignore\n\t\t\treturn (await import('@php-wasm/web-8-1')).getIntlExtensionPath();\n\t\tcase '8.0':\n\t\t\t// @ts-ignore\n\t\t\treturn (await import('@php-wasm/web-8-0')).getIntlExtensionPath();\n\t\tcase '7.4':\n\t\t\t// @ts-ignore\n\t\t\treturn (await import('@php-wasm/web-7-4')).getIntlExtensionPath();\n\t\tcase '7.3':\n\t\t\t// @ts-ignore\n\t\t\treturn (await import('@php-wasm/web-7-3')).getIntlExtensionPath();\n\t\tcase '7.2':\n\t\t\t// @ts-ignore\n\t\t\treturn (await import('@php-wasm/web-7-2')).getIntlExtensionPath();\n\t}\n\tthrow new Error(`Unsupported PHP version ${version}`);\n}\n","import type {\n\tEmscriptenOptions,\n\tPHPRuntime,\n\tSupportedPHPVersion,\n} from '@php-wasm/universal';\nimport { LatestSupportedPHPVersion, FSHelpers } from '@php-wasm/universal';\nimport { getIntlExtensionModule } from './get-intl-extension-module';\nimport { createMemoizedFetch } from '@wp-playground/common';\n\nexport async function withIntl(\n\tversion: SupportedPHPVersion = LatestSupportedPHPVersion,\n\toptions: EmscriptenOptions\n): Promise<EmscriptenOptions> {\n\tconst memoizedFetch = createMemoizedFetch(fetch);\n\n\tconst extensionName = 'intl.so';\n\tconst dataName = 'icu.dat';\n\n\tconst extensionPath = await getIntlExtensionModule(version);\n\t// @ts-ignore\n\tconst dataPath = (await import('../../../../public/shared/icu.dat'))\n\t\t.default;\n\n\tconst [extension, ICUData] = await Promise.all([\n\t\tmemoizedFetch(extensionPath).then((response) => response.arrayBuffer()),\n\t\tmemoizedFetch(dataPath).then((response) => response.arrayBuffer()),\n\t]);\n\n\treturn {\n\t\t...options,\n\t\tENV: {\n\t\t\t...options.ENV,\n\t\t\tPHP_INI_SCAN_DIR: '/internal/shared/extensions',\n\t\t\tICU_DATA: '/internal/shared',\n\t\t},\n\t\tonRuntimeInitialized: (phpRuntime: PHPRuntime) => {\n\t\t\tif (options.onRuntimeInitialized) {\n\t\t\t\toptions.onRuntimeInitialized(phpRuntime);\n\t\t\t}\n\t\t\t/**\n\t\t\t * The extension file previously read\n\t\t\t * is written inside the /extensions directory\n\t\t\t */\n\t\t\tif (\n\t\t\t\t!FSHelpers.fileExists(\n\t\t\t\t\tphpRuntime.FS,\n\t\t\t\t\t'/internal/shared/extensions'\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\tphpRuntime.FS.mkdirTree('/internal/shared/extensions');\n\t\t\t}\n\t\t\tif (\n\t\t\t\t!FSHelpers.fileExists(\n\t\t\t\t\tphpRuntime.FS,\n\t\t\t\t\t`/internal/shared/extensions/${extensionName}`\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\tphpRuntime.FS.writeFile(\n\t\t\t\t\t`/internal/shared/extensions/${extensionName}`,\n\t\t\t\t\tnew Uint8Array(extension)\n\t\t\t\t);\n\t\t\t}\n\t\t\t/* The extension has its share of ini entries\n\t\t\t * to write in a separate ini file\n\t\t\t */\n\t\t\tif (\n\t\t\t\t!FSHelpers.fileExists(\n\t\t\t\t\tphpRuntime.FS,\n\t\t\t\t\t'/internal/shared/extensions/intl.ini'\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\tphpRuntime.FS.writeFile(\n\t\t\t\t\t'/internal/shared/extensions/intl.ini',\n\t\t\t\t\t[\n\t\t\t\t\t\t`extension=/internal/shared/extensions/${extensionName}`,\n\t\t\t\t\t].join('\\n')\n\t\t\t\t);\n\t\t\t}\n\t\t\t/*\n\t\t\t * An ICU data file must be loaded to support Intl extension.\n\t\t\t * To achieve this, a shared directory is mounted and referenced\n\t\t\t * via the ICU_DATA environment variable.\n\t\t\t * By default, this variable is set to '/internal/shared',\n\t\t\t * which corresponds to the actual file location.\n\t\t\t *\n\t\t\t * The Intl extension is hard-coded to look for the `icudt74l` filename,\n\t\t\t * which means the ICU data file must use that exact name.\n\t\t\t */\n\t\t\tif (\n\t\t\t\t!FSHelpers.fileExists(\n\t\t\t\t\tphpRuntime.FS,\n\t\t\t\t\t`${phpRuntime.ENV.ICU_DATA}/${dataName}`\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\tphpRuntime.FS.mkdirTree(phpRuntime.ENV.ICU_DATA);\n\t\t\t\tphpRuntime.FS.writeFile(\n\t\t\t\t\t`${phpRuntime.ENV.ICU_DATA}/icudt74l.dat`,\n\t\t\t\t\tnew Uint8Array(ICUData)\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\t};\n}\n","import type {\n\tSupportedPHPVersion,\n\tEmscriptenOptions,\n\tPHPLoaderModule,\n} from '@php-wasm/universal';\nimport { loadPHPRuntime } from '@php-wasm/universal';\nimport { getPHPLoaderModule } from './get-php-loader-module';\nimport type { TCPOverFetchOptions } from './tcp-over-fetch-websocket';\nimport { tcpOverFetchWebsocket } from './tcp-over-fetch-websocket';\nimport { withIntl } from './extensions/intl/with-intl';\n\nexport interface LoaderOptions {\n\temscriptenOptions?: EmscriptenOptions;\n\tonPhpLoaderModuleLoaded?: (module: PHPLoaderModule) => void;\n\ttcpOverFetch?: TCPOverFetchOptions;\n\twithIntl?: boolean;\n}\n\n/**\n * Fake a websocket connection to prevent errors in the web app\n * from cascading and breaking the Playground.\n */\nconst fakeWebsocket = () => {\n\treturn {\n\t\twebsocket: {\n\t\t\tdecorator: (WebSocketConstructor: any) => {\n\t\t\t\treturn class FakeWebsocketConstructor extends WebSocketConstructor {\n\t\t\t\t\tconstructor() {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tsuper();\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t// pass\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tsend() {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t},\n\t\t},\n\t};\n};\n\ninterface PHPWorkerGlobalScope extends WorkerGlobalScope {\n\tsetImmediate: (fn: () => void) => void;\n}\n\nexport async function loadWebRuntime(\n\tphpVersion: SupportedPHPVersion,\n\tloaderOptions: LoaderOptions = {}\n) {\n\t/*\n\t * Provide `setImmediate` so Emscripten doesn’t install its message-based\n\t * polyfill, which retains references to the Wasm HEAP and prevents the\n\t * PHP instance from being garbage-collected.\n\t *\n\t * https://github.com/emscripten-core/emscripten/blob/6d61ffd7076309cb08af37aba496f25c23cdb5a4/src/lib/libeventloop.js#L57\n\t */\n\tif (!('setImmediate' in globalThis)) {\n\t\t(globalThis as unknown as PHPWorkerGlobalScope).setImmediate = (\n\t\t\tfn: () => void\n\t\t) => setTimeout(fn, 0);\n\t}\n\n\tlet emscriptenOptions: EmscriptenOptions | Promise<EmscriptenOptions> = {\n\t\t...fakeWebsocket(),\n\t\t...(loaderOptions.emscriptenOptions || {}),\n\t};\n\n\tif (loaderOptions.tcpOverFetch) {\n\t\temscriptenOptions = tcpOverFetchWebsocket(\n\t\t\temscriptenOptions,\n\t\t\tloaderOptions.tcpOverFetch\n\t\t);\n\t}\n\n\tif (loaderOptions.withIntl) {\n\t\temscriptenOptions = withIntl(phpVersion, emscriptenOptions);\n\t}\n\n\tconst [phpLoaderModule, options] = await Promise.all([\n\t\tgetPHPLoaderModule(phpVersion),\n\t\temscriptenOptions,\n\t]);\n\n\tloaderOptions.onPhpLoaderModuleLoaded?.(phpLoaderModule);\n\n\treturn await loadPHPRuntime(phpLoaderModule, options);\n}\n","/**\n * Setup a postMessage relay between the parent window and a nested iframe.\n *\n * When we're running a Playground instance inside an iframe, sometimes that\n * iframe will contain another iframe and so on. The parent application,\n * however, needs to be able to communicate with the innermost iframe. This\n * function relays the communication both ways. Call it in in every iframe\n * layer between the topmost window and the innermost iframe.\n *\n * @param nestedFrame The nested iframe element\n * @param expectedOrigin The origin that the nested iframe is expected to be on. If not\n * provided, any origin is allowed.\n */\nexport function setupPostMessageRelay(\n\tnestedFrame: HTMLIFrameElement,\n\texpectedOrigin?: string\n) {\n\t// Relay Messages from WP to Parent\n\twindow.addEventListener('message', (event) => {\n\t\tif (event.source !== nestedFrame.contentWindow) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (expectedOrigin && event.origin !== expectedOrigin) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (typeof event.data !== 'object' || event.data.type !== 'relay') {\n\t\t\treturn;\n\t\t}\n\n\t\twindow.parent.postMessage(event.data, '*');\n\t});\n\n\t// Relay Messages from Parent to WP\n\twindow.addEventListener('message', (event) => {\n\t\tif (event.source !== window.parent) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (typeof event.data !== 'object' || event.data.type !== 'relay') {\n\t\t\treturn;\n\t\t}\n\n\t\tnestedFrame?.contentWindow?.postMessage(event.data);\n\t});\n}\n","/**\n * Spawns a new Worker Thread.\n *\n * @param workerUrl The absolute URL of the worker script.\n * @returns The spawned Worker Thread.\n */\nexport async function spawnPHPWorkerThread(workerUrl: string) {\n\tconst worker = new Worker(workerUrl, { type: 'module' });\n\treturn new Promise<Worker>((resolve, reject) => {\n\t\tworker.onerror = (e) => {\n\t\t\tconst error = new Error(\n\t\t\t\t`WebWorker failed to load at ${workerUrl}. ${\n\t\t\t\t\te.message ? `Original error: ${e.message}` : ''\n\t\t\t\t}`\n\t\t\t);\n\t\t\t(error as any).filename = e.filename;\n\t\t\treject(error);\n\t\t};\n\t\t// There is no way to know when the worker script has started\n\t\t// executing, so we use a message to signal that.\n\t\tfunction onStartup(event: { data: string }) {\n\t\t\tif (event.data === 'worker-script-started') {\n\t\t\t\tresolve(worker);\n\t\t\t\tworker.removeEventListener('message', onStartup);\n\t\t\t}\n\t\t}\n\t\tworker.addEventListener('message', onStartup);\n\t});\n}\n","import type { Emscripten, MountHandler, PHP } from '@php-wasm/universal';\nimport { FSHelpers, __private__dont__use } from '@php-wasm/universal';\nimport { Semaphore, basename, joinPaths } from '@php-wasm/util';\nimport { logger } from '@php-wasm/logger';\nimport type { FilesystemOperation } from '@php-wasm/fs-journal';\nimport { normalizeFilesystemOperations } from '@php-wasm/fs-journal';\nimport { journalFSEvents } from '@php-wasm/fs-journal';\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport type * as pleaseLoadTypes from 'wicg-file-system-access';\n\ndeclare global {\n\tinterface FileSystemFileHandle {\n\t\tmove(target: FileSystemDirectoryHandle): Promise<void>;\n\t\tmove(name: string): Promise<void>;\n\t\tmove(target: FileSystemDirectoryHandle, name: string): Promise<void>;\n\t\tcreateWritable(): Promise<FileSystemWritableFileStream>;\n\t}\n\tinterface FileSystemWritableFileStream {\n\t\twrite(\n\t\t\tbuffer: BufferSource,\n\t\t\toptions?: FileSystemReadWriteOptions\n\t\t): Promise<number>;\n\t\tclose(): Promise<void>;\n\t\tseek(offset: number): Promise<void>;\n\t\ttruncate(newSize: number): Promise<void>;\n\t}\n}\n\nexport type MountDevice =\n\t| {\n\t\t\ttype: 'opfs';\n\t\t\tpath: string;\n\t }\n\t| {\n\t\t\ttype: 'local-fs';\n\t\t\thandle: FileSystemDirectoryHandle;\n\t };\n\nexport interface MountOptions {\n\tinitialSync: {\n\t\tdirection?: 'opfs-to-memfs' | 'memfs-to-opfs';\n\t\tonProgress?: SyncProgressCallback;\n\t};\n}\nexport type SyncProgress = {\n\t/** The number of files that have been synced. */\n\tfiles: number;\n\t/** The number of all files that need to be synced. */\n\ttotal: number;\n};\nexport type SyncProgressCallback = (progress: SyncProgress) => void;\n\nexport function createDirectoryHandleMountHandler(\n\thandle: FileSystemDirectoryHandle,\n\toptions: MountOptions = { initialSync: {} }\n): MountHandler {\n\toptions = {\n\t\t...options,\n\t\tinitialSync: {\n\t\t\t...options.initialSync,\n\t\t\tdirection: options.initialSync.direction ?? 'opfs-to-memfs',\n\t\t},\n\t};\n\n\treturn async function (php, FS, vfsMountPoint) {\n\t\tif (options.initialSync.direction === 'opfs-to-memfs') {\n\t\t\tif (FSHelpers.fileExists(FS, vfsMountPoint)) {\n\t\t\t\tFSHelpers.rmdir(FS, vfsMountPoint);\n\t\t\t}\n\t\t\tFSHelpers.mkdir(FS, vfsMountPoint);\n\t\t\tawait copyOpfsToMemfs(FS, handle, vfsMountPoint);\n\t\t} else {\n\t\t\tawait copyMemfsToOpfs(\n\t\t\t\tFS,\n\t\t\t\thandle,\n\t\t\t\tvfsMountPoint,\n\t\t\t\toptions.initialSync.onProgress\n\t\t\t);\n\t\t}\n\t\tconst unbindJournal = journalFSEventsToOpfs(php, handle, vfsMountPoint);\n\t\treturn unbindJournal;\n\t};\n}\n\nasync function copyOpfsToMemfs(\n\tFS: Emscripten.RootFS,\n\topfsRoot: FileSystemDirectoryHandle,\n\tmemfsRoot: string\n) {\n\tFSHelpers.mkdir(FS, memfsRoot);\n\n\t/**\n\t * Semaphores are used to limit the number of concurrent operations.\n\t * Flooding the browser with 2000 FS operations at the same time\n\t * can get quite slow.\n\t */\n\tconst semaphore = new Semaphore({\n\t\tconcurrency: 40,\n\t});\n\n\tconst ops: Array<Promise<void>> = [];\n\tconst stack: Array<[FileSystemDirectoryHandle, string]> = [\n\t\t[opfsRoot, memfsRoot],\n\t];\n\twhile (stack.length > 0) {\n\t\tconst [opfsParent, memfsParentPath] = stack.pop()!;\n\n\t\tfor await (const opfsHandle of opfsParent.values()) {\n\t\t\tconst op = semaphore.run(async () => {\n\t\t\t\tconst memfsEntryPath = joinPaths(\n\t\t\t\t\tmemfsParentPath,\n\t\t\t\t\topfsHandle.name\n\t\t\t\t);\n\t\t\t\tif (opfsHandle.kind === 'directory') {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tFS.mkdir(memfsEntryPath);\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\tif ((e as any)?.errno !== 20) {\n\t\t\t\t\t\t\tlogger.error(e);\n\t\t\t\t\t\t\t// We ignore the error if the directory already exists,\n\t\t\t\t\t\t\t// and throw otherwise.\n\t\t\t\t\t\t\tthrow e;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tstack.push([opfsHandle, memfsEntryPath]);\n\t\t\t\t} else if (opfsHandle.kind === 'file') {\n\t\t\t\t\tconst file = await opfsHandle.getFile();\n\t\t\t\t\tconst byteArray = new Uint8Array(await file.arrayBuffer());\n\t\t\t\t\tFS.createDataFile(\n\t\t\t\t\t\tmemfsParentPath,\n\t\t\t\t\t\topfsHandle.name,\n\t\t\t\t\t\tbyteArray,\n\t\t\t\t\t\ttrue,\n\t\t\t\t\t\ttrue,\n\t\t\t\t\t\ttrue\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tops.splice(ops.indexOf(op), 1);\n\t\t\t});\n\t\t\tops.push(op);\n\t\t}\n\t\t// Let the ongoing operations catch-up to the stack.\n\t\twhile (stack.length === 0 && ops.length > 0) {\n\t\t\tawait Promise.any(ops);\n\t\t}\n\t}\n}\n\nexport async function copyMemfsToOpfs(\n\tFS: Emscripten.RootFS,\n\topfsRoot: FileSystemDirectoryHandle,\n\tmemfsRoot: string,\n\tonProgress?: SyncProgressCallback\n) {\n\t// Ensure the memfs directory exists.\n\tFS.mkdirTree(memfsRoot);\n\n\t// Create all MEMFS directories in OPFS but don't create\n\t// files yet. This is quite fast.\n\tconst filesToCreate: Array<[FileSystemDirectoryHandle, string, string]> =\n\t\t[];\n\tasync function mirrorMemfsDirectoryinOpfs(\n\t\tmemfsParent: string,\n\t\topfsDir: FileSystemDirectoryHandle\n\t) {\n\t\tawait Promise.all(\n\t\t\tFS.readdir(memfsParent)\n\t\t\t\t.filter(\n\t\t\t\t\t(entryName: string) =>\n\t\t\t\t\t\tentryName !== '.' && entryName !== '..'\n\t\t\t\t)\n\t\t\t\t.map(async (entryName: string) => {\n\t\t\t\t\tconst memfsPath = joinPaths(memfsParent, entryName);\n\t\t\t\t\tif (!isMemfsDir(FS, memfsPath)) {\n\t\t\t\t\t\tfilesToCreate.push([opfsDir, memfsPath, entryName]);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst handle = await opfsDir.getDirectoryHandle(entryName, {\n\t\t\t\t\t\tcreate: true,\n\t\t\t\t\t});\n\t\t\t\t\treturn await mirrorMemfsDirectoryinOpfs(memfsPath, handle);\n\t\t\t\t})\n\t\t);\n\t}\n\tawait mirrorMemfsDirectoryinOpfs(memfsRoot, opfsRoot);\n\n\t// Now let's create all the required files in OPFS. This can be quite slow\n\t// so we report progress. Throttle the progress callback to avoid flooding\n\t// the main thread with excessive updates.\n\tlet numFilesCompleted = 0;\n\tconst throttledProgressCallback = onProgress && throttle(onProgress, 100);\n\n\t// Limit max concurrent writes because Safari may otherwise encounter\n\t// an error like \"UnknownError: Invalid platform file handle\" after opening\n\t// a sufficient number of FileSyncAccessHandles (near 128).\n\t// 2024-09-21: This limit was chosen based on perceived performance while\n\t// testing with Safari, Chrome, and Firefox. It felt like a sweet spot.\n\t// Writing one-at-a-time with no concurrency had similar performance\n\t// but felt slightly slower. We can revisit and take better measurements\n\t// if needed.\n\tconst maxConcurrentWrites = 100;\n\tconst concurrentWrites = new Set();\n\n\ttry {\n\t\tfor (const [opfsDir, memfsPath, entryName] of filesToCreate) {\n\t\t\tconst promise = overwriteOpfsFile(\n\t\t\t\topfsDir,\n\t\t\t\tentryName,\n\t\t\t\tFS,\n\t\t\t\tmemfsPath\n\t\t\t).then(() => {\n\t\t\t\tnumFilesCompleted++;\n\t\t\t\tconcurrentWrites.delete(promise);\n\n\t\t\t\tthrottledProgressCallback?.({\n\t\t\t\t\tfiles: numFilesCompleted,\n\t\t\t\t\ttotal: filesToCreate.length,\n\t\t\t\t});\n\t\t\t});\n\t\t\tconcurrentWrites.add(promise);\n\n\t\t\tif (concurrentWrites.size >= maxConcurrentWrites) {\n\t\t\t\tawait Promise.race(concurrentWrites);\n\t\t\t\tthrottledProgressCallback?.({\n\t\t\t\t\tfiles: numFilesCompleted,\n\t\t\t\t\ttotal: filesToCreate.length,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t} finally {\n\t\t// Make sure all FS-related activity has completed one way or another\n\t\t// before returning. Otherwise, an error followed by a retry might lead\n\t\t// to a conflict with writes from the earlier attempt.\n\t\tawait Promise.allSettled(concurrentWrites);\n\t}\n}\n\nfunction isMemfsDir(FS: Emscripten.RootFS, path: string) {\n\treturn FS.isDir(FS.lookupPath(path, { follow: true }).node.mode);\n}\n\nasync function overwriteOpfsFile(\n\topfsParent: FileSystemDirectoryHandle,\n\tname: string,\n\tFS: Emscripten.RootFS,\n\tmemfsPath: string\n) {\n\tlet buffer;\n\ttry {\n\t\tbuffer = FS.readFile(memfsPath, {\n\t\t\tencoding: 'binary',\n\t\t});\n\t} catch {\n\t\t// File was removed, ignore\n\t\treturn;\n\t}\n\n\tconst opfsFile = await opfsParent.getFileHandle(name, { create: true });\n\tconst writer =\n\t\topfsFile.createWritable !== undefined\n\t\t\t? // Google Chrome, Firefox, probably more browsers\n\t\t\t await opfsFile.createWritable()\n\t\t\t: // Safari\n\t\t\t await opfsFile.createSyncAccessHandle();\n\ttry {\n\t\tawait writer.truncate(0);\n\t\tawait writer.write(buffer);\n\t} finally {\n\t\tawait writer.close();\n\t}\n}\n\nexport function journalFSEventsToOpfs(\n\tphp: PHP,\n\topfsRoot: FileSystemDirectoryHandle,\n\tmemfsRoot: string\n) {\n\tconst journal: FilesystemOperation[] = [];\n\tconst unbindJournal = journalFSEvents(php, memfsRoot, (entry) => {\n\t\tjournal.push(entry);\n\t});\n\tconst rewriter = new OpfsRewriter(php, opfsRoot, memfsRoot);\n\n\tasync function flushJournal() {\n\t\tif (journal.length === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst release = await php.semaphore.acquire();\n\n\t\t// Concurrency safety note\n\t\t// As I understand it, journal is specific to a PHP instance,\n\t\t// so it's not possible to have concurrency push of entries to journal\n\t\t// But this can change in future so it doesn't hurt to read from journal\n\t\t// in a concurrent safe way, which is what we are doing here.\n\n\t\t// We first copy it to a new array\n\t\tconst journalEntries = [...journal];\n\t\t// and then only delete however many entries we were able to grab\n\t\t// since with concurrent writes there could have been more insertions\n\t\tjournal.splice(0, journalEntries.length);\n\n\t\tconst compressedJournal = normalizeFilesystemOperations(journalEntries);\n\t\ttry {\n\t\t\t// @TODO This is way too slow in practice, we need to batch the\n\t\t\t// changes into groups of parallelizable operations.\n\t\t\tfor (const entry of compressedJournal) {\n\t\t\t\tawait rewriter.processEntry(entry);\n\t\t\t}\n\t\t} finally {\n\t\t\trelease();\n\t\t}\n\t}\n\tphp.addEventListener('request.end', flushJournal);\n\tphp.addEventListener('filesystem.write', flushJournal);\n\treturn function () {\n\t\tunbindJournal();\n\t\tphp.removeEventListener('request.end', flushJournal);\n\t\tphp.removeEventListener('filesystem.write', flushJournal);\n\t};\n}\n\ntype JournalEntry = FilesystemOperation;\n\nclass OpfsRewriter {\n\tprivate memfsRoot: string;\n\tprivate php: PHP;\n\tprivate opfs: FileSystemDirectoryHandle;\n\n\tconstructor(php: PHP, opfs: FileSystemDirectoryHandle, memfsRoot: string) {\n\t\tthis.php = php;\n\t\tthis.opfs = opfs;\n\t\tthis.memfsRoot = normalizeMemfsPath(memfsRoot);\n\t}\n\n\tprivate toOpfsPath(path: string) {\n\t\treturn normalizeMemfsPath(path.substring(this.memfsRoot.length));\n\t}\n\n\tpublic async processEntry(entry: JournalEntry) {\n\t\tif (\n\t\t\t!entry.path.startsWith(this.memfsRoot) ||\n\t\t\tentry.path === this.memfsRoot\n\t\t) {\n\t\t\treturn;\n\t\t}\n\t\tconst opfsPath = this.toOpfsPath(entry.path);\n\t\tconst opfsParent = await resolveParent(this.opfs, opfsPath);\n\t\tconst name = getFilename(opfsPath);\n\t\tif (!name) {\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tif (entry.operation === 'DELETE') {\n\t\t\t\ttry {\n\t\t\t\t\tawait opfsParent.removeEntry(name, {\n\t\t\t\t\t\trecursive: true,\n\t\t\t\t\t});\n\t\t\t\t} catch {\n\t\t\t\t\t// If the directory already doesn't exist, it's fine\n\t\t\t\t}\n\t\t\t} else if (entry.operation === 'CREATE') {\n\t\t\t\tif (entry.nodeType === 'directory') {\n\t\t\t\t\tawait opfsParent.getDirectoryHandle(name, {\n\t\t\t\t\t\tcreate: true,\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tawait opfsParent.getFileHandle(name, {\n\t\t\t\t\t\tcreate: true,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} else if (entry.operation === 'WRITE') {\n\t\t\t\tawait overwriteOpfsFile(\n\t\t\t\t\topfsParent,\n\t\t\t\t\tname,\n\t\t\t\t\tthis.php[__private__dont__use].FS,\n\t\t\t\t\tentry.path\n\t\t\t\t);\n\t\t\t} else if (\n\t\t\t\tentry.operation === 'RENAME' &&\n\t\t\t\tentry.toPath.startsWith(this.memfsRoot)\n\t\t\t) {\n\t\t\t\tconst opfsTargetPath = this.toOpfsPath(entry.toPath);\n\t\t\t\tconst opfsTargetParent = await resolveParent(\n\t\t\t\t\tthis.opfs,\n\t\t\t\t\topfsTargetPath\n\t\t\t\t);\n\n\t\t\t\tif (entry.nodeType === 'directory') {\n\t\t\t\t\tconst opfsDir = await opfsTargetParent.getDirectoryHandle(\n\t\t\t\t\t\tname,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcreate: true,\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t\t\t// in OPFS, move() doesn't work for directories :-(\n\t\t\t\t\t// We have to copy the directory recursively instead.\n\t\t\t\t\tawait copyMemfsToOpfs(\n\t\t\t\t\t\tthis.php[__private__dont__use].FS,\n\t\t\t\t\t\topfsDir,\n\t\t\t\t\t\tentry.toPath\n\t\t\t\t\t);\n\t\t\t\t\t// Then delete the old directory\n\t\t\t\t\tawait opfsParent.removeEntry(name, {\n\t\t\t\t\t\trecursive: true,\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\t/**\n\t\t\t\t\t * Delete the old file and creating a new one.\n\t\t\t\t\t *\n\t\t\t\t\t * We cannot use the OPFS move() method here. Imagine pulling from\n\t\t\t\t\t * a Git repository – each pulled object is first buffered in a\n\t\t\t\t\t * file called \".tmp\" and then renamed to its final name. However,\n\t\t\t\t\t * the WRITE operation does not store the written bytes, only the\n\t\t\t\t\t * path.\n\t\t\t\t\t *\n\t\t\t\t\t * By the time the filesystem journal is flushed, we cannot\n\t\t\t\t\t * assume that the \"rename from\" path still contains the same bytes\n\t\t\t\t\t * as it did when the WRITE operation was executed. Therefore, it's\n\t\t\t\t\t * safer to delete the old file and create a new one.\n\t\t\t\t\t *\n\t\t\t\t\t * It is still possible that the new file was already deleted\n\t\t\t\t\t * or renamed to another location. That's fine. A later stage\n\t\t\t\t\t * of replaying the journal will take care of that.\n\t\t\t\t\t *\n\t\t\t\t\t * Ideally, PHP.wasm would not use journaling at all, but\n\t\t\t\t\t * a native WASMFS layer for handling OPFS.\n\t\t\t\t\t *\n\t\t\t\t\t * See https://github.com/WordPress/wordpress-playground/pull/1878\n\t\t\t\t\t * for more details.\n\t\t\t\t\t */\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait opfsParent.removeEntry(name);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// If the directory already doesn't exist, it's fine\n\t\t\t\t\t}\n\t\t\t\t\tawait overwriteOpfsFile(\n\t\t\t\t\t\topfsTargetParent,\n\t\t\t\t\t\tbasename(opfsTargetPath),\n\t\t\t\t\t\tthis.php[__private__dont__use].FS,\n\t\t\t\t\t\tentry.toPath\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (e) {\n\t\t\t// Useful for debugging – the original error gets lost in the\n\t\t\t// Comlink proxy.\n\t\t\tlogger.log({ entry, name });\n\t\t\tlogger.error(e);\n\t\t\tthrow e;\n\t\t}\n\t}\n}\n\nfunction normalizeMemfsPath(path: string) {\n\treturn path.replace(/\\/$/, '').replace(/\\/\\/+/g, '/');\n}\n\nfunction getFilename(path: string) {\n\treturn path.substring(path.lastIndexOf('/') + 1);\n}\n\nasync function resolveParent(\n\topfs: FileSystemDirectoryHandle,\n\trelativePath: string\n): Promise<FileSystemDirectoryHandle> {\n\tconst normalizedPath = relativePath\n\t\t.replace(/^\\/+|\\/+$/g, '')\n\t\t.replace(/\\/+/, '/');\n\tif (!normalizedPath) {\n\t\treturn opfs;\n\t}\n\tconst segments = normalizedPath.split('/');\n\tlet handle: FileSystemDirectoryHandle | FileSystemFileHandle = opfs;\n\tfor (let i = 0; i < segments.length - 1; i++) {\n\t\tconst segment = segments[i];\n\t\thandle = await handle.getDirectoryHandle(segment, { create: true });\n\t}\n\treturn handle as any;\n}\n\nfunction throttle<T extends (...args: any[]) => any>(\n\tfn: T,\n\tdebounceMs: number\n): T {\n\tlet lastCallTime = 0;\n\tlet timeoutId: ReturnType<typeof setTimeout> | undefined;\n\tlet pendingArgs: Parameters<T> | undefined;\n\n\treturn function throttledCallback(...args: Parameters<T>) {\n\t\tpendingArgs = args;\n\n\t\tconst timeSinceLastCall = Date.now() - lastCallTime;\n\t\tif (timeoutId === undefined) {\n\t\t\tconst delay = Math.max(0, debounceMs - timeSinceLastCall);\n\t\t\ttimeoutId = setTimeout(() => {\n\t\t\t\ttimeoutId = undefined;\n\t\t\t\tlastCallTime = Date.now();\n\t\t\t\tfn(...pendingArgs!);\n\t\t\t}, delay);\n\t\t}\n\t} as T;\n}\n"],"names":["getPHPLoaderModule","version","LatestSupportedPHPVersion","flipObject","obj","k","v","as2Bytes","value","as3Bytes","as8Bytes","buffer","ArrayBufferReader","length","ArrayBufferWriter","ExtensionTypes","ExtensionNames","ServerNameTypes","ServerNameNames","ServerNameExtension","data","view","offset","listLength","serverNameList","nameType","valueLength","serverNames","writer","CipherSuites","CipherSuitesNames","SupportedGroups","SupportedGroupsNames","SupportedGroupsExtension","reader","groups","group","ECPointFormats","ECPointFormatNames","ECPointFormatsExtension","formats","i","format","SignatureAlgorithms","SignatureAlgorithmsNames","HashAlgorithms","HashAlgorithmsNames","SignatureAlgorithmsExtension","parsedAlgorithms","hash","algorithm","logger","TLSExtensionsHandlers","parseClientHelloExtensions","parsed","initialOffset","extensionType","extensionTypeName","extensionLength","extensionBytes","handler","tls12Prf","secret","label","seed","outputLength","seedBytes","concatArrayBuffers","hmacKey","A","resultBuffers","hmacSha256","hmacInput","fragment","key","CompressionMethod","AlertLevels","AlertLevelNames","AlertDescriptions","AlertDescriptionNames","ContentTypes","HandshakeType","ECCurveTypes","ECNamedCurves","TLSConnectionClosed","TLS_Version_1_2","generalEcdheKeyPair","TLS_1_2_Connection","chunkStream","tlsConnection","chunk","e","certificatePrivateKey","certificatesDER","clientHelloRecord","serverRandom","MessageEncoder","ecdheKeyPair","clientRandom","serverKeyExchange","clientKeyExchangeRecord","serverPrivateKey","clientPublicKey","preMasterSecret","masterSecret","concatUint8Arrays","keyBlock","clientWriteKey","serverWriteKey","clientIV","serverIV","messageType","message","requestedType","record","accumulatedPayload","TLSDecoder","header","type","severity","description","done","resolve","requestedBytes","appData","contentType","payload","implicitIV","explicitIV","iv","decrypted","additionalData","ciphertextWithTag","cipherSuites","suite","msg_type","bodyBytes","body","buff","sessionIdLength","cipherSuitesLength","compressionMethodsLength","extensionsLength","chunkSize","controller","certsBodies","cert","certsBody","rsaPrivateKey","publicKey","params","signedParams","signatureBytes","signatureAlgorithm","clientHello","compressionAlgorithm","extensionsParts","extension","x","extensions","handshakeMessages","handshakeHash","verifyData","generateCertificate","issuerKeyPair","CertificateGenerator","certificateToPEM","certificate","formatPEM","encodeUint8ArrayAsBase64","privateKeyToPEM","privateKey","pkcs8","tbsDescription","subjectKeyPair","tbsCertificate","signature","ASN1Encoder","subjectPublicKey","serialNumber","oidByName","nameInfo","values","oidName","entry","validity","ASN1Tags","formatDateASN1","addYears","ca","pathLenConstraint","sequence","keyUsage","keyUsageBits","extKeyUsage","nsCertType","bits","altNames","generalNames","_a","name","dnsName","ipAddresses","_b","ip","ipAddress","sanExtensionValue","oids","requestedName","oid","constructedBit","tempLength","lengthBytesArray","numLengthBytes","result","tag","lengthBytes","number","extendedNumber","unusedBits","combined","oidParts","encodedParts","bytes","j","str","utf8Bytes","items","tagNumber","constructed","pemString","date","year","month","padNumber","day","hours","minutes","seconds","num","years","newDate","FirewallInterferenceError","url","status","statusText","CORS_PROXY_HEADER","fetchWithCorsProxy","input","init","corsProxyUrl","playgroundUrl","requestObject","playgroundUrlObj","requestUrlObj","httpsUrl","cloneRequest","request1","request2","teeRequest","corsProxyAllowedHeaders","requestIntendsToPassCredentials","newRequest","response","ChunkedDecoderStream","state","chunkRemainingBytes","chunkBytesNb","byte","chunkSizeHex","bytesToRead","tcpOverFetchWebsocket","emOptions","tcpOptions","_","host","port","TCPOverFetchWebsocket","wsOptions","options","CAroot","outputType","wsUrl","eventName","callback","wrapper","listeners","listener","guessProtocol","siteCert","request","RawBytesFetch","HTTP_METHODS","decodedFirstLine","method","error","encoder","headersObject","headers","string","requestBytesStream","protocol","inputBuffer","requestDataExhausted","headersEndIndex","requestBytesReader","findSequenceInBuffer","headersBuffer","parsedHeaders","terminationMode","contentLength","outboundBodyStream","seenBytes","last5Bytes","emptyChunk","index","hostname","httpRequestBytes","httpRequest","statusLineMaybe","path","line","bufferLength","sequenceLength","lastPossibleIndex","found","getIntlExtensionModule","withIntl","memoizedFetch","createMemoizedFetch","extensionName","dataName","extensionPath","dataPath","ICUData","phpRuntime","FSHelpers","fakeWebsocket","WebSocketConstructor","loadWebRuntime","phpVersion","loaderOptions","fn","emscriptenOptions","phpLoaderModule","loadPHPRuntime","setupPostMessageRelay","nestedFrame","expectedOrigin","event","spawnPHPWorkerThread","workerUrl","worker","reject","onStartup","createDirectoryHandleMountHandler","handle","php","FS","vfsMountPoint","copyOpfsToMemfs","copyMemfsToOpfs","journalFSEventsToOpfs","opfsRoot","memfsRoot","semaphore","Semaphore","ops","stack","opfsParent","memfsParentPath","opfsHandle","op","memfsEntryPath","joinPaths","file","byteArray","onProgress","filesToCreate","mirrorMemfsDirectoryinOpfs","memfsParent","opfsDir","entryName","memfsPath","isMemfsDir","numFilesCompleted","throttledProgressCallback","throttle","maxConcurrentWrites","concurrentWrites","promise","overwriteOpfsFile","opfsFile","journal","unbindJournal","journalFSEvents","rewriter","OpfsRewriter","flushJournal","release","journalEntries","compressedJournal","normalizeFilesystemOperations","opfs","normalizeMemfsPath","opfsPath","resolveParent","getFilename","__private__dont__use","opfsTargetPath","opfsTargetParent","basename","relativePath","normalizedPath","segments","segment","debounceMs","lastCallTime","timeoutId","pendingArgs","args","timeSinceLastCall","delay"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../../../../packages/php-wasm/web/src/lib/get-php-loader-module.ts","../../../../packages/php-wasm/web/src/lib/tls/utils.ts","../../../../packages/php-wasm/web/src/lib/tls/extensions/types.ts","../../../../packages/php-wasm/web/src/lib/tls/extensions/0_server_name.ts","../../../../packages/php-wasm/web/src/lib/tls/cipher-suites.ts","../../../../packages/php-wasm/web/src/lib/tls/extensions/10_supported_groups.ts","../../../../packages/php-wasm/web/src/lib/tls/extensions/11_ec_point_formats.ts","../../../../packages/php-wasm/web/src/lib/tls/extensions/13_signature_algorithms.ts","../../../../packages/php-wasm/web/src/lib/tls/extensions/parse-extensions.ts","../../../../packages/php-wasm/web/src/lib/tls/1_2/prf.ts","../../../../packages/php-wasm/web/src/lib/tls/1_2/types.ts","../../../../packages/php-wasm/web/src/lib/tls/1_2/connection.ts","../../../../packages/php-wasm/web/src/lib/tls/certificates.ts","../../../../packages/php-wasm/web/src/lib/firewall-interference-error.ts","../../../../packages/php-wasm/web/src/lib/fetch-with-cors-proxy.ts","../../../../packages/php-wasm/web/src/lib/chunked-decoder.ts","../../../../packages/php-wasm/web/src/lib/tcp-over-fetch-websocket.ts","../../../../packages/php-wasm/web/src/lib/extensions/intl/get-intl-extension-module.ts","../../../../packages/php-wasm/web/src/lib/extensions/intl/with-intl.ts","../../../../packages/php-wasm/web/src/lib/load-runtime.ts","../../../../packages/php-wasm/web/src/lib/setup-post-message-relay.ts","../../../../packages/php-wasm/web/src/lib/worker-thread/spawn-php-worker-thread.ts","../../../../packages/php-wasm/web/src/lib/directory-handle-mount.ts"],"sourcesContent":["import type { PHPLoaderModule, SupportedPHPVersion } from '@php-wasm/universal';\nimport { LatestSupportedPHPVersion } from '@php-wasm/universal';\n\n/**\n * Loads the PHP loader module for the given PHP version.\n *\n * Each PHP version is packaged separately to reduce bundle size.\n * - @php-wasm/web-8-5\n * - @php-wasm/web-8-4\n * - @php-wasm/web-8-3\n * - etc.\n *\n * @param version The PHP version to load.\n * @returns The PHP loader module.\n */\nexport async function getPHPLoaderModule(\n\tversion: SupportedPHPVersion = LatestSupportedPHPVersion\n): Promise<PHPLoaderModule> {\n\tswitch (version) {\n\t\tcase '8.5':\n\t\t\t// @ts-ignore\n\t\t\treturn (await import('@php-wasm/web-8-5')).getPHPLoaderModule();\n\t\tcase '8.4':\n\t\t\t// @ts-ignore\n\t\t\treturn (await import('@php-wasm/web-8-4')).getPHPLoaderModule();\n\t\tcase '8.3':\n\t\t\t// @ts-ignore\n\t\t\treturn (await import('@php-wasm/web-8-3')).getPHPLoaderModule();\n\t\tcase '8.2':\n\t\t\t// @ts-ignore\n\t\t\treturn (await import('@php-wasm/web-8-2')).getPHPLoaderModule();\n\t\tcase '8.1':\n\t\t\t// @ts-ignore\n\t\t\treturn (await import('@php-wasm/web-8-1')).getPHPLoaderModule();\n\t\tcase '8.0':\n\t\t\t// @ts-ignore\n\t\t\treturn (await import('@php-wasm/web-8-0')).getPHPLoaderModule();\n\t\tcase '7.4':\n\t\t\t// @ts-ignore\n\t\t\treturn (await import('@php-wasm/web-7-4')).getPHPLoaderModule();\n\t\tcase '7.3':\n\t\t\t// @ts-ignore\n\t\t\treturn (await import('@php-wasm/web-7-3')).getPHPLoaderModule();\n\t\tcase '7.2':\n\t\t\t// @ts-ignore\n\t\t\treturn (await import('@php-wasm/web-7-2')).getPHPLoaderModule();\n\t}\n\tthrow new Error(`Unsupported PHP version ${version}`);\n}\n","export function flipObject(obj: Record<any, any>) {\n\treturn Object.fromEntries(Object.entries(obj).map(([k, v]) => [v, k]));\n}\n\nexport function as2Bytes(value: number): Uint8Array {\n\treturn new Uint8Array([(value >> 8) & 0xff, value & 0xff]);\n}\n\nexport function as3Bytes(value: number): Uint8Array {\n\treturn new Uint8Array([\n\t\t(value >> 16) & 0xff,\n\t\t(value >> 8) & 0xff,\n\t\tvalue & 0xff,\n\t]);\n}\n\nexport function as8Bytes(value: number): Uint8Array {\n\tconst buffer = new ArrayBuffer(8);\n\tconst view = new DataView(buffer);\n\tview.setBigUint64(0, BigInt(value), false); // false for big-endian\n\treturn new Uint8Array(buffer);\n}\nexport class ArrayBufferReader {\n\tprivate view: DataView;\n\toffset = 0;\n\tprivate buffer: ArrayBuffer;\n\n\tconstructor(buffer: ArrayBuffer) {\n\t\tthis.buffer = buffer;\n\t\tthis.view = new DataView(buffer);\n\t}\n\n\treadUint8(): number {\n\t\tconst value = this.view.getUint8(this.offset);\n\t\tthis.offset += 1;\n\t\treturn value;\n\t}\n\treadUint16(): number {\n\t\tconst value = this.view.getUint16(this.offset);\n\t\tthis.offset += 2;\n\t\treturn value;\n\t}\n\treadUint32(): number {\n\t\tconst value = this.view.getUint32(this.offset);\n\t\tthis.offset += 4;\n\t\treturn value;\n\t}\n\treadUint8Array(length: number): Uint8Array {\n\t\tconst value = this.buffer.slice(this.offset, this.offset + length);\n\t\tthis.offset += length;\n\t\treturn new Uint8Array(value);\n\t}\n\n\tisFinished() {\n\t\treturn this.offset >= this.buffer.byteLength;\n\t}\n}\n\nexport class ArrayBufferWriter {\n\tbuffer: ArrayBuffer;\n\tview: DataView;\n\tuint8Array: Uint8Array;\n\n\tprivate offset = 0;\n\n\tconstructor(length: number) {\n\t\tthis.buffer = new ArrayBuffer(length);\n\t\tthis.uint8Array = new Uint8Array(this.buffer);\n\t\tthis.view = new DataView(this.buffer);\n\t}\n\n\twriteUint8(value: number) {\n\t\tthis.view.setUint8(this.offset, value);\n\t\tthis.offset += 1;\n\t}\n\n\twriteUint16(value: number) {\n\t\tthis.view.setUint16(this.offset, value);\n\t\tthis.offset += 2;\n\t}\n\n\twriteUint32(value: number) {\n\t\tthis.view.setUint32(this.offset, value);\n\t\tthis.offset += 4;\n\t}\n\n\twriteUint8Array(value: Uint8Array) {\n\t\tthis.uint8Array.set(value, this.offset);\n\t\tthis.offset += value.length;\n\t}\n}\n","/**\n * IANA maintains a list of TLS extensions here:\n * https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml\n */\nexport const ExtensionTypes = {\n\tserver_name: 0,\n\tmax_fragment_length: 1,\n\tclient_certificate_url: 2,\n\ttrusted_ca_keys: 3,\n\ttruncated_hmac: 4,\n\tstatus_request: 5,\n\tuser_mapping: 6,\n\tclient_authz: 7,\n\tserver_authz: 8,\n\tcert_type: 9,\n\tsupported_groups: 10,\n\tec_point_formats: 11,\n\tsrp: 12,\n\tsignature_algorithms: 13,\n\tuse_srtp: 14,\n\theartbeat: 15,\n\tapplication_layer_protocol_negotiation: 16,\n\tstatus_request_v2: 17,\n\tsigned_certificate_timestamp: 18,\n\tclient_certificate_type: 19,\n\tserver_certificate_type: 20,\n\tpadding: 21,\n\tencrypt_then_mac: 22,\n\textended_master_secret: 23,\n\ttoken_binding: 24,\n\tcached_info: 25,\n\ttls_its: 26,\n\tcompress_certificate: 27,\n\trecord_size_limit: 28,\n\tpwd_protect: 29,\n\tpwo_clear: 30,\n\tpassword_salt: 31,\n\tticket_pinning: 32,\n\ttls_cert_with_extern_psk: 33,\n\tdelegated_credential: 34,\n\tsession_ticket: 35,\n\tTLMSP: 36,\n\tTLMSP_proxying: 37,\n\tTLMSP_delegate: 38,\n\tsupported_ekt_ciphers: 39,\n\tpre_shared_key: 41,\n\tearly_data: 42,\n\tsupported_versions: 43,\n\tcookie: 44,\n\tpsk_key_exchange_modes: 45,\n\treserved: 46,\n\tcertificate_authorities: 47,\n\toid_filters: 48,\n\tpost_handshake_auth: 49,\n\tsignature_algorithms_cert: 50,\n\tkey_share: 51,\n\ttransparency_info: 52,\n\tconnection_id: 54,\n} as const;\n\nimport { flipObject } from '../utils';\n\nexport type ExtensionType = keyof typeof ExtensionTypes;\n\nexport const ExtensionNames = flipObject(ExtensionTypes);\nexport type ExtensionName = keyof typeof ExtensionNames;\n","/**\n * TLS server_name extension\n * https://www.rfc-editor.org/rfc/rfc6066.html\n */\n\nimport { ArrayBufferWriter } from '../utils';\nimport { ExtensionTypes } from './types';\nimport { flipObject } from '../utils';\n\nexport interface ServerNameList {\n\tserver_name_list: ServerName[];\n}\n\nexport interface ServerName {\n\tname_type: typeof ServerNameTypes;\n\tname: {\n\t\thost_name: string;\n\t};\n}\n\nexport const ServerNameTypes = {\n\thost_name: 0,\n} as const;\nexport type ServerNameType =\n\t(typeof ServerNameTypes)[keyof typeof ServerNameTypes];\nexport const ServerNameNames = flipObject(ServerNameTypes);\n\nexport class ServerNameExtension {\n\tstatic decodeFromClient(data: Uint8Array): ServerNameList {\n\t\tconst view = new DataView(data.buffer);\n\t\tlet offset = 0;\n\n\t\tconst listLength = view.getUint16(offset);\n\t\toffset += 2;\n\n\t\tconst serverNameList: ServerName[] = [];\n\n\t\twhile (offset < listLength + 2) {\n\t\t\tconst nameType = data[offset] as ServerNameType;\n\t\t\toffset += 1;\n\n\t\t\tconst valueLength = view.getUint16(offset);\n\t\t\toffset += 2;\n\n\t\t\tconst value = data.slice(offset, offset + valueLength);\n\t\t\toffset += valueLength;\n\n\t\t\tswitch (nameType) {\n\t\t\t\tcase ServerNameTypes.host_name:\n\t\t\t\t\tserverNameList.push({\n\t\t\t\t\t\tname_type: ServerNameNames[nameType],\n\t\t\t\t\t\tname: {\n\t\t\t\t\t\t\thost_name: new TextDecoder().decode(value),\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tthrow new Error(`Unsupported name type ${nameType}`);\n\t\t\t}\n\t\t}\n\n\t\treturn { server_name_list: serverNameList };\n\t}\n\n\t/**\n\t * Encode the server_name extension\n\t *\n\t * +------------------------------------+\n\t * | Extension Type (server_name) [2B] |\n\t * | 0x00 0x00 |\n\t * +------------------------------------+\n\t * | Extension Length [2B] |\n\t * | 0x00 0x00 |\n\t * +------------------------------------+\n\t */\n\tstatic encodeForClient(serverNames?: ServerNameList) {\n\t\tif (serverNames?.server_name_list.length) {\n\t\t\tthrow new Error(\n\t\t\t\t'Encoding non-empty lists for ClientHello is not supported yet. ' +\n\t\t\t\t\t'Only empty lists meant for ServerHello are supported today.'\n\t\t\t);\n\t\t}\n\n\t\tconst writer = new ArrayBufferWriter(4);\n\t\twriter.writeUint16(ExtensionTypes.server_name);\n\t\t// Zero body length encoded using two bytes\n\t\twriter.writeUint16(0);\n\t\treturn writer.uint8Array;\n\t}\n}\n","import { flipObject } from './utils';\n\n/**\n * TLS1 cipher suites sourced from OpenSSL:\n *\n * https://github.com/openssl/openssl/blob/36254fda37fe169e136079404a3c32aeea35cbd4/include/openssl/tls1.h#L371\n */\nexport const CipherSuites = {\n\tTLS1_CK_PSK_WITH_RC4_128_SHA: 0x008a,\n\tTLS1_CK_PSK_WITH_3DES_EDE_CBC_SHA: 0x008b,\n\tTLS1_CK_PSK_WITH_AES_128_CBC_SHA: 0x008c,\n\tTLS1_CK_PSK_WITH_AES_256_CBC_SHA: 0x008d,\n\tTLS1_CK_DHE_PSK_WITH_RC4_128_SHA: 0x008e,\n\tTLS1_CK_DHE_PSK_WITH_3DES_EDE_CBC_SHA: 0x008f,\n\tTLS1_CK_DHE_PSK_WITH_AES_128_CBC_SHA: 0x0090,\n\tTLS1_CK_DHE_PSK_WITH_AES_256_CBC_SHA: 0x0091,\n\tTLS1_CK_RSA_PSK_WITH_RC4_128_SHA: 0x0092,\n\tTLS1_CK_RSA_PSK_WITH_3DES_EDE_CBC_SHA: 0x0093,\n\tTLS1_CK_RSA_PSK_WITH_AES_128_CBC_SHA: 0x0094,\n\tTLS1_CK_RSA_PSK_WITH_AES_256_CBC_SHA: 0x0095,\n\tTLS1_CK_PSK_WITH_AES_128_GCM_SHA256: 0x00a8,\n\tTLS1_CK_PSK_WITH_AES_256_GCM_SHA384: 0x00a9,\n\tTLS1_CK_DHE_PSK_WITH_AES_128_GCM_SHA256: 0x00aa,\n\tTLS1_CK_DHE_PSK_WITH_AES_256_GCM_SHA384: 0x00ab,\n\tTLS1_CK_RSA_PSK_WITH_AES_128_GCM_SHA256: 0x00ac,\n\tTLS1_CK_RSA_PSK_WITH_AES_256_GCM_SHA384: 0x00ad,\n\tTLS1_CK_PSK_WITH_AES_128_CBC_SHA256: 0x00ae,\n\tTLS1_CK_PSK_WITH_AES_256_CBC_SHA384: 0x00af,\n\tTLS1_CK_PSK_WITH_NULL_SHA256: 0x00b0,\n\tTLS1_CK_PSK_WITH_NULL_SHA384: 0x00b1,\n\tTLS1_CK_DHE_PSK_WITH_AES_128_CBC_SHA256: 0x00b2,\n\tTLS1_CK_DHE_PSK_WITH_AES_256_CBC_SHA384: 0x00b3,\n\tTLS1_CK_DHE_PSK_WITH_NULL_SHA256: 0x00b4,\n\tTLS1_CK_DHE_PSK_WITH_NULL_SHA384: 0x00b5,\n\tTLS1_CK_RSA_PSK_WITH_AES_128_CBC_SHA256: 0x00b6,\n\tTLS1_CK_RSA_PSK_WITH_AES_256_CBC_SHA384: 0x00b7,\n\tTLS1_CK_RSA_PSK_WITH_NULL_SHA256: 0x00b8,\n\tTLS1_CK_RSA_PSK_WITH_NULL_SHA384: 0x00b9,\n\tTLS1_CK_PSK_WITH_NULL_SHA: 0x002c,\n\tTLS1_CK_DHE_PSK_WITH_NULL_SHA: 0x002d,\n\tTLS1_CK_RSA_PSK_WITH_NULL_SHA: 0x002e,\n\tTLS1_CK_RSA_WITH_AES_128_SHA: 0x002f,\n\tTLS1_CK_DH_DSS_WITH_AES_128_SHA: 0x0030,\n\tTLS1_CK_DH_RSA_WITH_AES_128_SHA: 0x0031,\n\tTLS1_CK_DHE_DSS_WITH_AES_128_SHA: 0x0032,\n\tTLS1_CK_DHE_RSA_WITH_AES_128_SHA: 0x0033,\n\tTLS1_CK_ADH_WITH_AES_128_SHA: 0x0034,\n\tTLS1_CK_RSA_WITH_AES_256_SHA: 0x0035,\n\tTLS1_CK_DH_DSS_WITH_AES_256_SHA: 0x0036,\n\tTLS1_CK_DH_RSA_WITH_AES_256_SHA: 0x0037,\n\tTLS1_CK_DHE_DSS_WITH_AES_256_SHA: 0x0038,\n\tTLS1_CK_DHE_RSA_WITH_AES_256_SHA: 0x0039,\n\tTLS1_CK_ADH_WITH_AES_256_SHA: 0x003a,\n\tTLS1_CK_RSA_WITH_NULL_SHA256: 0x003b,\n\tTLS1_CK_RSA_WITH_AES_128_SHA256: 0x003c,\n\tTLS1_CK_RSA_WITH_AES_256_SHA256: 0x003d,\n\tTLS1_CK_DH_DSS_WITH_AES_128_SHA256: 0x003e,\n\tTLS1_CK_DH_RSA_WITH_AES_128_SHA256: 0x003f,\n\tTLS1_CK_DHE_DSS_WITH_AES_128_SHA256: 0x0040,\n\tTLS1_CK_RSA_WITH_CAMELLIA_128_CBC_SHA: 0x0041,\n\tTLS1_CK_DH_DSS_WITH_CAMELLIA_128_CBC_SHA: 0x0042,\n\tTLS1_CK_DH_RSA_WITH_CAMELLIA_128_CBC_SHA: 0x0043,\n\tTLS1_CK_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA: 0x0044,\n\tTLS1_CK_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA: 0x0045,\n\tTLS1_CK_ADH_WITH_CAMELLIA_128_CBC_SHA: 0x0046,\n\tTLS1_CK_DHE_RSA_WITH_AES_128_SHA256: 0x0067,\n\tTLS1_CK_DH_DSS_WITH_AES_256_SHA256: 0x0068,\n\tTLS1_CK_DH_RSA_WITH_AES_256_SHA256: 0x0069,\n\tTLS1_CK_DHE_DSS_WITH_AES_256_SHA256: 0x006a,\n\tTLS1_CK_DHE_RSA_WITH_AES_256_SHA256: 0x006b,\n\tTLS1_CK_ADH_WITH_AES_128_SHA256: 0x006c,\n\tTLS1_CK_ADH_WITH_AES_256_SHA256: 0x006d,\n\tTLS1_CK_RSA_WITH_CAMELLIA_256_CBC_SHA: 0x0084,\n\tTLS1_CK_DH_DSS_WITH_CAMELLIA_256_CBC_SHA: 0x0085,\n\tTLS1_CK_DH_RSA_WITH_CAMELLIA_256_CBC_SHA: 0x0086,\n\tTLS1_CK_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA: 0x0087,\n\tTLS1_CK_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA: 0x0088,\n\tTLS1_CK_ADH_WITH_CAMELLIA_256_CBC_SHA: 0x0089,\n\tTLS1_CK_RSA_WITH_SEED_SHA: 0x0096,\n\tTLS1_CK_DH_DSS_WITH_SEED_SHA: 0x0097,\n\tTLS1_CK_DH_RSA_WITH_SEED_SHA: 0x0098,\n\tTLS1_CK_DHE_DSS_WITH_SEED_SHA: 0x0099,\n\tTLS1_CK_DHE_RSA_WITH_SEED_SHA: 0x009a,\n\tTLS1_CK_ADH_WITH_SEED_SHA: 0x009b,\n\tTLS1_CK_RSA_WITH_AES_128_GCM_SHA256: 0x009c,\n\tTLS1_CK_RSA_WITH_AES_256_GCM_SHA384: 0x009d,\n\tTLS1_CK_DHE_RSA_WITH_AES_128_GCM_SHA256: 0x009e,\n\tTLS1_CK_DHE_RSA_WITH_AES_256_GCM_SHA384: 0x009f,\n\tTLS1_CK_DH_RSA_WITH_AES_128_GCM_SHA256: 0x00a0,\n\tTLS1_CK_DH_RSA_WITH_AES_256_GCM_SHA384: 0x00a1,\n\tTLS1_CK_DHE_DSS_WITH_AES_128_GCM_SHA256: 0x00a2,\n\tTLS1_CK_DHE_DSS_WITH_AES_256_GCM_SHA384: 0x00a3,\n\tTLS1_CK_DH_DSS_WITH_AES_128_GCM_SHA256: 0x00a4,\n\tTLS1_CK_DH_DSS_WITH_AES_256_GCM_SHA384: 0x00a5,\n\tTLS1_CK_ADH_WITH_AES_128_GCM_SHA256: 0x00a6,\n\tTLS1_CK_ADH_WITH_AES_256_GCM_SHA384: 0x00a7,\n\tTLS1_CK_RSA_WITH_AES_128_CCM: 0xc09c,\n\tTLS1_CK_RSA_WITH_AES_256_CCM: 0xc09d,\n\tTLS1_CK_DHE_RSA_WITH_AES_128_CCM: 0xc09e,\n\tTLS1_CK_DHE_RSA_WITH_AES_256_CCM: 0xc09f,\n\tTLS1_CK_RSA_WITH_AES_128_CCM_8: 0xc0a0,\n\tTLS1_CK_RSA_WITH_AES_256_CCM_8: 0xc0a1,\n\tTLS1_CK_DHE_RSA_WITH_AES_128_CCM_8: 0xc0a2,\n\tTLS1_CK_DHE_RSA_WITH_AES_256_CCM_8: 0xc0a3,\n\tTLS1_CK_PSK_WITH_AES_128_CCM: 0xc0a4,\n\tTLS1_CK_PSK_WITH_AES_256_CCM: 0xc0a5,\n\tTLS1_CK_DHE_PSK_WITH_AES_128_CCM: 0xc0a6,\n\tTLS1_CK_DHE_PSK_WITH_AES_256_CCM: 0xc0a7,\n\tTLS1_CK_PSK_WITH_AES_128_CCM_8: 0xc0a8,\n\tTLS1_CK_PSK_WITH_AES_256_CCM_8: 0xc0a9,\n\tTLS1_CK_DHE_PSK_WITH_AES_128_CCM_8: 0xc0aa,\n\tTLS1_CK_DHE_PSK_WITH_AES_256_CCM_8: 0xc0ab,\n\tTLS1_CK_ECDHE_ECDSA_WITH_AES_128_CCM: 0xc0ac,\n\tTLS1_CK_ECDHE_ECDSA_WITH_AES_256_CCM: 0xc0ad,\n\tTLS1_CK_ECDHE_ECDSA_WITH_AES_128_CCM_8: 0xc0ae,\n\tTLS1_CK_ECDHE_ECDSA_WITH_AES_256_CCM_8: 0xc0af,\n\tTLS1_CK_RSA_WITH_CAMELLIA_128_CBC_SHA256: 0x00ba,\n\tTLS1_CK_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256: 0x00bb,\n\tTLS1_CK_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256: 0x00bc,\n\tTLS1_CK_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256: 0x00bd,\n\tTLS1_CK_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: 0x00be,\n\tTLS1_CK_ADH_WITH_CAMELLIA_128_CBC_SHA256: 0x00bf,\n\tTLS1_CK_RSA_WITH_CAMELLIA_256_CBC_SHA256: 0x00c0,\n\tTLS1_CK_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256: 0x00c1,\n\tTLS1_CK_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256: 0x00c2,\n\tTLS1_CK_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256: 0x00c3,\n\tTLS1_CK_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256: 0x00c4,\n\tTLS1_CK_ADH_WITH_CAMELLIA_256_CBC_SHA256: 0x00c5,\n\tTLS1_CK_ECDH_ECDSA_WITH_NULL_SHA: 0xc001,\n\tTLS1_CK_ECDH_ECDSA_WITH_RC4_128_SHA: 0xc002,\n\tTLS1_CK_ECDH_ECDSA_WITH_DES_192_CBC3_SHA: 0xc003,\n\tTLS1_CK_ECDH_ECDSA_WITH_AES_128_CBC_SHA: 0xc004,\n\tTLS1_CK_ECDH_ECDSA_WITH_AES_256_CBC_SHA: 0xc005,\n\tTLS1_CK_ECDHE_ECDSA_WITH_NULL_SHA: 0xc006,\n\tTLS1_CK_ECDHE_ECDSA_WITH_RC4_128_SHA: 0xc007,\n\tTLS1_CK_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA: 0xc008,\n\tTLS1_CK_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: 0xc009,\n\tTLS1_CK_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: 0xc00a,\n\tTLS1_CK_ECDH_RSA_WITH_NULL_SHA: 0xc00b,\n\tTLS1_CK_ECDH_RSA_WITH_RC4_128_SHA: 0xc00c,\n\tTLS1_CK_ECDH_RSA_WITH_DES_192_CBC3_SHA: 0xc00d,\n\tTLS1_CK_ECDH_RSA_WITH_AES_128_CBC_SHA: 0xc00e,\n\tTLS1_CK_ECDH_RSA_WITH_AES_256_CBC_SHA: 0xc00f,\n\tTLS1_CK_ECDHE_RSA_WITH_NULL_SHA: 0xc010,\n\tTLS1_CK_ECDHE_RSA_WITH_RC4_128_SHA: 0xc011,\n\tTLS1_CK_ECDHE_RSA_WITH_DES_192_CBC3_SHA: 0xc012,\n\tTLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA: 0xc013,\n\tTLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA: 0xc014,\n\tTLS1_CK_ECDH_anon_WITH_NULL_SHA: 0xc015,\n\tTLS1_CK_ECDH_anon_WITH_RC4_128_SHA: 0xc016,\n\tTLS1_CK_ECDH_anon_WITH_DES_192_CBC3_SHA: 0xc017,\n\tTLS1_CK_ECDH_anon_WITH_AES_128_CBC_SHA: 0xc018,\n\tTLS1_CK_ECDH_anon_WITH_AES_256_CBC_SHA: 0xc019,\n\tTLS1_CK_SRP_SHA_WITH_3DES_EDE_CBC_SHA: 0xc01a,\n\tTLS1_CK_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA: 0xc01b,\n\tTLS1_CK_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA: 0xc01c,\n\tTLS1_CK_SRP_SHA_WITH_AES_128_CBC_SHA: 0xc01d,\n\tTLS1_CK_SRP_SHA_RSA_WITH_AES_128_CBC_SHA: 0xc01e,\n\tTLS1_CK_SRP_SHA_DSS_WITH_AES_128_CBC_SHA: 0xc01f,\n\tTLS1_CK_SRP_SHA_WITH_AES_256_CBC_SHA: 0xc020,\n\tTLS1_CK_SRP_SHA_RSA_WITH_AES_256_CBC_SHA: 0xc021,\n\tTLS1_CK_SRP_SHA_DSS_WITH_AES_256_CBC_SHA: 0xc022,\n\tTLS1_CK_ECDHE_ECDSA_WITH_AES_128_SHA256: 0xc023,\n\tTLS1_CK_ECDHE_ECDSA_WITH_AES_256_SHA384: 0xc024,\n\tTLS1_CK_ECDH_ECDSA_WITH_AES_128_SHA256: 0xc025,\n\tTLS1_CK_ECDH_ECDSA_WITH_AES_256_SHA384: 0xc026,\n\tTLS1_CK_ECDHE_RSA_WITH_AES_128_SHA256: 0xc027,\n\tTLS1_CK_ECDHE_RSA_WITH_AES_256_SHA384: 0xc028,\n\tTLS1_CK_ECDH_RSA_WITH_AES_128_SHA256: 0xc029,\n\tTLS1_CK_ECDH_RSA_WITH_AES_256_SHA384: 0xc02a,\n\tTLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: 0xc02b,\n\tTLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: 0xc02c,\n\tTLS1_CK_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: 0xc02d,\n\tTLS1_CK_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: 0xc02e,\n\tTLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256: 0xc02f,\n\tTLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384: 0xc030,\n\tTLS1_CK_ECDH_RSA_WITH_AES_128_GCM_SHA256: 0xc031,\n\tTLS1_CK_ECDH_RSA_WITH_AES_256_GCM_SHA384: 0xc032,\n\tTLS1_CK_ECDHE_PSK_WITH_RC4_128_SHA: 0xc033,\n\tTLS1_CK_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA: 0xc034,\n\tTLS1_CK_ECDHE_PSK_WITH_AES_128_CBC_SHA: 0xc035,\n\tTLS1_CK_ECDHE_PSK_WITH_AES_256_CBC_SHA: 0xc036,\n\tTLS1_CK_ECDHE_PSK_WITH_AES_128_CBC_SHA256: 0xc037,\n\tTLS1_CK_ECDHE_PSK_WITH_AES_256_CBC_SHA384: 0xc038,\n\tTLS1_CK_ECDHE_PSK_WITH_NULL_SHA: 0xc039,\n\tTLS1_CK_ECDHE_PSK_WITH_NULL_SHA256: 0xc03a,\n\tTLS1_CK_ECDHE_PSK_WITH_NULL_SHA384: 0xc03b,\n\tTLS1_CK_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: 0xc072,\n\tTLS1_CK_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: 0xc073,\n\tTLS1_CK_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256: 0xc074,\n\tTLS1_CK_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384: 0xc075,\n\tTLS1_CK_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256: 0xc076,\n\tTLS1_CK_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384: 0xc077,\n\tTLS1_CK_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256: 0xc078,\n\tTLS1_CK_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384: 0xc079,\n\tTLS1_CK_PSK_WITH_CAMELLIA_128_CBC_SHA256: 0xc094,\n\tTLS1_CK_PSK_WITH_CAMELLIA_256_CBC_SHA384: 0xc095,\n\tTLS1_CK_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256: 0xc096,\n\tTLS1_CK_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384: 0xc097,\n\tTLS1_CK_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256: 0xc098,\n\tTLS1_CK_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384: 0xc099,\n\tTLS1_CK_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256: 0xc09a,\n\tTLS1_CK_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384: 0xc09b,\n\tTLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305: 0xcca8,\n\tTLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305: 0xcca9,\n\tTLS1_CK_DHE_RSA_WITH_CHACHA20_POLY1305: 0xccaa,\n\tTLS1_CK_PSK_WITH_CHACHA20_POLY1305: 0xccab,\n\tTLS1_CK_ECDHE_PSK_WITH_CHACHA20_POLY1305: 0xccac,\n\tTLS1_CK_DHE_PSK_WITH_CHACHA20_POLY1305: 0xccad,\n\tTLS1_CK_RSA_PSK_WITH_CHACHA20_POLY1305: 0xccae,\n} as const;\n\nexport const CipherSuitesNames = flipObject(CipherSuites);\n","/**\n * TLS supported_groups extension\n * https://www.iana.org/go/rfc7919\n * https://www.iana.org/go/rfc8422\n */\n\nimport { ArrayBufferReader, ArrayBufferWriter } from '../utils';\nimport { ExtensionTypes } from './types';\nimport { flipObject } from '../utils';\n\nexport const SupportedGroups = {\n\tsecp256r1: 23,\n\tsecp384r1: 24,\n\tsecp521r1: 25,\n\tx25519: 29,\n\tx448: 30,\n} as const;\nexport const SupportedGroupsNames = flipObject(SupportedGroups);\nexport type SupportedGroup = keyof typeof SupportedGroups;\n\nexport type ParsedSupportedGroups = (keyof typeof SupportedGroups)[];\n\nexport class SupportedGroupsExtension {\n\t/**\n\t * +--------------------------------------------------+\n\t * | Payload Length [2B] |\n\t * +--------------------------------------------------+\n\t * | Supported Groups List Length [2B] |\n\t * +--------------------------------------------------+\n\t * | Supported Group 1 [2B] |\n\t * +--------------------------------------------------+\n\t * | Supported Group 2 [2B] |\n\t * +--------------------------------------------------+\n\t * | ... |\n\t * +--------------------------------------------------+\n\t * | Supported Group n [2B] |\n\t * +--------------------------------------------------+\n\t */\n\tstatic decodeFromClient(data: Uint8Array): ParsedSupportedGroups {\n\t\tconst reader = new ArrayBufferReader(data.buffer);\n\t\t// Skip the length field\n\t\treader.readUint16();\n\t\tconst groups = [];\n\t\twhile (!reader.isFinished()) {\n\t\t\tconst group = reader.readUint16();\n\t\t\tif (!(group in SupportedGroupsNames)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tgroups.push(SupportedGroupsNames[group]);\n\t\t}\n\t\treturn groups;\n\t}\n\n\t/**\n\t * +--------------------------------------------------+\n\t * | Extension Type (supported_groups) [2B] |\n\t * | 0x00 0x0A |\n\t * +--------------------------------------------------+\n\t * | Extension Length [2B] |\n\t * +--------------------------------------------------+\n\t * | Selected Group [2B] |\n\t * +--------------------------------------------------+\n\t */\n\tstatic encodeForClient(group: SupportedGroup): Uint8Array {\n\t\tconst writer = new ArrayBufferWriter(6);\n\t\twriter.writeUint16(ExtensionTypes.supported_groups);\n\t\twriter.writeUint16(2);\n\t\twriter.writeUint16(SupportedGroups[group]);\n\t\treturn writer.uint8Array;\n\t}\n}\n","/**\n * TLS ec_point_formats extension\n * https://www.rfc-editor.org/rfc/rfc4492#section-5.1.2\n */\n\nimport { ArrayBufferReader, ArrayBufferWriter } from '../utils';\nimport { ExtensionTypes } from './types';\nimport { flipObject } from '../utils';\n\nexport const ECPointFormats = {\n\tuncompressed: 0,\n\tansiX962_compressed_prime: 1,\n\tansiX962_compressed_char2: 2,\n} as const;\nexport type ECPointFormat = keyof typeof ECPointFormats;\n\nexport const ECPointFormatNames = flipObject(ECPointFormats);\n\nexport type ParsedECPointFormats = (keyof typeof ECPointFormats)[];\n\nexport class ECPointFormatsExtension {\n\t/**\n\t * +--------------------------------------------------+\n\t * | Payload Length [2B] |\n\t * +--------------------------------------------------+\n\t * | EC Point Formats Length [1B] |\n\t * +--------------------------------------------------+\n\t * | EC Point Format 1 [1B] |\n\t * +--------------------------------------------------+\n\t * | EC Point Format 2 [1B] |\n\t * +--------------------------------------------------+\n\t * | ... |\n\t * +--------------------------------------------------+\n\t * | EC Point Format n [1B] |\n\t * +--------------------------------------------------+\n\t */\n\tstatic decodeFromClient(data: Uint8Array): ParsedECPointFormats {\n\t\tconst reader = new ArrayBufferReader(data.buffer);\n\t\t// Read the EC Point Formats Length\n\t\tconst length = reader.readUint8();\n\t\tconst formats = [];\n\t\tfor (let i = 0; i < length; i++) {\n\t\t\tconst format = reader.readUint8();\n\t\t\tif (format in ECPointFormatNames) {\n\t\t\t\tformats.push(ECPointFormatNames[format]);\n\t\t\t}\n\t\t}\n\t\treturn formats;\n\t}\n\n\t/**\n\t * Encode the ec_point_formats extension\n\t *\n\t * +--------------------------------------------------+\n\t * | Extension Type (ec_point_formats) [2B] |\n\t * | 0x00 0x0B |\n\t * +--------------------------------------------------+\n\t * | Body Length [2B] |\n\t * +--------------------------------------------------+\n\t * | EC Point Format Length [1B] |\n\t * +--------------------------------------------------+\n\t * | EC Point Format [1B] |\n\t * +--------------------------------------------------+\n\t */\n\tstatic encodeForClient(format: ECPointFormat): Uint8Array {\n\t\tconst writer = new ArrayBufferWriter(6);\n\t\twriter.writeUint16(ExtensionTypes.ec_point_formats);\n\t\twriter.writeUint16(2); // Body length\n\t\twriter.writeUint8(1); // EC Point Formats Length\n\t\twriter.writeUint8(ECPointFormats[format]);\n\t\treturn writer.uint8Array;\n\t}\n}\n","/**\n * TLS signature_algorithms extension\n * https://www.rfc-editor.org/rfc/rfc8446.html#page-41\n */\n\nimport { ArrayBufferReader, ArrayBufferWriter } from '../utils';\nimport { ExtensionTypes } from './types';\nimport { flipObject } from '../utils';\nimport { logger } from '@php-wasm/logger';\n\n/**\n * A list of supported signature algorithms,\n * one byte per algorithm.\n */\nexport type SignatureAlgorithms = Uint8Array;\n\n/**\n * Signature algorithms from\n * https://datatracker.ietf.org/doc/html/rfc5246#section-7.4.1.4.1\n */\nexport const SignatureAlgorithms = {\n\tanonymous: 0,\n\trsa: 1,\n\tdsa: 2,\n\tecdsa: 3,\n};\nexport type SignatureAlgorithm = keyof typeof SignatureAlgorithms;\nexport const SignatureAlgorithmsNames = flipObject(SignatureAlgorithms);\n\n/**\n * Hash algorithms from\n * https://datatracker.ietf.org/doc/html/rfc5246#section-7.4.1.4.1\n */\nexport const HashAlgorithms = {\n\tnone: 0,\n\tmd5: 1,\n\tsha1: 2,\n\tsha224: 3,\n\tsha256: 4,\n\tsha384: 5,\n\tsha512: 6,\n};\nexport type HashAlgorithm = keyof typeof HashAlgorithms;\nexport const HashAlgorithmsNames = flipObject(HashAlgorithms);\n\nexport type ParsedSignatureAlgorithm = {\n\thash: HashAlgorithm;\n\talgorithm: SignatureAlgorithm;\n};\n\n/**\n * Handles the signature algorithms extension as defined in\n * https://www.rfc-editor.org/rfc/rfc8446.html#page-41\n */\nexport class SignatureAlgorithmsExtension {\n\t/**\n\t * Binary layout:\n\t *\n\t * +------------------------------------+\n\t * | Payload Length [2B] |\n\t * +------------------------------------+\n\t * | Hash Algorithm 1 [1B] |\n\t * | Signature Algorithm 1 [1B] |\n\t * +------------------------------------+\n\t * | Hash Algorithm 2 [1B] |\n\t * | Signature Algorithm 2 [1B] |\n\t * +------------------------------------+\n\t * | ... |\n\t * +------------------------------------+\n\t */\n\tstatic decodeFromClient(data: Uint8Array): ParsedSignatureAlgorithm[] {\n\t\tconst reader = new ArrayBufferReader(data.buffer);\n\t\treader.readUint16(); // Skip algorithms length\n\t\tconst parsedAlgorithms: ParsedSignatureAlgorithm[] = [];\n\t\twhile (!reader.isFinished()) {\n\t\t\tconst hash = reader.readUint8();\n\t\t\tconst algorithm = reader.readUint8();\n\t\t\tif (!SignatureAlgorithmsNames[algorithm]) {\n\t\t\t\t// Unknown signature algorithm. It's fine, the client just supports\n\t\t\t\t// more algorithms than the server.\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!HashAlgorithmsNames[hash]) {\n\t\t\t\tlogger.warn(`Unknown hash algorithm: ${hash}`);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tparsedAlgorithms.push({\n\t\t\t\talgorithm: SignatureAlgorithmsNames[algorithm],\n\t\t\t\thash: HashAlgorithmsNames[hash],\n\t\t\t});\n\t\t}\n\t\treturn parsedAlgorithms;\n\t}\n\n\t/**\n\t * +--------------------------------------------------+\n\t * | Extension Type (signature_algorithms) [2B] |\n\t * | 0x00 0x0D |\n\t * +--------------------------------------------------+\n\t * | Body Length [2B] |\n\t * +--------------------------------------------------+\n\t * | Hash Algorithm [1B] |\n\t * | Signature Algorithm [1B] |\n\t * +--------------------------------------------------+\n\t */\n\tstatic encodeforClient(\n\t\thash: HashAlgorithm,\n\t\talgorithm: SignatureAlgorithm\n\t): Uint8Array {\n\t\tconst writer = new ArrayBufferWriter(6);\n\t\twriter.writeUint16(ExtensionTypes.signature_algorithms);\n\t\twriter.writeUint16(2);\n\t\twriter.writeUint8(HashAlgorithms[hash]);\n\t\twriter.writeUint8(SignatureAlgorithms[algorithm]);\n\t\treturn writer.uint8Array;\n\t}\n}\n","/**\n * Glue for the implemented TLS extensions\n * For the full list of TLS extensions, see\n * https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml */\nimport { ArrayBufferReader } from '../utils';\nimport type { ServerNameList } from './0_server_name';\nimport { ServerNameExtension } from './0_server_name';\nimport type { ParsedSupportedGroups } from './10_supported_groups';\nimport { SupportedGroupsExtension } from './10_supported_groups';\nimport type { ParsedECPointFormats } from './11_ec_point_formats';\nimport { ECPointFormatsExtension } from './11_ec_point_formats';\nimport type { SignatureAlgorithms } from './13_signature_algorithms';\nimport { SignatureAlgorithmsExtension } from './13_signature_algorithms';\nimport { ExtensionNames } from './types';\n\nexport const TLSExtensionsHandlers = {\n\tserver_name: ServerNameExtension,\n\tsignature_algorithms: SignatureAlgorithmsExtension,\n\tsupported_groups: SupportedGroupsExtension,\n\tec_point_formats: ECPointFormatsExtension,\n} as const;\n\nexport type SupportedTLSExtension = keyof typeof TLSExtensionsHandlers;\n\nexport type ParsedExtension =\n\t| {\n\t\t\ttype: 'server_name';\n\t\t\tdata: ServerNameList;\n\t\t\traw: Uint8Array;\n\t }\n\t| {\n\t\t\ttype: 'signature_algorithms';\n\t\t\tdata: SignatureAlgorithms;\n\t\t\traw: Uint8Array;\n\t }\n\t| {\n\t\t\ttype: 'ec_point_formats';\n\t\t\tdata: ParsedECPointFormats;\n\t\t\traw: Uint8Array;\n\t }\n\t| {\n\t\t\ttype: 'supported_groups';\n\t\t\tdata: ParsedSupportedGroups;\n\t\t\traw: Uint8Array;\n\t };\n\n/**\n * The extensions in a ClientHello message are encoded as follows:\n *\n * struct {\n * ExtensionType extension_type;\n * opaque extension_data<0..2^16-1>;\n * } Extension;\n *\n * The overall extensions structure is:\n *\n * Extension extensions<0..2^16-1>;\n *\n * This means:\n * •\tThere's a 2-byte length field for the entire extensions block.\n * •\tFollowed by zero or more individual extensions.\n *\n * Binary Data Layout\n *\n * +-----------------------------+\n * | Extension 1 Type (2 bytes) |\n * +-----------------------------+\n * | Extension 1 Length (2 bytes)|\n * +-----------------------------+\n * | Extension 1 Data (variable) |\n * +-----------------------------+\n * | Extension 2 Type (2 bytes) |\n * +-----------------------------+\n * | Extension 2 Length (2 bytes)|\n * +-----------------------------+\n * | Extension 2 Data (variable) |\n * +-----------------------------+\n * | ... (more extensions) |\n * +-----------------------------+\n *\n * @param data\n * @returns\n */\nexport function parseClientHelloExtensions(data: Uint8Array) {\n\tconst reader = new ArrayBufferReader(data.buffer);\n\n\tconst parsed: ParsedExtension[] = [];\n\twhile (!reader.isFinished()) {\n\t\tconst initialOffset = reader.offset;\n\t\tconst extensionType = reader.readUint16();\n\t\tconst extensionTypeName = ExtensionNames[extensionType];\n\t\tconst extensionLength = reader.readUint16();\n\t\tconst extensionBytes = reader.readUint8Array(extensionLength);\n\n\t\tif (!(extensionTypeName in TLSExtensionsHandlers)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst handler =\n\t\t\tTLSExtensionsHandlers[\n\t\t\t\textensionTypeName as keyof typeof TLSExtensionsHandlers\n\t\t\t];\n\t\tparsed.push({\n\t\t\ttype: extensionTypeName,\n\t\t\tdata: handler.decodeFromClient(extensionBytes) as any,\n\t\t\traw: data.slice(initialOffset, initialOffset + 4 + extensionLength),\n\t\t});\n\t}\n\n\treturn parsed;\n}\n","import { concatArrayBuffers } from '@php-wasm/util';\n\n/**\n * Implements the TLS 1.2 PRF using HMAC-SHA256.\n *\n * See https://datatracker.ietf.org/doc/html/rfc5246#section-5\n */\nexport async function tls12Prf(\n\tsecret: ArrayBuffer,\n\tlabel: ArrayBuffer,\n\tseed: ArrayBuffer,\n\toutputLength: number\n): Promise<ArrayBuffer> {\n\tconst seedBytes = concatArrayBuffers([label, seed]);\n\n\t// Import the secret as a CryptoKey\n\tconst hmacKey = await crypto.subtle.importKey(\n\t\t'raw',\n\t\tsecret,\n\t\t{ name: 'HMAC', hash: { name: 'SHA-256' } },\n\t\tfalse,\n\t\t['sign']\n\t);\n\n\tlet A = seedBytes; // Initialize A(0) = seedBytes\n\tconst resultBuffers: ArrayBuffer[] = [];\n\n\twhile (concatArrayBuffers(resultBuffers).byteLength < outputLength) {\n\t\t// A(i) = HMAC_hash(secret, A(i-1))\n\t\tA = await hmacSha256(hmacKey, A);\n\n\t\t// Compute HMAC_hash(secret, A(i) + seedBytes)\n\t\tconst hmacInput = concatArrayBuffers([A, seedBytes]);\n\t\tconst fragment = await hmacSha256(hmacKey, hmacInput);\n\n\t\tresultBuffers.push(fragment);\n\t}\n\n\t// Concatenate and trim the result to the desired length\n\tconst fullResult = concatArrayBuffers(resultBuffers);\n\treturn fullResult.slice(0, outputLength);\n}\n\nexport async function hmacSha256(\n\tkey: CryptoKey,\n\tdata: ArrayBuffer\n): Promise<ArrayBuffer> {\n\treturn await crypto.subtle.sign(\n\t\t{ name: 'HMAC', hash: 'SHA-256' },\n\t\tkey,\n\t\tdata\n\t);\n}\n","/**\n * TLS 1.2 Record layer types defined after the structs\n * from the TLS 1.2 RFC.\n * https://datatracker.ietf.org/doc/html/rfc5246#section-6.2\n */\n\nimport type { ParsedExtension } from '../extensions/parse-extensions';\nimport { flipObject } from '../utils';\n\nexport const CompressionMethod = {\n\tNull: 0,\n\tDeflate: 1,\n} as const;\nexport type CompressionMethod =\n\t(typeof CompressionMethod)[keyof typeof CompressionMethod];\n\n/**\n * TLS 1.2 Record layer types defined after the structs\n * from the TLS 1.2 RFC.\n * https://datatracker.ietf.org/doc/html/rfc5246#section-6.2.1\n */\n\nexport interface TLSRecord {\n\ttype: ContentType; // 1 byte\n\tversion: ProtocolVersion; // 2 bytes\n\tlength: number; // 2 bytes\n\tfragment: Uint8Array; // variable length\n}\n\nexport interface ProtocolVersion {\n\tmajor: number;\n\tminor: number;\n}\n\nexport interface GenericStreamCipher {\n\tcontent: Uint8Array;\n\tMAC: Uint8Array;\n}\n\nexport interface GenericBlockCipher {\n\tIV: Uint8Array;\n\tblock_ciphered: BlockCiphered;\n}\n\nexport interface BlockCiphered {\n\tcontent: Uint8Array;\n\tMAC: Uint8Array;\n\tpadding: Uint8Array;\n\tpadding_length: number;\n}\n\nexport interface GenericAEADCipher {\n\tnonce_explicit: Uint8Array;\n\taead_encrypted: Uint8Array;\n}\n\n/**\n * TLS 1.2 Handshake types defined after the structs\n * from the TLS 1.2 RFC.\n * https://datatracker.ietf.org/doc/html/rfc5246#section-7.4\n */\n\nexport type TLSMessage =\n\t| AlertMessage\n\t| HandshakeMessage<any>\n\t| ChangeCipherSpecMessage\n\t| ApplicationDataMessage;\n\nexport interface AlertMessage {\n\ttype: typeof ContentTypes.Alert;\n\tlevel: AlertLevel;\n\tdescription: AlertDescription;\n}\n\nexport const AlertLevels = {\n\tWarning: 1,\n\tFatal: 2,\n} as const;\nexport type AlertLevel = (typeof AlertLevels)[keyof typeof AlertLevels];\nexport const AlertLevelNames = flipObject(AlertLevels);\n\nexport const AlertDescriptions = {\n\tCloseNotify: 0,\n\tUnexpectedMessage: 10,\n\tBadRecordMac: 20,\n\tDecryptionFailed: 21,\n\tRecordOverflow: 22,\n\tDecompressionFailure: 30,\n\tHandshakeFailure: 40,\n\tNoCertificate: 41,\n\tBadCertificate: 42,\n\tUnsupportedCertificate: 43,\n\tCertificateRevoked: 44,\n\tCertificateExpired: 45,\n\tCertificateUnknown: 46,\n\tIllegalParameter: 47,\n\tUnknownCa: 48,\n\tAccessDenied: 49,\n\tDecodeError: 50,\n\tDecryptError: 51,\n\tExportRestriction: 60,\n\tProtocolVersion: 70,\n\tInsufficientSecurity: 71,\n\tInternalError: 80,\n\tUserCanceled: 90,\n\tNoRenegotiation: 100,\n\tUnsupportedExtension: 110,\n} as const;\nexport type AlertDescription =\n\t(typeof AlertDescriptions)[keyof typeof AlertDescriptions];\nexport const AlertDescriptionNames = flipObject(AlertDescriptions);\n\nexport interface ChangeCipherSpecMessage {\n\ttype: typeof ContentTypes.ChangeCipherSpec;\n\tbody: Uint8Array;\n}\n\nexport interface ApplicationDataMessage {\n\ttype: typeof ContentTypes.ApplicationData;\n\tbody: Uint8Array;\n}\n\nexport const ContentTypes = {\n\tChangeCipherSpec: 20,\n\tAlert: 21,\n\tHandshake: 22,\n\tApplicationData: 23,\n} as const;\nexport type ContentType = (typeof ContentTypes)[keyof typeof ContentTypes];\n\nexport const HandshakeType = {\n\tHelloRequest: 0,\n\tClientHello: 1,\n\tServerHello: 2,\n\tCertificate: 11,\n\tServerKeyExchange: 12,\n\tCertificateRequest: 13,\n\tServerHelloDone: 14,\n\tCertificateVerify: 15,\n\tClientKeyExchange: 16,\n\tFinished: 20,\n} as const;\nexport type HandshakeType = (typeof HandshakeType)[keyof typeof HandshakeType];\n\nexport type HandshakeMessageBody =\n\t| HelloRequest\n\t| ClientHello\n\t| ServerHello\n\t| Certificate\n\t| ServerKeyExchange\n\t| CertificateRequest\n\t| ServerHelloDone\n\t| CertificateVerify\n\t| ClientKeyExchange\n\t| Finished;\n\nexport interface HandshakeMessage<Body extends HandshakeMessageBody> {\n\ttype: typeof ContentTypes.Handshake;\n\tmsg_type: HandshakeType; // 1 byte\n\tlength: number; // 2 bytes\n\t// Custom property to hold the raw body of the message\n\tbody: Body;\n}\n\n// Specific Handshake Message Types\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface HelloRequest {} // Empty for TLS 1.2\n\n/**\n * 1 byte\n */\nexport type SessionId = Uint8Array;\nexport interface ClientHello {\n\tclient_version: Uint8Array; // 2 bytes\n\trandom: Uint8Array; // 32 bytes\n\tsession_id: SessionId;\n\tcipher_suites: string[];\n\tcompression_methods: Uint8Array;\n\textensions: ParsedExtension[];\n}\n\nexport interface ServerHello {\n\tserver_version: Uint8Array; // 2 bytes\n\trandom: Uint8Array; // 32 bytes\n\tsession_id: Uint8Array;\n\tcipher_suite: Uint8Array; // 2 bytes\n\tcompression_method: number;\n\textensions?: Uint8Array;\n}\n\nexport interface Certificate {\n\tcertificate_list: Uint8Array[];\n}\n\nexport interface ServerKeyExchange {\n\tparams: Uint8Array;\n\tsigned_params: Uint8Array;\n}\n\n/**\n * ECCurveType from\n * https://datatracker.ietf.org/doc/html/rfc4492#section-5.4\n */\nexport const ECCurveTypes = {\n\t/**\n\t * Indicates the elliptic curve domain parameters are\n\t * conveyed verbosely, and the underlying finite field is a prime\n\t * field.\n\t */\n\tExplicitPrime: 1,\n\t/**\n\t * Indicates the elliptic curve domain parameters are\n\t * conveyed verbosely, and the underlying finite field is a\n\t * characteristic-2 field.\n\t */\n\tExplicitChar2: 2,\n\t/**\n\t * Indicates that a named curve is used. This option\n\t * SHOULD be used when applicable.\n\t */\n\tNamedCurve: 3,\n\t/**\n\t * Values 248 through 255 are reserved for private use.\n\t */\n};\n\n/**\n * Named elliptic curves from\n * https://datatracker.ietf.org/doc/html/rfc4492#section-5.1.1\n */\nexport const ECNamedCurves = {\n\tsect163k1: 1,\n\tsect163r1: 2,\n\tsect163r2: 3,\n\tsect193r1: 4,\n\tsect193r2: 5,\n\tsect233k1: 6,\n\tsect233r1: 7,\n\tsect239k1: 8,\n\tsect283k1: 9,\n\tsect283r1: 10,\n\tsect409k1: 11,\n\tsect409r1: 12,\n\tsecp256k1: 22,\n\tsecp256r1: 23,\n\tsecp384r1: 24,\n\tsecp521r1: 25,\n\tarbitrary_explicit_prime_curves: 0xff01,\n\tarbitrary_explicit_char2_curves: 0xff02,\n};\n\nexport interface CertificateRequest {\n\tcertificate_types: Uint8Array;\n\tsupported_signature_algorithms: Uint8Array;\n\tcertificate_authorities: Uint8Array;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface ServerHelloDone {} // Empty for TLS 1.2\n\nexport interface CertificateVerify {\n\talgorithm: Uint8Array;\n\tsignature: Uint8Array;\n}\n\nexport interface ClientKeyExchange {\n\texchange_keys: Uint8Array;\n}\n\nexport interface Finished {\n\tverify_data: Uint8Array;\n}\n\nexport type SessionKeys = {\n\tmasterSecret: Uint8Array;\n\tclientWriteKey: CryptoKey;\n\tserverWriteKey: CryptoKey;\n\tclientIV: Uint8Array;\n\tserverIV: Uint8Array;\n};\n","import { concatUint8Arrays } from '@php-wasm/util';\n\nimport { ServerNameExtension } from '../extensions/0_server_name';\nimport { CipherSuitesNames } from '../cipher-suites';\nimport { CipherSuites } from '../cipher-suites';\nimport { parseClientHelloExtensions } from '../extensions/parse-extensions';\nimport { ArrayBufferReader, as2Bytes, as3Bytes, as8Bytes } from '../utils';\nimport {\n\tHashAlgorithms,\n\tSignatureAlgorithms,\n} from '../extensions/13_signature_algorithms';\nimport { tls12Prf } from './prf';\nimport type {\n\tSessionKeys,\n\tHandshakeMessage,\n\tClientHello,\n\tClientKeyExchange,\n\tFinished,\n\tApplicationDataMessage,\n\tAlertMessage,\n\tChangeCipherSpecMessage,\n\tTLSMessage,\n\tContentType,\n\tTLSRecord,\n\tHandshakeMessageBody,\n\tHelloRequest,\n} from './types';\nimport {\n\tCompressionMethod,\n\tHandshakeType,\n\tContentTypes,\n\tAlertLevelNames,\n\tAlertDescriptionNames,\n\tECCurveTypes,\n\tECNamedCurves,\n} from './types';\n\nclass TLSConnectionClosed extends Error {}\nconst TLS_Version_1_2 = new Uint8Array([0x03, 0x03]);\n\n/**\n * Reuse the same ECDHE key pair for all connections to\n * save some CPU cycles. We can do this because this TLS\n * implementation is not meant to be secure.\n */\nconst generalEcdheKeyPair = crypto.subtle.generateKey(\n\t{\n\t\tname: 'ECDH',\n\t\tnamedCurve: 'P-256', // Use secp256r1 curve\n\t},\n\ttrue, // Extractable\n\t['deriveKey', 'deriveBits'] // Key usage\n);\n\n/**\n * This isomorphic class implements the server end of\n * the client <-> server TLS 1.2 connection. It has two ends:\n *\n * * Client end, that emits and accepts TLS encrypted data.\n * * Server end, that emits and accepts unencrypted data.\n *\n * The API consumer is responsible for connecting both ends\n * to the appropriate handlers.\n *\n * See https://datatracker.ietf.org/doc/html/rfc5246.\n *\n * ## Warning\n *\n * **WARNING** NEVER USE THIS CODE AS A SERVER-SIDE TLS HANDLER.\n *\n * This code is not secure. It is a minimal subset required\n * to decrypt the TLS traffic from a PHP-wasm worker. Yes,\n * it can speak TLS. No, it won't protect your data.\n *\n * ## Rationale\n *\n * This is useful for running PHP.wasm in web browsers.\n * Function calls such as `file_get_contents(\"https://w.org\")`\n * emit encrypted TLS traffic. With this class, you\n * can decrypt it, serve the requested data, and encrypt\n * the response before passing it back to the PHP.wasm\n * module.\n *\n * ## Implementation details\n *\n * TLS_1_2_Connection implements the minimal subset of TLS 1.2\n * required to exchange encrypted data with PHP.wasm:\n *\n * * TLS Handshake\n * * All TLS 1.2 record types, including messages spanning multiple\n * records and empty records.\n * * Encryption and decryption of application data.\n * * Auto-chunking long data blobs before encrypting them to\n * respect the AES-GCM record size limit.\n *\n * The logic is based on numerous RFCs:\n *\n * * RFC 5246: The TLS Protocol Version 1.2\n * * RFC 8446: TLS 1.3\n * * RFC 6066: TLS Extensions\n * * RFC 4492: Elliptic Curve Cryptography (ECC) Cipher Suites for TLS\n * * RFC 5288: AES Galois Counter Mode (GCM) Cipher Suites for TLS\n * * RFC 6070: PKCS #5: Password-Based Key Derivation Function 2 (PBKDF2) Test Vectors\n *\n * ... and a few others.\n *\n * ## Limitations\n *\n * * Multiple ChangeCipherSpec messages are not supported.\n * * Only uncompressed mode (compression method 0) is supported.\n * * Only the TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256 cipher suite is\n * supported, primarily because `crypto.subtle` supports AES-GCM.\n * For AES-GCM details, see https://datatracker.ietf.org/doc/html/rfc5288.\n */\nexport class TLS_1_2_Connection {\n\t/**\n\t * Sequence number of the last received TLS record.\n\t *\n\t * AES-GCM requires transmitting the sequence number\n\t * in the clear in the additional data to prevent a\n\t * potential attacker from re-transmitting the same\n\t * TLS record in a different context.\n\t */\n\tprivate receivedRecordSequenceNumber = 0;\n\n\t/**\n\t * Sequence number of the last sent TLS record.\n\t *\n\t * AES-GCM requires transmitting the sequence number\n\t * in the clear in the additional data to prevent a\n\t * potential attacker from re-transmitting the same\n\t * TLS record in a different context.\n\t */\n\tprivate sentRecordSequenceNumber = 0;\n\n\t/**\n\t * Encryption keys for this connection derived during\n\t * the TLS handshake.\n\t */\n\tprivate sessionKeys: SessionKeys | undefined;\n\n\t/**\n\t * Whether this connection have been closed.\n\t */\n\tprivate closed = false;\n\n\t/**\n\t * Bytes received from the client but not yet parsed\n\t * as TLS records.\n\t */\n\tprivate receivedBytesBuffer: Uint8Array = new Uint8Array();\n\n\t/**\n\t * TLS records received from the client but not yet\n\t * parsed as TLS messages.\n\t */\n\tprivate receivedTLSRecords: Array<TLSRecord> = [];\n\n\t/**\n\t * TLS messages can span multiple TLS records. This\n\t * map holds partial TLS messages that are still incomplete\n\t * after parsing one or more TLS records.\n\t */\n\tprivate partialTLSMessages: Partial<Record<ContentType, Uint8Array>> = {};\n\n\t/**\n\t * A log of all the exchanged TLS handshake messages.\n\t * This is required to build the Finished message and\n\t * verify the integrity of the handshake.\n\t */\n\tprivate handshakeMessages: Uint8Array[] = [];\n\n\t/**\n\t * Maximum chunk size supported by the cipher suite used\n\t * in this TLS implementation.\n\t */\n\tprivate MAX_CHUNK_SIZE = 1024 * 16;\n\n\t/**\n\t * The client end of the TLS connection.\n\t * This is where the WASM module can write and read the\n\t * encrypted data.\n\t */\n\tclientEnd = {\n\t\t// We don't need to chunk the encrypted data.\n\t\t// OpenSSL already done that for us.\n\t\tupstream: new TransformStream<Uint8Array, Uint8Array>(),\n\t\tdownstream: new TransformStream<Uint8Array, Uint8Array>(),\n\t};\n\n\tprivate clientDownstreamWriter =\n\t\tthis.clientEnd.downstream.writable.getWriter();\n\tprivate clientUpstreamReader = this.clientEnd.upstream.readable.getReader();\n\n\t/**\n\t * The server end of the TLS connection.\n\t * This is where the JavaScript handler can write and read the\n\t * unencrypted data.\n\t */\n\tserverEnd = {\n\t\tupstream: new TransformStream<Uint8Array, Uint8Array>(),\n\t\t/**\n\t\t * Chunk the data before encrypting it. The\n\t\t * TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256 cipher suite\n\t\t * only supports up to 16KB of data per record.\n\t\t *\n\t\t * This will spread some messages across multiple records,\n\t\t * but TLS supports it so that's fine.\n\t\t */\n\t\tdownstream: chunkStream(this.MAX_CHUNK_SIZE),\n\t};\n\n\tprivate serverUpstreamWriter = this.serverEnd.upstream.writable.getWriter();\n\n\tconstructor() {\n\t\t// eslint-disable-next-line @typescript-eslint/no-this-alias\n\t\tconst tlsConnection = this;\n\t\t// Whenever the \"server handler\" produces data, encrypt it\n\t\t// and send it back to the client.\n\t\tthis.serverEnd.downstream.readable\n\t\t\t.pipeTo(\n\t\t\t\tnew WritableStream({\n\t\t\t\t\tasync write(chunk) {\n\t\t\t\t\t\tawait tlsConnection.writeTLSRecord(\n\t\t\t\t\t\t\tContentTypes.ApplicationData,\n\t\t\t\t\t\t\tchunk\n\t\t\t\t\t\t);\n\t\t\t\t\t},\n\t\t\t\t\tasync abort(e) {\n\t\t\t\t\t\ttlsConnection.clientDownstreamWriter.releaseLock();\n\t\t\t\t\t\ttlsConnection.clientEnd.downstream.writable.abort(e);\n\t\t\t\t\t\ttlsConnection.close();\n\t\t\t\t\t},\n\t\t\t\t\tclose() {\n\t\t\t\t\t\ttlsConnection.close();\n\t\t\t\t\t},\n\t\t\t\t})\n\t\t\t)\n\t\t\t.catch(() => {\n\t\t\t\t// Ignore failures arising from stream errors. The caller\n\t\t\t\t// should react to the readable stream erroring out.\n\t\t\t});\n\t}\n\n\t/**\n\t * Marks this connections as closed and closes all the associated\n\t * streams.\n\t */\n\tasync close() {\n\t\tif (this.closed) {\n\t\t\treturn;\n\t\t}\n\t\tthis.closed = true;\n\t\ttry {\n\t\t\tawait this.clientDownstreamWriter.close();\n\t\t} catch {\n\t\t\t// Ignore\n\t\t}\n\t\ttry {\n\t\t\tawait this.clientUpstreamReader.cancel();\n\t\t} catch {\n\t\t\t// Ignore\n\t\t}\n\t\ttry {\n\t\t\tawait this.serverUpstreamWriter.close();\n\t\t} catch {\n\t\t\t// Ignore\n\t\t}\n\t\ttry {\n\t\t\tawait this.clientEnd.upstream.readable.cancel();\n\t\t} catch {\n\t\t\t// Ignore\n\t\t}\n\t\ttry {\n\t\t\tawait this.clientEnd.downstream.writable.close();\n\t\t} catch {\n\t\t\t// Ignore\n\t\t}\n\t}\n\n\t/**\n\t * TLS handshake as per RFC 5246.\n\t *\n\t * https://datatracker.ietf.org/doc/html/rfc5246#section-7.4\n\t */\n\tasync TLSHandshake(\n\t\tcertificatePrivateKey: CryptoKey,\n\t\tcertificatesDER: Uint8Array[]\n\t): Promise<void> {\n\t\t// Step 1: Receive ClientHello\n\t\tconst clientHelloRecord = await this.readNextHandshakeMessage(\n\t\t\tHandshakeType.ClientHello\n\t\t);\n\t\tif (!clientHelloRecord.body.cipher_suites.length) {\n\t\t\tthrow new Error(\n\t\t\t\t'Client did not propose any supported cipher suites.'\n\t\t\t);\n\t\t}\n\n\t\t// Step 2: Choose hashing, encryption etc. and tell the\n\t\t// client about our choices. Also share the certificate\n\t\t// and the encryption keys.\n\t\tconst serverRandom = crypto.getRandomValues(new Uint8Array(32));\n\t\tawait this.writeTLSRecord(\n\t\t\tContentTypes.Handshake,\n\t\t\tMessageEncoder.serverHello(\n\t\t\t\tclientHelloRecord.body,\n\t\t\t\tserverRandom,\n\t\t\t\tCompressionMethod.Null\n\t\t\t)\n\t\t);\n\n\t\tawait this.writeTLSRecord(\n\t\t\tContentTypes.Handshake,\n\t\t\tMessageEncoder.certificate(certificatesDER)\n\t\t);\n\n\t\tconst ecdheKeyPair = await generalEcdheKeyPair;\n\t\tconst clientRandom = clientHelloRecord.body.random;\n\t\tconst serverKeyExchange = await MessageEncoder.ECDHEServerKeyExchange(\n\t\t\tclientRandom,\n\t\t\tserverRandom,\n\t\t\tecdheKeyPair,\n\t\t\tcertificatePrivateKey\n\t\t);\n\t\tawait this.writeTLSRecord(ContentTypes.Handshake, serverKeyExchange);\n\t\tawait this.writeTLSRecord(\n\t\t\tContentTypes.Handshake,\n\t\t\tMessageEncoder.serverHelloDone()\n\t\t);\n\n\t\t// Step 3: Receive the client's response, encryption keys, and\n\t\t// decrypt the first encrypted message.\n\t\tconst clientKeyExchangeRecord = await this.readNextHandshakeMessage(\n\t\t\tHandshakeType.ClientKeyExchange\n\t\t);\n\t\tawait this.readNextMessage(ContentTypes.ChangeCipherSpec);\n\n\t\tthis.sessionKeys = await this.deriveSessionKeys({\n\t\t\tclientRandom,\n\t\t\tserverRandom,\n\t\t\tserverPrivateKey: ecdheKeyPair.privateKey,\n\t\t\tclientPublicKey: await crypto.subtle.importKey(\n\t\t\t\t'raw',\n\t\t\t\tclientKeyExchangeRecord.body.exchange_keys,\n\t\t\t\t{ name: 'ECDH', namedCurve: 'P-256' },\n\t\t\t\tfalse,\n\t\t\t\t[]\n\t\t\t),\n\t\t});\n\n\t\tawait this.readNextHandshakeMessage(HandshakeType.Finished);\n\n\t\t// We're not actually verifying the hash provided by client\n\t\t// as we're not concerned with the client's identity.\n\n\t\tawait this.writeTLSRecord(\n\t\t\tContentTypes.ChangeCipherSpec,\n\t\t\tMessageEncoder.changeCipherSpec()\n\t\t);\n\t\tawait this.writeTLSRecord(\n\t\t\tContentTypes.Handshake,\n\t\t\tawait MessageEncoder.createFinishedMessage(\n\t\t\t\tthis.handshakeMessages,\n\t\t\t\tthis.sessionKeys!.masterSecret\n\t\t\t)\n\t\t);\n\t\t// Clean up the handshake messages as they are no longer needed.\n\t\tthis.handshakeMessages = [];\n\n\t\tthis.pollForClientMessages();\n\t}\n\n\t/**\n\t * Derives the session keys from the random values and the\n\t * pre-master secret – as per RFC 5246.\n\t */\n\tprivate async deriveSessionKeys({\n\t\tclientRandom,\n\t\tserverRandom,\n\t\tserverPrivateKey,\n\t\tclientPublicKey,\n\t}: {\n\t\tclientRandom: Uint8Array;\n\t\tserverRandom: Uint8Array;\n\t\tserverPrivateKey: CryptoKey;\n\t\tclientPublicKey: CryptoKey;\n\t}): Promise<SessionKeys> {\n\t\tconst preMasterSecret = await crypto.subtle.deriveBits(\n\t\t\t{\n\t\t\t\tname: 'ECDH',\n\t\t\t\tpublic: clientPublicKey,\n\t\t\t},\n\t\t\tserverPrivateKey,\n\t\t\t256 // Length of the derived secret (256 bits for P-256)\n\t\t);\n\n\t\tconst masterSecret = new Uint8Array(\n\t\t\tawait tls12Prf(\n\t\t\t\tpreMasterSecret,\n\t\t\t\tnew TextEncoder().encode('master secret'),\n\t\t\t\tconcatUint8Arrays([clientRandom, serverRandom]),\n\t\t\t\t48\n\t\t\t)\n\t\t);\n\n\t\tconst keyBlock = await tls12Prf(\n\t\t\tmasterSecret,\n\t\t\tnew TextEncoder().encode('key expansion'),\n\t\t\tconcatUint8Arrays([serverRandom, clientRandom]),\n\t\t\t// Client key, server key, client IV, server IV\n\t\t\t16 + 16 + 4 + 4\n\t\t);\n\n\t\tconst reader = new ArrayBufferReader(keyBlock);\n\t\tconst clientWriteKey = reader.readUint8Array(16);\n\t\tconst serverWriteKey = reader.readUint8Array(16);\n\t\tconst clientIV = reader.readUint8Array(4);\n\t\tconst serverIV = reader.readUint8Array(4);\n\n\t\treturn {\n\t\t\tmasterSecret,\n\t\t\tclientWriteKey: await crypto.subtle.importKey(\n\t\t\t\t'raw',\n\t\t\t\tclientWriteKey,\n\t\t\t\t{ name: 'AES-GCM' },\n\t\t\t\tfalse,\n\t\t\t\t['encrypt', 'decrypt']\n\t\t\t),\n\t\t\tserverWriteKey: await crypto.subtle.importKey(\n\t\t\t\t'raw',\n\t\t\t\tserverWriteKey,\n\t\t\t\t{ name: 'AES-GCM' },\n\t\t\t\tfalse,\n\t\t\t\t['encrypt', 'decrypt']\n\t\t\t),\n\t\t\tclientIV,\n\t\t\tserverIV,\n\t\t};\n\t}\n\n\tprivate async readNextHandshakeMessage(\n\t\tmessageType: typeof HandshakeType.ClientHello\n\t): Promise<HandshakeMessage<ClientHello>>;\n\tprivate async readNextHandshakeMessage(\n\t\tmessageType: typeof HandshakeType.ClientKeyExchange\n\t): Promise<HandshakeMessage<ClientKeyExchange>>;\n\tprivate async readNextHandshakeMessage(\n\t\tmessageType: typeof HandshakeType.Finished\n\t): Promise<HandshakeMessage<Finished>>;\n\tprivate async readNextHandshakeMessage(\n\t\tmessageType:\n\t\t\t| typeof HandshakeType.ClientHello\n\t\t\t| typeof HandshakeType.ClientKeyExchange\n\t\t\t| typeof HandshakeType.Finished\n\t): Promise<HandshakeMessage<any>> {\n\t\tconst message = await this.readNextMessage(ContentTypes.Handshake);\n\t\tif (message.msg_type !== messageType) {\n\t\t\tthrow new Error(`Expected ${messageType} message`);\n\t\t}\n\t\treturn message;\n\t}\n\n\tprivate async readNextMessage(\n\t\trequestedType: (typeof ContentTypes)['Handshake']\n\t): Promise<HandshakeMessage<any>>;\n\tprivate async readNextMessage(\n\t\trequestedType: (typeof ContentTypes)['ApplicationData']\n\t): Promise<ApplicationDataMessage>;\n\tprivate async readNextMessage(\n\t\trequestedType: (typeof ContentTypes)['Alert']\n\t): Promise<AlertMessage>;\n\tprivate async readNextMessage(\n\t\trequestedType: (typeof ContentTypes)['ChangeCipherSpec']\n\t): Promise<ChangeCipherSpecMessage>;\n\tprivate async readNextMessage<Message extends TLSMessage>(\n\t\trequestedType: ContentType\n\t): Promise<Message> {\n\t\tlet record: TLSRecord;\n\t\tlet accumulatedPayload: false | Uint8Array = false;\n\t\tdo {\n\t\t\trecord = await this.readNextTLSRecord(requestedType);\n\t\t\taccumulatedPayload = await this.accumulateUntilMessageIsComplete(\n\t\t\t\trecord\n\t\t\t);\n\t\t} while (accumulatedPayload === false);\n\n\t\tconst message = TLSDecoder.TLSMessage(\n\t\t\trecord.type,\n\t\t\taccumulatedPayload\n\t\t) as Message;\n\t\tif (record.type === ContentTypes.Handshake) {\n\t\t\tthis.handshakeMessages.push(record.fragment);\n\t\t}\n\t\treturn message;\n\t}\n\n\tprivate async readNextTLSRecord(\n\t\trequestedType: ContentType\n\t): Promise<TLSRecord> {\n\t\twhile (true) {\n\t\t\t// First, check if we have a complete record of the requested type.\n\t\t\tfor (let i = 0; i < this.receivedTLSRecords.length; i++) {\n\t\t\t\tconst record = this.receivedTLSRecords[i];\n\t\t\t\tif (record.type !== requestedType) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tthis.receivedTLSRecords.splice(i, 1);\n\t\t\t\treturn record;\n\t\t\t}\n\n\t\t\t// We don't have a complete record of the requested type yet.\n\t\t\t// Let's read the next TLS record, then.\n\t\t\tconst header = await this.pollBytes(5);\n\t\t\tconst length = (header[3] << 8) | header[4];\n\t\t\tconst type = header[0];\n\t\t\tconst fragment = await this.pollBytes(length);\n\t\t\tconst record = {\n\t\t\t\ttype,\n\t\t\t\tversion: {\n\t\t\t\t\tmajor: header[1],\n\t\t\t\t\tminor: header[2],\n\t\t\t\t},\n\t\t\t\tlength,\n\t\t\t\tfragment:\n\t\t\t\t\tthis.sessionKeys && type !== ContentTypes.ChangeCipherSpec\n\t\t\t\t\t\t? await this.decryptData(type, fragment)\n\t\t\t\t\t\t: fragment,\n\t\t\t} as TLSRecord;\n\n\t\t\tif (record.type === ContentTypes.Alert) {\n\t\t\t\tconst severity = AlertLevelNames[record.fragment[0]];\n\t\t\t\tconst description = AlertDescriptionNames[record.fragment[1]];\n\t\t\t\t/**\n\t\t\t\t * @TODO: Handle TLS warnings, e.g. this one:\n\t\t\t\t *\n\t\t\t\t * close_notify\n\t\t\t\t * Either party may initiate a close by sending a close_notify alert.\n\t\t\t\t * Any data received after a closure alert is ignored.\n\t\t\t\t *\n\t\t\t\t * Unless some other fatal alert has been transmitted, each party is\n\t\t\t\t * required to send a close_notify alert before closing the write side\n\t\t\t\t * of the connection. The other party MUST respond with a close_notify\n\t\t\t\t * alert of its own and close down the connection immediately,\n\t\t\t\t * discarding any pending writes.\n\t\t\t\t */\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`TLS non-warning alert received: ${severity} ${description}`\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.receivedTLSRecords.push(record);\n\t\t}\n\t}\n\n\t/**\n\t * Returns the requested number of bytes from the client.\n\t * Waits for the bytes to arrive if necessary.\n\t */\n\tprivate async pollBytes(length: number) {\n\t\twhile (this.receivedBytesBuffer.length < length) {\n\t\t\tconst { value, done } = await this.clientUpstreamReader.read();\n\t\t\tif (done) {\n\t\t\t\tawait this.close();\n\t\t\t\tthrow new TLSConnectionClosed('TLS connection closed');\n\t\t\t}\n\t\t\tthis.receivedBytesBuffer = concatUint8Arrays([\n\t\t\t\tthis.receivedBytesBuffer,\n\t\t\t\tvalue,\n\t\t\t]);\n\t\t\tif (this.receivedBytesBuffer.length >= length) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t// Patience is the key...\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, 100));\n\t\t}\n\t\tconst requestedBytes = this.receivedBytesBuffer.slice(0, length);\n\t\tthis.receivedBytesBuffer = this.receivedBytesBuffer.slice(length);\n\t\treturn requestedBytes;\n\t}\n\n\t/**\n\t * Listens for all incoming messages and passes them to the\n\t * server handler.\n\t */\n\tprivate async pollForClientMessages() {\n\t\ttry {\n\t\t\twhile (true) {\n\t\t\t\tconst appData = await this.readNextMessage(\n\t\t\t\t\tContentTypes.ApplicationData\n\t\t\t\t);\n\t\t\t\tthis.serverUpstreamWriter.write(appData.body);\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tif (e instanceof TLSConnectionClosed) {\n\t\t\t\t// Connection closed, no more application data to emit.\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthrow e;\n\t\t}\n\t}\n\n\t/**\n\t * Decrypts data in a TLS 1.2-compliant manner using\n\t * the AES-GCM algorithm.\n\t */\n\tprivate async decryptData(\n\t\tcontentType: number,\n\t\tpayload: Uint8Array\n\t): Promise<Uint8Array> {\n\t\tconst implicitIV = this.sessionKeys!.clientIV;\n\t\t// Part of the IV is randomly generated for each record\n\t\t// and prepended in its unencrypted form before the\n\t\t// ciphertext.\n\t\tconst explicitIV = payload.slice(0, 8);\n\t\tconst iv = new Uint8Array([...implicitIV, ...explicitIV]);\n\n\t\tconst decrypted = await crypto.subtle.decrypt(\n\t\t\t{\n\t\t\t\tname: 'AES-GCM',\n\t\t\t\tiv,\n\t\t\t\tadditionalData: new Uint8Array([\n\t\t\t\t\t...as8Bytes(this.receivedRecordSequenceNumber),\n\t\t\t\t\tcontentType,\n\t\t\t\t\t...TLS_Version_1_2,\n\t\t\t\t\t// Payload length without IV and tag\n\t\t\t\t\t...as2Bytes(payload.length - 8 - 16),\n\t\t\t\t]),\n\t\t\t\ttagLength: 128,\n\t\t\t},\n\t\t\tthis.sessionKeys!.clientWriteKey,\n\t\t\t// Payload without the explicit IV\n\t\t\tpayload.slice(8)\n\t\t);\n\t\t++this.receivedRecordSequenceNumber;\n\n\t\treturn new Uint8Array(decrypted);\n\t}\n\n\tprivate async accumulateUntilMessageIsComplete(\n\t\trecord: TLSRecord\n\t): Promise<false | Uint8Array> {\n\t\tthis.partialTLSMessages[record.type] = concatUint8Arrays([\n\t\t\tthis.partialTLSMessages[record.type] || new Uint8Array(),\n\t\t\trecord.fragment,\n\t\t]);\n\t\tconst message = this.partialTLSMessages[record.type]!;\n\t\tswitch (record.type) {\n\t\t\tcase ContentTypes.Handshake: {\n\t\t\t\t// We don't have the message header yet, let's wait for more data.\n\t\t\t\tif (message.length < 4) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tconst length = (message[1] << 8) | message[2];\n\t\t\t\tif (message.length < 3 + length) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase ContentTypes.Alert: {\n\t\t\t\tif (message.length < 2) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase ContentTypes.ChangeCipherSpec:\n\t\t\tcase ContentTypes.ApplicationData:\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthrow new Error(`TLS: Unsupported record type ${record.type}`);\n\t\t}\n\t\tdelete this.partialTLSMessages[record.type];\n\t\treturn message;\n\t}\n\n\t/**\n\t * Passes a TLS record to the client.\n\t *\n\t * Accepts unencrypted data and ensures it gets encrypted\n\t * if needed before sending it to the client. The encryption\n\t * only kicks in after the handshake is complete.\n\t */\n\tprivate async writeTLSRecord(\n\t\tcontentType: number,\n\t\tpayload: Uint8Array\n\t): Promise<void> {\n\t\tif (contentType === ContentTypes.Handshake) {\n\t\t\tthis.handshakeMessages.push(payload);\n\t\t}\n\t\tif (this.sessionKeys && contentType !== ContentTypes.ChangeCipherSpec) {\n\t\t\tpayload = await this.encryptData(contentType, payload);\n\t\t}\n\n\t\tconst version = TLS_Version_1_2;\n\t\tconst length = payload.length;\n\t\tconst header = new Uint8Array(5);\n\t\theader[0] = contentType;\n\t\theader[1] = version[0];\n\t\theader[2] = version[1];\n\t\theader[3] = (length >> 8) & 0xff;\n\t\theader[4] = length & 0xff;\n\n\t\tconst record = concatUint8Arrays([header, payload]);\n\t\tthis.clientDownstreamWriter.write(record);\n\t}\n\n\t/**\n\t * Encrypts data in a TLS 1.2-compliant manner using\n\t * the AES-GCM algorithm.\n\t */\n\tprivate async encryptData(\n\t\tcontentType: number,\n\t\tpayload: Uint8Array\n\t): Promise<Uint8Array> {\n\t\tconst implicitIV = this.sessionKeys!.serverIV;\n\t\t// Part of the IV is randomly generated for each record\n\t\t// and prepended in its unencrypted form before the\n\t\t// ciphertext.\n\t\tconst explicitIV = crypto.getRandomValues(new Uint8Array(8));\n\t\tconst iv = new Uint8Array([...implicitIV, ...explicitIV]);\n\n\t\tconst additionalData = new Uint8Array([\n\t\t\t...as8Bytes(this.sentRecordSequenceNumber),\n\t\t\tcontentType,\n\t\t\t...TLS_Version_1_2,\n\t\t\t// Payload length without IV and tag\n\t\t\t...as2Bytes(payload.length),\n\t\t]);\n\t\tconst ciphertextWithTag = await crypto.subtle.encrypt(\n\t\t\t{\n\t\t\t\tname: 'AES-GCM',\n\t\t\t\tiv,\n\t\t\t\tadditionalData,\n\t\t\t\ttagLength: 128,\n\t\t\t},\n\t\t\tthis.sessionKeys!.serverWriteKey,\n\t\t\tpayload\n\t\t);\n\t\t++this.sentRecordSequenceNumber;\n\n\t\tconst encrypted = concatUint8Arrays([\n\t\t\texplicitIV,\n\t\t\tnew Uint8Array(ciphertextWithTag),\n\t\t]);\n\n\t\treturn encrypted;\n\t}\n}\n\nclass TLSDecoder {\n\tstatic TLSMessage(\n\t\ttype: ContentType,\n\t\taccumulatedPayload: Uint8Array\n\t): TLSMessage {\n\t\tswitch (type) {\n\t\t\tcase ContentTypes.Handshake: {\n\t\t\t\treturn TLSDecoder.clientHandshake(accumulatedPayload);\n\t\t\t}\n\t\t\tcase ContentTypes.Alert: {\n\t\t\t\treturn TLSDecoder.alert(accumulatedPayload);\n\t\t\t}\n\t\t\tcase ContentTypes.ChangeCipherSpec: {\n\t\t\t\treturn TLSDecoder.changeCipherSpec();\n\t\t\t}\n\t\t\tcase ContentTypes.ApplicationData: {\n\t\t\t\treturn TLSDecoder.applicationData(accumulatedPayload);\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\tthrow new Error(`TLS: Unsupported TLS record type ${type}`);\n\t\t}\n\t}\n\n\t/**\n\t * Parses the cipher suites from the server hello message.\n\t *\n\t * The cipher suites are encoded as a list of 2-byte values.\n\t *\n\t * Binary layout:\n\t *\n\t * +----------------------------+\n\t * | Cipher Suites Length | 2 bytes\n\t * +----------------------------+\n\t * | Cipher Suite 1 | 2 bytes\n\t * +----------------------------+\n\t * | Cipher Suite 2 | 2 bytes\n\t * +----------------------------+\n\t * | ... |\n\t * +----------------------------+\n\t * | Cipher Suite n | 2 bytes\n\t * +----------------------------+\n\t *\n\t * The full list of supported cipher suites values is available at:\n\t *\n\t * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-4\n\t */\n\tstatic parseCipherSuites(buffer: ArrayBuffer): string[] {\n\t\tconst reader = new ArrayBufferReader(buffer);\n\t\t// Skip the length of the cipher suites\n\t\treader.readUint16();\n\n\t\tconst cipherSuites = [];\n\t\twhile (!reader.isFinished()) {\n\t\t\tconst suite = reader.readUint16();\n\t\t\tif (!(suite in CipherSuitesNames)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tcipherSuites.push(CipherSuitesNames[suite]);\n\t\t}\n\t\treturn cipherSuites;\n\t}\n\n\tstatic applicationData(message: Uint8Array): ApplicationDataMessage {\n\t\treturn {\n\t\t\ttype: ContentTypes.ApplicationData,\n\t\t\tbody: message,\n\t\t};\n\t}\n\n\tstatic changeCipherSpec(): ChangeCipherSpecMessage {\n\t\treturn {\n\t\t\ttype: ContentTypes.ChangeCipherSpec,\n\t\t\tbody: new Uint8Array(),\n\t\t};\n\t}\n\n\tstatic alert(message: Uint8Array): AlertMessage {\n\t\treturn {\n\t\t\ttype: ContentTypes.Alert,\n\t\t\tlevel: AlertLevelNames[message[0]],\n\t\t\tdescription: AlertDescriptionNames[message[1]],\n\t\t};\n\t}\n\n\tstatic clientHandshake<T extends HandshakeMessageBody>(\n\t\tmessage: Uint8Array\n\t): HandshakeMessage<T> {\n\t\tconst msg_type = message[0];\n\t\tconst length = (message[1] << 16) | (message[2] << 8) | message[3];\n\t\tconst bodyBytes = message.slice(4);\n\t\tlet body: HandshakeMessageBody | undefined = undefined;\n\t\tswitch (msg_type) {\n\t\t\tcase HandshakeType.HelloRequest:\n\t\t\t\tbody = TLSDecoder.clientHelloRequestPayload();\n\t\t\t\tbreak;\n\t\t\tcase HandshakeType.ClientHello:\n\t\t\t\tbody = TLSDecoder.clientHelloPayload(bodyBytes);\n\t\t\t\tbreak;\n\t\t\tcase HandshakeType.ClientKeyExchange:\n\t\t\t\tbody = TLSDecoder.clientKeyExchangePayload(bodyBytes);\n\t\t\t\tbreak;\n\t\t\tcase HandshakeType.Finished:\n\t\t\t\tbody = TLSDecoder.clientFinishedPayload(bodyBytes);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthrow new Error(`Invalid handshake type ${msg_type}`);\n\t\t}\n\t\treturn {\n\t\t\ttype: ContentTypes.Handshake,\n\t\t\tmsg_type,\n\t\t\tlength,\n\t\t\tbody: body as T,\n\t\t};\n\t}\n\n\tstatic clientHelloRequestPayload(): HelloRequest {\n\t\treturn {};\n\t}\n\n\t/**\n\t *\tOffset Size Field\n\t *\t(bytes) (bytes)\n\t *\t+------+------+---------------------------+\n\t *\t| 0000 | 1 | Handshake Type (1 = ClientHello)\n\t *\t+------+------+---------------------------+\n\t *\t| 0001 | 3 | Length of ClientHello\n\t *\t+------+------+---------------------------+\n\t *\t| 0004 | 2 | Protocol Version\n\t *\t+------+------+---------------------------+\n\t *\t| 0006 | 32 | Client Random\n\t *\t| | | (4 bytes timestamp +\n\t *\t| | | 28 bytes random)\n\t *\t+------+------+---------------------------+\n\t *\t| 0038 | 1 | Session ID Length\n\t *\t+------+------+---------------------------+\n\t *\t| 0039 | 0+ | Session ID (variable)\n\t *\t| | | (0-32 bytes)\n\t *\t+------+------+---------------------------+\n\t *\t| 003A*| 2 | Cipher Suites Length\n\t *\t+------+------+---------------------------+\n\t *\t| 003C*| 2+ | Cipher Suites\n\t *\t| | | (2 bytes each)\n\t *\t+------+------+---------------------------+\n\t *\t| xxxx | 1 | Compression Methods Length\n\t *\t+------+------+---------------------------+\n\t *\t| xxxx | 1+ | Compression Methods\n\t *\t| | | (1 byte each)\n\t *\t+------+------+---------------------------+\n\t *\t| xxxx | 2 | Extensions Length\n\t *\t+------+------+---------------------------+\n\t *\t| xxxx | 2 | Extension Type\n\t *\t+------+------+---------------------------+\n\t *\t| xxxx | 2 | Extension Length\n\t *\t+------+------+---------------------------+\n\t *\t| xxxx | v | Extension Data\n\t *\t+------+------+---------------------------+\n\t *\t| | | (Additional extensions...)\n\t *\t+------+------+---------------------------+\n\t */\n\tstatic clientHelloPayload(data: Uint8Array): ClientHello {\n\t\tconst reader = new ArrayBufferReader(data.buffer);\n\t\tconst buff: Partial<ClientHello> = {\n\t\t\tclient_version: reader.readUint8Array(2),\n\t\t\t/**\n\t\t\t * Technically this consists of a GMT timestamp\n\t\t\t * and 28 random bytes, but we don't need to\n\t\t\t * parse this further.\n\t\t\t */\n\t\t\trandom: reader.readUint8Array(32),\n\t\t};\n\t\tconst sessionIdLength = reader.readUint8();\n\t\tbuff.session_id = reader.readUint8Array(sessionIdLength);\n\n\t\tconst cipherSuitesLength = reader.readUint16();\n\t\tbuff.cipher_suites = TLSDecoder.parseCipherSuites(\n\t\t\treader.readUint8Array(cipherSuitesLength).buffer\n\t\t);\n\n\t\tconst compressionMethodsLength = reader.readUint8();\n\t\tbuff.compression_methods = reader.readUint8Array(\n\t\t\tcompressionMethodsLength\n\t\t);\n\n\t\tconst extensionsLength = reader.readUint16();\n\t\tbuff.extensions = parseClientHelloExtensions(\n\t\t\treader.readUint8Array(extensionsLength)\n\t\t);\n\t\treturn buff as ClientHello;\n\t}\n\n\t/**\n\t * Binary layout:\n\t *\n\t *\t+------------------------------------+\n\t *\t| ECDH Client Public Key Length [1B] |\n\t *\t+------------------------------------+\n\t *\t| ECDH Client Public Key [variable]|\n\t *\t+------------------------------------+\n\t */\n\tstatic clientKeyExchangePayload(data: Uint8Array): ClientKeyExchange {\n\t\treturn {\n\t\t\t// Skip the first byte, which is the length of the public key\n\t\t\texchange_keys: data.slice(1, data.length),\n\t\t};\n\t}\n\n\tstatic clientFinishedPayload(data: Uint8Array): Finished {\n\t\treturn {\n\t\t\tverify_data: data,\n\t\t};\n\t}\n}\n\n/**\n * Creates a stream that emits chunks not larger than\n * the specified size.\n */\nfunction chunkStream(chunkSize: number) {\n\treturn new TransformStream({\n\t\ttransform(chunk, controller) {\n\t\t\twhile (chunk.length > 0) {\n\t\t\t\tcontroller.enqueue(chunk.slice(0, chunkSize));\n\t\t\t\tchunk = chunk.slice(chunkSize);\n\t\t\t}\n\t\t},\n\t});\n}\n\nclass MessageEncoder {\n\tstatic certificate(certificatesDER: ArrayBuffer[]): Uint8Array {\n\t\tconst certsBodies: Uint8Array[] = [];\n\t\tfor (const cert of certificatesDER) {\n\t\t\tcertsBodies.push(as3Bytes(cert.byteLength));\n\t\t\tcertsBodies.push(new Uint8Array(cert));\n\t\t}\n\t\tconst certsBody = concatUint8Arrays(certsBodies);\n\t\tconst body = new Uint8Array([\n\t\t\t...as3Bytes(certsBody.byteLength),\n\t\t\t...certsBody,\n\t\t]);\n\t\treturn new Uint8Array([\n\t\t\tHandshakeType.Certificate,\n\t\t\t...as3Bytes(body.length),\n\t\t\t...body,\n\t\t]);\n\t}\n\n\t/*\n\t * Byte layout of the ServerKeyExchange message:\n\t *\n\t * +-----------------------------------+\n\t * | ServerKeyExchange Message |\n\t * +-----------------------------------+\n\t * | Handshake type (1 byte) |\n\t * +-----------------------------------+\n\t * | Length (3 bytes) |\n\t * +-----------------------------------+\n\t * | Curve Type (1 byte) |\n\t * +-----------------------------------+\n\t * | Named Curve (2 bytes) |\n\t * +-----------------------------------+\n\t * | EC Point Format (1 byte) |\n\t * +-----------------------------------+\n\t * | Public Key Length (1 byte) |\n\t * +-----------------------------------+\n\t * | Public Key (variable) |\n\t * +-----------------------------------+\n\t * | Signature Algorithm (2 bytes) |\n\t * +-----------------------------------+\n\t * | Signature Length (2 bytes) |\n\t * +-----------------------------------+\n\t * | Signature (variable) |\n\t * +-----------------------------------+\n\t *\n\t * @param clientRandom - 32 bytes from ClientHello\n\t * @param serverRandom - 32 bytes from ServerHello\n\t * @param ecdheKeyPair - ECDHE key pair\n\t * @param rsaPrivateKey - RSA private key for signing\n\t * @returns\n\t */\n\tstatic async ECDHEServerKeyExchange(\n\t\tclientRandom: Uint8Array,\n\t\tserverRandom: Uint8Array,\n\t\tecdheKeyPair: CryptoKeyPair,\n\t\trsaPrivateKey: CryptoKey\n\t): Promise<Uint8Array> {\n\t\t// 65 bytes (04 followed by x and y coordinates)\n\t\tconst publicKey = new Uint8Array(\n\t\t\tawait crypto.subtle.exportKey('raw', ecdheKeyPair.publicKey)\n\t\t);\n\n\t\t/*\n\t\t * The ServerKeyExchange message is extended as follows.\n\t\t *\n\t\t * select (KeyExchangeAlgorithm) {\n\t\t * case ec_diffie_hellman:\n\t\t * ServerECDHParams params;\n\t\t * Signature signed_params;\n\t\t * } ServerKeyExchange;\n\t\t *\n\t\t * struct {\n\t\t * ECCurveType curve_type;\n\t\t * NamedCurve namedcurve;\n\t\t * ECPoint public;\n\t\t * } ServerECDHParams;\n\t\t */\n\t\tconst params = new Uint8Array([\n\t\t\t// Curve type (1 byte)\n\t\t\tECCurveTypes.NamedCurve,\n\t\t\t// Curve name (2 bytes)\n\t\t\t...as2Bytes(ECNamedCurves.secp256r1),\n\n\t\t\t// Public key length (1 byte)\n\t\t\tpublicKey.byteLength,\n\n\t\t\t// Public key (65 bytes, uncompressed format)\n\t\t\t...publicKey,\n\t\t]);\n\n\t\t/**\n\t\t * signed_params:\n\t\t * A hash of the params, with the signature appropriate to that hash\n\t\t * applied. The private key corresponding to the certified public key\n\t\t * in the server's Certificate message is used for signing.\n\t\t *\n\t\t * Signature = encrypt(SHA(\n\t\t * ClientHello.random + ServerHello.random + ServerECDHParams\n\t\t * ));\n\t\t */\n\t\tconst signedParams = await crypto.subtle.sign(\n\t\t\t{\n\t\t\t\tname: 'RSASSA-PKCS1-v1_5',\n\t\t\t\thash: 'SHA-256',\n\t\t\t},\n\t\t\trsaPrivateKey,\n\t\t\tnew Uint8Array([...clientRandom, ...serverRandom, ...params])\n\t\t);\n\t\tconst signatureBytes = new Uint8Array(signedParams);\n\n\t\t/**\n\t\t * SignatureAlgorithm is \"rsa\" for the ECDHE_RSA key exchange\n\t\t * These cases are defined in TLS [RFC2246].\n\t\t */\n\t\tconst signatureAlgorithm = new Uint8Array([\n\t\t\tHashAlgorithms.sha256,\n\t\t\tSignatureAlgorithms.rsa,\n\t\t]);\n\n\t\t// Step 6: Construct the complete Server Key Exchange message\n\t\tconst body = new Uint8Array([\n\t\t\t...params,\n\t\t\t...signatureAlgorithm,\n\t\t\t...as2Bytes(signatureBytes.length),\n\t\t\t...signatureBytes,\n\t\t]);\n\n\t\treturn new Uint8Array([\n\t\t\tHandshakeType.ServerKeyExchange,\n\t\t\t...as3Bytes(body.length),\n\t\t\t...body,\n\t\t]);\n\t}\n\n\t/**\n\t * +------------------------------------+\n\t * | Content Type (Handshake) [1B] |\n\t * | 0x16 |\n\t * +------------------------------------+\n\t * | Version (TLS 1.2) [2B] |\n\t * | 0x03 0x03 |\n\t * +------------------------------------+\n\t * | Length [2B] |\n\t * +------------------------------------+\n\t * | Handshake Type (ServerHello) [1B] |\n\t * | 0x02 |\n\t * +------------------------------------+\n\t * | Handshake Length [3B] |\n\t * +------------------------------------+\n\t * | Server Version [2B] |\n\t * +------------------------------------+\n\t * | Server Random [32B] |\n\t * +------------------------------------+\n\t * | Session ID Length [1B] |\n\t * +------------------------------------+\n\t * | Session ID [0-32B] |\n\t * +------------------------------------+\n\t * | Cipher Suite [2B] |\n\t * +------------------------------------+\n\t * | Compression Method [1B] |\n\t * +------------------------------------+\n\t * | Extensions Length [2B] |\n\t * +------------------------------------+\n\t * | Extension: ec_point_formats |\n\t * | Type (0x00 0x0B) [2B] |\n\t * | Length [2B] |\n\t * | EC Point Formats Length [1B] |\n\t * | EC Point Format [1B] |\n\t * +------------------------------------+\n\t * | Other Extensions... |\n\t * +------------------------------------+\n\t */\n\tstatic serverHello(\n\t\tclientHello: ClientHello,\n\t\tserverRandom: Uint8Array,\n\t\tcompressionAlgorithm: number\n\t): Uint8Array {\n\t\tconst extensionsParts: Uint8Array[] = clientHello.extensions\n\t\t\t.map((extension) => {\n\t\t\t\tswitch (extension['type']) {\n\t\t\t\t\tcase 'server_name':\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * The server SHALL include an extension of type \"server_name\" in the\n\t\t\t\t\t\t * (extended) server hello. The \"extension_data\" field of this extension\n\t\t\t\t\t\t * SHALL be empty.\n\t\t\t\t\t\t *\n\t\t\t\t\t\t * Source: dfile:///Users/cloudnik/Library/Application%20Support/Dash/User%20Contributed/RFCs/RFCs.docset/Contents/Resources/Documents/rfc6066.html#section-3\n\t\t\t\t\t\t */\n\t\t\t\t\t\treturn ServerNameExtension.encodeForClient();\n\t\t\t\t}\n\t\t\t\treturn undefined;\n\t\t\t})\n\t\t\t.filter((x): x is Uint8Array => x !== undefined);\n\t\tconst extensions = concatUint8Arrays(extensionsParts);\n\n\t\tconst body = new Uint8Array([\n\t\t\t// Version field – 0x03, 0x03 means TLS 1.2\n\t\t\t...TLS_Version_1_2,\n\n\t\t\t...serverRandom,\n\n\t\t\tclientHello.session_id.length,\n\t\t\t...clientHello.session_id,\n\n\t\t\t...as2Bytes(CipherSuites.TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256),\n\n\t\t\tcompressionAlgorithm,\n\n\t\t\t// Extensions length (2 bytes)\n\t\t\t...as2Bytes(extensions.length),\n\n\t\t\t...extensions,\n\t\t]);\n\n\t\treturn new Uint8Array([\n\t\t\tHandshakeType.ServerHello,\n\t\t\t...as3Bytes(body.length),\n\t\t\t...body,\n\t\t]);\n\t}\n\n\tstatic serverHelloDone(): Uint8Array {\n\t\treturn new Uint8Array([HandshakeType.ServerHelloDone, ...as3Bytes(0)]);\n\t}\n\n\t/**\n\t * Server finished message.\n\t * The structure is defined in:\n\t * https://datatracker.ietf.org/doc/html/rfc5246#section-7.4.9\n\t *\n\t * struct {\n\t * opaque verify_data[verify_data_length];\n\t * } Finished;\n\t *\n\t * verify_data\n\t * PRF(master_secret, finished_label, Hash(handshake_messages))\n\t * [0..verify_data_length-1];\n\t *\n\t * finished_label\n\t * For Finished messages sent by the client, the string\n\t * \"client finished\". For Finished messages sent by the server,\n\t * the string \"server finished\".\n\t */\n\tstatic async createFinishedMessage(\n\t\thandshakeMessages: Uint8Array[],\n\t\tmasterSecret: ArrayBuffer\n\t): Promise<Uint8Array> {\n\t\t// Step 1: Compute the hash of the handshake messages\n\t\tconst handshakeHash = await crypto.subtle.digest(\n\t\t\t'SHA-256',\n\t\t\tconcatUint8Arrays(handshakeMessages)\n\t\t);\n\n\t\t// Step 2: Compute the verify_data using the PRF\n\t\tconst verifyData = new Uint8Array(\n\t\t\tawait tls12Prf(\n\t\t\t\tmasterSecret,\n\t\t\t\tnew TextEncoder().encode('server finished'),\n\t\t\t\thandshakeHash,\n\t\t\t\t// verify_data length. TLS 1.2 specifies 12 bytes for verify_data\n\t\t\t\t12\n\t\t\t)\n\t\t);\n\n\t\t// Step 3: Construct the Finished message\n\t\treturn new Uint8Array([\n\t\t\tHandshakeType.Finished,\n\t\t\t...as3Bytes(verifyData.length),\n\t\t\t...verifyData,\n\t\t]);\n\t}\n\n\tstatic changeCipherSpec(): Uint8Array {\n\t\treturn new Uint8Array([0x01]);\n\t}\n}\n","import { concatUint8Arrays } from '@php-wasm/util';\n\n/**\n * Generates an X.509 certificate from the given description.\n *\n * If the issuer key pair is provided, the certificate will be signed\n * using the provided issuer's private key. Otherwise, the certificate\n * will be self-signed.\n *\n * The code below is underdocumented. The following links may provide\n * more clarity about X.509, ASN.1, DER, PEM, and other data formats\n * this module encodes:\n *\n * * https://letsencrypt.org/docs/a-warm-welcome-to-asn1-and-der/\n * * https://dev.to/wayofthepie/structure-of-an-ssl-x-509-certificate-16b\n * * https://www.oss.com/asn1/resources/asn1-made-simple/asn1-quick-reference/asn1-tags.html\n */\nexport function generateCertificate(\n\tdescription: TBSCertificateDescription,\n\tissuerKeyPair?: CryptoKeyPair\n): Promise<GeneratedCertificate> {\n\treturn CertificateGenerator.generateCertificate(description, issuerKeyPair);\n}\n\nexport function certificateToPEM(certificate: Uint8Array): string {\n\treturn `-----BEGIN CERTIFICATE-----\\n${formatPEM(\n\t\tencodeUint8ArrayAsBase64(certificate.buffer)\n\t)}\\n-----END CERTIFICATE-----`;\n}\n\nexport async function privateKeyToPEM(privateKey: CryptoKey): Promise<string> {\n\tconst pkcs8 = await crypto.subtle.exportKey('pkcs8', privateKey);\n\treturn `-----BEGIN PRIVATE KEY-----\\n${formatPEM(\n\t\tencodeUint8ArrayAsBase64(pkcs8)\n\t)}\\n-----END PRIVATE KEY-----`;\n}\n\nclass CertificateGenerator {\n\tstatic async generateCertificate(\n\t\ttbsDescription: TBSCertificateDescription,\n\t\tissuerKeyPair?: CryptoKeyPair\n\t) {\n\t\tconst subjectKeyPair = await crypto.subtle.generateKey(\n\t\t\t{\n\t\t\t\tname: 'RSASSA-PKCS1-v1_5',\n\t\t\t\thash: 'SHA-256',\n\t\t\t\tmodulusLength: 2048,\n\t\t\t\tpublicExponent: new Uint8Array([0x01, 0x00, 0x01]),\n\t\t\t},\n\t\t\ttrue, // extractable\n\t\t\t['sign', 'verify']\n\t\t);\n\t\tconst tbsCertificate = await this.signingRequest(\n\t\t\ttbsDescription,\n\t\t\tsubjectKeyPair.publicKey\n\t\t);\n\t\tconst certificate = await this.sign(\n\t\t\ttbsCertificate,\n\t\t\tissuerKeyPair?.privateKey ?? subjectKeyPair.privateKey\n\t\t);\n\t\treturn {\n\t\t\tkeyPair: subjectKeyPair,\n\t\t\tcertificate,\n\t\t\ttbsCertificate,\n\t\t\ttbsDescription,\n\t\t};\n\t}\n\n\tstatic async sign(\n\t\ttbsCertificate: TBSCertificate,\n\t\tprivateKey: CryptoKey\n\t): Promise<Uint8Array> {\n\t\t// Step 3: Sign the TBSCertificate\n\t\tconst signature = await crypto.subtle.sign(\n\t\t\t{\n\t\t\t\tname: 'RSASSA-PKCS1-v1_5',\n\t\t\t\thash: 'SHA-256',\n\t\t\t},\n\t\t\tprivateKey,\n\t\t\ttbsCertificate.buffer\n\t\t);\n\n\t\t// Step 4: Build the final Certificate sequence\n\t\tconst certificate = ASN1Encoder.sequence([\n\t\t\tnew Uint8Array(tbsCertificate.buffer),\n\t\t\tthis.signatureAlgorithm('sha256WithRSAEncryption'),\n\t\t\tASN1Encoder.bitString(new Uint8Array(signature)),\n\t\t]);\n\t\treturn certificate;\n\t}\n\n\tstatic async signingRequest(\n\t\tdescription: TBSCertificateDescription,\n\t\tsubjectPublicKey: CryptoKey\n\t): Promise<TBSCertificate> {\n\t\tconst extensions: Uint8Array[] = [];\n\t\tif (description.keyUsage) {\n\t\t\textensions.push(this.keyUsage(description.keyUsage));\n\t\t}\n\t\tif (description.extKeyUsage) {\n\t\t\textensions.push(this.extKeyUsage(description.extKeyUsage));\n\t\t}\n\t\tif (description.subjectAltNames) {\n\t\t\textensions.push(this.subjectAltName(description.subjectAltNames));\n\t\t}\n\t\tif (description.nsCertType) {\n\t\t\textensions.push(this.nsCertType(description.nsCertType));\n\t\t}\n\t\tif (description.basicConstraints) {\n\t\t\textensions.push(\n\t\t\t\tthis.basicConstraints(description.basicConstraints)\n\t\t\t);\n\t\t}\n\t\treturn ASN1Encoder.sequence([\n\t\t\tthis.version(description.version),\n\t\t\tthis.serialNumber(description.serialNumber),\n\t\t\tthis.signatureAlgorithm(description.signatureAlgorithm),\n\t\t\tthis.distinguishedName(description.issuer ?? description.subject),\n\t\t\tthis.validity(description.validity),\n\t\t\tthis.distinguishedName(description.subject),\n\t\t\tawait this.subjectPublicKeyInfo(subjectPublicKey),\n\t\t\tthis.extensions(extensions),\n\t\t]);\n\t}\n\n\tprivate static version(version = 0x02) {\n\t\t// [0] EXPLICIT Version: 2 (v3)\n\t\treturn ASN1Encoder.ASN1(\n\t\t\t0xa0,\n\t\t\tASN1Encoder.integer(new Uint8Array([version]))\n\t\t);\n\t}\n\n\tprivate static serialNumber(\n\t\tserialNumber = crypto.getRandomValues(new Uint8Array(4))\n\t) {\n\t\treturn ASN1Encoder.integer(serialNumber);\n\t}\n\n\tprivate static signatureAlgorithm(\n\t\talgorithm: OIDName = 'sha256WithRSAEncryption'\n\t) {\n\t\treturn ASN1Encoder.sequence([\n\t\t\tASN1Encoder.objectIdentifier(oidByName(algorithm)),\n\t\t\tASN1Encoder.null(),\n\t\t]);\n\t}\n\n\tprivate static async subjectPublicKeyInfo(publicKey: CryptoKey) {\n\t\t// ExportKey already returns data in ASN.1 DER format, we don't\n\t\t// need to wrap it in a sequence agin.\n\t\treturn new Uint8Array(await crypto.subtle.exportKey('spki', publicKey));\n\t}\n\n\tprivate static extensions(extensions: Uint8Array[]) {\n\t\treturn ASN1Encoder.ASN1(0xa3, ASN1Encoder.sequence(extensions));\n\t}\n\n\tprivate static distinguishedName(nameInfo: DistinguishedName) {\n\t\tconst values = [];\n\t\tfor (const [oidName, value] of Object.entries(nameInfo)) {\n\t\t\tconst entry = [\n\t\t\t\tASN1Encoder.objectIdentifier(oidByName(oidName as OIDName)),\n\t\t\t];\n\t\t\tswitch (oidName) {\n\t\t\t\tcase 'countryName':\n\t\t\t\t\tentry.push(ASN1Encoder.printableString(value));\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tentry.push(ASN1Encoder.utf8String(value));\n\t\t\t}\n\t\t\tvalues.push(ASN1Encoder.set([ASN1Encoder.sequence(entry)]));\n\t\t}\n\t\treturn ASN1Encoder.sequence(values);\n\t}\n\n\tprivate static validity(validity?: Validity) {\n\t\treturn ASN1Encoder.sequence([\n\t\t\tASN1Encoder.ASN1(\n\t\t\t\tASN1Tags.UTCTime,\n\t\t\t\tnew TextEncoder().encode(\n\t\t\t\t\tformatDateASN1(validity?.notBefore ?? new Date())\n\t\t\t\t)\n\t\t\t),\n\t\t\tASN1Encoder.ASN1(\n\t\t\t\tASN1Tags.UTCTime,\n\t\t\t\tnew TextEncoder().encode(\n\t\t\t\t\tformatDateASN1(\n\t\t\t\t\t\tvalidity?.notAfter ?? addYears(new Date(), 10)\n\t\t\t\t\t)\n\t\t\t\t)\n\t\t\t),\n\t\t]);\n\t}\n\n\tprivate static basicConstraints({\n\t\tca = true,\n\t\tpathLenConstraint = undefined,\n\t}: BasicConstraints) {\n\t\tconst sequence = [ASN1Encoder.boolean(ca)];\n\t\tif (pathLenConstraint !== undefined) {\n\t\t\tsequence.push(\n\t\t\t\tASN1Encoder.integer(new Uint8Array([pathLenConstraint]))\n\t\t\t);\n\t\t}\n\t\treturn ASN1Encoder.sequence([\n\t\t\tASN1Encoder.objectIdentifier(oidByName('basicConstraints')),\n\t\t\tASN1Encoder.octetString(ASN1Encoder.sequence(sequence)),\n\t\t]);\n\t}\n\n\tprivate static keyUsage(keyUsage?: KeyUsage) {\n\t\tconst keyUsageBits = new Uint8Array([0b00000000]);\n\t\tif (keyUsage?.digitalSignature) {\n\t\t\tkeyUsageBits[0] |= 0b00000001;\n\t\t}\n\t\tif (keyUsage?.nonRepudiation) {\n\t\t\tkeyUsageBits[0] |= 0b00000010;\n\t\t}\n\t\tif (keyUsage?.keyEncipherment) {\n\t\t\tkeyUsageBits[0] |= 0b00000100;\n\t\t}\n\t\tif (keyUsage?.dataEncipherment) {\n\t\t\tkeyUsageBits[0] |= 0b00001000;\n\t\t}\n\t\tif (keyUsage?.keyAgreement) {\n\t\t\tkeyUsageBits[0] |= 0b00010000;\n\t\t}\n\t\tif (keyUsage?.keyCertSign) {\n\t\t\tkeyUsageBits[0] |= 0b00100000;\n\t\t}\n\t\tif (keyUsage?.cRLSign) {\n\t\t\tkeyUsageBits[0] |= 0b01000000;\n\t\t}\n\t\tif (keyUsage?.encipherOnly) {\n\t\t\tkeyUsageBits[0] |= 0b10000000;\n\t\t}\n\t\tif (keyUsage?.decipherOnly) {\n\t\t\tkeyUsageBits[0] |= 0b01000000;\n\t\t}\n\t\treturn ASN1Encoder.sequence([\n\t\t\tASN1Encoder.objectIdentifier(oidByName('keyUsage')),\n\t\t\tASN1Encoder.boolean(true), // Critical\n\t\t\tASN1Encoder.octetString(ASN1Encoder.bitString(keyUsageBits)),\n\t\t]);\n\t}\n\n\tprivate static extKeyUsage(extKeyUsage: ExtKeyUsage = {}) {\n\t\treturn ASN1Encoder.sequence([\n\t\t\tASN1Encoder.objectIdentifier(oidByName('extKeyUsage')),\n\t\t\tASN1Encoder.boolean(true), // Critical\n\t\t\tASN1Encoder.octetString(\n\t\t\t\tASN1Encoder.sequence(\n\t\t\t\t\tObject.entries(extKeyUsage).map(([oidName, value]) => {\n\t\t\t\t\t\tif (value) {\n\t\t\t\t\t\t\treturn ASN1Encoder.objectIdentifier(\n\t\t\t\t\t\t\t\toidByName(oidName as OIDName)\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn ASN1Encoder.null();\n\t\t\t\t\t})\n\t\t\t\t)\n\t\t\t),\n\t\t]);\n\t}\n\n\tprivate static nsCertType(nsCertType: NSCertType) {\n\t\tconst bits = new Uint8Array([0x00]);\n\t\tif (nsCertType.client) {\n\t\t\tbits[0] |= 0x01;\n\t\t}\n\t\tif (nsCertType.server) {\n\t\t\tbits[0] |= 0x02;\n\t\t}\n\t\tif (nsCertType.email) {\n\t\t\tbits[0] |= 0x04;\n\t\t}\n\t\tif (nsCertType.objsign) {\n\t\t\tbits[0] |= 0x08;\n\t\t}\n\t\tif (nsCertType.sslCA) {\n\t\t\tbits[0] |= 0x10;\n\t\t}\n\t\tif (nsCertType.emailCA) {\n\t\t\tbits[0] |= 0x20;\n\t\t}\n\t\tif (nsCertType.objCA) {\n\t\t\tbits[0] |= 0x40;\n\t\t}\n\t\treturn ASN1Encoder.sequence([\n\t\t\tASN1Encoder.objectIdentifier(oidByName('nsCertType')),\n\t\t\tASN1Encoder.octetString(bits),\n\t\t]);\n\t}\n\n\tprivate static subjectAltName(altNames: SubjectAltNames) {\n\t\tconst generalNames =\n\t\t\taltNames.dnsNames?.map((name) => {\n\t\t\t\tconst dnsName = ASN1Encoder.ia5String(name);\n\t\t\t\treturn ASN1Encoder.contextSpecific(2, dnsName);\n\t\t\t}) || [];\n\t\tconst ipAddresses =\n\t\t\taltNames.ipAddresses?.map((ip) => {\n\t\t\t\tconst ipAddress = ASN1Encoder.ia5String(ip);\n\t\t\t\treturn ASN1Encoder.contextSpecific(7, ipAddress);\n\t\t\t}) || [];\n\t\tconst sanExtensionValue = ASN1Encoder.octetString(\n\t\t\tASN1Encoder.sequence([...generalNames, ...ipAddresses])\n\t\t);\n\t\treturn ASN1Encoder.sequence([\n\t\t\tASN1Encoder.objectIdentifier(oidByName('subjectAltName')),\n\t\t\tASN1Encoder.boolean(true),\n\t\t\tsanExtensionValue,\n\t\t]);\n\t}\n}\n\n/**\n * OIDs used in X.509 certificates.\n *\n * Source: https://oidref.com/\n */\nconst oids = {\n\t// Algorithm OIDs\n\t'1.2.840.113549.1.1.1': 'rsaEncryption',\n\t'1.2.840.113549.1.1.4': 'md5WithRSAEncryption',\n\t'1.2.840.113549.1.1.5': 'sha1WithRSAEncryption',\n\t'1.2.840.113549.1.1.7': 'RSAES-OAEP',\n\t'1.2.840.113549.1.1.8': 'mgf1',\n\t'1.2.840.113549.1.1.9': 'pSpecified',\n\t'1.2.840.113549.1.1.10': 'RSASSA-PSS',\n\t'1.2.840.113549.1.1.11': 'sha256WithRSAEncryption',\n\t'1.2.840.113549.1.1.12': 'sha384WithRSAEncryption',\n\t'1.2.840.113549.1.1.13': 'sha512WithRSAEncryption',\n\t'1.3.101.112': 'EdDSA25519',\n\t'1.2.840.10040.4.3': 'dsa-with-sha1',\n\t'1.3.14.3.2.7': 'desCBC',\n\t'1.3.14.3.2.26': 'sha1',\n\t'1.3.14.3.2.29': 'sha1WithRSASignature',\n\t'2.16.840.1.101.3.4.2.1': 'sha256',\n\t'2.16.840.1.101.3.4.2.2': 'sha384',\n\t'2.16.840.1.101.3.4.2.3': 'sha512',\n\t'2.16.840.1.101.3.4.2.4': 'sha224',\n\t'2.16.840.1.101.3.4.2.5': 'sha512-224',\n\t'2.16.840.1.101.3.4.2.6': 'sha512-256',\n\t'1.2.840.113549.2.2': 'md2',\n\t'1.2.840.113549.2.5': 'md5',\n\n\t// pkcs#7 content types\n\t'1.2.840.113549.1.7.1': 'data',\n\t'1.2.840.113549.1.7.2': 'signedData',\n\t'1.2.840.113549.1.7.3': 'envelopedData',\n\t'1.2.840.113549.1.7.4': 'signedAndEnvelopedData',\n\t'1.2.840.113549.1.7.5': 'digestedData',\n\t'1.2.840.113549.1.7.6': 'encryptedData',\n\n\t// pkcs#9 oids\n\t'1.2.840.113549.1.9.1': 'emailAddress',\n\t'1.2.840.113549.1.9.2': 'unstructuredName',\n\t'1.2.840.113549.1.9.3': 'contentType',\n\t'1.2.840.113549.1.9.4': 'messageDigest',\n\t'1.2.840.113549.1.9.5': 'signingTime',\n\t'1.2.840.113549.1.9.6': 'counterSignature',\n\t'1.2.840.113549.1.9.7': 'challengePassword',\n\t'1.2.840.113549.1.9.8': 'unstructuredAddress',\n\t'1.2.840.113549.1.9.14': 'extensionRequest',\n\t'1.2.840.113549.1.9.20': 'friendlyName',\n\t'1.2.840.113549.1.9.21': 'localKeyId',\n\t'1.2.840.113549.1.9.22.1': 'x509Certificate',\n\n\t// pkcs#12 safe bags\n\t'1.2.840.113549.1.12.10.1.1': 'keyBag',\n\t'1.2.840.113549.1.12.10.1.2': 'pkcs8ShroudedKeyBag',\n\t'1.2.840.113549.1.12.10.1.3': 'certBag',\n\t'1.2.840.113549.1.12.10.1.4': 'crlBag',\n\t'1.2.840.113549.1.12.10.1.5': 'secretBag',\n\t'1.2.840.113549.1.12.10.1.6': 'safeContentsBag',\n\n\t// password-based-encryption for pkcs#12\n\t'1.2.840.113549.1.5.13': 'pkcs5PBES2',\n\t'1.2.840.113549.1.5.12': 'pkcs5PBKDF2',\n\t'1.2.840.113549.1.12.1.1': 'pbeWithSHAAnd128BitRC4',\n\t'1.2.840.113549.1.12.1.2': 'pbeWithSHAAnd40BitRC4',\n\t'1.2.840.113549.1.12.1.3': 'pbeWithSHAAnd3-KeyTripleDES-CBC',\n\t'1.2.840.113549.1.12.1.4': 'pbeWithSHAAnd2-KeyTripleDES-CBC',\n\t'1.2.840.113549.1.12.1.5': 'pbeWithSHAAnd128BitRC2-CBC',\n\t'1.2.840.113549.1.12.1.6': 'pbewithSHAAnd40BitRC2-CBC',\n\n\t// hmac OIDs\n\t'1.2.840.113549.2.7': 'hmacWithSHA1',\n\t'1.2.840.113549.2.8': 'hmacWithSHA224',\n\t'1.2.840.113549.2.9': 'hmacWithSHA256',\n\t'1.2.840.113549.2.10': 'hmacWithSHA384',\n\t'1.2.840.113549.2.11': 'hmacWithSHA512',\n\n\t// symmetric key algorithm oids\n\t'1.2.840.113549.3.7': 'des-EDE3-CBC',\n\t'2.16.840.1.101.3.4.1.2': 'aes128-CBC',\n\t'2.16.840.1.101.3.4.1.22': 'aes192-CBC',\n\t'2.16.840.1.101.3.4.1.42': 'aes256-CBC',\n\n\t// certificate issuer/subject OIDs\n\t'2.5.4.3': 'commonName',\n\t'2.5.4.4': 'surname',\n\t'2.5.4.5': 'serialNumber',\n\t'2.5.4.6': 'countryName',\n\t'2.5.4.7': 'localityName',\n\t'2.5.4.8': 'stateOrProvinceName',\n\t'2.5.4.9': 'streetAddress',\n\t'2.5.4.10': 'organizationName',\n\t'2.5.4.11': 'organizationalUnitName',\n\t'2.5.4.12': 'title',\n\t'2.5.4.13': 'description',\n\t'2.5.4.15': 'businessCategory',\n\t'2.5.4.17': 'postalCode',\n\t'2.5.4.42': 'givenName',\n\t'1.3.6.1.4.1.311.60.2.1.2':\n\t\t'jurisdictionOfIncorporationStateOrProvinceName',\n\t'1.3.6.1.4.1.311.60.2.1.3': 'jurisdictionOfIncorporationCountryName',\n\n\t// X.509 extension OIDs\n\t'2.16.840.1.113730.1.1': 'nsCertType',\n\t'2.16.840.1.113730.1.13': 'nsComment',\n\t'2.5.29.14': 'subjectKeyIdentifier',\n\t'2.5.29.15': 'keyUsage',\n\t'2.5.29.17': 'subjectAltName',\n\t'2.5.29.18': 'issuerAltName',\n\t'2.5.29.19': 'basicConstraints',\n\t'2.5.29.31': 'cRLDistributionPoints',\n\t'2.5.29.32': 'certificatePolicies',\n\t'2.5.29.35': 'authorityKeyIdentifier',\n\t'2.5.29.37': 'extKeyUsage',\n\n\t// extKeyUsage purposes\n\t'1.3.6.1.4.1.11129.2.4.2': 'timestampList',\n\t'1.3.6.1.5.5.7.1.1': 'authorityInfoAccess',\n\t'1.3.6.1.5.5.7.3.1': 'serverAuth',\n\t'1.3.6.1.5.5.7.3.2': 'clientAuth',\n\t'1.3.6.1.5.5.7.3.3': 'codeSigning',\n\t'1.3.6.1.5.5.7.3.4': 'emailProtection',\n\t'1.3.6.1.5.5.7.3.8': 'timeStamping',\n} as const;\n\nfunction oidByName(requestedName: OIDName): OID {\n\tfor (const [oid, name] of Object.entries(oids)) {\n\t\tif (name === requestedName) {\n\t\t\treturn oid as OID;\n\t\t}\n\t}\n\tthrow new Error(`OID not found for name: ${requestedName}`);\n}\n\nconst constructedBit = 0b00100000;\nconst ASN1Tags = {\n\tEOC: 0,\n\tBoolean: 1,\n\tInteger: 2,\n\tBitString: 3,\n\tOctetString: 4,\n\tNull: 5,\n\tOID: 6,\n\tObjectDescriptor: 7,\n\tExternal: 8,\n\tReal: 9, // float\n\tEnumeration: 10,\n\tPDV: 11,\n\tUtf8String: 12,\n\tRelativeOID: 13,\n\tSequence: 16 | constructedBit,\n\tSet: 17 | constructedBit,\n\tNumericString: 18,\n\tPrintableString: 19,\n\tT61String: 20,\n\tVideotexString: 21,\n\tIA5String: 22,\n\tUTCTime: 23,\n\tGeneralizedTime: 24,\n\tGraphicString: 25,\n\tVisibleString: 26,\n\tGeneralString: 28,\n\tUniversalString: 29,\n\tCharacterString: 30,\n\tBMPString: 31,\n\tConstructor: 32,\n\tContext: 128,\n};\n\nclass ASN1Encoder {\n\t// Helper functions for ASN.1 DER encoding\n\tstatic length_(length: number): Uint8Array {\n\t\tif (length < 0x80) {\n\t\t\t// Short form: single byte length\n\t\t\treturn new Uint8Array([length]);\n\t\t} else {\n\t\t\t// Long form: first byte is 0x80 + number of length bytes\n\t\t\t// Subsequent bytes are the length, big-endian\n\t\t\tlet tempLength = length;\n\t\t\tconst lengthBytesArray: number[] = [];\n\t\t\twhile (tempLength > 0) {\n\t\t\t\tlengthBytesArray.unshift(tempLength & 0xff);\n\t\t\t\ttempLength >>= 8;\n\t\t\t}\n\t\t\tconst numLengthBytes = lengthBytesArray.length;\n\t\t\tconst result = new Uint8Array(1 + numLengthBytes);\n\t\t\tresult[0] = 0x80 | numLengthBytes;\n\t\t\tfor (let i = 0; i < numLengthBytes; i++) {\n\t\t\t\tresult[i + 1] = lengthBytesArray[i];\n\t\t\t}\n\t\t\treturn result;\n\t\t}\n\t}\n\n\tstatic ASN1(tag: number, data: Uint8Array): Uint8Array {\n\t\tconst lengthBytes = ASN1Encoder.length_(data.length);\n\t\tconst result = new Uint8Array(1 + lengthBytes.length + data.length);\n\t\tresult[0] = tag;\n\t\tresult.set(lengthBytes, 1);\n\t\tresult.set(data, 1 + lengthBytes.length);\n\t\treturn result;\n\t}\n\n\tstatic integer(number: Uint8Array): Uint8Array {\n\t\t// Ensure number is positive and first bit is 0\n\t\tif (number[0] > 0x7f) {\n\t\t\tconst extendedNumber = new Uint8Array(number.length + 1);\n\t\t\textendedNumber[0] = 0x00;\n\t\t\textendedNumber.set(number, 1);\n\t\t\tnumber = extendedNumber;\n\t\t}\n\t\treturn ASN1Encoder.ASN1(ASN1Tags.Integer, number);\n\t}\n\n\tstatic bitString(data: Uint8Array): Uint8Array {\n\t\tconst unusedBits = new Uint8Array([0x00]);\n\t\tconst combined = new Uint8Array(unusedBits.length + data.length);\n\t\tcombined.set(unusedBits);\n\t\tcombined.set(data, unusedBits.length);\n\t\treturn ASN1Encoder.ASN1(ASN1Tags.BitString, combined);\n\t}\n\n\tstatic octetString(data: Uint8Array): Uint8Array {\n\t\treturn ASN1Encoder.ASN1(ASN1Tags.OctetString, data);\n\t}\n\n\tstatic null(): Uint8Array {\n\t\treturn ASN1Encoder.ASN1(ASN1Tags.Null, new Uint8Array(0));\n\t}\n\n\tstatic objectIdentifier(oid: string): Uint8Array {\n\t\tconst oidParts = oid.split('.').map(Number);\n\t\tconst firstByte = oidParts[0] * 40 + oidParts[1];\n\t\tconst encodedParts = [firstByte];\n\t\tfor (let i = 2; i < oidParts.length; i++) {\n\t\t\tlet value = oidParts[i];\n\t\t\tconst bytes: number[] = [];\n\t\t\tdo {\n\t\t\t\tbytes.unshift(value & 0x7f);\n\t\t\t\tvalue >>= 7;\n\t\t\t} while (value > 0);\n\t\t\tfor (let j = 0; j < bytes.length - 1; j++) {\n\t\t\t\tbytes[j] |= 0x80;\n\t\t\t}\n\t\t\tencodedParts.push(...bytes);\n\t\t}\n\t\treturn ASN1Encoder.ASN1(ASN1Tags.OID, new Uint8Array(encodedParts));\n\t}\n\n\tstatic utf8String(str: string): Uint8Array {\n\t\tconst utf8Bytes = new TextEncoder().encode(str);\n\t\treturn ASN1Encoder.ASN1(ASN1Tags.Utf8String, utf8Bytes);\n\t}\n\n\tstatic printableString(str: string): Uint8Array {\n\t\tconst utf8Bytes = new TextEncoder().encode(str);\n\t\treturn ASN1Encoder.ASN1(ASN1Tags.PrintableString, utf8Bytes);\n\t}\n\n\tstatic sequence(items: Uint8Array[]): Uint8Array {\n\t\treturn ASN1Encoder.ASN1(ASN1Tags.Sequence, concatUint8Arrays(items));\n\t}\n\n\tstatic set(items: Uint8Array[]): Uint8Array {\n\t\treturn ASN1Encoder.ASN1(ASN1Tags.Set, concatUint8Arrays(items));\n\t}\n\n\tstatic ia5String(str: string): Uint8Array {\n\t\tconst utf8Bytes = new TextEncoder().encode(str);\n\t\treturn ASN1Encoder.ASN1(ASN1Tags.IA5String, utf8Bytes);\n\t}\n\n\tstatic contextSpecific(\n\t\ttagNumber: number,\n\t\tdata: Uint8Array,\n\t\tconstructed = false\n\t): Uint8Array {\n\t\tconst tag = (constructed ? 0xa0 : 0x80) | tagNumber;\n\t\treturn ASN1Encoder.ASN1(tag, data);\n\t}\n\n\tstatic boolean(value: boolean): Uint8Array {\n\t\treturn ASN1Encoder.ASN1(\n\t\t\tASN1Tags.Boolean,\n\t\t\tnew Uint8Array([value ? 0xff : 0x00])\n\t\t);\n\t}\n}\n\nexport interface DistinguishedName {\n\tcountryName?: string;\n\torganizationName?: string;\n\tcommonName?: string;\n\tlocalityName?: string;\n\tstateOrProvinceName?: string;\n\tstreetAddress?: string;\n\tpostalCode?: string;\n\temailAddress?: string;\n\torganizationalUnitName?: string;\n\ttitle?: string;\n\tdescription?: string;\n\tbusinessCategory?: string;\n}\n\nexport type Validity = {\n\tnotBefore: Date;\n\tnotAfter: Date;\n};\n\nexport type OID = keyof typeof oids;\nexport type OIDName = (typeof oids)[OID];\n\nexport interface BasicConstraints {\n\tca: boolean;\n\tpathLenConstraint?: number;\n}\n\nexport interface KeyUsage {\n\tdigitalSignature?: boolean;\n\tnonRepudiation?: boolean;\n\tkeyEncipherment?: boolean;\n\tdataEncipherment?: boolean;\n\tkeyAgreement?: boolean;\n\tkeyCertSign?: boolean;\n\tcRLSign?: boolean;\n\tencipherOnly?: boolean;\n\tdecipherOnly?: boolean;\n}\n\nexport interface ExtKeyUsage {\n\tserverAuth?: boolean;\n\tclientAuth?: boolean;\n\tcodeSigning?: boolean;\n\temailProtection?: boolean;\n\ttimeStamping?: boolean;\n}\n\nexport interface NSCertType {\n\tclient?: boolean;\n\tserver?: boolean;\n\temail?: boolean;\n\tobjsign?: boolean;\n\tsslCA?: boolean;\n\temailCA?: boolean;\n\tobjCA?: boolean;\n}\n\nexport interface SubjectAltNames {\n\tdnsNames?: string[];\n\tipAddresses?: string[];\n}\n\nexport interface TBSCertificateDescription {\n\tversion?: number;\n\tserialNumber?: Uint8Array;\n\tsignatureAlgorithm?: OIDName;\n\tissuer?: DistinguishedName;\n\tvalidity?: Validity;\n\tsubject: DistinguishedName;\n\tbasicConstraints?: BasicConstraints;\n\tkeyUsage?: KeyUsage;\n\textKeyUsage?: ExtKeyUsage;\n\tsubjectAltNames?: SubjectAltNames;\n\tnsCertType?: NSCertType;\n}\nexport type TBSCertificate = Uint8Array;\n\nexport type GeneratedCertificate = {\n\tkeyPair: CryptoKeyPair;\n\tcertificate: Uint8Array;\n\ttbsDescription: TBSCertificateDescription;\n\ttbsCertificate: TBSCertificate;\n};\n\n// Helper functions\nfunction encodeUint8ArrayAsBase64(bytes: ArrayBuffer) {\n\treturn btoa(String.fromCodePoint(...new Uint8Array(bytes)));\n}\n\nfunction formatPEM(pemString: string): string {\n\treturn pemString.match(/.{1,64}/g)?.join('\\n') || pemString;\n}\n\nfunction formatDateASN1(date: Date): string {\n\t// Format date to YYMMDDHHMMSSZ for UTCTime\n\tconst year = date.getUTCFullYear().toString().substr(2);\n\tconst month = padNumber(date.getUTCMonth() + 1);\n\tconst day = padNumber(date.getUTCDate());\n\tconst hours = padNumber(date.getUTCHours());\n\tconst minutes = padNumber(date.getUTCMinutes());\n\tconst seconds = padNumber(date.getUTCSeconds());\n\treturn `${year}${month}${day}${hours}${minutes}${seconds}Z`;\n}\n\nfunction padNumber(num: number): string {\n\treturn num.toString().padStart(2, '0');\n}\n\nfunction addYears(date: Date, years: number): Date {\n\tconst newDate = new Date(date);\n\tnewDate.setUTCFullYear(newDate.getUTCFullYear() + years);\n\treturn newDate;\n}\n","/**\n * Error thrown when a CORS proxy response appears to have been\n * intercepted by a network firewall or corporate proxy.\n *\n * This is detected when a response from the CORS proxy is missing\n * the X-Playground-Cors-Proxy header that legitimate responses include.\n */\nexport class FirewallInterferenceError extends Error {\n\tpublic readonly url: string;\n\tpublic readonly status: number;\n\tpublic readonly statusText: string;\n\n\tconstructor(url: string, status: number, statusText: string) {\n\t\tsuper(\n\t\t\t`Could not fetch ${url} – your network appears to be blocking this request (HTTP ${status}). ` +\n\t\t\t\t`This often happens on school, university, or corporate networks. ` +\n\t\t\t\t`Try switching to a different network or using a VPN.`\n\t\t);\n\t\tthis.name = 'FirewallInterferenceError';\n\t\tthis.url = url;\n\t\tthis.status = status;\n\t\tthis.statusText = statusText;\n\t}\n}\n","import { cloneRequest, teeRequest } from '@php-wasm/web-service-worker';\nimport { FirewallInterferenceError } from './firewall-interference-error';\n\nconst CORS_PROXY_HEADER = 'X-Playground-Cors-Proxy';\n\nexport async function fetchWithCorsProxy(\n\tinput: RequestInfo,\n\tinit?: RequestInit,\n\tcorsProxyUrl?: string,\n\tplaygroundUrl?: string\n): Promise<Response> {\n\tlet requestObject =\n\t\ttypeof input === 'string' ? new Request(input, init) : input;\n\tconst playgroundUrlObj = playgroundUrl ? new URL(playgroundUrl) : null;\n\tlet requestUrlObj = playgroundUrlObj\n\t\t? new URL(requestObject.url, playgroundUrlObj)\n\t\t: new URL(requestObject.url);\n\tif (requestUrlObj.protocol === 'http:') {\n\t\trequestUrlObj.protocol = 'https:';\n\t\tconst httpsUrl = requestUrlObj.toString();\n\t\trequestObject = await cloneRequest(requestObject, { url: httpsUrl });\n\t\trequestUrlObj = new URL(httpsUrl);\n\t}\n\tif (!corsProxyUrl) {\n\t\treturn await fetch(requestObject);\n\t}\n\n\t/**\n\t * Never try to proxy requests to the playground itself. The remote proxy\n\t * won't be able to reach it. At best, it will produce a cryptic error\n\t * message. At worst, it will time out, making the user wait for 30 seconds.\n\t */\n\tif (\n\t\tplaygroundUrlObj &&\n\t\trequestUrlObj.protocol === playgroundUrlObj.protocol &&\n\t\trequestUrlObj.hostname === playgroundUrlObj.hostname &&\n\t\trequestUrlObj.port === playgroundUrlObj.port &&\n\t\trequestUrlObj.pathname.startsWith(playgroundUrlObj.pathname)\n\t) {\n\t\treturn await fetch(requestObject);\n\t}\n\n\t// Tee the request to avoid consuming the request body stream on the initial\n\t// fetch() so that we can retry through the cors proxy.\n\tconst [request1, request2] = await teeRequest(requestObject);\n\n\ttry {\n\t\treturn await fetch(request1);\n\t} catch {\n\t\t// If the developer has explicitly allowed the request to pass the\n\t\t// credentials headers with the X-Cors-Proxy-Allowed-Request-Headers header,\n\t\t// then let's include those credentials in the fetch() request.\n\t\tconst headers = new Headers(request2.headers);\n\t\tconst corsProxyAllowedHeaders =\n\t\t\theaders.get('x-cors-proxy-allowed-request-headers')?.split(',') ||\n\t\t\t[];\n\t\tconst requestIntendsToPassCredentials =\n\t\t\tcorsProxyAllowedHeaders.includes('authorization') ||\n\t\t\tcorsProxyAllowedHeaders.includes('cookie');\n\n\t\tconst newRequest = await cloneRequest(request2, {\n\t\t\turl: `${corsProxyUrl}${requestObject.url}`,\n\t\t\t...(requestIntendsToPassCredentials && { credentials: 'include' }),\n\t\t});\n\n\t\tconst response = await fetch(newRequest, init);\n\n\t\t// Check for firewall interference: if we got a response but it's\n\t\t// missing the CORS proxy identification header, the response likely\n\t\t// came from a network firewall rather than the actual CORS proxy.\n\t\tif (!response.headers.has(CORS_PROXY_HEADER)) {\n\t\t\tthrow new FirewallInterferenceError(\n\t\t\t\trequestObject.url,\n\t\t\t\tresponse.status,\n\t\t\t\tresponse.statusText\n\t\t\t);\n\t\t}\n\n\t\treturn response;\n\t}\n}\n","import { concatUint8Arrays } from '@php-wasm/util';\n\n/**\n * A TransformStream that decodes HTTP chunked transfer encoding.\n * Each chunk starts with the chunk size in hex followed by CRLF,\n * then the chunk data, then CRLF. A chunk size of 0 indicates the end.\n */\nexport class ChunkedDecoderStream extends TransformStream<\n\tUint8Array,\n\tUint8Array\n> {\n\tconstructor() {\n\t\tlet buffer = new Uint8Array(0);\n\t\tlet state:\n\t\t\t| 'SCAN_CHUNK_SIZE'\n\t\t\t| 'SCAN_CHUNK_DATA'\n\t\t\t| 'SCAN_CHUNK_TRAILER'\n\t\t\t| 'SCAN_FINAL_CHUNK' = 'SCAN_CHUNK_SIZE';\n\t\tlet chunkRemainingBytes = 0;\n\n\t\tsuper({\n\t\t\ttransform(chunk, controller) {\n\t\t\t\t// Add new chunk to buffer\n\t\t\t\tbuffer = concatUint8Arrays([buffer, chunk]);\n\n\t\t\t\twhile (buffer.length > 0) {\n\t\t\t\t\tif (state === 'SCAN_CHUNK_SIZE') {\n\t\t\t\t\t\t// Need at least \"0\\r\\n\" (3 bytes)\n\t\t\t\t\t\tif (buffer.length < 3) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Find the chunk size hex digits\n\t\t\t\t\t\tlet chunkBytesNb = 0;\n\t\t\t\t\t\twhile (chunkBytesNb < buffer.length) {\n\t\t\t\t\t\t\tconst byte = buffer[chunkBytesNb];\n\t\t\t\t\t\t\tconst isHexDigit =\n\t\t\t\t\t\t\t\t(byte >= 48 && byte <= 57) || // 0-9\n\t\t\t\t\t\t\t\t(byte >= 97 && byte <= 102) || // a-f\n\t\t\t\t\t\t\t\t(byte >= 65 && byte <= 70); // A-F\n\t\t\t\t\t\t\tif (!isHexDigit) break;\n\t\t\t\t\t\t\tchunkBytesNb++;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (chunkBytesNb === 0) {\n\t\t\t\t\t\t\tthrow new Error('Invalid chunk size format');\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Look for CRLF after chunk size\n\t\t\t\t\t\tif (buffer.length < chunkBytesNb + 2) {\n\t\t\t\t\t\t\t// Not enough data, let's wait for more\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tbuffer[chunkBytesNb] !== 13 || // \\r\n\t\t\t\t\t\t\tbuffer[chunkBytesNb + 1] !== 10 // \\n\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\t'Invalid chunk size format. Expected CRLF after chunk size'\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Parse the chunk size\n\t\t\t\t\t\tconst chunkSizeHex = new TextDecoder().decode(\n\t\t\t\t\t\t\tbuffer.slice(0, chunkBytesNb)\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconst chunkSize = parseInt(chunkSizeHex, 16);\n\n\t\t\t\t\t\t// Remove chunk header from buffer\n\t\t\t\t\t\tbuffer = buffer.slice(chunkBytesNb + 2);\n\n\t\t\t\t\t\tif (chunkSize === 0) {\n\t\t\t\t\t\t\tstate = 'SCAN_FINAL_CHUNK';\n\t\t\t\t\t\t\tcontroller.terminate();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tchunkRemainingBytes = chunkSize;\n\t\t\t\t\t\tstate = 'SCAN_CHUNK_DATA';\n\t\t\t\t\t} else if (state === 'SCAN_CHUNK_DATA') {\n\t\t\t\t\t\tconst bytesToRead = Math.min(\n\t\t\t\t\t\t\tchunkRemainingBytes,\n\t\t\t\t\t\t\tbuffer.length\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconst data = buffer.slice(0, bytesToRead);\n\t\t\t\t\t\tbuffer = buffer.slice(bytesToRead);\n\t\t\t\t\t\tchunkRemainingBytes -= bytesToRead;\n\n\t\t\t\t\t\tcontroller.enqueue(data);\n\n\t\t\t\t\t\tif (chunkRemainingBytes === 0) {\n\t\t\t\t\t\t\tstate = 'SCAN_CHUNK_TRAILER';\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (state === 'SCAN_CHUNK_TRAILER') {\n\t\t\t\t\t\tif (buffer.length < 2) {\n\t\t\t\t\t\t\t// Not enough data, let's wait for more\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (buffer[0] !== 13 || buffer[1] !== 10) {\n\t\t\t\t\t\t\t// \\r\\n\n\t\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\t'Invalid chunk trailer format. Expected CRLF after chunk data'\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbuffer = buffer.slice(2);\n\t\t\t\t\t\tstate = 'SCAN_CHUNK_SIZE';\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\t}\n}\n","/**\n * This is the secret sauce that enables HTTPS requests from PHP\n * via file_get_contents(), curl, and all other networking mechanisms.\n *\n * This is effectively a MITM attack on the PHP instance. The code\n * in this module decrypts the outbound traffic, runs the request\n * using fetch(), and then provides an encrypted response. From\n * PHP's perspective, it is indistinguishable from a direct connection\n * to the right server.\n *\n * ## How does it work?\n *\n * Emscripten can be configured to stream all network traffic through a\n * WebSocket. `@php-wasm/node` and `wp-now` use that to access the internet\n * via a local WebSocket->TCP proxy, but the in-browser version of WordPress\n * Playground exposes no such proxy.\n *\n * This module implements a \"fake\" WebSocket class. Instead of starting a `ws://`\n * connection, it translates the raw HTTP/HTTPS bytes into a `fetch()` call.\n *\n * In case of HTTP, the raw request bytes are parsed into a Request object with\n * a body stream and passes it to `fetch()`. Then, as the response status, headers,\n * and the body arrive, they're stream-encoded as raw response bytes and exposed as\n * incoming WebSocket data.\n *\n * In case of HTTPS, we the raw bytes are first piped through a custom TCPConnection\n * class as follows:\n *\n * 1. We generate a self-signed CA certificate and tell PHP to trust it using the\n * `openssl.cafile` PHP.ini option\n * 2. We create a domain-specific child certificate and sign it with the CA private key.\n * 3. We start accepting raw encrypted bytes, process them as structured TLS records,\n * and perform the TLS handshake.\n * 4. Encrypted tunnel is established\n * * TLSConnection decrypts the encrypted outbound data sent by PHP\n * * TLSConnection encrypts the unencrypted inbound data fed back to PHP\n *\n * From there, the plaintext data is treated by the same HTTP<->fetch() machinery as\n * described in the previous paragraph.\n */\nimport { TLS_1_2_Connection } from './tls/1_2/connection';\nimport type { GeneratedCertificate } from './tls/certificates';\nimport { generateCertificate } from './tls/certificates';\nimport { ContentTypes } from './tls/1_2/types';\nimport { fetchWithCorsProxy } from './fetch-with-cors-proxy';\nimport { ChunkedDecoderStream } from './chunked-decoder';\nimport type { EmscriptenOptions } from '@php-wasm/universal';\nimport { concatUint8Arrays } from '@php-wasm/util';\n\nexport type TCPOverFetchOptions = {\n\tCAroot: GeneratedCertificate;\n\tcorsProxyUrl?: string;\n};\n\n/**\n * Sets up a WebSocket that analyzes the received bytes and, if they look like\n * TLS or HTTP, handles the network transmission using fetch().\n */\nexport const tcpOverFetchWebsocket = (\n\temOptions: EmscriptenOptions,\n\ttcpOptions: TCPOverFetchOptions\n) => {\n\treturn {\n\t\t...emOptions,\n\t\twebsocket: {\n\t\t\turl: (_: any, host: string, port: string) => {\n\t\t\t\tconst query = new URLSearchParams({\n\t\t\t\t\thost,\n\t\t\t\t\tport,\n\t\t\t\t}).toString();\n\t\t\t\treturn `ws://playground.internal/?${query}`;\n\t\t\t},\n\t\t\tsubprotocol: 'binary',\n\t\t\tdecorator: () => {\n\t\t\t\treturn class extends TCPOverFetchWebsocket {\n\t\t\t\t\tconstructor(url: string, wsOptions: string[]) {\n\t\t\t\t\t\tsuper(url, wsOptions, {\n\t\t\t\t\t\t\tCAroot: tcpOptions.CAroot,\n\t\t\t\t\t\t\tcorsProxyUrl: tcpOptions.corsProxyUrl,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t},\n\t\t},\n\t};\n};\n\nexport interface TCPOverFetchWebsocketOptions {\n\tCAroot?: GeneratedCertificate;\n\t/**\n\t * If true, the WebSocket will emit 'message' events with the received bytes\n\t * and the 'close' event when the WebSocket is closed.\n\t *\n\t * If false, the consumer will be responsible for reading the bytes from the\n\t * clientDownstream stream and tracking the closure of that stream.\n\t */\n\toutputType?: 'messages' | 'stream';\n\tcorsProxyUrl?: string;\n}\n\nexport class TCPOverFetchWebsocket {\n\tCONNECTING = 0;\n\tOPEN = 1;\n\tCLOSING = 2;\n\tCLOSED = 3;\n\treadyState = this.CONNECTING;\n\tbinaryType = 'blob';\n\tbufferedAmount = 0;\n\textensions = '';\n\tprotocol = 'ws';\n\thost = '';\n\tport = 0;\n\tlisteners = new Map<string, any>();\n\tCAroot?: GeneratedCertificate;\n\tcorsProxyUrl?: string;\n\n\tclientUpstream = new TransformStream();\n\tclientUpstreamWriter = this.clientUpstream.writable.getWriter();\n\tclientDownstream = new TransformStream();\n\tfetchInitiated = false;\n\tbufferedBytesFromClient: Uint8Array = new Uint8Array(0);\n\n\turl: string;\n\toptions: string[];\n\n\tconstructor(\n\t\turl: string,\n\t\toptions: string[],\n\t\t{\n\t\t\tCAroot,\n\t\t\tcorsProxyUrl,\n\t\t\toutputType = 'messages',\n\t\t}: TCPOverFetchWebsocketOptions = {}\n\t) {\n\t\tthis.url = url;\n\t\tthis.options = options;\n\n\t\tconst wsUrl = new URL(url);\n\t\tthis.host = wsUrl.searchParams.get('host')!;\n\t\tthis.port = parseInt(wsUrl.searchParams.get('port')!, 10);\n\t\tthis.binaryType = 'arraybuffer';\n\n\t\tthis.corsProxyUrl = corsProxyUrl;\n\t\tthis.CAroot = CAroot;\n\t\tif (outputType === 'messages') {\n\t\t\tthis.clientDownstream.readable\n\t\t\t\t.pipeTo(\n\t\t\t\t\tnew WritableStream({\n\t\t\t\t\t\twrite: (chunk) => {\n\t\t\t\t\t\t\t/**\n\t\t\t\t\t\t\t * Emscripten expects the message event to be emitted\n\t\t\t\t\t\t\t * so let's emit it.\n\t\t\t\t\t\t\t */\n\t\t\t\t\t\t\tthis.emit('message', { data: chunk });\n\t\t\t\t\t\t},\n\t\t\t\t\t\tabort: () => {\n\t\t\t\t\t\t\t// We don't know what went wrong and the browser\n\t\t\t\t\t\t\t// won't tell us much either, so let's just pretend\n\t\t\t\t\t\t\t// the server is unreachable.\n\t\t\t\t\t\t\tthis.emit('error', new Error('ECONNREFUSED'));\n\t\t\t\t\t\t\tthis.close();\n\t\t\t\t\t\t},\n\t\t\t\t\t\tclose: () => {\n\t\t\t\t\t\t\tthis.close();\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t)\n\t\t\t\t.catch(() => {\n\t\t\t\t\t// Ignore failures arising from stream errors.\n\t\t\t\t\t// This class communicates problems to the caller\n\t\t\t\t\t// via the 'error' event.\n\t\t\t\t});\n\t\t}\n\t\tthis.readyState = this.OPEN;\n\t\tthis.emit('open');\n\t}\n\n\ton(eventName: string, callback: (e: any) => void) {\n\t\tthis.addEventListener(eventName, callback);\n\t}\n\n\tonce(eventName: string, callback: (e: any) => void) {\n\t\tconst wrapper = (e: any) => {\n\t\t\tcallback(e);\n\t\t\tthis.removeEventListener(eventName, wrapper);\n\t\t};\n\t\tthis.addEventListener(eventName, wrapper);\n\t}\n\n\taddEventListener(eventName: string, callback: (e: any) => void) {\n\t\tif (!this.listeners.has(eventName)) {\n\t\t\tthis.listeners.set(eventName, new Set());\n\t\t}\n\t\tthis.listeners.get(eventName).add(callback);\n\t}\n\n\tremoveListener(eventName: string, callback: (e: any) => void) {\n\t\tthis.removeEventListener(eventName, callback);\n\t}\n\n\tremoveEventListener(eventName: string, callback: (e: any) => void) {\n\t\tconst listeners = this.listeners.get(eventName);\n\t\tif (listeners) {\n\t\t\tlisteners.delete(callback);\n\t\t}\n\t}\n\n\temit(eventName: string, data: any = {}) {\n\t\tif (eventName === 'message') {\n\t\t\tthis.onmessage(data);\n\t\t} else if (eventName === 'close') {\n\t\t\tthis.onclose(data);\n\t\t} else if (eventName === 'error') {\n\t\t\tthis.onerror(data);\n\t\t} else if (eventName === 'open') {\n\t\t\tthis.onopen(data);\n\t\t}\n\t\tconst listeners = this.listeners.get(eventName);\n\t\tif (listeners) {\n\t\t\tfor (const listener of listeners) {\n\t\t\t\tlistener(data);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Default event handlers that can be overridden by the user\n\t// eslint-disable-next-line @typescript-eslint/no-unused-vars\n\tonclose(data: any) {}\n\t// eslint-disable-next-line @typescript-eslint/no-unused-vars\n\tonerror(data: any) {}\n\t// eslint-disable-next-line @typescript-eslint/no-unused-vars\n\tonmessage(data: any) {}\n\t// eslint-disable-next-line @typescript-eslint/no-unused-vars\n\tonopen(data: any) {}\n\n\t/**\n\t * Emscripten calls this method whenever the WASM module\n\t * writes bytes to the TCP socket.\n\t */\n\tsend(data: ArrayBuffer) {\n\t\tif (\n\t\t\tthis.readyState === this.CLOSING ||\n\t\t\tthis.readyState === this.CLOSED\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.clientUpstreamWriter.write(new Uint8Array(data));\n\n\t\tif (this.fetchInitiated) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Guess the protocol type first so we can learn\n\t\t// what to do with the incoming bytes.\n\t\tthis.bufferedBytesFromClient = concatUint8Arrays([\n\t\t\tthis.bufferedBytesFromClient,\n\t\t\tnew Uint8Array(data),\n\t\t]);\n\t\tswitch (guessProtocol(this.port, this.bufferedBytesFromClient)) {\n\t\t\tcase false:\n\t\t\t\t// Not enough data to classify the protocol,\n\t\t\t\t// let's wait for more.\n\t\t\t\treturn;\n\t\t\tcase 'other':\n\t\t\t\tthis.emit('error', new Error('Unsupported protocol'));\n\t\t\t\tthis.close();\n\t\t\t\tbreak;\n\t\t\tcase 'tls':\n\t\t\t\tthis.fetchOverTLS();\n\t\t\t\tthis.fetchInitiated = true;\n\t\t\t\tbreak;\n\t\t\tcase 'http':\n\t\t\t\tthis.fetchOverHTTP();\n\t\t\t\tthis.fetchInitiated = true;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tasync fetchOverTLS() {\n\t\tif (!this.CAroot) {\n\t\t\tthrow new Error(\n\t\t\t\t'TLS protocol is only supported when the TCPOverFetchWebsocket is ' +\n\t\t\t\t\t'instantiated with a CAroot'\n\t\t\t);\n\t\t}\n\t\tconst siteCert = await generateCertificate(\n\t\t\t{\n\t\t\t\tsubject: {\n\t\t\t\t\tcommonName: this.host,\n\t\t\t\t\torganizationName: this.host,\n\t\t\t\t\tcountryName: 'US',\n\t\t\t\t},\n\t\t\t\tissuer: this.CAroot.tbsDescription.subject,\n\t\t\t},\n\t\t\tthis.CAroot.keyPair\n\t\t);\n\n\t\tconst tlsConnection = new TLS_1_2_Connection();\n\n\t\t// Connect this WebSocket's client end to the TLS connection.\n\t\t// Forward the encrypted bytes from the WebSocket to the TLS connection.\n\t\tthis.clientUpstream.readable\n\t\t\t.pipeTo(tlsConnection.clientEnd.upstream.writable)\n\t\t\t.catch(() => {\n\t\t\t\t// Ignore failures arising from pipeTo() errors.\n\t\t\t\t// The caller will observe the clientEnd.downstream.writable stream\n\t\t\t\t// erroring out.\n\t\t\t});\n\n\t\t// Forward the decrypted bytes from the TLS connection to this WebSocket.\n\t\ttlsConnection.clientEnd.downstream.readable\n\t\t\t.pipeTo(this.clientDownstream.writable)\n\t\t\t.catch(() => {\n\t\t\t\t// Ignore failures arising from pipeTo() errors.\n\t\t\t\t// The caller will observe the clientEnd.downstream.writable stream\n\t\t\t\t// erroring out.\n\t\t\t});\n\n\t\t// Perform the TLS handshake\n\t\tawait tlsConnection.TLSHandshake(siteCert.keyPair.privateKey, [\n\t\t\tsiteCert.certificate,\n\t\t\tthis.CAroot.certificate,\n\t\t]);\n\n\t\t// Connect the TLS server end to the fetch() request\n\t\tconst request = await RawBytesFetch.parseHttpRequest(\n\t\t\ttlsConnection.serverEnd.upstream.readable,\n\t\t\tthis.host,\n\t\t\t'https'\n\t\t);\n\t\ttry {\n\t\t\tawait RawBytesFetch.fetchRawResponseBytes(\n\t\t\t\trequest,\n\t\t\t\tthis.corsProxyUrl\n\t\t\t).pipeTo(tlsConnection.serverEnd.downstream.writable);\n\t\t} catch {\n\t\t\t// Ignore errors from fetch()\n\t\t\t// They are handled in the constructor\n\t\t\t// via this.clientDownstream.readable.pipeTo()\n\t\t\t// and if we let the failures they would be logged\n\t\t\t// as an unhandled promise rejection.\n\t\t}\n\t}\n\n\tasync fetchOverHTTP() {\n\t\t// Connect this WebSocket's client end to the fetch() request\n\t\tconst request = await RawBytesFetch.parseHttpRequest(\n\t\t\tthis.clientUpstream.readable,\n\t\t\tthis.host,\n\t\t\t'http'\n\t\t);\n\t\ttry {\n\t\t\tawait RawBytesFetch.fetchRawResponseBytes(\n\t\t\t\trequest,\n\t\t\t\tthis.corsProxyUrl\n\t\t\t).pipeTo(this.clientDownstream.writable);\n\t\t} catch {\n\t\t\t// Ignore errors from fetch()\n\t\t\t// They are handled in the constructor\n\t\t\t// via this.clientDownstream.readable.pipeTo()\n\t\t\t// and if we let the failures they would be logged\n\t\t\t// as an unhandled promise rejection.\n\t\t}\n\t}\n\n\tclose() {\n\t\t/**\n\t\t * Workaround a PHP.wasm issue – if the WebSocket is\n\t\t * closed asynchronously after the last chunk is received,\n\t\t * the PHP.wasm runtime enters an infinite polling loop.\n\t\t *\n\t\t * The root cause of the problem is unclear at the time\n\t\t * of writing this comment. There's a chance it's a regular\n\t\t * POSIX behavior.\n\t\t *\n\t\t * Either way, sending an empty data chunk before closing\n\t\t * the WebSocket resolves the problem.\n\t\t */\n\t\tthis.emit('message', { data: new Uint8Array(0) });\n\n\t\tthis.readyState = this.CLOSING;\n\t\tthis.emit('close');\n\t\tthis.readyState = this.CLOSED;\n\t}\n}\n\nconst HTTP_METHODS = [\n\t'GET',\n\t'POST',\n\t'HEAD',\n\t'PATCH',\n\t'OPTIONS',\n\t'DELETE',\n\t'PUT',\n\t'TRACE',\n];\n\nfunction guessProtocol(port: number, data: Uint8Array) {\n\tif (data.length < 8) {\n\t\t// Not enough data to classify the protocol, let's wait for more.\n\t\treturn false;\n\t}\n\n\t// Assume TLS if we're on the usual HTTPS port and the\n\t// first three bytes look like a TLS handshake record.\n\tconst looksLikeTls =\n\t\tport === 443 &&\n\t\tdata[0] === ContentTypes.Handshake &&\n\t\t// TLS versions between 1.0 and 1.2\n\t\tdata[1] === 0x03 &&\n\t\tdata[2] >= 0x01 &&\n\t\tdata[2] <= 0x03;\n\tif (looksLikeTls) {\n\t\treturn 'tls';\n\t}\n\n\t// Assume HTTP if we're on the usual HTTP port and the\n\t// first starts with an HTTP method and a space.\n\tconst decodedFirstLine = new TextDecoder('latin1', {\n\t\tfatal: true,\n\t}).decode(data);\n\tconst looksLikeHttp = HTTP_METHODS.some((method) =>\n\t\tdecodedFirstLine.startsWith(method + ' ')\n\t);\n\tif (looksLikeHttp) {\n\t\treturn 'http';\n\t}\n\n\treturn 'other';\n}\n\nexport class RawBytesFetch {\n\t/**\n\t * Streams a HTTP response including the status line and headers.\n\t */\n\tstatic fetchRawResponseBytes(request: Request, corsProxyUrl?: string) {\n\t\t// This initially used a TransformStream and piped the response\n\t\t// body to the writable side of the TransformStream.\n\t\t//\n\t\t// Unfortunately, the first response body chunk was not correctly\n\t\t// enqueued so we switched to a customReadableStream.\n\t\treturn new ReadableStream({\n\t\t\tasync start(controller) {\n\t\t\t\tlet response: Response;\n\t\t\t\ttry {\n\t\t\t\t\tresponse = await fetchWithCorsProxy(\n\t\t\t\t\t\trequest,\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t\tcorsProxyUrl\n\t\t\t\t\t);\n\t\t\t\t} catch (error) {\n\t\t\t\t\t/**\n\t\t\t\t\t * Pretend we've got a 400 Bad Request response whenever\n\t\t\t\t\t * the fetch() call fails.\n\t\t\t\t\t *\n\t\t\t\t\t * Just propagating an error and closing a WebSocket does\n\t\t\t\t\t * not make PHP aware the socket closed abruptly. This means\n\t\t\t\t\t * the AsyncHttp\\Client will keep polling the socket indefinitely\n\t\t\t\t\t * until the request times out. This isn't perfect, as we want\n\t\t\t\t\t * to close the socket as soon as possible to avoid, e.g., 10 seconds\n\t\t\t\t\t * of unnecessary waitin for the timeout\n\t\t\t\t\t *\n\t\t\t\t\t * The root cause is unknown and likely related to the low-level\n\t\t\t\t\t * implementation of polling file descriptors. The following\n\t\t\t\t\t * workaround is far from ideal, but it must suffice until we\n\t\t\t\t\t * have a platform-level resolution.\n\t\t\t\t\t */\n\t\t\t\t\tcontroller.enqueue(\n\t\t\t\t\t\tnew TextEncoder().encode(\n\t\t\t\t\t\t\t'HTTP/1.1 400 Bad Request\\r\\nContent-Length: 0\\r\\n\\r\\n'\n\t\t\t\t\t\t)\n\t\t\t\t\t);\n\t\t\t\t\tcontroller.error(error);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tcontroller.enqueue(RawBytesFetch.headersAsBytes(response));\n\t\t\t\tconst reader = response.body?.getReader();\n\t\t\t\tif (!reader) {\n\t\t\t\t\tcontroller.close();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst encoder = new TextEncoder();\n\t\t\t\twhile (true) {\n\t\t\t\t\tconst { done, value } = await reader.read();\n\t\t\t\t\tif (value) {\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * Pass the body stream assuming the response uses\n\t\t\t\t\t\t * chunked transfer encoding.\n\t\t\t\t\t\t *\n\t\t\t\t\t\t * See `headersAsBytes()` for the details.\n\t\t\t\t\t\t */\n\t\t\t\t\t\tcontroller.enqueue(\n\t\t\t\t\t\t\tencoder.encode(`${value.length.toString(16)}\\r\\n`)\n\t\t\t\t\t\t);\n\t\t\t\t\t\tcontroller.enqueue(value);\n\t\t\t\t\t\tcontroller.enqueue(encoder.encode('\\r\\n'));\n\t\t\t\t\t}\n\t\t\t\t\tif (done) {\n\t\t\t\t\t\tcontroller.enqueue(encoder.encode('0\\r\\n\\r\\n'));\n\t\t\t\t\t\tcontroller.close();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\t}\n\n\tprivate static headersAsBytes(response: Response) {\n\t\tconst status = `HTTP/1.1 ${response.status} ${response.statusText}`;\n\n\t\tconst headersObject: Record<string, string> = {};\n\t\tresponse.headers.forEach((value, name) => {\n\t\t\theadersObject[name.toLowerCase()] = value;\n\t\t});\n\n\t\t/**\n\t\t * Best-effort attempt to provide the correct content-length\n\t\t * to the PHP-side request handler.\n\t\t *\n\t\t * Web servers often respond with a combination of Content-Length\n\t\t * and Content-Encoding. For example, a 16kb text file may be compressed\n\t\t * to 4kb with gzip and served with a Content-Encoding of `gzip` and a\n\t\t * Content-Length of 4KB.\n\t\t *\n\t\t * The web browser, however, exposes neither the Content-Encoding header\n\t\t * nor the gzipped data stream. All we have access to is the original\n\t\t * Content-Length value of the gzipped file and a decompressed data stream.\n\t\t *\n\t\t * If we just pass that along to the PHP-side request handler, it would\n\t\t * see a 16KB body stream with a Content-Length of 4KB. It would then\n\t\t * truncate the body stream at 4KB and discard the rest of the data.\n\t\t *\n\t\t * This is not what we want.\n\t\t *\n\t\t * To correct that behavior, we're stripping the Content-Length entirely.\n\t\t * We do that for every single response because we don't have any way\n\t\t * of knowing whether any Content-Encoding was used. Furthermore, we can't\n\t\t * just calculate the correct Content-Length value without consuming the\n\t\t * entire content stream – and we want to pass each data chunk to PHP\n\t\t * as we receive it.\n\t\t *\n\t\t * Instead of a fixed Content-Length, we'll use Content-Encoding: Chunked,\n\t\t * and then provide a per-chunk Content-Length. See fetchRawResponseBytes()\n\t\t * for the details.\n\t\t */\n\t\tdelete headersObject['content-length'];\n\t\theadersObject['transfer-encoding'] = 'chunked';\n\n\t\tconst headers: string[] = [];\n\t\tfor (const [name, value] of Object.entries(headersObject)) {\n\t\t\theaders.push(`${name}: ${value}`);\n\t\t}\n\t\tconst string = [status, ...headers].join('\\r\\n') + '\\r\\n\\r\\n';\n\t\treturn new TextEncoder().encode(string);\n\t}\n\n\t/**\n\t * Parses a raw, streamed HTTP request into a Request object\n\t * with known headers and a readable body stream.\n\t */\n\tstatic async parseHttpRequest(\n\t\trequestBytesStream: ReadableStream<Uint8Array>,\n\t\thost: string,\n\t\tprotocol: 'http' | 'https'\n\t) {\n\t\tlet inputBuffer: Uint8Array = new Uint8Array(0);\n\n\t\tlet requestDataExhausted = false;\n\t\tlet headersEndIndex = -1;\n\t\tconst requestBytesReader = requestBytesStream.getReader();\n\t\twhile (headersEndIndex === -1) {\n\t\t\tconst { done, value } = await requestBytesReader.read();\n\t\t\tif (done) {\n\t\t\t\trequestDataExhausted = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tinputBuffer = concatUint8Arrays([inputBuffer, value]);\n\t\t\t// Find the end of the headers (\\r\\n\\r\\n). This is\n\t\t\t// not optimal as we may end up scanning the same\n\t\t\t// bytes multiple times, but the overhead is negligible\n\t\t\t// and the code is much simpler this way.\n\t\t\theadersEndIndex = findSequenceInBuffer(\n\t\t\t\tinputBuffer,\n\t\t\t\tnew Uint8Array([0x0d, 0x0a, 0x0d, 0x0a])\n\t\t\t);\n\t\t}\n\t\trequestBytesReader.releaseLock();\n\n\t\tconst headersBuffer = inputBuffer.slice(0, headersEndIndex);\n\t\tconst parsedHeaders = RawBytesFetch.parseRequestHeaders(headersBuffer);\n\t\tconst terminationMode =\n\t\t\tparsedHeaders.headers.get('Transfer-Encoding') !== null\n\t\t\t\t? 'chunked'\n\t\t\t\t: 'content-length';\n\t\tconst contentLength =\n\t\t\tparsedHeaders.headers.get('Content-Length') !== null\n\t\t\t\t? parseInt(parsedHeaders.headers.get('Content-Length')!, 10)\n\t\t\t\t: undefined;\n\n\t\tconst bodyBytes = inputBuffer.slice(\n\t\t\theadersEndIndex + 4 /* Skip \\r\\n\\r\\n */\n\t\t);\n\t\tlet outboundBodyStream: ReadableStream<Uint8Array> | undefined;\n\t\tif (parsedHeaders.method !== 'GET') {\n\t\t\tconst requestBytesReader = requestBytesStream.getReader();\n\t\t\tlet seenBytes = bodyBytes.length;\n\t\t\tlet last5Bytes = bodyBytes.slice(-6);\n\t\t\tconst emptyChunk = new TextEncoder().encode('0\\r\\n\\r\\n');\n\t\t\toutboundBodyStream = new ReadableStream<Uint8Array>({\n\t\t\t\tasync start(controller) {\n\t\t\t\t\tif (bodyBytes.length > 0) {\n\t\t\t\t\t\tcontroller.enqueue(bodyBytes);\n\t\t\t\t\t}\n\t\t\t\t\tif (requestDataExhausted) {\n\t\t\t\t\t\tcontroller.close();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tasync pull(controller) {\n\t\t\t\t\tconst { done, value } = await requestBytesReader.read();\n\t\t\t\t\tseenBytes += value?.length || 0;\n\t\t\t\t\tif (value) {\n\t\t\t\t\t\tcontroller.enqueue(value);\n\t\t\t\t\t\tlast5Bytes = concatUint8Arrays([\n\t\t\t\t\t\t\tlast5Bytes,\n\t\t\t\t\t\t\tvalue || new Uint8Array(),\n\t\t\t\t\t\t]).slice(-5);\n\t\t\t\t\t}\n\t\t\t\t\tconst shouldTerminate =\n\t\t\t\t\t\tdone ||\n\t\t\t\t\t\t(terminationMode === 'content-length' &&\n\t\t\t\t\t\t\tcontentLength !== undefined &&\n\t\t\t\t\t\t\tseenBytes >= contentLength) ||\n\t\t\t\t\t\t(terminationMode === 'chunked' &&\n\t\t\t\t\t\t\tlast5Bytes.every(\n\t\t\t\t\t\t\t\t(byte, index) => byte === emptyChunk[index]\n\t\t\t\t\t\t\t));\n\t\t\t\t\tif (shouldTerminate) {\n\t\t\t\t\t\tcontroller.close();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tif (terminationMode === 'chunked') {\n\t\t\t\t// Strip chunked transfer encoding from the request body stream.\n\t\t\t\t// PHP may encode the request body with chunked transfer encoding,\n\t\t\t\t// giving us a stream of chunks with a size line ending in \\r\\n,\n\t\t\t\t// a body chunk, and a chunk trailer ending in \\r\\n.\n\t\t\t\t//\n\t\t\t\t// We must not include the chunk headers and trailers in the\n\t\t\t\t// transmitted data. fetch() trusts us to provide the body stream\n\t\t\t\t// in its original form and will pass treat the chunked encoding\n\t\t\t\t// artifacts as a part of the data to be transmitted to the server.\n\t\t\t\t// This, in turn, means sending over a corrupted request body.\n\t\t\t\t//\n\t\t\t\t// Therefore, let's just strip any chunked encoding-related bytes.\n\t\t\t\toutboundBodyStream = outboundBodyStream.pipeThrough(\n\t\t\t\t\tnew ChunkedDecoderStream()\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t * Prefer the Host header to the host from the URL used in a PHP\n\t\t * function call.\n\t\t *\n\t\t * There are tradeoffs involved in this decision.\n\t\t *\n\t\t * The URL from the PHP function call is the actual network location\n\t\t * the caller intended to reach, e.g. `http://192.168.1.100` or\n\t\t * `http://127.0.0.1`.\n\t\t *\n\t\t * The Host header is what the developer wanted to provide to the\n\t\t * web server, e.g. `wordpress.org` or `localhost`.\n\t\t *\n\t\t * The Host header is not a reliable indication of the target URL.\n\t\t * However, `fetch()` does not support Host spoofing. Furthermore,\n\t\t * a webserver running on 127.0.0.1 may only respond correctly\n\t\t * when it is provided with the Host header `localhost`.\n\t\t *\n\t\t * Prefering the Host header over the host from the PHP function call\n\t\t * is not perfect, but it seems like the lesser of two evils.\n\t\t */\n\t\tconst hostname = parsedHeaders.headers.get('Host') ?? host;\n\t\tconst url = new URL(parsedHeaders.path, protocol + '://' + hostname);\n\n\t\treturn new Request(url.toString(), {\n\t\t\tmethod: parsedHeaders.method,\n\t\t\theaders: parsedHeaders.headers,\n\t\t\tbody: outboundBodyStream,\n\t\t\t// In Node.js, duplex: 'half' is required when\n\t\t\t// the body stream is provided.\n\t\t\t// @ts-expect-error\n\t\t\tduplex: 'half',\n\t\t});\n\t}\n\n\tprivate static parseRequestHeaders(httpRequestBytes: Uint8Array) {\n\t\tconst httpRequest = new TextDecoder().decode(httpRequestBytes);\n\t\tconst statusLineMaybe = httpRequest.split('\\n')[0];\n\t\tconst [method, path] = statusLineMaybe.split(' ');\n\n\t\tconst headers = new Headers();\n\t\tfor (const line of httpRequest.split('\\r\\n').slice(1)) {\n\t\t\tif (line === '') {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tconst [name, value] = line.split(': ');\n\t\t\theaders.set(name, value);\n\t\t}\n\n\t\treturn { method, path, headers };\n\t}\n}\n\nfunction findSequenceInBuffer(\n\tbuffer: Uint8Array,\n\tsequence: Uint8Array\n): number {\n\tconst bufferLength = buffer.length;\n\tconst sequenceLength = sequence.length;\n\tconst lastPossibleIndex = bufferLength - sequenceLength;\n\n\tfor (let i = 0; i <= lastPossibleIndex; i++) {\n\t\tlet found = true;\n\t\tfor (let j = 0; j < sequenceLength; j++) {\n\t\t\tif (buffer[i + j] !== sequence[j]) {\n\t\t\t\tfound = false;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (found) {\n\t\t\treturn i;\n\t\t}\n\t}\n\treturn -1;\n}\n","import { LatestSupportedPHPVersion } from '@php-wasm/universal';\nimport type { SupportedPHPVersion } from '@php-wasm/universal';\n\n/**\n * Returns the path to the intl extension for the specified PHP version.\n *\n * Each PHP version's intl extension is packaged separately. Install the\n * version-specific package you need:\n * - @php-wasm/web-8-5\n * - @php-wasm/web-8-4\n * - etc.\n */\nexport async function getIntlExtensionModule(\n\tversion: SupportedPHPVersion = LatestSupportedPHPVersion\n): Promise<any> {\n\tswitch (version) {\n\t\tcase '8.5':\n\t\t\t// @ts-ignore\n\t\t\treturn (await import('@php-wasm/web-8-5')).getIntlExtensionPath();\n\t\tcase '8.4':\n\t\t\t// @ts-ignore\n\t\t\treturn (await import('@php-wasm/web-8-4')).getIntlExtensionPath();\n\t\tcase '8.3':\n\t\t\t// @ts-ignore\n\t\t\treturn (await import('@php-wasm/web-8-3')).getIntlExtensionPath();\n\t\tcase '8.2':\n\t\t\t// @ts-ignore\n\t\t\treturn (await import('@php-wasm/web-8-2')).getIntlExtensionPath();\n\t\tcase '8.1':\n\t\t\t// @ts-ignore\n\t\t\treturn (await import('@php-wasm/web-8-1')).getIntlExtensionPath();\n\t\tcase '8.0':\n\t\t\t// @ts-ignore\n\t\t\treturn (await import('@php-wasm/web-8-0')).getIntlExtensionPath();\n\t\tcase '7.4':\n\t\t\t// @ts-ignore\n\t\t\treturn (await import('@php-wasm/web-7-4')).getIntlExtensionPath();\n\t\tcase '7.3':\n\t\t\t// @ts-ignore\n\t\t\treturn (await import('@php-wasm/web-7-3')).getIntlExtensionPath();\n\t\tcase '7.2':\n\t\t\t// @ts-ignore\n\t\t\treturn (await import('@php-wasm/web-7-2')).getIntlExtensionPath();\n\t}\n\tthrow new Error(`Unsupported PHP version ${version}`);\n}\n","import type {\n\tEmscriptenOptions,\n\tPHPRuntime,\n\tSupportedPHPVersion,\n} from '@php-wasm/universal';\nimport { LatestSupportedPHPVersion, FSHelpers } from '@php-wasm/universal';\nimport { getIntlExtensionModule } from './get-intl-extension-module';\nimport { createMemoizedFetch } from '@wp-playground/common';\n\nexport async function withIntl(\n\tversion: SupportedPHPVersion = LatestSupportedPHPVersion,\n\toptions: EmscriptenOptions\n): Promise<EmscriptenOptions> {\n\tconst memoizedFetch = createMemoizedFetch(fetch);\n\n\tconst extensionName = 'intl.so';\n\tconst dataName = 'icu.dat';\n\n\tconst extensionPath = await getIntlExtensionModule(version);\n\t// @ts-ignore\n\tconst dataPath = (await import('./shared/icu.dat')).default;\n\n\tconst [extension, ICUData] = await Promise.all([\n\t\tmemoizedFetch(extensionPath).then((response) => response.arrayBuffer()),\n\t\tmemoizedFetch(dataPath).then((response) => response.arrayBuffer()),\n\t]);\n\n\treturn {\n\t\t...options,\n\t\tENV: {\n\t\t\t...options.ENV,\n\t\t\tPHP_INI_SCAN_DIR: '/internal/shared/extensions',\n\t\t\tICU_DATA: '/internal/shared',\n\t\t},\n\t\tonRuntimeInitialized: (phpRuntime: PHPRuntime) => {\n\t\t\tif (options.onRuntimeInitialized) {\n\t\t\t\toptions.onRuntimeInitialized(phpRuntime);\n\t\t\t}\n\t\t\t/**\n\t\t\t * The extension file previously read\n\t\t\t * is written inside the /extensions directory\n\t\t\t */\n\t\t\tif (\n\t\t\t\t!FSHelpers.fileExists(\n\t\t\t\t\tphpRuntime.FS,\n\t\t\t\t\t'/internal/shared/extensions'\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\tphpRuntime.FS.mkdirTree('/internal/shared/extensions');\n\t\t\t}\n\t\t\tif (\n\t\t\t\t!FSHelpers.fileExists(\n\t\t\t\t\tphpRuntime.FS,\n\t\t\t\t\t`/internal/shared/extensions/${extensionName}`\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\tphpRuntime.FS.writeFile(\n\t\t\t\t\t`/internal/shared/extensions/${extensionName}`,\n\t\t\t\t\tnew Uint8Array(extension)\n\t\t\t\t);\n\t\t\t}\n\t\t\t/* The extension has its share of ini entries\n\t\t\t * to write in a separate ini file\n\t\t\t */\n\t\t\tif (\n\t\t\t\t!FSHelpers.fileExists(\n\t\t\t\t\tphpRuntime.FS,\n\t\t\t\t\t'/internal/shared/extensions/intl.ini'\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\tphpRuntime.FS.writeFile(\n\t\t\t\t\t'/internal/shared/extensions/intl.ini',\n\t\t\t\t\t[\n\t\t\t\t\t\t`extension=/internal/shared/extensions/${extensionName}`,\n\t\t\t\t\t].join('\\n')\n\t\t\t\t);\n\t\t\t}\n\t\t\t/*\n\t\t\t * An ICU data file must be loaded to support Intl extension.\n\t\t\t * To achieve this, a shared directory is mounted and referenced\n\t\t\t * via the ICU_DATA environment variable.\n\t\t\t * By default, this variable is set to '/internal/shared',\n\t\t\t * which corresponds to the actual file location.\n\t\t\t *\n\t\t\t * The Intl extension is hard-coded to look for the `icudt74l` filename,\n\t\t\t * which means the ICU data file must use that exact name.\n\t\t\t */\n\t\t\tif (\n\t\t\t\t!FSHelpers.fileExists(\n\t\t\t\t\tphpRuntime.FS,\n\t\t\t\t\t`${phpRuntime.ENV.ICU_DATA}/${dataName}`\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\tphpRuntime.FS.mkdirTree(phpRuntime.ENV.ICU_DATA);\n\t\t\t\tphpRuntime.FS.writeFile(\n\t\t\t\t\t`${phpRuntime.ENV.ICU_DATA}/icudt74l.dat`,\n\t\t\t\t\tnew Uint8Array(ICUData)\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\t};\n}\n","import type {\n\tSupportedPHPVersion,\n\tEmscriptenOptions,\n\tPHPLoaderModule,\n} from '@php-wasm/universal';\nimport { loadPHPRuntime } from '@php-wasm/universal';\nimport { getPHPLoaderModule } from './get-php-loader-module';\nimport type { TCPOverFetchOptions } from './tcp-over-fetch-websocket';\nimport { tcpOverFetchWebsocket } from './tcp-over-fetch-websocket';\nimport { withIntl } from './extensions/intl/with-intl';\n\nexport interface LoaderOptions {\n\temscriptenOptions?: EmscriptenOptions;\n\tonPhpLoaderModuleLoaded?: (module: PHPLoaderModule) => void;\n\ttcpOverFetch?: TCPOverFetchOptions;\n\twithIntl?: boolean;\n}\n\n/**\n * Fake a websocket connection to prevent errors in the web app\n * from cascading and breaking the Playground.\n */\nconst fakeWebsocket = () => {\n\treturn {\n\t\twebsocket: {\n\t\t\tdecorator: (WebSocketConstructor: any) => {\n\t\t\t\treturn class FakeWebsocketConstructor extends WebSocketConstructor {\n\t\t\t\t\tconstructor() {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tsuper();\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t// pass\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tsend() {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t},\n\t\t},\n\t};\n};\n\ninterface PHPWorkerGlobalScope extends WorkerGlobalScope {\n\tsetImmediate: (fn: () => void) => void;\n}\n\nexport async function loadWebRuntime(\n\tphpVersion: SupportedPHPVersion,\n\tloaderOptions: LoaderOptions = {}\n) {\n\t/*\n\t * Provide `setImmediate` so Emscripten doesn’t install its message-based\n\t * polyfill, which retains references to the Wasm HEAP and prevents the\n\t * PHP instance from being garbage-collected.\n\t *\n\t * https://github.com/emscripten-core/emscripten/blob/6d61ffd7076309cb08af37aba496f25c23cdb5a4/src/lib/libeventloop.js#L57\n\t */\n\tif (!('setImmediate' in globalThis)) {\n\t\t(globalThis as unknown as PHPWorkerGlobalScope).setImmediate = (\n\t\t\tfn: () => void\n\t\t) => setTimeout(fn, 0);\n\t}\n\n\tlet emscriptenOptions: EmscriptenOptions | Promise<EmscriptenOptions> = {\n\t\t...fakeWebsocket(),\n\t\t...(loaderOptions.emscriptenOptions || {}),\n\t};\n\n\tif (loaderOptions.tcpOverFetch) {\n\t\temscriptenOptions = tcpOverFetchWebsocket(\n\t\t\temscriptenOptions,\n\t\t\tloaderOptions.tcpOverFetch\n\t\t);\n\t}\n\n\tif (loaderOptions.withIntl) {\n\t\temscriptenOptions = withIntl(phpVersion, emscriptenOptions);\n\t}\n\n\tconst [phpLoaderModule, options] = await Promise.all([\n\t\tgetPHPLoaderModule(phpVersion),\n\t\temscriptenOptions,\n\t]);\n\n\tloaderOptions.onPhpLoaderModuleLoaded?.(phpLoaderModule);\n\n\treturn await loadPHPRuntime(phpLoaderModule, options);\n}\n","/**\n * Setup a postMessage relay between the parent window and a nested iframe.\n *\n * When we're running a Playground instance inside an iframe, sometimes that\n * iframe will contain another iframe and so on. The parent application,\n * however, needs to be able to communicate with the innermost iframe. This\n * function relays the communication both ways. Call it in in every iframe\n * layer between the topmost window and the innermost iframe.\n *\n * @param nestedFrame The nested iframe element\n * @param expectedOrigin The origin that the nested iframe is expected to be on. If not\n * provided, any origin is allowed.\n */\nexport function setupPostMessageRelay(\n\tnestedFrame: HTMLIFrameElement,\n\texpectedOrigin?: string\n) {\n\t// Relay Messages from WP to Parent\n\twindow.addEventListener('message', (event) => {\n\t\tif (event.source !== nestedFrame.contentWindow) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (expectedOrigin && event.origin !== expectedOrigin) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (typeof event.data !== 'object' || event.data.type !== 'relay') {\n\t\t\treturn;\n\t\t}\n\n\t\twindow.parent.postMessage(event.data, '*');\n\t});\n\n\t// Relay Messages from Parent to WP\n\twindow.addEventListener('message', (event) => {\n\t\tif (event.source !== window.parent) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (typeof event.data !== 'object' || event.data.type !== 'relay') {\n\t\t\treturn;\n\t\t}\n\n\t\tnestedFrame?.contentWindow?.postMessage(event.data);\n\t});\n}\n","/**\n * Spawns a new Worker Thread.\n *\n * @param workerUrl The absolute URL of the worker script.\n * @returns The spawned Worker Thread.\n */\nexport async function spawnPHPWorkerThread(workerUrl: string) {\n\tconst worker = new Worker(workerUrl, { type: 'module' });\n\treturn new Promise<Worker>((resolve, reject) => {\n\t\tworker.onerror = (e) => {\n\t\t\tconst error = new Error(\n\t\t\t\t`WebWorker failed to load at ${workerUrl}. ${\n\t\t\t\t\te.message ? `Original error: ${e.message}` : ''\n\t\t\t\t}`\n\t\t\t);\n\t\t\t(error as any).filename = e.filename;\n\t\t\treject(error);\n\t\t};\n\t\t// There is no way to know when the worker script has started\n\t\t// executing, so we use a message to signal that.\n\t\tfunction onStartup(event: { data: string }) {\n\t\t\tif (event.data === 'worker-script-started') {\n\t\t\t\tresolve(worker);\n\t\t\t\tworker.removeEventListener('message', onStartup);\n\t\t\t}\n\t\t}\n\t\tworker.addEventListener('message', onStartup);\n\t});\n}\n","import type { Emscripten, MountHandler, PHP } from '@php-wasm/universal';\nimport { FSHelpers, __private__dont__use } from '@php-wasm/universal';\nimport { Semaphore, basename, joinPaths } from '@php-wasm/util';\nimport { logger } from '@php-wasm/logger';\nimport type { FilesystemOperation } from '@php-wasm/fs-journal';\nimport { normalizeFilesystemOperations } from '@php-wasm/fs-journal';\nimport { journalFSEvents } from '@php-wasm/fs-journal';\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport type * as pleaseLoadTypes from 'wicg-file-system-access';\n\ndeclare global {\n\tinterface FileSystemFileHandle {\n\t\tmove(target: FileSystemDirectoryHandle): Promise<void>;\n\t\tmove(name: string): Promise<void>;\n\t\tmove(target: FileSystemDirectoryHandle, name: string): Promise<void>;\n\t\tcreateWritable(): Promise<FileSystemWritableFileStream>;\n\t}\n\tinterface FileSystemWritableFileStream {\n\t\twrite(\n\t\t\tbuffer: BufferSource,\n\t\t\toptions?: FileSystemReadWriteOptions\n\t\t): Promise<number>;\n\t\tclose(): Promise<void>;\n\t\tseek(offset: number): Promise<void>;\n\t\ttruncate(newSize: number): Promise<void>;\n\t}\n}\n\nexport type MountDevice =\n\t| {\n\t\t\ttype: 'opfs';\n\t\t\tpath: string;\n\t }\n\t| {\n\t\t\ttype: 'local-fs';\n\t\t\thandle: FileSystemDirectoryHandle;\n\t };\n\nexport interface MountOptions {\n\tinitialSync: {\n\t\tdirection?: 'opfs-to-memfs' | 'memfs-to-opfs';\n\t\tonProgress?: SyncProgressCallback;\n\t};\n}\nexport type SyncProgress = {\n\t/** The number of files that have been synced. */\n\tfiles: number;\n\t/** The number of all files that need to be synced. */\n\ttotal: number;\n};\nexport type SyncProgressCallback = (progress: SyncProgress) => void;\n\nexport function createDirectoryHandleMountHandler(\n\thandle: FileSystemDirectoryHandle,\n\toptions: MountOptions = { initialSync: {} }\n): MountHandler {\n\toptions = {\n\t\t...options,\n\t\tinitialSync: {\n\t\t\t...options.initialSync,\n\t\t\tdirection: options.initialSync.direction ?? 'opfs-to-memfs',\n\t\t},\n\t};\n\n\treturn async function (php, FS, vfsMountPoint) {\n\t\tif (options.initialSync.direction === 'opfs-to-memfs') {\n\t\t\tif (FSHelpers.fileExists(FS, vfsMountPoint)) {\n\t\t\t\tFSHelpers.rmdir(FS, vfsMountPoint);\n\t\t\t}\n\t\t\tFSHelpers.mkdir(FS, vfsMountPoint);\n\t\t\tawait copyOpfsToMemfs(FS, handle, vfsMountPoint);\n\t\t} else {\n\t\t\tawait copyMemfsToOpfs(\n\t\t\t\tFS,\n\t\t\t\thandle,\n\t\t\t\tvfsMountPoint,\n\t\t\t\toptions.initialSync.onProgress\n\t\t\t);\n\t\t}\n\t\tconst unbindJournal = journalFSEventsToOpfs(php, handle, vfsMountPoint);\n\t\treturn unbindJournal;\n\t};\n}\n\nasync function copyOpfsToMemfs(\n\tFS: Emscripten.RootFS,\n\topfsRoot: FileSystemDirectoryHandle,\n\tmemfsRoot: string\n) {\n\tFSHelpers.mkdir(FS, memfsRoot);\n\n\t/**\n\t * Semaphores are used to limit the number of concurrent operations.\n\t * Flooding the browser with 2000 FS operations at the same time\n\t * can get quite slow.\n\t */\n\tconst semaphore = new Semaphore({\n\t\tconcurrency: 40,\n\t});\n\n\tconst ops: Array<Promise<void>> = [];\n\tconst stack: Array<[FileSystemDirectoryHandle, string]> = [\n\t\t[opfsRoot, memfsRoot],\n\t];\n\twhile (stack.length > 0) {\n\t\tconst [opfsParent, memfsParentPath] = stack.pop()!;\n\n\t\tfor await (const opfsHandle of opfsParent.values()) {\n\t\t\tconst op = semaphore.run(async () => {\n\t\t\t\tconst memfsEntryPath = joinPaths(\n\t\t\t\t\tmemfsParentPath,\n\t\t\t\t\topfsHandle.name\n\t\t\t\t);\n\t\t\t\tif (opfsHandle.kind === 'directory') {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tFS.mkdir(memfsEntryPath);\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\tif ((e as any)?.errno !== 20) {\n\t\t\t\t\t\t\tlogger.error(e);\n\t\t\t\t\t\t\t// We ignore the error if the directory already exists,\n\t\t\t\t\t\t\t// and throw otherwise.\n\t\t\t\t\t\t\tthrow e;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tstack.push([opfsHandle, memfsEntryPath]);\n\t\t\t\t} else if (opfsHandle.kind === 'file') {\n\t\t\t\t\tconst file = await opfsHandle.getFile();\n\t\t\t\t\tconst byteArray = new Uint8Array(await file.arrayBuffer());\n\t\t\t\t\tFS.createDataFile(\n\t\t\t\t\t\tmemfsParentPath,\n\t\t\t\t\t\topfsHandle.name,\n\t\t\t\t\t\tbyteArray,\n\t\t\t\t\t\ttrue,\n\t\t\t\t\t\ttrue,\n\t\t\t\t\t\ttrue\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tops.splice(ops.indexOf(op), 1);\n\t\t\t});\n\t\t\tops.push(op);\n\t\t}\n\t\t// Let the ongoing operations catch-up to the stack.\n\t\twhile (stack.length === 0 && ops.length > 0) {\n\t\t\tawait Promise.any(ops);\n\t\t}\n\t}\n}\n\nexport async function copyMemfsToOpfs(\n\tFS: Emscripten.RootFS,\n\topfsRoot: FileSystemDirectoryHandle,\n\tmemfsRoot: string,\n\tonProgress?: SyncProgressCallback\n) {\n\t// Ensure the memfs directory exists.\n\tFS.mkdirTree(memfsRoot);\n\n\t// Create all MEMFS directories in OPFS but don't create\n\t// files yet. This is quite fast.\n\tconst filesToCreate: Array<[FileSystemDirectoryHandle, string, string]> =\n\t\t[];\n\tasync function mirrorMemfsDirectoryinOpfs(\n\t\tmemfsParent: string,\n\t\topfsDir: FileSystemDirectoryHandle\n\t) {\n\t\tawait Promise.all(\n\t\t\tFS.readdir(memfsParent)\n\t\t\t\t.filter(\n\t\t\t\t\t(entryName: string) =>\n\t\t\t\t\t\tentryName !== '.' && entryName !== '..'\n\t\t\t\t)\n\t\t\t\t.map(async (entryName: string) => {\n\t\t\t\t\tconst memfsPath = joinPaths(memfsParent, entryName);\n\t\t\t\t\tif (!isMemfsDir(FS, memfsPath)) {\n\t\t\t\t\t\tfilesToCreate.push([opfsDir, memfsPath, entryName]);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst handle = await opfsDir.getDirectoryHandle(entryName, {\n\t\t\t\t\t\tcreate: true,\n\t\t\t\t\t});\n\t\t\t\t\treturn await mirrorMemfsDirectoryinOpfs(memfsPath, handle);\n\t\t\t\t})\n\t\t);\n\t}\n\tawait mirrorMemfsDirectoryinOpfs(memfsRoot, opfsRoot);\n\n\t// Now let's create all the required files in OPFS. This can be quite slow\n\t// so we report progress. Throttle the progress callback to avoid flooding\n\t// the main thread with excessive updates.\n\tlet numFilesCompleted = 0;\n\tconst throttledProgressCallback = onProgress && throttle(onProgress, 100);\n\n\t// Limit max concurrent writes because Safari may otherwise encounter\n\t// an error like \"UnknownError: Invalid platform file handle\" after opening\n\t// a sufficient number of FileSyncAccessHandles (near 128).\n\t// 2024-09-21: This limit was chosen based on perceived performance while\n\t// testing with Safari, Chrome, and Firefox. It felt like a sweet spot.\n\t// Writing one-at-a-time with no concurrency had similar performance\n\t// but felt slightly slower. We can revisit and take better measurements\n\t// if needed.\n\tconst maxConcurrentWrites = 100;\n\tconst concurrentWrites = new Set();\n\n\ttry {\n\t\tfor (const [opfsDir, memfsPath, entryName] of filesToCreate) {\n\t\t\tconst promise = overwriteOpfsFile(\n\t\t\t\topfsDir,\n\t\t\t\tentryName,\n\t\t\t\tFS,\n\t\t\t\tmemfsPath\n\t\t\t).then(() => {\n\t\t\t\tnumFilesCompleted++;\n\t\t\t\tconcurrentWrites.delete(promise);\n\n\t\t\t\tthrottledProgressCallback?.({\n\t\t\t\t\tfiles: numFilesCompleted,\n\t\t\t\t\ttotal: filesToCreate.length,\n\t\t\t\t});\n\t\t\t});\n\t\t\tconcurrentWrites.add(promise);\n\n\t\t\tif (concurrentWrites.size >= maxConcurrentWrites) {\n\t\t\t\tawait Promise.race(concurrentWrites);\n\t\t\t\tthrottledProgressCallback?.({\n\t\t\t\t\tfiles: numFilesCompleted,\n\t\t\t\t\ttotal: filesToCreate.length,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t} finally {\n\t\t// Make sure all FS-related activity has completed one way or another\n\t\t// before returning. Otherwise, an error followed by a retry might lead\n\t\t// to a conflict with writes from the earlier attempt.\n\t\tawait Promise.allSettled(concurrentWrites);\n\t}\n}\n\nfunction isMemfsDir(FS: Emscripten.RootFS, path: string) {\n\treturn FS.isDir(FS.lookupPath(path, { follow: true }).node.mode);\n}\n\nasync function overwriteOpfsFile(\n\topfsParent: FileSystemDirectoryHandle,\n\tname: string,\n\tFS: Emscripten.RootFS,\n\tmemfsPath: string\n) {\n\tlet buffer;\n\ttry {\n\t\tbuffer = FS.readFile(memfsPath, {\n\t\t\tencoding: 'binary',\n\t\t});\n\t} catch {\n\t\t// File was removed, ignore\n\t\treturn;\n\t}\n\n\tconst opfsFile = await opfsParent.getFileHandle(name, { create: true });\n\tconst writer =\n\t\topfsFile.createWritable !== undefined\n\t\t\t? // Google Chrome, Firefox, probably more browsers\n\t\t\t await opfsFile.createWritable()\n\t\t\t: // Safari\n\t\t\t await opfsFile.createSyncAccessHandle();\n\ttry {\n\t\tawait writer.truncate(0);\n\t\tawait writer.write(buffer);\n\t} finally {\n\t\tawait writer.close();\n\t}\n}\n\nexport function journalFSEventsToOpfs(\n\tphp: PHP,\n\topfsRoot: FileSystemDirectoryHandle,\n\tmemfsRoot: string\n) {\n\tconst journal: FilesystemOperation[] = [];\n\tconst unbindJournal = journalFSEvents(php, memfsRoot, (entry) => {\n\t\tjournal.push(entry);\n\t});\n\tconst rewriter = new OpfsRewriter(php, opfsRoot, memfsRoot);\n\n\tasync function flushJournal() {\n\t\tif (journal.length === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst release = await php.semaphore.acquire();\n\n\t\t// Concurrency safety note\n\t\t// As I understand it, journal is specific to a PHP instance,\n\t\t// so it's not possible to have concurrency push of entries to journal\n\t\t// But this can change in future so it doesn't hurt to read from journal\n\t\t// in a concurrent safe way, which is what we are doing here.\n\n\t\t// We first copy it to a new array\n\t\tconst journalEntries = [...journal];\n\t\t// and then only delete however many entries we were able to grab\n\t\t// since with concurrent writes there could have been more insertions\n\t\tjournal.splice(0, journalEntries.length);\n\n\t\tconst compressedJournal = normalizeFilesystemOperations(journalEntries);\n\t\ttry {\n\t\t\t// @TODO This is way too slow in practice, we need to batch the\n\t\t\t// changes into groups of parallelizable operations.\n\t\t\tfor (const entry of compressedJournal) {\n\t\t\t\tawait rewriter.processEntry(entry);\n\t\t\t}\n\t\t} finally {\n\t\t\trelease();\n\t\t}\n\t}\n\tphp.addEventListener('request.end', flushJournal);\n\tphp.addEventListener('filesystem.write', flushJournal);\n\treturn function () {\n\t\tunbindJournal();\n\t\tphp.removeEventListener('request.end', flushJournal);\n\t\tphp.removeEventListener('filesystem.write', flushJournal);\n\t};\n}\n\ntype JournalEntry = FilesystemOperation;\n\nclass OpfsRewriter {\n\tprivate memfsRoot: string;\n\tprivate php: PHP;\n\tprivate opfs: FileSystemDirectoryHandle;\n\n\tconstructor(php: PHP, opfs: FileSystemDirectoryHandle, memfsRoot: string) {\n\t\tthis.php = php;\n\t\tthis.opfs = opfs;\n\t\tthis.memfsRoot = normalizeMemfsPath(memfsRoot);\n\t}\n\n\tprivate toOpfsPath(path: string) {\n\t\treturn normalizeMemfsPath(path.substring(this.memfsRoot.length));\n\t}\n\n\tpublic async processEntry(entry: JournalEntry) {\n\t\tif (\n\t\t\t!entry.path.startsWith(this.memfsRoot) ||\n\t\t\tentry.path === this.memfsRoot\n\t\t) {\n\t\t\treturn;\n\t\t}\n\t\tconst opfsPath = this.toOpfsPath(entry.path);\n\t\tconst opfsParent = await resolveParent(this.opfs, opfsPath);\n\t\tconst name = getFilename(opfsPath);\n\t\tif (!name) {\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tif (entry.operation === 'DELETE') {\n\t\t\t\ttry {\n\t\t\t\t\tawait opfsParent.removeEntry(name, {\n\t\t\t\t\t\trecursive: true,\n\t\t\t\t\t});\n\t\t\t\t} catch {\n\t\t\t\t\t// If the directory already doesn't exist, it's fine\n\t\t\t\t}\n\t\t\t} else if (entry.operation === 'CREATE') {\n\t\t\t\tif (entry.nodeType === 'directory') {\n\t\t\t\t\tawait opfsParent.getDirectoryHandle(name, {\n\t\t\t\t\t\tcreate: true,\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tawait opfsParent.getFileHandle(name, {\n\t\t\t\t\t\tcreate: true,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} else if (entry.operation === 'WRITE') {\n\t\t\t\tawait overwriteOpfsFile(\n\t\t\t\t\topfsParent,\n\t\t\t\t\tname,\n\t\t\t\t\tthis.php[__private__dont__use].FS,\n\t\t\t\t\tentry.path\n\t\t\t\t);\n\t\t\t} else if (\n\t\t\t\tentry.operation === 'RENAME' &&\n\t\t\t\tentry.toPath.startsWith(this.memfsRoot)\n\t\t\t) {\n\t\t\t\tconst opfsTargetPath = this.toOpfsPath(entry.toPath);\n\t\t\t\tconst opfsTargetParent = await resolveParent(\n\t\t\t\t\tthis.opfs,\n\t\t\t\t\topfsTargetPath\n\t\t\t\t);\n\n\t\t\t\tif (entry.nodeType === 'directory') {\n\t\t\t\t\tconst opfsDir = await opfsTargetParent.getDirectoryHandle(\n\t\t\t\t\t\tname,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcreate: true,\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t\t\t// in OPFS, move() doesn't work for directories :-(\n\t\t\t\t\t// We have to copy the directory recursively instead.\n\t\t\t\t\tawait copyMemfsToOpfs(\n\t\t\t\t\t\tthis.php[__private__dont__use].FS,\n\t\t\t\t\t\topfsDir,\n\t\t\t\t\t\tentry.toPath\n\t\t\t\t\t);\n\t\t\t\t\t// Then delete the old directory\n\t\t\t\t\tawait opfsParent.removeEntry(name, {\n\t\t\t\t\t\trecursive: true,\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\t/**\n\t\t\t\t\t * Delete the old file and creating a new one.\n\t\t\t\t\t *\n\t\t\t\t\t * We cannot use the OPFS move() method here. Imagine pulling from\n\t\t\t\t\t * a Git repository – each pulled object is first buffered in a\n\t\t\t\t\t * file called \".tmp\" and then renamed to its final name. However,\n\t\t\t\t\t * the WRITE operation does not store the written bytes, only the\n\t\t\t\t\t * path.\n\t\t\t\t\t *\n\t\t\t\t\t * By the time the filesystem journal is flushed, we cannot\n\t\t\t\t\t * assume that the \"rename from\" path still contains the same bytes\n\t\t\t\t\t * as it did when the WRITE operation was executed. Therefore, it's\n\t\t\t\t\t * safer to delete the old file and create a new one.\n\t\t\t\t\t *\n\t\t\t\t\t * It is still possible that the new file was already deleted\n\t\t\t\t\t * or renamed to another location. That's fine. A later stage\n\t\t\t\t\t * of replaying the journal will take care of that.\n\t\t\t\t\t *\n\t\t\t\t\t * Ideally, PHP.wasm would not use journaling at all, but\n\t\t\t\t\t * a native WASMFS layer for handling OPFS.\n\t\t\t\t\t *\n\t\t\t\t\t * See https://github.com/WordPress/wordpress-playground/pull/1878\n\t\t\t\t\t * for more details.\n\t\t\t\t\t */\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait opfsParent.removeEntry(name);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// If the directory already doesn't exist, it's fine\n\t\t\t\t\t}\n\t\t\t\t\tawait overwriteOpfsFile(\n\t\t\t\t\t\topfsTargetParent,\n\t\t\t\t\t\tbasename(opfsTargetPath),\n\t\t\t\t\t\tthis.php[__private__dont__use].FS,\n\t\t\t\t\t\tentry.toPath\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (e) {\n\t\t\t// Useful for debugging – the original error gets lost in the\n\t\t\t// Comlink proxy.\n\t\t\tlogger.log({ entry, name });\n\t\t\tlogger.error(e);\n\t\t\tthrow e;\n\t\t}\n\t}\n}\n\nfunction normalizeMemfsPath(path: string) {\n\treturn path.replace(/\\/$/, '').replace(/\\/\\/+/g, '/');\n}\n\nfunction getFilename(path: string) {\n\treturn path.substring(path.lastIndexOf('/') + 1);\n}\n\nasync function resolveParent(\n\topfs: FileSystemDirectoryHandle,\n\trelativePath: string\n): Promise<FileSystemDirectoryHandle> {\n\tconst normalizedPath = relativePath\n\t\t.replace(/^\\/+|\\/+$/g, '')\n\t\t.replace(/\\/+/, '/');\n\tif (!normalizedPath) {\n\t\treturn opfs;\n\t}\n\tconst segments = normalizedPath.split('/');\n\tlet handle: FileSystemDirectoryHandle | FileSystemFileHandle = opfs;\n\tfor (let i = 0; i < segments.length - 1; i++) {\n\t\tconst segment = segments[i];\n\t\thandle = await handle.getDirectoryHandle(segment, { create: true });\n\t}\n\treturn handle as any;\n}\n\nfunction throttle<T extends (...args: any[]) => any>(\n\tfn: T,\n\tdebounceMs: number\n): T {\n\tlet lastCallTime = 0;\n\tlet timeoutId: ReturnType<typeof setTimeout> | undefined;\n\tlet pendingArgs: Parameters<T> | undefined;\n\n\treturn function throttledCallback(...args: Parameters<T>) {\n\t\tpendingArgs = args;\n\n\t\tconst timeSinceLastCall = Date.now() - lastCallTime;\n\t\tif (timeoutId === undefined) {\n\t\t\tconst delay = Math.max(0, debounceMs - timeSinceLastCall);\n\t\t\ttimeoutId = setTimeout(() => {\n\t\t\t\ttimeoutId = undefined;\n\t\t\t\tlastCallTime = Date.now();\n\t\t\t\tfn(...pendingArgs!);\n\t\t\t}, delay);\n\t\t}\n\t} as T;\n}\n"],"names":["getPHPLoaderModule","version","LatestSupportedPHPVersion","flipObject","obj","k","v","as2Bytes","value","as3Bytes","as8Bytes","buffer","ArrayBufferReader","length","ArrayBufferWriter","ExtensionTypes","ExtensionNames","ServerNameTypes","ServerNameNames","ServerNameExtension","data","view","offset","listLength","serverNameList","nameType","valueLength","serverNames","writer","CipherSuites","CipherSuitesNames","SupportedGroups","SupportedGroupsNames","SupportedGroupsExtension","reader","groups","group","ECPointFormats","ECPointFormatNames","ECPointFormatsExtension","formats","i","format","SignatureAlgorithms","SignatureAlgorithmsNames","HashAlgorithms","HashAlgorithmsNames","SignatureAlgorithmsExtension","parsedAlgorithms","hash","algorithm","logger","TLSExtensionsHandlers","parseClientHelloExtensions","parsed","initialOffset","extensionType","extensionTypeName","extensionLength","extensionBytes","handler","tls12Prf","secret","label","seed","outputLength","seedBytes","concatArrayBuffers","hmacKey","A","resultBuffers","hmacSha256","hmacInput","fragment","key","CompressionMethod","AlertLevels","AlertLevelNames","AlertDescriptions","AlertDescriptionNames","ContentTypes","HandshakeType","ECCurveTypes","ECNamedCurves","TLSConnectionClosed","TLS_Version_1_2","generalEcdheKeyPair","TLS_1_2_Connection","chunkStream","tlsConnection","chunk","e","certificatePrivateKey","certificatesDER","clientHelloRecord","serverRandom","MessageEncoder","ecdheKeyPair","clientRandom","serverKeyExchange","clientKeyExchangeRecord","serverPrivateKey","clientPublicKey","preMasterSecret","masterSecret","concatUint8Arrays","keyBlock","clientWriteKey","serverWriteKey","clientIV","serverIV","messageType","message","requestedType","record","accumulatedPayload","TLSDecoder","header","type","severity","description","done","resolve","requestedBytes","appData","contentType","payload","implicitIV","explicitIV","iv","decrypted","additionalData","ciphertextWithTag","cipherSuites","suite","msg_type","bodyBytes","body","buff","sessionIdLength","cipherSuitesLength","compressionMethodsLength","extensionsLength","chunkSize","controller","certsBodies","cert","certsBody","rsaPrivateKey","publicKey","params","signedParams","signatureBytes","signatureAlgorithm","clientHello","compressionAlgorithm","extensionsParts","extension","x","extensions","handshakeMessages","handshakeHash","verifyData","generateCertificate","issuerKeyPair","CertificateGenerator","certificateToPEM","certificate","formatPEM","encodeUint8ArrayAsBase64","privateKeyToPEM","privateKey","pkcs8","tbsDescription","subjectKeyPair","tbsCertificate","signature","ASN1Encoder","subjectPublicKey","serialNumber","oidByName","nameInfo","values","oidName","entry","validity","ASN1Tags","formatDateASN1","addYears","ca","pathLenConstraint","sequence","keyUsage","keyUsageBits","extKeyUsage","nsCertType","bits","altNames","generalNames","_a","name","dnsName","ipAddresses","_b","ip","ipAddress","sanExtensionValue","oids","requestedName","oid","constructedBit","tempLength","lengthBytesArray","numLengthBytes","result","tag","lengthBytes","number","extendedNumber","unusedBits","combined","oidParts","encodedParts","bytes","j","str","utf8Bytes","items","tagNumber","constructed","pemString","date","year","month","padNumber","day","hours","minutes","seconds","num","years","newDate","FirewallInterferenceError","url","status","statusText","CORS_PROXY_HEADER","fetchWithCorsProxy","input","init","corsProxyUrl","playgroundUrl","requestObject","playgroundUrlObj","requestUrlObj","httpsUrl","cloneRequest","request1","request2","teeRequest","corsProxyAllowedHeaders","requestIntendsToPassCredentials","newRequest","response","ChunkedDecoderStream","state","chunkRemainingBytes","chunkBytesNb","byte","chunkSizeHex","bytesToRead","tcpOverFetchWebsocket","emOptions","tcpOptions","_","host","port","TCPOverFetchWebsocket","wsOptions","options","CAroot","outputType","wsUrl","eventName","callback","wrapper","listeners","listener","guessProtocol","siteCert","request","RawBytesFetch","HTTP_METHODS","decodedFirstLine","method","error","encoder","headersObject","headers","string","requestBytesStream","protocol","inputBuffer","requestDataExhausted","headersEndIndex","requestBytesReader","findSequenceInBuffer","headersBuffer","parsedHeaders","terminationMode","contentLength","outboundBodyStream","seenBytes","last5Bytes","emptyChunk","index","hostname","httpRequestBytes","httpRequest","statusLineMaybe","path","line","bufferLength","sequenceLength","lastPossibleIndex","found","getIntlExtensionModule","withIntl","memoizedFetch","createMemoizedFetch","extensionName","dataName","extensionPath","dataPath","ICUData","phpRuntime","FSHelpers","fakeWebsocket","WebSocketConstructor","loadWebRuntime","phpVersion","loaderOptions","fn","emscriptenOptions","phpLoaderModule","loadPHPRuntime","setupPostMessageRelay","nestedFrame","expectedOrigin","event","spawnPHPWorkerThread","workerUrl","worker","reject","onStartup","createDirectoryHandleMountHandler","handle","php","FS","vfsMountPoint","copyOpfsToMemfs","copyMemfsToOpfs","journalFSEventsToOpfs","opfsRoot","memfsRoot","semaphore","Semaphore","ops","stack","opfsParent","memfsParentPath","opfsHandle","op","memfsEntryPath","joinPaths","file","byteArray","onProgress","filesToCreate","mirrorMemfsDirectoryinOpfs","memfsParent","opfsDir","entryName","memfsPath","isMemfsDir","numFilesCompleted","throttledProgressCallback","throttle","maxConcurrentWrites","concurrentWrites","promise","overwriteOpfsFile","opfsFile","journal","unbindJournal","journalFSEvents","rewriter","OpfsRewriter","flushJournal","release","journalEntries","compressedJournal","normalizeFilesystemOperations","opfs","normalizeMemfsPath","opfsPath","resolveParent","getFilename","__private__dont__use","opfsTargetPath","opfsTargetParent","basename","relativePath","normalizedPath","segments","segment","debounceMs","lastCallTime","timeoutId","pendingArgs","args","timeSinceLastCall","delay"],"mappings":"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"}