diff options
author | 2022-01-19 02:29:07 -0800 | |
---|---|---|
committer | 2022-01-19 02:29:07 -0800 | |
commit | d3a93d527336af73df838d69ca42ad1b18adebb8 (patch) | |
tree | 726dad460bf4ee2608ffa9557943df11da56f8c3 /integration/bunjs-only-snippets | |
parent | ed9637de5056af4572ec5e0a75feee9ca858798e (diff) | |
download | bun-d3a93d527336af73df838d69ca42ad1b18adebb8.tar.gz bun-d3a93d527336af73df838d69ca42ad1b18adebb8.tar.zst bun-d3a93d527336af73df838d69ca42ad1b18adebb8.zip |
`fs.*Sync()`, `bun wiptest`, and More ™ (#106)
* very very wip
* almost ready to fix the errors
* Update identity_context.zig
* Update base.zig
* [bun test] It runs successfully
* Remove unnecessary call
* [Bun.js] Improve JS <> Zig unicode string interop
This fixes longstanding unicode bugs with `console.log` & `fetch`.
I believe @evanwashere reported this first awhile ago
* [Bun.js] Implement `Object.is()` binding and a way to set a timeout for script execution
* Update PLCrashReport.zig
* [Bun.js] Make `console.log` more closely match Node.js and Deno
* [Bun.js] Implement formatting specifier for console.*
* Implement `console.clear()`
* bug fix
* Support console.clear()
* Buffer stderr
* [bun test] Begin implementing Node.js `fs`
* Update darwin_c.zig
* Implement more of `fs`
* `mkdir`, `mkdir` recursive, `mkdtemp`
* `open`, `read` (and pread)
* Move some things into more files
* Implement readdir
* `readFile`, `readLink`, and `realpath`
* `writeFile`, `symlink`, `chown`, `rename`, `stat`, `unlink`, `truncate`
* `lutimes`
* Implement `SystemError` and begin wiring up the `fs` module
* `"fs"` - Most of the arguments / validation
* `fs` - Rest of the arguments / validations
* Begin wiring up the `fs` module
* Fix all the build errors
* support printing typed arrays in console.log
* It...works?
* Support `require("fs")`, `import fs from 'fs';`, `import * as fs from 'fs'`
* Fix a couple bugs
* get rid of the crash reporter for now
* Update fs.exports.js
* [bun.js] slight improvement to startup time
* [bun.js] Improve error message printing
* [Bun.js] Add `Bun.gc()` to run the garbage collector manually and report heap size
* [Bun.js] Add Bun.generateHeapSnapshot to return what JS types are using memory
* [Bun.js] Add `Bun.shrink()` to tell JSC to shrink the VM size
* Improve encoding reader
* [bun.js] Improve callback & microtask performance
* Update node_fs.zig
* Implement `console.assert`
* simple test
* [Bun.js] Prepare for multiple globals/realms to support testing
* Create callbacks-overhead.mjs
* Update http.zig
* [Bun.js] Implement `queueMicrotask`
* Add test for queueMicrotask
* :sleepy:
* [Bun.js] Implement `process.versions`, `process.pid`, `process.ppid`, `process.nextTick`, `process.versions`,
* Implement `process.env.toJSON()`
* [Bun.js] Improve performance of `fs.existsSync`
* :nail_care:
* [Bun.js] Implement `process.chdir(str)` and `process.cwd()`, support up to 4 args in `process.nextTick`
* Make creating Zig::Process lazy
* Split processi nto separte file
* [Bun.js] Node.js Streams - Part 1/?
* [Bun.js] Node.js streams 2/?
* WIP streams
* fix crash
* Reduce allocations in many places
* swap
* Make `bun` start 2ms faster
* Always use an apiLock()
* libBacktrace doesn't really work yet
* Fix crash in the upgrade checker
* Clean up code for importing the runtime when not bundling
* :camera:
* Update linker.zig
* 68!
* backtrace
* no, really backtrace
* Fix
* Linux fixes
* Fixes on Linux
* Update mimalloc
* [bun test] Automatically scan for {.test,_test,.spec,_spec}.{jsx,tsx,js,cts,mts,ts,cjs}
Diffstat (limited to 'integration/bunjs-only-snippets')
-rw-r--r-- | integration/bunjs-only-snippets/console-log.js | 58 | ||||
-rw-r--r-- | integration/bunjs-only-snippets/fetch.js | 14 | ||||
-rw-r--r-- | integration/bunjs-only-snippets/fetch.js.txt | 46 | ||||
-rw-r--r-- | integration/bunjs-only-snippets/fs-stream.js | 23 | ||||
-rw-r--r-- | integration/bunjs-only-snippets/fs.test.js | 35 | ||||
-rw-r--r-- | integration/bunjs-only-snippets/import-meta.test.js | 13 | ||||
-rw-r--r-- | integration/bunjs-only-snippets/microtask.js | 76 | ||||
-rw-r--r-- | integration/bunjs-only-snippets/process-nexttick.js | 91 | ||||
-rw-r--r-- | integration/bunjs-only-snippets/process.js | 48 | ||||
-rw-r--r-- | integration/bunjs-only-snippets/readFileSync.txt | 1 | ||||
-rw-r--r-- | integration/bunjs-only-snippets/readdir.js | 9 | ||||
-rw-r--r-- | integration/bunjs-only-snippets/sleep.js | 4 | ||||
-rw-r--r-- | integration/bunjs-only-snippets/some-fs.js | 51 |
13 files changed, 467 insertions, 2 deletions
diff --git a/integration/bunjs-only-snippets/console-log.js b/integration/bunjs-only-snippets/console-log.js new file mode 100644 index 000000000..e8aa200ac --- /dev/null +++ b/integration/bunjs-only-snippets/console-log.js @@ -0,0 +1,58 @@ +console.log("Hello World!"); +console.log(123); +console.log(-123); +console.log(123.567); +console.log(-123.567); +console.log(true); +console.log(false); +console.log(null); +console.log(undefined); +console.log(Symbol("Symbol Description")); +console.log(new Date(2021, 12, 30, 666, 777, 888, 999)); +console.log([123, 456, 789]); +console.log({ a: 123, b: 456, c: 789 }); +console.log({ + a: { + b: { + c: 123, + }, + bacon: true, + }, +}); + +console.log(new Promise(() => {})); + +class Foo {} + +console.log(() => {}); +console.log(Foo); +console.log(new Foo()); +console.log(function foooo() {}); + +console.log(/FooRegex/); + +console.error("uh oh"); +console.time("Check"); + +console.log( + "Is it a bug or a feature that formatting numbers like %d is colored", + 123 +); +console.log(globalThis); + +console.log( + "String %s should be 2nd word, 456 == %s and percent s %s == %s", + "123", + "456", + "%s", + "What", + "okay" +); + +const infinteLoop = { + foo: {}, + bar: {}, +}; + +infinteLoop.bar = infinteLoop; +console.log(infinteLoop, "am"); diff --git a/integration/bunjs-only-snippets/fetch.js b/integration/bunjs-only-snippets/fetch.js new file mode 100644 index 000000000..cc83b5af4 --- /dev/null +++ b/integration/bunjs-only-snippets/fetch.js @@ -0,0 +1,14 @@ +import fs from "fs"; + +const response = await fetch("http://example.com/"); +const text = await response.text(); + +if ( + fs.readFileSync( + import.meta.path.substring(0, import.meta.path.lastIndexOf("/")) + + "/fetch.js.txt", + "utf8" + ) !== text +) { + throw new Error("Expected fetch.js.txt to match snapshot"); +} diff --git a/integration/bunjs-only-snippets/fetch.js.txt b/integration/bunjs-only-snippets/fetch.js.txt new file mode 100644 index 000000000..5a9b52fcf --- /dev/null +++ b/integration/bunjs-only-snippets/fetch.js.txt @@ -0,0 +1,46 @@ +<!doctype html> +<html> +<head> + <title>Example Domain</title> + + <meta charset="utf-8" /> + <meta http-equiv="Content-type" content="text/html; charset=utf-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + <style type="text/css"> + body { + background-color: #f0f0f2; + margin: 0; + padding: 0; + font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; + + } + div { + width: 600px; + margin: 5em auto; + padding: 2em; + background-color: #fdfdff; + border-radius: 0.5em; + box-shadow: 2px 3px 7px 2px rgba(0,0,0,0.02); + } + a:link, a:visited { + color: #38488f; + text-decoration: none; + } + @media (max-width: 700px) { + div { + margin: 0 auto; + width: auto; + } + } + </style> +</head> + +<body> +<div> + <h1>Example Domain</h1> + <p>This domain is for use in illustrative examples in documents. You may use this + domain in literature without prior coordination or asking for permission.</p> + <p><a href="https://www.iana.org/domains/example">More information...</a></p> +</div> +</body> +</html> diff --git a/integration/bunjs-only-snippets/fs-stream.js b/integration/bunjs-only-snippets/fs-stream.js new file mode 100644 index 000000000..4b71c95b7 --- /dev/null +++ b/integration/bunjs-only-snippets/fs-stream.js @@ -0,0 +1,23 @@ +import { createReadStream, createWriteStream, readFileSync } from "fs"; + +await new Promise((resolve, reject) => { + createReadStream("fs-stream.js") + .pipe(createWriteStream("/tmp/fs-stream.copy.js")) + .once("error", (err) => reject(err)) + .once("finish", () => { + try { + const copied = readFileSync("/tmp/fs-stream.copy.js", "utf8"); + const real = readFileSync("/tmp/fs-stream.js", "utf8"); + if (copied !== real) { + reject( + new Error("fs-stream.js is not the same as fs-stream.copy.js") + ); + return; + } + + resolve(true); + } catch (err) { + reject(err); + } + }); +}); diff --git a/integration/bunjs-only-snippets/fs.test.js b/integration/bunjs-only-snippets/fs.test.js new file mode 100644 index 000000000..4fc5c9e91 --- /dev/null +++ b/integration/bunjs-only-snippets/fs.test.js @@ -0,0 +1,35 @@ +import { describe, it, expect } from "bun:test"; +import { + mkdirSync, + existsSync, + readFileSync, + mkdtempSync, + writeFileSync, +} from "node:fs"; + +const tmp = mkdtempSync("fs-test"); + +describe("mkdirSync", () => { + it("should create a directory", () => { + const tempdir = `${tmp}/1234/hi`; + expect(existsSync(tempdir)).toBe(false); + expect(tempdir.includes(mkdirSync(tempdir, { recursive: true }))).toBe( + true + ); + expect(existsSync(tempdir)).toBe(true); + }); +}); + +describe("readFileSync", () => { + it("works", () => { + const text = readFileSync(import.meta.dir + "/readFileSync.txt", "utf8"); + expect(text).toBe("File read successfully"); + }); +}); + +describe("writeFileSync", () => { + it("works", () => { + const text = writeFileSync(`${tmp}/writeFileSync.txt`, "utf8"); + expect(text).toBe("File read successfully"); + }); +}); diff --git a/integration/bunjs-only-snippets/import-meta.test.js b/integration/bunjs-only-snippets/import-meta.test.js new file mode 100644 index 000000000..226dd396b --- /dev/null +++ b/integration/bunjs-only-snippets/import-meta.test.js @@ -0,0 +1,13 @@ +import { it, expect } from "bun:test"; + +const { path, dir } = import.meta; + +it("import.meta.dir", () => { + expect(dir.endsWith("/bun/integration/bunjs-only-snippets")).toBe(true); +}); + +it("import.meta.path", () => { + expect( + path.endsWith("/bun/integration/bunjs-only-snippets/import-meta.test.js") + ).toBe(true); +}); diff --git a/integration/bunjs-only-snippets/microtask.js b/integration/bunjs-only-snippets/microtask.js new file mode 100644 index 000000000..c5acfd578 --- /dev/null +++ b/integration/bunjs-only-snippets/microtask.js @@ -0,0 +1,76 @@ +// You can verify this test is correct by copy pasting this into a browser's console and checking it doesn't throw an error. +var run = 0; + +await new Promise((resolve, reject) => { + queueMicrotask(() => { + if (run++ != 0) { + reject(new Error("Microtask execution order is wrong: " + run)); + } + queueMicrotask(() => { + if (run++ != 3) { + reject(new Error("Microtask execution order is wrong: " + run)); + } + }); + }); + queueMicrotask(() => { + if (run++ != 1) { + reject(new Error("Microtask execution order is wrong: " + run)); + } + queueMicrotask(() => { + if (run++ != 4) { + reject(new Error("Microtask execution order is wrong: " + run)); + } + + queueMicrotask(() => { + if (run++ != 6) { + reject(new Error("Microtask execution order is wrong: " + run)); + } + }); + }); + }); + queueMicrotask(() => { + if (run++ != 2) { + reject(new Error("Microtask execution order is wrong: " + run)); + } + queueMicrotask(() => { + if (run++ != 5) { + reject(new Error("Microtask execution order is wrong: " + run)); + } + + queueMicrotask(() => { + if (run++ != 7) { + reject(new Error("Microtask execution order is wrong: " + run)); + } + resolve(true); + }); + }); + }); +}); + +{ + var passed = false; + try { + queueMicrotask(1234); + } catch (exception) { + passed = exception instanceof TypeError; + } + + if (!passed) + throw new Error( + "queueMicrotask should throw a TypeError if the argument is not a function" + ); +} + +{ + var passed = false; + try { + queueMicrotask(); + } catch (exception) { + passed = exception instanceof TypeError; + } + + if (!passed) + throw new Error( + "queueMicrotask should throw a TypeError if the argument is empty" + ); +} diff --git a/integration/bunjs-only-snippets/process-nexttick.js b/integration/bunjs-only-snippets/process-nexttick.js new file mode 100644 index 000000000..337977c0a --- /dev/null +++ b/integration/bunjs-only-snippets/process-nexttick.js @@ -0,0 +1,91 @@ +// You can verify this test is correct by copy pasting this into a browser's console and checking it doesn't throw an error. +var run = 0; + +var queueMicrotask = process.nextTick; + +await new Promise((resolve, reject) => { + queueMicrotask(() => { + if (run++ != 0) { + reject(new Error("Microtask execution order is wrong: " + run)); + } + queueMicrotask(() => { + if (run++ != 3) { + reject(new Error("Microtask execution order is wrong: " + run)); + } + }); + }); + queueMicrotask(() => { + if (run++ != 1) { + reject(new Error("Microtask execution order is wrong: " + run)); + } + queueMicrotask(() => { + if (run++ != 4) { + reject(new Error("Microtask execution order is wrong: " + run)); + } + + queueMicrotask(() => { + if (run++ != 6) { + reject(new Error("Microtask execution order is wrong: " + run)); + } + }); + }); + }); + queueMicrotask(() => { + if (run++ != 2) { + reject(new Error("Microtask execution order is wrong: " + run)); + } + queueMicrotask(() => { + if (run++ != 5) { + reject(new Error("Microtask execution order is wrong: " + run)); + } + + queueMicrotask(() => { + if (run++ != 7) { + reject(new Error("Microtask execution order is wrong: " + run)); + } + resolve(true); + }); + }); + }); +}); + +{ + var passed = false; + try { + queueMicrotask(1234); + } catch (exception) { + passed = exception instanceof TypeError; + } + + if (!passed) + throw new Error( + "queueMicrotask should throw a TypeError if the argument is not a function" + ); +} + +{ + var passed = false; + try { + queueMicrotask(); + } catch (exception) { + passed = exception instanceof TypeError; + } + + if (!passed) + throw new Error( + "queueMicrotask should throw a TypeError if the argument is empty" + ); +} + +await new Promise((resolve, reject) => { + process.nextTick( + (first, second) => { + console.log(first, second); + if (first !== 12345 || second !== "hello") + reject(new Error("process.nextTick called with wrong arguments")); + resolve(true); + }, + 12345, + "hello" + ); +}); diff --git a/integration/bunjs-only-snippets/process.js b/integration/bunjs-only-snippets/process.js new file mode 100644 index 000000000..486d20f46 --- /dev/null +++ b/integration/bunjs-only-snippets/process.js @@ -0,0 +1,48 @@ +// this property isn't implemented yet but it should at least return a string +const isNode = !process.isBun; + +if (!isNode && process.title !== "bun") + throw new Error("process.title is not 'bun'"); + +if (typeof process.env.USER !== "string") + throw new Error("process.env is not an object"); + +if (process.env.USER.length === 0) + throw new Error("process.env is missing a USER property"); + +if (process.platform !== "darwin" && process.platform !== "linux") + throw new Error("process.platform is invalid"); + +if (isNode) throw new Error("process.isBun is invalid"); + +// partially to test it doesn't crash due to various strange types +process.env.BACON = "yummy"; +if (process.env.BACON !== "yummy") { + throw new Error("process.env is not writable"); +} + +delete process.env.BACON; +if (typeof process.env.BACON !== "undefined") { + throw new Error("process.env is not deletable"); +} + +process.env.BACON = "yummy"; +if (process.env.BACON !== "yummy") { + throw new Error("process.env is not re-writable"); +} + +if (JSON.parse(JSON.stringify(process.env)).BACON !== "yummy") { + throw new Error("process.env is not serializable"); +} + +if (typeof JSON.parse(JSON.stringify(process.env)).toJSON !== "undefined") { + throw new Error("process.env should call toJSON to hide its internal state"); +} + +var { env, ...proces } = process; +console.log(JSON.stringify(proces, null, 2)); +console.log(proces); + +console.log("CWD", process.cwd()); +console.log("SET CWD", process.chdir("../")); +console.log("CWD", process.cwd()); diff --git a/integration/bunjs-only-snippets/readFileSync.txt b/integration/bunjs-only-snippets/readFileSync.txt new file mode 100644 index 000000000..ddc94b988 --- /dev/null +++ b/integration/bunjs-only-snippets/readFileSync.txt @@ -0,0 +1 @@ +File read successfully
\ No newline at end of file diff --git a/integration/bunjs-only-snippets/readdir.js b/integration/bunjs-only-snippets/readdir.js new file mode 100644 index 000000000..18c111d0a --- /dev/null +++ b/integration/bunjs-only-snippets/readdir.js @@ -0,0 +1,9 @@ +const { readdirSync } = require("fs"); + +const count = parseInt(process.env.ITERATIONS || "1", 10) || 1; + +for (let i = 0; i < count; i++) { + readdirSync("."); +} + +console.log(readdirSync(".")); diff --git a/integration/bunjs-only-snippets/sleep.js b/integration/bunjs-only-snippets/sleep.js index 9a62201c5..080597424 100644 --- a/integration/bunjs-only-snippets/sleep.js +++ b/integration/bunjs-only-snippets/sleep.js @@ -1,7 +1,7 @@ -const interval = 0.5; +const interval = 0.01; const now = performance.now(); console.time("Slept"); -Bun.sleep(interval); +Bun.sleepSync(interval); const elapsed = performance.now() - now; if (elapsed < interval) { throw new Error("Didn't sleep"); diff --git a/integration/bunjs-only-snippets/some-fs.js b/integration/bunjs-only-snippets/some-fs.js new file mode 100644 index 000000000..e6b31f162 --- /dev/null +++ b/integration/bunjs-only-snippets/some-fs.js @@ -0,0 +1,51 @@ +const { mkdirSync, existsSync } = require("fs"); + +var performance = globalThis.performance; +if (!performance) { + try { + performance = require("perf_hooks").performance; + } catch (e) {} +} + +const count = parseInt(process.env.ITERATIONS || "1", 10) || 1; +var tempdir = `/tmp/some-fs-test/dir/${Date.now()}/hi`; + +for (let i = 0; i < count; i++) { + tempdir += `/${i.toString(36)}`; +} + +if (existsSync(tempdir)) { + throw new Error( + `existsSync reports ${tempdir} exists, but it probably does not` + ); +} + +var origTempDir = tempdir; +var iterations = new Array(count * count).fill(""); +var total = 0; +for (let i = 0; i < count; i++) { + for (let j = 0; j < count; j++) { + iterations[total++] = `${origTempDir}/${j.toString(36)}-${i.toString(36)}`; + } +} +tempdir = origTempDir; +mkdirSync(origTempDir, { recursive: true }); +const recurse = { recursive: false }; +const start = performance.now(); +for (let i = 0; i < total; i++) { + mkdirSync(iterations[i], recurse); +} + +console.log("MKDIR " + total + " depth took:", performance.now() - start, "ms"); + +if (!existsSync(tempdir)) { + throw new Error( + "Expected directory to exist after mkdirSync, but it doesn't" + ); +} + +if (mkdirSync(tempdir, { recursive: true })) { + throw new Error( + "mkdirSync shouldn't return directory name on existing directories" + ); +} |