import assert from "assert"; import { describe, expect } from "bun:test"; import { itBundled } from "./expectBundled"; describe("bundler", () => { const nodePolyfillList = { "assert": "polyfill", "buffer": "polyfill", "child_process": "no-op", "cluster": "no-op", "console": "polyfill", "constants": "polyfill", "crypto": "polyfill", "dgram": "no-op", "dns": "no-op", "domain": "polyfill", "events": "polyfill", "fs": "no-op", "http": "polyfill", "https": "polyfill", "module": "no-op", "net": "polyfill", "os": "polyfill", "path": "polyfill", "perf_hooks": "no-op", "process": "polyfill", "punycode": "polyfill", "querystring": "polyfill", "readline": "no-op", "repl": "no-op", "stream": "polyfill", "string_decoder": "polyfill", "sys": "polyfill", "timers": "polyfill", "tls": "no-op", "tty": "polyfill", "url": "polyfill", "util": "polyfill", "v8": "no-op", "vm": "no-op", "zlib": "polyfill", }; itBundled("browser/NodeBuffer#21522", { files: { "/entry.js": /* js */ ` import { Buffer } from "node:buffer"; const x = Buffer.alloc(5); x.write("68656c6c6f", "hex"); console.log(x); `, }, target: "browser", run: { stdout: "", }, onAfterBundle(api) { api.expectFile("out.js").not.toInclude("import "); }, }); itBundled("browser/NodeBuffer#12272", { files: { "/entry.js": /* js */ ` import * as buffer from "node:buffer"; import { Buffer } from "buffer"; import Buffer2 from "buffer"; import { Blob, File } from "buffer"; if (Buffer !== Buffer2) throw new Error("Buffer is not the same"); if (Blob !== globalThis.Blob) throw new Error("Blob is not the same"); if (File !== globalThis.File) throw new Error("File is not the same"); if (Buffer.from("foo").toString("hex") !== "666f6f") throw new Error("Buffer.from is broken"); if (buffer.isAscii("foo") !== true) throw new Error("Buffer.isAscii is broken"); if (Buffer2.alloc(10, 'b').toString("hex") !== "62626262626262626262") throw new Error("Buffer.alloc is broken"); console.log("Success!"); `, }, target: "browser", run: { stdout: "Success!", }, onAfterBundle(api) { api.expectFile("out.js").not.toInclude("import "); }, }); itBundled("browser/NodeFS", { files: { "/entry.js": /* js */ ` import * as fs from "node:fs"; import * as fs2 from "fs"; import { readFileSync } from "fs"; console.log(typeof fs); console.log(typeof fs2); console.log(typeof readFileSync); `, }, target: "browser", run: { stdout: "function\nfunction\nundefined", }, onAfterBundle(api) { api.expectFile("out.js").not.toInclude("import "); }, }); itBundled("browser/NodeTTY", { files: { "/entry.js": /* js */ ` import { isatty, ReadStream, WriteStream } from "node:tty"; console.log(typeof ReadStream); console.log(typeof WriteStream); console.log(isatty(0)); `, }, target: "browser", run: { stdout: "function\nfunction\nfalse", }, onAfterBundle(api) { api.expectFile("out.js").not.toInclude("import "); }, }); // TODO: use nodePolyfillList to generate the code in here. const NodePolyfills = itBundled("browser/NodePolyfills", { files: { "/entry.js": /* js */ ` import * as assert from "node:assert"; import * as buffer from "node:buffer"; import * as child_process from "node:child_process"; import * as cluster from "node:cluster"; import * as console2 from "node:console"; import * as constants from "node:constants"; import * as crypto from "node:crypto"; import * as dgram from "node:dgram"; import * as dns from "node:dns"; import * as domain from "node:domain"; import * as events from "node:events"; import * as fs from "node:fs"; import * as http from "node:http"; import * as https from "node:https"; import * as module2 from "node:module"; import * as net from "node:net"; import * as os from "node:os"; import * as path from "node:path"; import * as perf_hooks from "node:perf_hooks"; import * as process from "node:process"; import * as punycode from "node:punycode"; import * as querystring from "node:querystring"; import * as readline from "node:readline"; import * as repl from "node:repl"; import * as stream from "node:stream"; import * as string_decoder from "node:string_decoder"; import * as sys from "node:sys"; import * as timers from "node:timers"; import * as tls from "node:tls"; import * as tty from "node:tty"; import * as url from "node:url"; import * as util from "node:util"; import * as v8 from "node:v8"; import * as vm from "node:vm"; import * as zlib from "node:zlib"; const modules = { assert, buffer, child_process, cluster, console2, constants, crypto, dgram, dns, domain, events, fs, http, https, module: module2, net, os, path, perf_hooks, process, punycode, querystring, readline, repl, stream, string_decoder, sys, timers, tls, tty, url, util, v8, vm, zlib, } console.log(Bun.inspect(modules)) `, }, target: "browser", run: { stdout: "{\n assert: {\n throws: [Getter/Setter],\n strictEqual: [Getter/Setter],\n strict: [Getter/Setter],\n rejects: [Getter/Setter],\n ok: [Getter/Setter],\n notStrictEqual: [Getter/Setter],\n notEqual: [Getter/Setter],\n notDeepStrictEqual: [Getter/Setter],\n notDeepEqual: [Getter/Setter],\n match: [Getter/Setter],\n ifError: [Getter/Setter],\n fail: [Getter/Setter],\n equal: [Getter/Setter],\n doesNotThrow: [Getter/Setter],\n doesNotReject: [Getter/Setter],\n doesNotMatch: [Getter/Setter],\n default: [Getter/Setter],\n deepStrictEqual: [Getter/Setter],\n deepEqual: [Getter/Setter],\n CallTracker: [Getter/Setter],\n AssertionError: [Getter/Setter],\n },\n buffer: {\n transcode: [Getter/Setter],\n resolveObjectURL: [Getter/Setter],\n kStringMaxLength: [Getter/Setter],\n kMaxLength: [Getter/Setter],\n isUtf8: [Getter/Setter],\n isAscii: [Getter/Setter],\n default: [Getter/Setter],\n constants: [Getter/Setter],\n btoa: [Getter/Setter],\n atob: [Getter/Setter],\n INSPECT_MAX_BYTES: [Getter/Setter],\n File: [Getter/Setter],\n Buffer: [Getter/Setter],\n Blob: [Getter/Setter],\n },\n child_process: [Function: child_process],\n cluster: [Function: cluster],\n console2: {\n default: [Getter/Setter],\n },\n constants: {\n X_OK: [Getter/Setter],\n W_OK: [Getter/Setter],\n UV_UDP_REUSEADDR: [Getter/Setter],\n S_IXUSR: [Getter/Setter],\n S_IXOTH: [Getter/Setter],\n S_IXGRP: [Getter/Setter],\n S_IWUSR: [Getter/Setter],\n S_IWOTH: [Getter/Setter],\n S_IWGRP: [Getter/Setter],\n S_IRWXU: [Getter/Setter],\n S_IRWXO: [Getter/Setter],\n S_IRWXG: [Getter/Setter],\n S_IRUSR: [Getter/Setter],\n S_IROTH: [Getter/Setter],\n S_IRGRP: [Getter/Setter],\n S_IFSOCK: [Getter/Setter],\n S_IFREG: [Getter/Setter],\n S_IFMT: [Getter/Setter],\n S_IFLNK: [Getter/Setter],\n S_IFIFO: [Getter/Setter],\n S_IFDIR: [Getter/Setter],\n S_IFCHR: [Getter/Setter],\n S_IFBLK: [Getter/Setter],\n SSL_OP_TLS_ROLLBACK_BUG: [Getter/Setter],\n SSL_OP_TLS_D5_BUG: [Getter/Setter],\n SSL_OP_TLS_BLOCK_PADDING_BUG: [Getter/Setter],\n SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG: [Getter/Setter],\n SSL_OP_SSLEAY_080_CLIENT_DH_BUG: [Getter/Setter],\n SSL_OP_SINGLE_ECDH_USE: [Getter/Setter],\n SSL_OP_SINGLE_DH_USE: [Getter/Setter],\n SSL_OP_PKCS1_CHECK_2: [Getter/Setter],\n SSL_OP_PKCS1_CHECK_1: [Getter/Setter],\n SSL_OP_NO_TLSv1_2: [Getter/Setter],\n SSL_OP_NO_TLSv1_1: [Getter/Setter],\n SSL_OP_NO_TLSv1: [Getter/Setter],\n SSL_OP_NO_TICKET: [Getter/Setter],\n SSL_OP_NO_SSLv3: [Getter/Setter],\n SSL_OP_NO_SSLv2: [Getter/Setter],\n SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION: [Getter/Setter],\n SSL_OP_NO_QUERY_MTU: [Getter/Setter],\n SSL_OP_NO_COMPRESSION: [Getter/Setter],\n SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG: [Getter/Setter],\n SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG: [Getter/Setter],\n SSL_OP_NETSCAPE_CHALLENGE_BUG: [Getter/Setter],\n SSL_OP_NETSCAPE_CA_DN_BUG: [Getter/Setter],\n SSL_OP_MSIE_SSLV2_RSA_PADDING: [Getter/Setter],\n SSL_OP_MICROSOFT_SESS_ID_BUG: [Getter/Setter],\n SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER: [Getter/Setter],\n SSL_OP_LEGACY_SERVER_CONNECT: [Getter/Setter],\n SSL_OP_EPHEMERAL_RSA: [Getter/Setter],\n SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS: [Getter/Setter],\n SSL_OP_CRYPTOPRO_TLSEXT_BUG: [Getter/Setter],\n SSL_OP_COOKIE_EXCHANGE: [Getter/Setter],\n SSL_OP_CISCO_ANYCONNECT: [Getter/Setter],\n SSL_OP_CIPHER_SERVER_PREFERENCE: [Getter/Setter],\n SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION: [Getter/Setter],\n SSL_OP_ALL: [Getter/Setter],\n SIGXFSZ: [Getter/Setter],\n SIGXCPU: [Getter/Setter],\n SIGWINCH: [Getter/Setter],\n SIGVTALRM: [Getter/Setter],\n SIGUSR2: [Getter/Setter],\n SIGUSR1: [Getter/Setter],\n SIGURG: [Getter/Setter],\n SIGTTOU: [Getter/Setter],\n SIGTTIN: [Getter/Setter],\n SIGTSTP: [Getter/Setter],\n SIGTRAP: [Getter/Setter],\n SIGTERM: [Getter/Setter],\n SIGSYS: [Getter/Setter],\n SIGSTOP: [Getter/Setter],\n SIGSEGV: [Getter/Setter],\n SIGQUIT: [Getter/Setter],\n SIGPROF: [Getter/Setter],\n SIGPIPE: [Getter/Setter],\n SIGKILL: [Getter/Setter],\n SIGIOT: [Getter/Setter],\n SIGIO: [Getter/Setter],\n SIGINT: [Getter/Setter],\n SIGILL: [Getter/Setter],\n SIGHUP: [Getter/Setter],\n SIGFPE: [Getter/Setter],\n SIGCONT: [Getter/Setter],\n SIGCHLD: [Getter/Setter],\n SIGBUS: [Getter/Setter],\n SIGALRM: [Getter/Setter],\n SIGABRT: [Getter/Setter],\n R_OK: [Getter/Setter],\n RSA_X931_PADDING: [Getter/Setter],\n RSA_SSLV23_PADDING: [Getter/Setter],\n RSA_PKCS1_PSS_PADDING: [Getter/Setter],\n RSA_PKCS1_PADDING: [Getter/Setter],\n RSA_PKCS1_OAEP_PADDING: [Getter/Setter],\n RSA_NO_PADDING: [Getter/Setter],\n POINT_CONVERSION_UNCOMPRESSED: [Getter/Setter],\n POINT_CONVERSION_HYBRID: [Getter/Setter],\n POINT_CONVERSION_COMPRESSED: [Getter/Setter],\n O_WRONLY: [Getter/Setter],\n O_TRUNC: [Getter/Setter],\n O_SYNC: [Getter/Setter],\n O_SYMLINK: [Getter/Setter],\n O_RDWR: [Getter/Setter],\n O_RDONLY: [Getter/Setter],\n O_NONBLOCK: [Getter/Setter],\n O_NOFOLLOW: [Getter/Setter],\n O_NOCTTY: [Getter/Setter],\n O_EXCL: [Getter/Setter],\n O_DIRECTORY: [Getter/Setter],\n O_CREAT: [Getter/Setter],\n O_APPEND: [Getter/Setter],\n NPN_ENABLED: [Getter/Setter],\n F_OK: [Getter/Setter],\n EXDEV: [Getter/Setter],\n EWOULDBLOCK: [Getter/Setter],\n ETXTBSY: [Getter/Setter],\n ETIMEDOUT: [Getter/Setter],\n ETIME: [Getter/Setter],\n ESTALE: [Getter/Setter],\n ESRCH: [Getter/Setter],\n ESPIPE: [Getter/Setter],\n EROFS: [Getter/Setter],\n ERANGE: [Getter/Setter],\n EPROTOTYPE: [Getter/Setter],\n EPROTONOSUPPORT: [Getter/Setter],\n EPROTO: [Getter/Setter],\n EPIPE: [Getter/Setter],\n EPERM: [Getter/Setter],\n EOVERFLOW: [Getter/Setter],\n EOPNOTSUPP: [Getter/Setter],\n ENXIO: [Getter/Setter],\n ENOTTY: [Getter/Setter],\n ENOTSUP: [Getter/Setter],\n ENOTSOCK: [Getter/Setter],\n ENOTEMPTY: [Getter/Setter],\n ENOTDIR: [Getter/Setter],\n ENOTCONN: [Getter/Setter],\n ENOSYS: [Getter/Setter],\n ENOSTR: [Getter/Setter],\n ENOSR: [Getter/Setter],\n ENOSPC: [Getter/Setter],\n ENOPROTOOPT: [Getter/Setter],\n ENOMSG: [Getter/Setter],\n ENOMEM: [Getter/Setter],\n ENOLINK: [Getter/Setter],\n ENOLCK: [Getter/Setter],\n ENOEXEC: [Getter/Setter],\n ENOENT: [Getter/Setter],\n ENODEV: [Getter/Setter],\n ENODATA: [Getter/Setter],\n ENOBUFS: [Getter/Setter],\n ENGINE_METHOD_STORE: [Getter/Setter],\n ENGINE_METHOD_RAND: [Getter/Setter],\n ENGINE_METHOD_PKEY_METHS: [Getter/Setter],\n ENGINE_METHOD_PKEY_ASN1_METHS: [Getter/Setter],\n ENGINE_METHOD_NONE: [Getter/Setter],\n ENGINE_METHOD_ECDSA: [Getter/Setter],\n ENGINE_METHOD_ECDH: [Getter/Setter],\n ENGINE_METHOD_DSA: [Getter/Setter],\n ENGINE_METHOD_DIGESTS: [Getter/Setter],\n ENGINE_METHOD_DH: [Getter/Setter],\n ENGINE_METHOD_CIPHERS: [Getter/Setter],\n ENGINE_METHOD_ALL: [Getter/Setter],\n ENFILE: [Getter/Setter],\n ENETUNREACH: [Getter/Setter],\n ENETRESET: [Getter/Setter],\n ENETDOWN: [Getter/Setter],\n ENAMETOOLONG: [Getter/Setter],\n EMULTIHOP: [Getter/Setter],\n EMSGSIZE: [Getter/Setter],\n EMLINK: [Getter/Setter],\n EMFILE: [Getter/Setter],\n ELOOP: [Getter/Setter],\n EISDIR: [Getter/Setter],\n EISCONN: [Getter/Setter],\n EIO: [Getter/Setter],\n EINVAL: [Getter/Setter],\n EINTR: [Getter/Setter],\n EINPROGRESS: [Getter/Setter],\n EILSEQ: [Getter/Setter],\n EIDRM: [Getter/Setter],\n EHOSTUNREACH: [Getter/Setter],\n EFBIG: [Getter/Setter],\n EFAULT: [Getter/Setter],\n EEXIST: [Getter/Setter],\n EDQUOT: [Getter/Setter],\n EDOM: [Getter/Setter],\n EDESTADDRREQ: [Getter/Setter],\n EDEADLK: [Getter/Setter],\n ECONNRESET: [Getter/Setter],\n ECONNREFUSED: [Getter/Setter],\n ECONNABORTED: [Getter/Setter],\n ECHILD: [Getter/Setter],\n ECANCELED: [Getter/Setter],\n EBUSY: [Getter/Setter],\n EBADMSG: [Getter/Setter],\n EBADF: [Getter/Setter],\n EALREADY: [Getter/Setter],\n EAGAIN: [Getter/Setter],\n EAFNOSUPPORT: [Getter/Setter],\n EADDRNOTAVAIL: [Getter/Setter],\n EADDRINUSE: [Getter/Setter],\n EACCES: [Getter/Setter],\n E2BIG: [Getter/Setter],\n DH_UNABLE_TO_CHECK_GENERATOR: [Getter/Setter],\n DH_NOT_SUITABLE_GENERATOR: [Getter/Setter],\n DH_CHECK_P_NOT_SAFE_PRIME: [Getter/Setter],\n DH_CHECK_P_NOT_PRIME: [Getter/Setter],\n },\n crypto: {\n webcrypto: [Getter/Setter],\n rng: [Getter/Setter],\n randomUUID: [Getter/Setter],\n randomFillSync: [Getter/Setter],\n randomFill: [Getter/Setter],\n randomBytes: [Getter/Setter],\n publicEncrypt: [Getter/Setter],\n publicDecrypt: [Getter/Setter],\n pseudoRandomBytes: [Getter/Setter],\n prng: [Getter/Setter],\n privateEncrypt: [Getter/Setter],\n privateDecrypt: [Getter/Setter],\n pbkdf2Sync: [Getter/Setter],\n pbkdf2: [Getter/Setter],\n listCiphers: [Getter/Setter],\n getRandomValues: [Getter/Setter],\n getHashes: [Getter/Setter],\n getDiffieHellman: [Getter/Setter],\n getCurves: [Getter/Setter],\n getCiphers: [Getter/Setter],\n default: [Getter/Setter],\n createVerify: [Getter/Setter],\n createSign: [Getter/Setter],\n createHmac: [Getter/Setter],\n createHash: [Getter/Setter],\n createECDH: [Getter/Setter],\n createDiffieHellmanGroup: [Getter/Setter],\n createDiffieHellman: [Getter/Setter],\n createDecipheriv: [Getter/Setter],\n createDecipher: [Getter/Setter],\n createCredentials: [Getter/Setter],\n createCipheriv: [Getter/Setter],\n createCipher: [Getter/Setter],\n constants: [Getter/Setter],\n Verify: [Getter/Setter],\n Sign: [Getter/Setter],\n Hmac: [Getter/Setter],\n Hash: [Getter/Setter],\n DiffieHellmanGroup: [Getter/Setter],\n DiffieHellman: [Getter/Setter],\n Decipheriv: [Getter/Setter],\n Decipher: [Getter/Setter],\n DEFAULT_ENCODING: [Getter/Setter],\n Cipheriv: [Getter/Setter],\n Cipher: [Getter/Setter],\n },\n dgram: [Function: dgram],\n dns: [Function: dns],\n domain: {\n createDomain: [Getter/Setter],\n create: [Getter/Setter],\n },\n events: {\n setMaxListeners: [Getter/Setter],\n once: [Getter/Setter],\n listenerCount: [Getter/Setter],\n init: [Getter/Setter],\n getMaxListeners: [Getter/Setter],\n getEventListeners: [Getter/Setter],\n default: [Getter/Setter],\n captureRejectionSymbol: [Getter/Setter],\n addAbortListener: [Getter/Setter],\n EventEmitter: [Getter/Setter],\n },\n fs: [Function: fs],\n http: {\n request: [Getter/Setter],\n globalAgent: [Getter/Setter],\n get: [Getter/Setter],\n default: [Getter/Setter],\n STATUS_CODES: [Getter/Setter],\n METHODS: [Getter/Setter],\n IncomingMessage: [Getter/Setter],\n ClientRequest: [Getter/Setter],\n Agent: [Getter/Setter],\n },\n https: {\n validateHeaderValue: [Getter/Setter],\n validateHeaderName: [Getter/Setter],\n setMaxIdleHTTPParsers: [Getter/Setter],\n request: [Getter/Setter],\n maxHeaderSize: [Getter/Setter],\n globalAgent: [Getter/Setter],\n get: [Getter/Setter],\n default: [Getter/Setter],\n createServer: [Getter/Setter],\n ServerResponse: [Getter/Setter],\n Server: [Getter/Setter],\n STATUS_CODES: [Getter/Setter],\n OutgoingMessage: [Getter/Setter],\n METHODS: [Getter/Setter],\n IncomingMessage: [Getter/Setter],\n ClientRequest: [Getter/Setter],\n Agent: [Getter/Setter],\n },\n module: [Function: module2],\n net: {\n isIPv6: [Getter/Setter],\n isIPv4: [Getter/Setter],\n isIP: [Getter/Setter],\n default: [Getter/Setter],\n },\n os: {\n uptime: [Getter/Setter],\n type: [Getter/Setter],\n totalmem: [Getter/Setter],\n tmpdir: [Getter/Setter],\n tmpDir: [Getter/Setter],\n release: [Getter/Setter],\n platform: [Getter/Setter],\n networkInterfaces: [Getter/Setter],\n loadavg: [Getter/Setter],\n hostname: [Getter/Setter],\n homedir: [Getter/Setter],\n getNetworkInterfaces: [Getter/Setter],\n freemem: [Getter/Setter],\n endianness: [Getter/Setter],\n cpus: [Getter/Setter],\n arch: [Getter/Setter],\n EOL: [Getter/Setter],\n },\n path: {\n sep: [Getter/Setter],\n resolve: [Getter/Setter],\n relative: [Getter/Setter],\n posix: [Getter/Setter],\n parse: [Getter/Setter],\n normalize: [Getter/Setter],\n join: [Getter/Setter],\n isAbsolute: [Getter/Setter],\n format: [Getter/Setter],\n extname: [Getter/Setter],\n dirname: [Getter/Setter],\n delimiter: [Getter/Setter],\n default: [Getter/Setter],\n basename: [Getter/Setter],\n _makeLong: [Getter/Setter],\n },\n perf_hooks: [Function: perf_hooks],\n process: {\n versions: [Getter/Setter],\n version: [Getter/Setter],\n umask: [Getter/Setter],\n title: [Getter/Setter],\n removeListener: [Getter/Setter],\n removeAllListeners: [Getter/Setter],\n prependOnceListener: [Getter/Setter],\n prependListener: [Getter/Setter],\n once: [Getter/Setter],\n on: [Getter/Setter],\n off: [Getter/Setter],\n nextTick: [Getter/Setter],\n listeners: [Getter/Setter],\n env: [Getter/Setter],\n emit: [Getter/Setter],\n cwd: [Getter/Setter],\n chdir: [Getter/Setter],\n browser: [Getter/Setter],\n binding: [Getter/Setter],\n argv: [Getter/Setter],\n addListener: [Getter/Setter],\n },\n punycode: {\n default: [Getter/Setter],\n },\n querystring: {\n unescapeBuffer: [Getter/Setter],\n unescape: [Getter/Setter],\n stringify: [Getter/Setter],\n parse: [Getter/Setter],\n escape: [Getter/Setter],\n encode: [Getter/Setter],\n default: [Getter/Setter],\n decode: [Getter/Setter],\n },\n readline: [Function: readline],\n repl: [Function: repl],\n stream: Function {\n default: [Stream: Readable],\n length: [Getter],\n name: [Getter],\n prototype: [Getter],\n ReadableState: [Getter],\n _fromList: [Getter],\n from: [Getter],\n fromWeb: [Getter],\n toWeb: [Getter],\n wrap: [Getter],\n _uint8ArrayToBuffer: [Getter],\n _isUint8Array: [Getter],\n isDisturbed: [Getter],\n isErrored: [Getter],\n isReadable: [Getter],\n Readable: [Getter],\n Writable: [Getter],\n Duplex: [Getter],\n Transform: [Getter],\n PassThrough: [Getter],\n addAbortSignal: [Getter],\n finished: [Getter],\n destroy: [Getter],\n pipeline: [Getter],\n compose: [Getter],\n Stream: [Getter],\n isDestroyed: [Function: isDestroyed],\n isWritable: [Function: isWritable],\n setDefaultHighWaterMark: [Function: setDefaultHighWaterMark],\n getDefaultHighWaterMark: [Function: getDefaultHighWaterMark],\n promises: [Getter],\n },\n string_decoder: {\n default: [Getter/Setter],\n StringDecoder: [Getter/Setter],\n },\n sys: {\n types: [Getter/Setter],\n promisify: [Getter/Setter],\n log: [Getter/Setter],\n isUndefined: [Getter/Setter],\n isSymbol: [Getter/Setter],\n isString: [Getter/Setter],\n isRegExp: [Getter/Setter],\n isPrimitive: [Getter/Setter],\n isObject: [Getter/Setter],\n isNumber: [Getter/Setter],\n isNullOrUndefined: [Getter/Setter],\n isNull: [Getter/Setter],\n isFunction: [Getter/Setter],\n isError: [Getter/Setter],\n isDate: [Getter/Setter],\n isBuffer: [Getter/Setter],\n isBoolean: [Getter/Setter],\n isArray: [Getter/Setter],\n inspect: [Getter/Setter],\n inherits: [Getter/Setter],\n format: [Getter/Setter],\n deprecate: [Getter/Setter],\n default: [Getter/Setter],\n debuglog: [Getter/Setter],\n callbackifyOnRejected: [Getter/Setter],\n callbackify: [Getter/Setter],\n _extend: [Getter/Setter],\n TextEncoder: [Getter/Setter],\n TextDecoder: [Getter/Setter],\n },\n timers: {\n setTimeout: [Getter/Setter],\n setInterval: [Getter/Setter],\n setImmediate: [Getter/Setter],\n promises: [Getter/Setter],\n clearTimeout: [Getter/Setter],\n clearInterval: [Getter/Setter],\n clearImmediate: [Getter/Setter],\n _unrefActive: [Getter/Setter],\n },\n tls: [Function: tls],\n tty: {\n isatty: [Getter/Setter],\n default: [Getter/Setter],\n WriteStream: [Getter/Setter],\n ReadStream: [Getter/Setter],\n },\n url: {\n resolveObject: [Getter/Setter],\n resolve: [Getter/Setter],\n parse: [Getter/Setter],\n format: [Getter/Setter],\n default: [Getter/Setter],\n Url: [Getter/Setter],\n URLSearchParams: [Getter/Setter],\n URL: [Getter/Setter],\n },\n util: {\n types: [Getter/Setter],\n promisify: [Getter/Setter],\n log: [Getter/Setter],\n isUndefined: [Getter/Setter],\n isSymbol: [Getter/Setter],\n isString: [Getter/Setter],\n isRegExp: [Getter/Setter],\n isPrimitive: [Getter/Setter],\n isObject: [Getter/Setter],\n isNumber: [Getter/Setter],\n isNullOrUndefined: [Getter/Setter],\n isNull: [Getter/Setter],\n isFunction: [Getter/Setter],\n isError: [Getter/Setter],\n isDate: [Getter/Setter],\n isBuffer: [Getter/Setter],\n isBoolean: [Getter/Setter],\n isArray: [Getter/Setter],\n inspect: [Getter/Setter],\n inherits: [Getter/Setter],\n format: [Getter/Setter],\n deprecate: [Getter/Setter],\n default: [Getter/Setter],\n debuglog: [Getter/Setter],\n callbackifyOnRejected: [Getter/Setter],\n callbackify: [Getter/Setter],\n _extend: [Getter/Setter],\n TextEncoder: [Getter/Setter],\n TextDecoder: [Getter/Setter],\n },\n v8: [Function: v8],\n vm: [Function: vm],\n zlib: {\n default: [Getter/Setter],\n },\n}", validate(ctx) {}, }, }); itBundled("browser/NodePolyfillExternal", { todo: true, skipOnEsbuild: true, files: { "/entry.js": NodePolyfills.options.files["/entry.js"], }, target: "browser", external: Object.keys(nodePolyfillList), onAfterBundle(api) { const file = api.readFile("/out.js"); const imports = new Bun.Transpiler().scanImports(file); expect(imports).toStrictEqual( Object.keys(nodePolyfillList).map(x => ({ kind: "import-statement", path: "node:" + x, })), ); }, }); // unsure: do we want polyfills or no-op stuff like node:* has // right now all error except bun:wrap which errors at resolve time, but is included if external const bunModules: Record = { "bun": "error", "bun:ffi": "error", "bun:dns": "error", "bun:test": "error", "bun:sqlite": "error", // "bun:wrap": "error", "bun:internal": "error", "bun:jsc": "error", }; const nonErroringBunModules = Object.entries(bunModules) .filter(x => x[1] !== "error") .map(x => x[0]); // all of them are set to error so this test doesnt make sense to run itBundled.skip("browser/BunPolyfill", { skipOnEsbuild: true, files: { "/entry.js": ` ${nonErroringBunModules.map((x, i) => `import * as bun_${i} from "${x}";`).join("\n")} function scan(obj) { if (typeof obj === 'function') obj = obj() return Object.keys(obj).length === 0 ? 'no-op' : 'polyfill' } ${nonErroringBunModules.map((x, i) => `console.log("${x.padEnd(12, " ")}:", scan(bun_${i}));`).join("\n")} `, }, target: "browser", onAfterBundle(api) { assert(!api.readFile("/out.js").includes("\0"), "bundle should not contain null bytes"); const file = api.readFile("/out.js"); const imports = new Bun.Transpiler().scanImports(file); expect(imports).toStrictEqual([]); }, run: { stdout: nonErroringBunModules.map(x => `${x.padEnd(12, " ")}: ${bunModules[x]}`).join("\n"), }, }); const ImportBunError = itBundled("browser/ImportBunError", { skipOnEsbuild: true, files: { "/entry.js": ` ${Object.keys(bunModules) .map((x, i) => `import * as bun_${i} from "${x}";`) .join("\n")} ${Object.keys(bunModules) .map((x, i) => `console.log("${x.padEnd(12, " ")}:", !!bun_${i});`) .join("\n")} `, }, target: "browser", bundleErrors: { "/entry.js": Object.keys(bunModules) .filter(x => bunModules[x] === "error") .map(x => `Browser build cannot import Bun builtin: "${x}". When bundling for Bun, set target to 'bun'`), }, }); // not implemented right now itBundled("browser/BunPolyfillExternal", { skipOnEsbuild: true, files: ImportBunError.options.files, target: "browser", external: Object.keys(bunModules), onAfterBundle(api) { const file = api.readFile("/out.js"); const imports = new Bun.Transpiler().scanImports(file); expect(imports).toStrictEqual( Object.keys(bunModules).map(x => ({ kind: "import-statement", path: x, })), ); }, }); itBundled("browser/ImportNonExistentNodeBuiltinShouldError", { skipOnEsbuild: true, files: { "/entry.js": ` import net1 from "node:net1"; `, }, bundleErrors: { "/entry.js": [`Could not resolve: "node:net1". Maybe you need to "bun install"?`], }, }); itBundled("browser/ImportNonExistentWithoutNodePrefix", { skipOnEsbuild: true, files: { "/entry.js": ` import net1 from "net1"; `, }, bundleErrors: { "/entry.js": [`Could not resolve: "net1". Maybe you need to "bun install"?`], }, }); itBundled("browser/TargetNodeNonExistentBuiltinShouldBeExternal", { files: { "/entry.js": ` import net1 from "node:net1"; `, }, target: "node", onAfterBundle(api) { const contents = api.readFile("out.js"); expect(contents).toBe(""); }, }); itBundled("browser/AwaitUsingStatement", { files: { "/entry.js": ` async function test() { await using resource = { async [Symbol.asyncDispose]() { console.log("The function was called"); await 42; console.log("and the await finished"); } }; console.log("Before!"); } test(); `, }, target: "browser", run: { stdout: "Before!\nThe function was called\nand the await finished\n", }, }); itBundled("browser/UsingStatement", { files: { "/entry.js": ` function test() { using resource = { [Symbol.dispose]() { console.log("The dispose function was called"); } }; console.log("Before!"); } test(); `, }, target: "browser", run: { stdout: "Before!\nThe dispose function was called\n", }, }); });