mirror of
https://github.com/oven-sh/bun
synced 2026-02-02 15:08:46 +00:00
change the directory structure
This commit is contained in:
138
test/README.md
Normal file
138
test/README.md
Normal file
@@ -0,0 +1,138 @@
|
||||
# Tests in Bun
|
||||
|
||||
Bun currently has four different kinds of tests
|
||||
|
||||
To run the tests:
|
||||
|
||||
```bash
|
||||
make test-all
|
||||
bun wiptest
|
||||
```
|
||||
|
||||
### Browser tests
|
||||
|
||||
Browser tests run end-to-end inside of Puppeteer and execute code transpiled by `bun dev`. These tests are in [./snippets](./snippets).
|
||||
|
||||
The interface is:
|
||||
|
||||
```js
|
||||
// this function is called after import()
|
||||
// if testDone() is never called, the test fails
|
||||
export function test() {
|
||||
return testDone(import.meta.url);
|
||||
}
|
||||
```
|
||||
|
||||
On success, it saves a snapshot to [./snapshots](./snapshots) which is checked into git.
|
||||
|
||||
#### Adding a new test
|
||||
|
||||
1. Create a new file in the `snippets` directory.
|
||||
2. Append the filename to [./scripts/snippets.json](./scripts/snippets.json)
|
||||
3. Run `bun dev` inside this folder in one terminal window
|
||||
4. Run `make integration-test-dev`
|
||||
|
||||
These tests are run twice. Once with HMR enabled and once with HMR disabled. HMR changes the output enough to warrant it's own special treatment.
|
||||
|
||||
#### Running the tests
|
||||
|
||||
To run the browser tests with HMR on a production build:
|
||||
|
||||
```bash
|
||||
make test-with-hmr
|
||||
```
|
||||
|
||||
To run the browser tests without HMR on a production build:
|
||||
|
||||
```bash
|
||||
make test-with-no-hmr
|
||||
```
|
||||
|
||||
To run the browser tests with HMR on a debug build:
|
||||
|
||||
```bash
|
||||
make test-dev-with-hmr
|
||||
```
|
||||
|
||||
To run the browser tests without HMR on a debug build:
|
||||
|
||||
```bash
|
||||
make test-dev-no-hmr
|
||||
```
|
||||
|
||||
To run the browser tests on whatever version of bun is running on port 3000:
|
||||
|
||||
```bash
|
||||
make integration-test-dev
|
||||
```
|
||||
|
||||
These were the first tests bun started with
|
||||
|
||||
### Runtime tests
|
||||
|
||||
These tests are in [./bun.js](./bun.js) and are files which are either `.test.js` or `.test.ts` files.
|
||||
|
||||
These test that the runtime behaves as expected. These also test the transpiler, both because test files are transpiled and directly by running the transpiler via `Bun.Transpiler`.
|
||||
|
||||
#### Adding a new test
|
||||
|
||||
1. Create a new file in [./bun.js](./bun.js/) with `.test` in the name.
|
||||
|
||||
These test use `bun:test` as the import (though you can also import from `vitest` or jest and it will work).
|
||||
|
||||
This will eventually be a public test runner for bun, but the reporter isn't very good yet and it doesn't run in parallel.
|
||||
|
||||
The syntax intends for Jest compatibility.
|
||||
|
||||
```ts
|
||||
import { describe, expect, it } from "bun:test";
|
||||
|
||||
describe("Example", () => {
|
||||
it("should work", () => {
|
||||
expect(1).toBe(1);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
#### Running the tests
|
||||
|
||||
Run `bun wiptest ${part-of-file-name}`
|
||||
|
||||
If you run the test in the top-level bun repo directory, it will take an extra couple seconds because `bun wiptest` will scan through all of WebKit recursively. Consider running it in the `bun.js` directory instead.
|
||||
|
||||
### CLI tests
|
||||
|
||||
These run the bash files in the `apps` directory.
|
||||
|
||||
They check end-to-end that the CLI works as expected.
|
||||
|
||||
```bash
|
||||
# Install dependencies for running tests
|
||||
# Does not run tests
|
||||
make test-install
|
||||
|
||||
# Check a Create React App created via `bun create react ./foo` returns HTML
|
||||
make test-create-react
|
||||
|
||||
# Check a Next.js app created via `bun create next ./foo` SSRs successfully
|
||||
make test-create-next
|
||||
|
||||
# Check that bun run works for the same CLI args passed to npm run
|
||||
make test-bun-run
|
||||
|
||||
# Check that "react" installed via bun install loads successfully
|
||||
# and that deleting/adding updates the lockfile as expected
|
||||
make test-bun-install
|
||||
|
||||
# Check that serving public paths works correctly
|
||||
# and that files which should be transpiled are transpiled and files which shouldn't be aren't
|
||||
make test-bun-dev
|
||||
```
|
||||
|
||||
### Zig tests
|
||||
|
||||
These tests live in various `.zig` files throughout Bun's codebase, leveraging Zig's builtin `test` keyword.
|
||||
|
||||
Currently, they're not run automatically nor is there a simple way to run all of them.
|
||||
|
||||
This is an area bun needs to improve in.
|
||||
57
test/apps/bun-create-next.sh
Normal file
57
test/apps/bun-create-next.sh
Normal file
@@ -0,0 +1,57 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# The important part of this test: make sure that bun.js successfully loads
|
||||
# The most likely reason for this test to fail is that something broke in the JavaScriptCore <> bun integration
|
||||
killall -9 $(basename $BUN_BIN) || echo ""
|
||||
|
||||
rm -rf /tmp/next-app
|
||||
mkdir -p /tmp/next-app
|
||||
$BUN_BIN create next /tmp/next-app
|
||||
|
||||
if (($?)); then
|
||||
echo "bun create failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "hi!" >/tmp/next-app/public/file.txt
|
||||
echo "export default 'string';" >/tmp/next-app/file.js
|
||||
|
||||
cd /tmp/next-app
|
||||
BUN_CRASH_WITHOUT_JIT=1 $BUN_BIN dev --port 8087 &
|
||||
sleep 0.1
|
||||
curl --fail -Ss http://localhost:8087/
|
||||
|
||||
if [[ "$(curl --fail -sS http://localhost:8087/file.txt)" != "hi!" ]]; then
|
||||
echo ""
|
||||
echo ""
|
||||
echo ""
|
||||
echo "ERR: Expected 'hi!', got '$(curl --fail -sS http://localhost:8087/file.txt)'"
|
||||
killall -9 $(basename $BUN_BIN) || echo ""
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "$(curl --fail -sS http://localhost:8087/file.js)" != *"string"* ]]; then
|
||||
echo ""
|
||||
echo ""
|
||||
echo ""
|
||||
echo "ERR: Expected file to contain string got '$(curl --fail -sS http://localhost:8087/file.js)'"
|
||||
killall -9 $(basename $BUN_BIN) || echo ""
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# very simple HMR test
|
||||
echo "export default 'string';" >/tmp/next-app/file2.js
|
||||
sleep 0.1
|
||||
|
||||
if [[ "$(curl --fail -sS http://localhost:8087/file2.js)" != *"string"* ]]; then
|
||||
echo ""
|
||||
echo ""
|
||||
echo ""
|
||||
echo "ERR: Expected file to contain string got '$(curl --fail -sS http://localhost:8087/file2.js)'"
|
||||
killall -9 $(basename $BUN_BIN) || echo ""
|
||||
exit 1
|
||||
fi
|
||||
|
||||
killall -9 $(basename $BUN_BIN) || echo ""
|
||||
20
test/apps/bun-create-react.sh
Normal file
20
test/apps/bun-create-react.sh
Normal file
@@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
|
||||
killall -9 $(basename $BUN_BIN) || echo ""
|
||||
|
||||
rm -rf /tmp/react-app
|
||||
mkdir -p /tmp/react-app
|
||||
$BUN_BIN create react /tmp/react-app
|
||||
|
||||
|
||||
if (($?)); then
|
||||
echo "bun create failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd /tmp/react-app
|
||||
BUN_CRASH_WITHOUT_JIT=1 $BUN_BIN --port 8087 &
|
||||
sleep 0.005
|
||||
|
||||
curl --fail http://localhost:8087/ && curl --fail http://localhost:8087/src/index.jsx && killall -9 $(basename $BUN_BIN) && echo "✅ bun create react passed."
|
||||
exit $?
|
||||
69
test/apps/bun-dev-index-html.sh
Normal file
69
test/apps/bun-dev-index-html.sh
Normal file
@@ -0,0 +1,69 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
killall -9 $(basename $BUN_BIN) || echo ""
|
||||
|
||||
dir=$(mktemp -d --suffix=bun-dev-check)
|
||||
|
||||
index_content="<html><body>index.html</body></html>"
|
||||
bacon_content="<html><body>bacon.html</body></html>"
|
||||
js_content="if(0) { var foo = 'TEST FAILED'; }"
|
||||
static_content="PASS"
|
||||
css_not_transpiled_content="@import url(/index.js); @import url(/i-dont-exist.css); @import url('/i-dont-exist.css'); @import url(\"/i-dont-exist.css\");"
|
||||
css_is_transpiled_import="*{background-color:red;}"
|
||||
css_is_transpiled="@import url(./css_is_transpiled_import.css);"
|
||||
|
||||
echo $index_content >"$dir/index.html"
|
||||
echo $js_content >"$dir/index.js"
|
||||
echo $bacon_content >"$dir/bacon.html"
|
||||
echo $static_content >"$dir/static.txt"
|
||||
echo $css_not_transpiled_content >"$dir/css_not_transpiled_content.css"
|
||||
|
||||
cd $dir
|
||||
$BUN_BIN --port 8087 &
|
||||
sleep 0.005
|
||||
|
||||
if [[ "$(curl --fail -sS http://localhost:8087/)" != "$index_content" ]]; then
|
||||
echo "ERR: Expected '$index_content', got '$(curl --fail -sS http://localhost:8087/)'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "$(curl --fail -sS http://localhost:8087/index)" != "$index_content" ]]; then
|
||||
echo "ERR: Expected '$index_content', got '$(curl --fail -sS http://localhost:8087/index)'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "$(curl --fail -sS http://localhost:8087/static.txt)" != "PASS" ]]; then
|
||||
echo "ERR: Expected static file, got '$(curl --fail -sS http://localhost:8087/static.txt)'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check that the file is actually transpiled
|
||||
if [[ "$(curl --fail -sS http://localhost:8087/index.js)" == *"TEST FAILED"* ]]; then
|
||||
echo "ERR: Expected file to be transpiled, got '$(curl --fail -sS http://localhost:8087/index.js)'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "$(curl --fail -sS http://localhost:8087/index.html)" != "$index_content" ]]; then
|
||||
echo "ERR: Expected '$index_content', got '$(curl --fail -sS http://localhost:8087/index.html)'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "$(curl --fail -sS http://localhost:8087/foo/foo)" != "$index_content" ]]; then
|
||||
echo "ERR: Expected '$index_content', got '$(curl --fail -sS http://localhost:8087/index.html)'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "$(curl --fail -sS http://localhost:8087/bacon)" != "$bacon_content" ]]; then
|
||||
echo "ERR: Expected '$bacon_content', got '$(curl --fail -sS http://localhost:8087/bacon)'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "$(curl --fail -sS http://localhost:8087/bacon.html)" != "$bacon_content" ]]; then
|
||||
echo "ERR: Expected '$bacon_content', got '$(curl --fail -sS http://localhost:8087/bacon.html)'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
killall -9 $(basename $BUN_BIN) || echo ""
|
||||
echo "✅ bun dev index html check passed."
|
||||
55
test/apps/bun-dev.sh
Normal file
55
test/apps/bun-dev.sh
Normal file
@@ -0,0 +1,55 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
killall -9 $(basename $BUN_BIN) || echo ""
|
||||
|
||||
dir=$(mktemp -d --suffix=bun-dev-check)
|
||||
|
||||
index_content="<html><body>index.html</body></html>"
|
||||
bacon_content="<html><body>bacon.html</body></html>"
|
||||
js_content="console.log('hi')"
|
||||
|
||||
mkdir -p $dir/public
|
||||
|
||||
echo $index_content >"$dir/public/index.html"
|
||||
echo $js_content >"$dir/index.js"
|
||||
echo $bacon_content >"$dir/public/bacon.html"
|
||||
|
||||
cd $dir
|
||||
|
||||
$BUN_BIN --port 8087 &
|
||||
sleep 0.005
|
||||
|
||||
if [ "$(curl --fail -sS http://localhost:8087/)" != "$index_content" ]; then
|
||||
echo "ERR: Expected '$index_content', got '$(curl --fail -sS http://localhost:8087/)'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$(curl --fail -sS http://localhost:8087/index)" != "$index_content" ]; then
|
||||
echo "ERR: Expected '$index_content', got '$(curl --fail -sS http://localhost:8087/index)'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$(curl --fail -sS http://localhost:8087/index.html)" != "$index_content" ]; then
|
||||
echo "ERR: Expected '$index_content', got '$(curl --fail -sS http://localhost:8087/index.html)'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$(curl --fail -sS http://localhost:8087/foo/foo)" != "$index_content" ]; then
|
||||
echo "ERR: Expected '$index_content', got '$(curl --fail -sS http://localhost:8087/index.html)'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$(curl --fail -sS http://localhost:8087/bacon)" != "$bacon_content" ]; then
|
||||
echo "ERR: Expected '$index_content', got '$(curl --fail -sS http://localhost:8087/bacon)'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$(curl --fail -sS http://localhost:8087/bacon.html)" != "$bacon_content" ]; then
|
||||
echo "ERR: Expected '$index_content', got '$(curl --fail -sS http://localhost:8087/bacon.html)'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
killall -9 $(basename $BUN_BIN) || echo ""
|
||||
echo "✅ bun dev index html check passed."
|
||||
65
test/apps/bun-install-lockfile-status.sh
Normal file
65
test/apps/bun-install-lockfile-status.sh
Normal file
@@ -0,0 +1,65 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
killall -9 $(basename $BUN_BIN) || echo ""
|
||||
|
||||
dir=$(mktemp -d --suffix=bun-lockfile)
|
||||
|
||||
cd $dir
|
||||
|
||||
$BUN_BIN add react
|
||||
|
||||
echo "node_modules" >.gitignore
|
||||
|
||||
git init && git add . && git commit -am "Initial commit"
|
||||
|
||||
$BUN_BIN install
|
||||
|
||||
ORIG_LOCKFILE="$($BUN_BIN pm hash-string)"
|
||||
|
||||
[[ -z $(git status --untracked-files=no --porcelain) ]] || {
|
||||
echo "ERR: Expected empty git status, got '$(git status --untracked-files=no --porcelain)'"
|
||||
exit 1
|
||||
}
|
||||
|
||||
$BUN_BIN add react
|
||||
|
||||
NEW_LOCKFILE="$($BUN_BIN pm hash-string)"
|
||||
|
||||
diff <(echo "$ORIG_LOCKFILE") <(echo "$NEW_LOCKFILE") || {
|
||||
echo "ERR: Expected lockfile to be unchanged, got '$NEW_LOCKFILE'"
|
||||
exit 1
|
||||
}
|
||||
|
||||
ORIG_HASH=$($BUN_BIN bun.lockb --hash)
|
||||
|
||||
$BUN_BIN remove react
|
||||
$BUN_BIN add react
|
||||
|
||||
NEW_HASH=$($BUN_BIN bun.lockb --hash)
|
||||
|
||||
diff <(echo "$ORIG_HASH") <(echo "$NEW_HASH") || {
|
||||
echo "ERR: Expected hash to be unchanged, got '$NEW_HASH'"
|
||||
exit 1
|
||||
}
|
||||
|
||||
echo '{ "dependencies": { "react": "17.0.2", "react-dom": "17.0.2" } }' >package.json
|
||||
|
||||
$BUN_BIN install
|
||||
|
||||
echo "var {version} = JSON.parse(require(\"fs\").readFileSync('./node_modules/react-dom/package.json', 'utf8')); if (version !== '17.0.2') {throw new Error('Unexpected react-dom version');}; " >index.js
|
||||
$BUN_BIN run ./index.js
|
||||
|
||||
echo "var {version} = JSON.parse(require(\"fs\").readFileSync('./node_modules/react/package.json', 'utf8')); if (version !== '17.0.2') {throw new Error('Unexpected react version');}; " >index.js
|
||||
$BUN_BIN run ./index.js
|
||||
|
||||
# This is just making sure that the JS was executed
|
||||
realpath -e node_modules/react-dom >/dev/null || {
|
||||
echo "ERR: Expected react-dom to be installed"
|
||||
exit 1
|
||||
}
|
||||
realpath -e node_modules/react >/dev/null || {
|
||||
echo "ERR: Expected react to be installed"
|
||||
exit 1
|
||||
}
|
||||
14
test/apps/bun-install-utf8.sh
Normal file
14
test/apps/bun-install-utf8.sh
Normal file
@@ -0,0 +1,14 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
killall -9 $(basename $BUN_BIN) || echo ""
|
||||
|
||||
dir=$(mktemp -d --suffix=bun-ADD)
|
||||
|
||||
cd $dir
|
||||
|
||||
# https://github.com/Jarred-Sumner/bun/issues/115
|
||||
echo '{ "author": "Arnaud Barré (https://github.com/ArnaudBarre)" }' >package.json
|
||||
|
||||
$BUN_BIN add react
|
||||
85
test/apps/bun-install.sh
Normal file
85
test/apps/bun-install.sh
Normal file
@@ -0,0 +1,85 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
dir=$(mktemp -d --suffix=bun-install-test-1)
|
||||
|
||||
cd $dir
|
||||
${NPM_CLIENT:-$(which bun)} add react react-dom @types/react @babel/parser esbuild
|
||||
|
||||
echo "console.log(typeof require(\"react\").createElement);" >index.js
|
||||
chmod +x index.js
|
||||
|
||||
JS_RUNTIME=${JS_RUNTIME:-"$(which bun)"}
|
||||
|
||||
if [ "$JS_RUNTIME" == "node" ]; then
|
||||
result="$(node ./index.js)"
|
||||
fi
|
||||
|
||||
if [ "$JS_RUNTIME" != "node" ]; then
|
||||
result="$($JS_RUNTIME run ./index.js)"
|
||||
fi
|
||||
|
||||
echo "console.log(typeof require(\"react-dom\").render);" >index.js
|
||||
chmod +x index.js
|
||||
|
||||
JS_RUNTIME=${JS_RUNTIME:-"$(which bun)"}
|
||||
|
||||
# If this fails to run, it means we didn't link @babel/parser correctly
|
||||
realpath -e ./node_modules/.bin/parser
|
||||
|
||||
# If this fails to run, it means we didn't link esbuild correctly
|
||||
./node_modules/.bin/esbuild --version >/dev/null
|
||||
|
||||
if [ "$JS_RUNTIME" == "node" ]; then
|
||||
result="$(node ./index.js)"
|
||||
fi
|
||||
|
||||
if [ "$JS_RUNTIME" != "node" ]; then
|
||||
result="$($JS_RUNTIME run ./index.js)"
|
||||
fi
|
||||
|
||||
if [ "$result" != "function" ]; then
|
||||
echo "ERR: Expected 'function', got '$result'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
${NPM_CLIENT:-$(which bun)} remove react-dom
|
||||
|
||||
if [ -d "node_modules/react-dom" ]; then
|
||||
echo "ERR: react-dom module still exists in $dir"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
yarn_dot_lock=$(${NPM_CLIENT:-$(which bun)} bun.lockb)
|
||||
|
||||
if echo "$yarn_dot_lock" | grep -q "react-dom"; then
|
||||
echo "ERR: react-dom module still exists in lockfile"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
${NPM_CLIENT:-$(which bun)} remove @types/react
|
||||
|
||||
yarn_dot_lock=$(${NPM_CLIENT:-$(which bun)} bun.lockb)
|
||||
|
||||
if echo "$yarn_dot_lock" | grep -q "@types/react"; then
|
||||
echo "ERR: @types/react module still exists in lockfile"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if echo "$yarn_dot_lock" | grep -q "@types/react"; then
|
||||
echo "ERR: @types/react module still exists in $dir"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
${NPM_CLIENT:-$(which bun)} remove react
|
||||
|
||||
if [ -d "node_modules/react" ]; then
|
||||
echo "ERR: react module still exists in $dir"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -d "bun.lockb" ]; then
|
||||
echo "ERR: empty bun.lockb should be deleted"
|
||||
exit 1
|
||||
fi
|
||||
7
test/apps/bun-run-check-package.json
Normal file
7
test/apps/bun-run-check-package.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"name": "check",
|
||||
"scripts": {
|
||||
"this-should-work": "echo \"✅ bun run test passed!\"",
|
||||
"argv": "node -e 'console.log(process.argv)'"
|
||||
}
|
||||
}
|
||||
43
test/apps/bun-run-check.sh
Normal file
43
test/apps/bun-run-check.sh
Normal file
@@ -0,0 +1,43 @@
|
||||
#!/bin/bash
|
||||
|
||||
(killall -9 $(basename $BUN_BIN) || echo "") >/dev/null 2>&1
|
||||
|
||||
# https://github.com/Jarred-Sumner/bun/issues/40
|
||||
# Define a function (details aren't important)
|
||||
fn() { :; }
|
||||
# The important bit: export the function
|
||||
export -f fn
|
||||
|
||||
rm -rf /tmp/bun-run-check
|
||||
mkdir -p /tmp/bun-run-check
|
||||
|
||||
cp ./bun-run-check-package.json /tmp/bun-run-check/package.json
|
||||
cd /tmp/bun-run-check
|
||||
|
||||
$BUN_BIN run bash -- -c ""
|
||||
|
||||
if (($?)); then
|
||||
echo "Bash exported functions are broken"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# https://github.com/Jarred-Sumner/bun/issues/53
|
||||
rm -f /tmp/bun-run-out.expected.txt /tmp/bun-run-out.txt >/dev/null 2>&1
|
||||
|
||||
$BUN_BIN run --silent argv -- foo bar baz >/tmp/bun-run-out.txt
|
||||
npm run --silent argv -- foo bar baz >/tmp/bun-run-out.expected.txt
|
||||
|
||||
cmp -s /tmp/bun-run-out.expected.txt /tmp/bun-run-out.txt
|
||||
if (($?)); then
|
||||
echo "argv failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
$BUN_BIN run --silent this-should-work
|
||||
|
||||
if (($?)); then
|
||||
echo "this-should work failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exit 0
|
||||
77
test/bun.js/atob.test.js
Normal file
77
test/bun.js/atob.test.js
Normal file
@@ -0,0 +1,77 @@
|
||||
import { expect, it } from "bun:test";
|
||||
|
||||
function expectInvalidCharacters(val) {
|
||||
try {
|
||||
atob(val);
|
||||
throw new Error("Expected error");
|
||||
} catch (error) {
|
||||
expect(error.message).toBe("The string contains invalid characters.");
|
||||
}
|
||||
}
|
||||
|
||||
it("atob", () => {
|
||||
expect(atob("YQ==")).toBe("a");
|
||||
expect(atob("YWI=")).toBe("ab");
|
||||
expect(atob("YWJj")).toBe("abc");
|
||||
expect(atob("YWJjZA==")).toBe("abcd");
|
||||
expect(atob("YWJjZGU=")).toBe("abcde");
|
||||
expect(atob("YWJjZGVm")).toBe("abcdef");
|
||||
expect(atob("zzzz")).toBe("Ï<ó");
|
||||
expect(atob("")).toBe("");
|
||||
expect(atob(null)).toBe("ée");
|
||||
expect(atob("6ek=")).toBe("éé");
|
||||
expect(atob("6ek")).toBe("éé");
|
||||
expect(atob("gIE=")).toBe("");
|
||||
expect(atob("zz")).toBe("Ï");
|
||||
expect(atob("zzz")).toBe("Ï<");
|
||||
expect(atob("zzz=")).toBe("Ï<");
|
||||
expect(atob(" YQ==")).toBe("a");
|
||||
expect(atob("YQ==\u000a")).toBe("a");
|
||||
|
||||
try {
|
||||
atob();
|
||||
} catch (error) {
|
||||
expect(error.name).toBe("TypeError");
|
||||
}
|
||||
expectInvalidCharacters(undefined);
|
||||
expectInvalidCharacters(" abcd===");
|
||||
expectInvalidCharacters("abcd=== ");
|
||||
expectInvalidCharacters("abcd ===");
|
||||
expectInvalidCharacters("тест");
|
||||
expectInvalidCharacters("z");
|
||||
expectInvalidCharacters("zzz==");
|
||||
expectInvalidCharacters("zzz===");
|
||||
expectInvalidCharacters("zzz====");
|
||||
expectInvalidCharacters("zzz=====");
|
||||
expectInvalidCharacters("zzzzz");
|
||||
expectInvalidCharacters("z=zz");
|
||||
expectInvalidCharacters("=");
|
||||
expectInvalidCharacters("==");
|
||||
expectInvalidCharacters("===");
|
||||
expectInvalidCharacters("====");
|
||||
expectInvalidCharacters("=====");
|
||||
});
|
||||
|
||||
it("btoa", () => {
|
||||
expect(btoa("a")).toBe("YQ==");
|
||||
expect(btoa("ab")).toBe("YWI=");
|
||||
expect(btoa("abc")).toBe("YWJj");
|
||||
expect(btoa("abcd")).toBe("YWJjZA==");
|
||||
expect(btoa("abcde")).toBe("YWJjZGU=");
|
||||
expect(btoa("abcdef")).toBe("YWJjZGVm");
|
||||
expect(typeof btoa).toBe("function");
|
||||
try {
|
||||
btoa();
|
||||
throw new Error("Expected error");
|
||||
} catch (error) {
|
||||
expect(error.name).toBe("TypeError");
|
||||
}
|
||||
var window = "[object Window]";
|
||||
expect(btoa("")).toBe("");
|
||||
expect(btoa(null)).toBe("bnVsbA==");
|
||||
expect(btoa(undefined)).toBe("dW5kZWZpbmVk");
|
||||
expect(btoa(window)).toBe("W29iamVjdCBXaW5kb3dd");
|
||||
expect(btoa("éé")).toBe("6ek=");
|
||||
expect(btoa("\u0080\u0081")).toBe("gIE=");
|
||||
expect(btoa(Bun)).toBe(btoa("[object Bun]"));
|
||||
});
|
||||
2
test/bun.js/baz.js
Normal file
2
test/bun.js/baz.js
Normal file
@@ -0,0 +1,2 @@
|
||||
// this file is used in resolve.test.js
|
||||
export default {};
|
||||
304
test/bun.js/buffer.test.js
Normal file
304
test/bun.js/buffer.test.js
Normal file
@@ -0,0 +1,304 @@
|
||||
// import { describe, it, expect, beforeEach, afterEach } from "bun:test";
|
||||
// import { gc } from "./gc";
|
||||
|
||||
// beforeEach(() => gc());
|
||||
// afterEach(() => gc());
|
||||
|
||||
// it("buffer", () => {
|
||||
// var buf = new Buffer(20);
|
||||
// gc();
|
||||
// // if this fails or infinitely loops, it means there is a memory issue with the JSC::Structure object
|
||||
// expect(Object.keys(buf).length > 0).toBe(true);
|
||||
// gc();
|
||||
// expect(buf.write("hello world ")).toBe(12);
|
||||
// expect(buf.write("hello world ", "utf8")).toBe(12);
|
||||
|
||||
// gc();
|
||||
// expect(buf.toString("utf8", 0, "hello world ".length)).toBe("hello world ");
|
||||
// gc();
|
||||
// expect(buf.toString("base64url", 0, "hello world ".length)).toBe(
|
||||
// btoa("hello world ")
|
||||
// );
|
||||
// gc();
|
||||
// expect(buf instanceof Uint8Array).toBe(true);
|
||||
// gc();
|
||||
// expect(buf instanceof Buffer).toBe(true);
|
||||
// gc();
|
||||
// expect(buf.slice() instanceof Uint8Array).toBe(true);
|
||||
// gc();
|
||||
// expect(buf.slice(0, 1) instanceof Buffer).toBe(true);
|
||||
// gc();
|
||||
// expect(buf.slice(0, 1) instanceof Uint8Array).toBe(true);
|
||||
// gc();
|
||||
// expect(buf.slice(0, 1) instanceof Buffer).toBe(true);
|
||||
// gc();
|
||||
// });
|
||||
|
||||
// it("Buffer", () => {
|
||||
// var inputs = [
|
||||
// "hello world",
|
||||
// "hello world".repeat(100),
|
||||
// `😋 Get Emoji — All Emojis to ✂️ Copy and 📋 Paste 👌`,
|
||||
// ];
|
||||
// var good = inputs.map((a) => new TextEncoder().encode(a));
|
||||
// for (let i = 0; i < inputs.length; i++) {
|
||||
// var input = inputs[i];
|
||||
// expect(new Buffer(input).toString("utf8")).toBe(inputs[i]);
|
||||
// gc();
|
||||
// expect(Array.from(new Buffer(input)).join(",")).toBe(good[i].join(","));
|
||||
// gc();
|
||||
// expect(Buffer.byteLength(input)).toBe(good[i].length);
|
||||
// gc();
|
||||
// expect(Buffer.from(input).byteLength).toBe(Buffer.byteLength(input));
|
||||
// }
|
||||
// });
|
||||
|
||||
// it("Buffer.byteLength", () => {
|
||||
// expect(Buffer.byteLength("😀😃😄😁😆😅😂🤣☺️😊😊😇")).toBe(
|
||||
// new TextEncoder().encode("😀😃😄😁😆😅😂🤣☺️😊😊😇").byteLength
|
||||
// );
|
||||
// });
|
||||
|
||||
// it("Buffer.isBuffer", () => {
|
||||
// expect(Buffer.isBuffer(new Buffer(1))).toBe(true);
|
||||
// gc();
|
||||
// expect(Buffer.isBuffer(new Buffer(0))).toBe(true);
|
||||
// gc();
|
||||
// expect(Buffer.isBuffer(new Uint8Array(0))).toBe(false);
|
||||
// gc();
|
||||
// expect(Buffer.isBuffer(new Uint8Array(1))).toBe(false);
|
||||
// gc();
|
||||
// var a = new Uint8Array(1);
|
||||
// gc();
|
||||
// expect(Buffer.isBuffer(a)).toBe(false);
|
||||
// gc();
|
||||
// Buffer.toBuffer(a);
|
||||
// gc();
|
||||
// expect(Buffer.isBuffer(a)).toBe(true);
|
||||
// gc();
|
||||
// });
|
||||
|
||||
// it("Buffer.toBuffer throws", () => {
|
||||
// const checks = [
|
||||
// [],
|
||||
// {},
|
||||
// "foo",
|
||||
// new Uint16Array(),
|
||||
// new DataView(new Uint8Array(14).buffer),
|
||||
// ];
|
||||
// for (let i = 0; i < checks.length; i++) {
|
||||
// try {
|
||||
// Buffer.toBuffer(checks[i]);
|
||||
// expect(false).toBe(true);
|
||||
// } catch (exception) {
|
||||
// expect(exception.message).toBe("Expected Uint8Array");
|
||||
// }
|
||||
// }
|
||||
// expect(true).toBe(true);
|
||||
// });
|
||||
|
||||
// it("Buffer.toBuffer works", () => {
|
||||
// var array = new Uint8Array(20);
|
||||
// expect(array instanceof Buffer).toBe(false);
|
||||
// var buf = Buffer.toBuffer(array);
|
||||
// expect(array instanceof Buffer).toBe(true);
|
||||
// // if this fails or infinitely loops, it means there is a memory issue with the JSC::Structure object
|
||||
// expect(Object.keys(buf).length > 0).toBe(true);
|
||||
|
||||
// expect(buf.write("hello world ")).toBe(12);
|
||||
// gc();
|
||||
// expect(buf.toString("utf8", 0, "hello world ".length)).toBe("hello world ");
|
||||
// gc();
|
||||
// expect(buf.toString("base64url", 0, "hello world ".length)).toBe(
|
||||
// btoa("hello world ")
|
||||
// );
|
||||
// gc();
|
||||
|
||||
// expect(buf instanceof Uint8Array).toBe(true);
|
||||
// expect(buf instanceof Buffer).toBe(true);
|
||||
// expect(buf.slice() instanceof Uint8Array).toBe(true);
|
||||
// expect(buf.slice(0, 1) instanceof Buffer).toBe(true);
|
||||
// expect(buf.slice(0, 1) instanceof Uint8Array).toBe(true);
|
||||
// expect(buf.slice(0, 1) instanceof Buffer).toBe(true);
|
||||
// expect(new Buffer(buf) instanceof Buffer).toBe(true);
|
||||
// expect(new Buffer(buf.buffer) instanceof Buffer).toBe(true);
|
||||
// });
|
||||
|
||||
// it("writeInt", () => {
|
||||
// var buf = new Buffer(1024);
|
||||
// var data = new DataView(buf.buffer);
|
||||
// buf.writeInt32BE(100);
|
||||
// expect(data.getInt32(0, false)).toBe(100);
|
||||
// buf.writeInt32BE(100);
|
||||
// expect(data.getInt32(0, false)).toBe(100);
|
||||
// var childBuf = buf.subarray(0, 4);
|
||||
// expect(data.getInt32(0, false)).toBe(100);
|
||||
// expect(childBuf.readInt32BE(0, false)).toBe(100);
|
||||
// });
|
||||
|
||||
// it("Buffer.from", () => {
|
||||
// expect(Buffer.from("hello world").toString("utf8")).toBe("hello world");
|
||||
// expect(Buffer.from("hello world", "ascii").toString("utf8")).toBe(
|
||||
// "hello world"
|
||||
// );
|
||||
// expect(Buffer.from("hello world", "latin1").toString("utf8")).toBe(
|
||||
// "hello world"
|
||||
// );
|
||||
// gc();
|
||||
// expect(Buffer.from([254]).join(",")).toBe("254");
|
||||
// expect(Buffer.from(123).join(",")).toBe(Uint8Array.from(123).join(","));
|
||||
// expect(Buffer.from({ length: 124 }).join(",")).toBe(
|
||||
// Uint8Array.from({ length: 124 }).join(",")
|
||||
// );
|
||||
|
||||
// expect(Buffer.from(new ArrayBuffer(1024), 0, 512).join(",")).toBe(
|
||||
// new Uint8Array(512).join(",")
|
||||
// );
|
||||
|
||||
// expect(Buffer.from(new Buffer(new ArrayBuffer(1024), 0, 512)).join(",")).toBe(
|
||||
// new Uint8Array(512).join(",")
|
||||
// );
|
||||
// gc();
|
||||
// });
|
||||
|
||||
// it("Buffer.equals", () => {
|
||||
// var a = new Uint8Array(10);
|
||||
// a[2] = 1;
|
||||
// var b = new Uint8Array(10);
|
||||
// b[2] = 1;
|
||||
// Buffer.toBuffer(a);
|
||||
// Buffer.toBuffer(b);
|
||||
// expect(a.equals(b)).toBe(true);
|
||||
// b[2] = 0;
|
||||
// expect(a.equals(b)).toBe(false);
|
||||
// });
|
||||
|
||||
// it("Buffer.compare", () => {
|
||||
// var a = new Uint8Array(10);
|
||||
// a[2] = 1;
|
||||
// var b = new Uint8Array(10);
|
||||
// b[2] = 1;
|
||||
// Buffer.toBuffer(a);
|
||||
// Buffer.toBuffer(b);
|
||||
// expect(a.compare(b)).toBe(0);
|
||||
// b[2] = 0;
|
||||
// expect(a.compare(b)).toBe(1);
|
||||
// expect(b.compare(a)).toBe(-1);
|
||||
// });
|
||||
|
||||
// it("Buffer.copy", () => {
|
||||
// var array1 = new Uint8Array(128);
|
||||
// array1.fill(100);
|
||||
// Buffer.toBuffer(array1);
|
||||
// var array2 = new Uint8Array(128);
|
||||
// array2.fill(200);
|
||||
// Buffer.toBuffer(array2);
|
||||
// var array3 = new Uint8Array(128);
|
||||
// Buffer.toBuffer(array3);
|
||||
// gc();
|
||||
// expect(array1.copy(array2)).toBe(128);
|
||||
// expect(array1.join("")).toBe(array2.join(""));
|
||||
// });
|
||||
|
||||
// it("Buffer.concat", () => {
|
||||
// var array1 = new Uint8Array(128);
|
||||
// array1.fill(100);
|
||||
// var array2 = new Uint8Array(128);
|
||||
// array2.fill(200);
|
||||
// var array3 = new Uint8Array(128);
|
||||
// array3.fill(300);
|
||||
// gc();
|
||||
// expect(Buffer.concat([array1, array2, array3]).join("")).toBe(
|
||||
// array1.join("") + array2.join("") + array3.join("")
|
||||
// );
|
||||
// expect(Buffer.concat([array1, array2, array3], 222).length).toBe(222);
|
||||
// expect(
|
||||
// Buffer.concat([array1, array2, array3], 222).subarray(0, 128).join("")
|
||||
// ).toBe("100".repeat(128));
|
||||
// expect(
|
||||
// Buffer.concat([array1, array2, array3], 222).subarray(129, 222).join("")
|
||||
// ).toBe("200".repeat(222 - 129));
|
||||
// });
|
||||
|
||||
// it("read", () => {
|
||||
// var buf = new Buffer(1024);
|
||||
// var data = new DataView(buf.buffer);
|
||||
// function reset() {
|
||||
// new Uint8Array(buf.buffer).fill(0);
|
||||
// }
|
||||
// data.setBigInt64(0, BigInt(1000), false);
|
||||
// expect(buf.readBigInt64BE(0)).toBe(BigInt(1000));
|
||||
// reset();
|
||||
|
||||
// data.setBigInt64(0, BigInt(1000), false);
|
||||
// expect(buf.readBigInt64LE(0)).toBe(BigInt(1000));
|
||||
// reset();
|
||||
|
||||
// data.setBigUint64(0, BigInt(1000), false);
|
||||
// expect(buf.readBigUInt64BE(0)).toBe(BigInt(1000));
|
||||
// reset();
|
||||
|
||||
// data.setBigUint64(0, BigInt(1000), false);
|
||||
// expect(buf.readBigUInt64LE(0)).toBe(BigInt(1000));
|
||||
// reset();
|
||||
|
||||
// data.setFloat64(0, 1000, false);
|
||||
// expect(buf.readDoubleBE(0)).toBe(1000);
|
||||
// reset();
|
||||
|
||||
// data.setFloat64(0, 1000, true);
|
||||
// expect(buf.readDoubleLE(0)).toBe(1000);
|
||||
// reset();
|
||||
|
||||
// data.setFloat32(0, 1000, false);
|
||||
// expect(buf.readFloatBE(0)).toBe(1000);
|
||||
// reset();
|
||||
|
||||
// data.setFloat32(0, 1000, true);
|
||||
// expect(buf.readFloatLE(0)).toBe(1000);
|
||||
// reset();
|
||||
|
||||
// data.setInt16(0, 1000, false);
|
||||
// expect(buf.readInt16BE(0)).toBe(1000);
|
||||
// reset();
|
||||
|
||||
// data.setInt16(0, 1000, true);
|
||||
// expect(buf.readInt16LE(0)).toBe(1000);
|
||||
// reset();
|
||||
|
||||
// data.setInt32(0, 1000, false);
|
||||
// expect(buf.readInt32BE(0)).toBe(1000);
|
||||
// reset();
|
||||
|
||||
// data.setInt32(0, 1000, true);
|
||||
// expect(buf.readInt32LE(0)).toBe(1000);
|
||||
// reset();
|
||||
|
||||
// data.setInt8(0, 100, false);
|
||||
// expect(buf.readInt8(0)).toBe(100);
|
||||
// reset();
|
||||
|
||||
// data.setUint16(0, 1000, false);
|
||||
// expect(buf.readUInt16BE(0)).toBe(1000);
|
||||
// reset();
|
||||
|
||||
// data.setUint16(0, 1000, true);
|
||||
// expect(buf.readUInt16LE(0)).toBe(1000);
|
||||
// reset();
|
||||
|
||||
// data.setUint32(0, 1000, false);
|
||||
// expect(buf.readUInt32BE(0)).toBe(1000);
|
||||
// reset();
|
||||
|
||||
// data.setUint32(0, 1000, true);
|
||||
// expect(buf.readUInt32LE(0)).toBe(1000);
|
||||
// reset();
|
||||
|
||||
// data.setUint8(0, 255, false);
|
||||
// expect(buf.readUInt8(0)).toBe(255);
|
||||
// reset();
|
||||
|
||||
// data.setUint8(0, 255, false);
|
||||
// expect(buf.readUInt8(0)).toBe(255);
|
||||
// reset();
|
||||
// });
|
||||
98
test/bun.js/bun-jsc.test.js
Normal file
98
test/bun.js/bun-jsc.test.js
Normal file
@@ -0,0 +1,98 @@
|
||||
import { describe, expect, it } from "bun:test";
|
||||
import {
|
||||
describe as jscDescribe,
|
||||
describeArray,
|
||||
gcAndSweep,
|
||||
fullGC,
|
||||
edenGC,
|
||||
heapSize,
|
||||
heapStats,
|
||||
memoryUsage,
|
||||
getRandomSeed,
|
||||
setRandomSeed,
|
||||
isRope,
|
||||
callerSourceOrigin,
|
||||
noFTL,
|
||||
noOSRExitFuzzing,
|
||||
optimizeNextInvocation,
|
||||
numberOfDFGCompiles,
|
||||
releaseWeakRefs,
|
||||
totalCompileTime,
|
||||
reoptimizationRetryCount,
|
||||
drainMicrotasks,
|
||||
startRemoteDebugger,
|
||||
} from "bun:jsc";
|
||||
|
||||
describe("bun:jsc", () => {
|
||||
function count() {
|
||||
var j = 0;
|
||||
for (var i = 0; i < 999999; i++) {
|
||||
j += i + 2;
|
||||
}
|
||||
|
||||
return j;
|
||||
}
|
||||
|
||||
it("describe", () => {
|
||||
jscDescribe([]);
|
||||
});
|
||||
it("describeArray", () => {
|
||||
describeArray([1, 2, 3]);
|
||||
});
|
||||
it("gcAndSweep", () => {
|
||||
gcAndSweep();
|
||||
});
|
||||
it("fullGC", () => {
|
||||
fullGC();
|
||||
});
|
||||
it("edenGC", () => {
|
||||
edenGC();
|
||||
});
|
||||
it("heapSize", () => {
|
||||
expect(heapSize() > 0).toBe(true);
|
||||
});
|
||||
it("heapStats", () => {
|
||||
heapStats();
|
||||
});
|
||||
it("memoryUsage", () => {
|
||||
memoryUsage();
|
||||
});
|
||||
it("getRandomSeed", () => {
|
||||
getRandomSeed(2);
|
||||
});
|
||||
it("setRandomSeed", () => {
|
||||
setRandomSeed(2);
|
||||
});
|
||||
it("isRope", () => {
|
||||
expect(isRope("a" + 123 + "b")).toBe(true);
|
||||
expect(isRope("abcdefgh")).toBe(false);
|
||||
});
|
||||
it("callerSourceOrigin", () => {
|
||||
expect(callerSourceOrigin()).toBe(import.meta.url);
|
||||
});
|
||||
it("noFTL", () => {});
|
||||
it("noOSRExitFuzzing", () => {});
|
||||
it("optimizeNextInvocation", () => {
|
||||
count();
|
||||
optimizeNextInvocation(count);
|
||||
count();
|
||||
});
|
||||
it("numberOfDFGCompiles", () => {
|
||||
expect(numberOfDFGCompiles(count) > 0).toBe(true);
|
||||
});
|
||||
it("releaseWeakRefs", () => {
|
||||
releaseWeakRefs();
|
||||
});
|
||||
it("totalCompileTime", () => {
|
||||
totalCompileTime(count);
|
||||
});
|
||||
it("reoptimizationRetryCount", () => {
|
||||
reoptimizationRetryCount(count);
|
||||
});
|
||||
it("drainMicrotasks", () => {
|
||||
drainMicrotasks();
|
||||
});
|
||||
it("startRemoteDebugger", () => {
|
||||
startRemoteDebugger("");
|
||||
});
|
||||
});
|
||||
BIN
test/bun.js/bun.lockb
Executable file
BIN
test/bun.js/bun.lockb
Executable file
Binary file not shown.
1
test/bun.js/bundled/always-bundled-module/always-bundled-module
Symbolic link
1
test/bun.js/bundled/always-bundled-module/always-bundled-module
Symbolic link
@@ -0,0 +1 @@
|
||||
node_modules/always-bundled-module
|
||||
10
test/bun.js/bundled/always-bundled-module/cjs.js
Normal file
10
test/bun.js/bundled/always-bundled-module/cjs.js
Normal file
@@ -0,0 +1,10 @@
|
||||
module.exports = {
|
||||
default: 0xdeadbeef,
|
||||
default() {
|
||||
return "ok";
|
||||
},
|
||||
default: true,
|
||||
ok() {
|
||||
return true;
|
||||
},
|
||||
};
|
||||
5
test/bun.js/bundled/always-bundled-module/esm.js
Normal file
5
test/bun.js/bundled/always-bundled-module/esm.js
Normal file
@@ -0,0 +1,5 @@
|
||||
const __esModule = true;
|
||||
|
||||
export const foo = () => __esModule;
|
||||
|
||||
export { __esModule, foo as default };
|
||||
4
test/bun.js/bundled/always-bundled-module/package.json
Normal file
4
test/bun.js/bundled/always-bundled-module/package.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "always-bundled-module",
|
||||
"version": "1.0.0"
|
||||
}
|
||||
13
test/bun.js/bundled/entrypoint.ts
Normal file
13
test/bun.js/bundled/entrypoint.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import "i-am-bundled/cjs";
|
||||
import "i-am-bundled/esm";
|
||||
import "always-bundled-module/esm";
|
||||
import "always-bundled-module/cjs";
|
||||
import { foo } from "i-am-bundled/esm";
|
||||
import { foo as foo2 } from "always-bundled-module/esm";
|
||||
import cJS from "always-bundled-module/cjs";
|
||||
|
||||
foo();
|
||||
foo2();
|
||||
cJS();
|
||||
|
||||
export default cJS();
|
||||
12
test/bun.js/bundled/package.json
Normal file
12
test/bun.js/bundled/package.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "to-bundle",
|
||||
"scripts": {
|
||||
"prebundle": "rm -rf node_modules; cp -r to_bundle_node_modules node_modules; ln -s always-bundled-module node_modules/always-bundled-module",
|
||||
"bundle": "${BUN_BIN:-$(which bun)} bun ./entrypoint.ts"
|
||||
},
|
||||
"bun": {
|
||||
"alwaysBundle": [
|
||||
"always-bundled-module"
|
||||
]
|
||||
}
|
||||
}
|
||||
10
test/bun.js/bundled/to_bundle_node_modules/i-am-bundled/cjs.js
generated
Normal file
10
test/bun.js/bundled/to_bundle_node_modules/i-am-bundled/cjs.js
generated
Normal file
@@ -0,0 +1,10 @@
|
||||
module.exports = {
|
||||
default: 0xdeadbeef,
|
||||
default() {
|
||||
return "ok";
|
||||
},
|
||||
default: true,
|
||||
ok() {
|
||||
return true;
|
||||
},
|
||||
};
|
||||
5
test/bun.js/bundled/to_bundle_node_modules/i-am-bundled/esm.js
generated
Normal file
5
test/bun.js/bundled/to_bundle_node_modules/i-am-bundled/esm.js
generated
Normal file
@@ -0,0 +1,5 @@
|
||||
const __esModule = true;
|
||||
|
||||
export const foo = () => __esModule;
|
||||
|
||||
export { __esModule, foo as default };
|
||||
4
test/bun.js/bundled/to_bundle_node_modules/i-am-bundled/package.json
generated
Normal file
4
test/bun.js/bundled/to_bundle_node_modules/i-am-bundled/package.json
generated
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "i-am-bundled",
|
||||
"version": "1.0.0"
|
||||
}
|
||||
6
test/bun.js/bundled/tsconfig.json
Normal file
6
test/bun.js/bundled/tsconfig.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"paths": {},
|
||||
"baseUrl": "."
|
||||
}
|
||||
}
|
||||
46
test/bun.js/concat.test.js
Normal file
46
test/bun.js/concat.test.js
Normal file
@@ -0,0 +1,46 @@
|
||||
import { describe, it, expect } from "bun:test";
|
||||
import { gcTick } from "./gc";
|
||||
import { concatArrayBuffers } from "bun";
|
||||
|
||||
describe("concat", () => {
|
||||
function polyfill(chunks) {
|
||||
var size = 0;
|
||||
for (const chunk of chunks) {
|
||||
size += chunk.byteLength;
|
||||
}
|
||||
var buffer = new ArrayBuffer(size);
|
||||
var view = new Uint8Array(buffer);
|
||||
var offset = 0;
|
||||
for (const chunk of chunks) {
|
||||
view.set(chunk, offset);
|
||||
offset += chunk.byteLength;
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
function concatToString(chunks) {
|
||||
return Array.from(new Uint8Array(concatArrayBuffers(chunks))).join("");
|
||||
}
|
||||
|
||||
function polyfillToString(chunks) {
|
||||
return Array.from(new Uint8Array(polyfill(chunks))).join("");
|
||||
}
|
||||
|
||||
it("works with one element", () => {
|
||||
expect(concatToString([new Uint8Array([123])])).toBe(
|
||||
polyfillToString([new Uint8Array([123])])
|
||||
);
|
||||
});
|
||||
|
||||
it("works with two elements", () => {
|
||||
expect(
|
||||
concatToString([Uint8Array.from([123]), Uint8Array.from([456])])
|
||||
).toBe(polyfillToString([Uint8Array.from([123]), Uint8Array.from([456])]));
|
||||
});
|
||||
|
||||
it("works with mix of ArrayBuffer and TypedArray elements", () => {
|
||||
expect(
|
||||
concatToString([Uint8Array.from([123]).buffer, Uint8Array.from([456])])
|
||||
).toBe(polyfillToString([Uint8Array.from([123]), Uint8Array.from([456])]));
|
||||
});
|
||||
});
|
||||
58
test/bun.js/console-log.js
Normal file
58
test/bun.js/console-log.js
Normal file
@@ -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");
|
||||
70
test/bun.js/crypto.test.js
Normal file
70
test/bun.js/crypto.test.js
Normal file
@@ -0,0 +1,70 @@
|
||||
import {
|
||||
sha,
|
||||
MD5,
|
||||
MD4,
|
||||
SHA1,
|
||||
SHA256,
|
||||
SHA384,
|
||||
SHA512,
|
||||
SHA512_256,
|
||||
gc,
|
||||
} from "bun";
|
||||
import { it, expect, describe } from "bun:test";
|
||||
import { readFileSync } from "fs";
|
||||
|
||||
describe("crypto", () => {
|
||||
for (let Hash of [MD5, MD4, SHA1, SHA256, SHA384, SHA512, SHA512_256]) {
|
||||
for (let [input, label] of [
|
||||
["hello world", '"hello world"'],
|
||||
["hello world".repeat(20).slice(), '"hello world" x 20'],
|
||||
["", "empty string"],
|
||||
["a", '"a"'],
|
||||
]) {
|
||||
describe(label, () => {
|
||||
gc(true);
|
||||
|
||||
it(`${Hash.name} base64`, () => {
|
||||
gc(true);
|
||||
const result = new Hash();
|
||||
result.update(input);
|
||||
expect(typeof result.digest("base64")).toBe("string");
|
||||
gc(true);
|
||||
});
|
||||
|
||||
it(`${Hash.name} hash base64`, () => {
|
||||
Hash.hash(input, "base64");
|
||||
gc(true);
|
||||
});
|
||||
|
||||
it(`${Hash.name} hex`, () => {
|
||||
const result = new Hash();
|
||||
result.update(input);
|
||||
expect(typeof result.digest("hex")).toBe("string");
|
||||
gc(true);
|
||||
});
|
||||
|
||||
it(`${Hash.name} hash hex`, () => {
|
||||
expect(typeof Hash.hash(input, "hex")).toBe("string");
|
||||
gc(true);
|
||||
});
|
||||
|
||||
it(`${Hash.name} buffer`, () => {
|
||||
var buf = new Uint8Array(256);
|
||||
const result = new Hash();
|
||||
|
||||
result.update(input);
|
||||
expect(result.digest(buf)).toBe(buf);
|
||||
expect(buf[0] != 0).toBe(true);
|
||||
gc(true);
|
||||
});
|
||||
|
||||
it(`${Hash.name} buffer`, () => {
|
||||
var buf = new Uint8Array(256);
|
||||
|
||||
expect(Hash.hash(input, buf) instanceof Uint8Array).toBe(true);
|
||||
gc(true);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
9
test/bun.js/dirname.test.js
Normal file
9
test/bun.js/dirname.test.js
Normal file
@@ -0,0 +1,9 @@
|
||||
import { expect, it } from "bun:test";
|
||||
|
||||
it("__dirname should work", () => {
|
||||
expect(import.meta.dir).toBe(__dirname);
|
||||
});
|
||||
|
||||
it("__filename should work", () => {
|
||||
expect(import.meta.path).toBe(__filename);
|
||||
});
|
||||
105
test/bun.js/escapeHTML.test.js
Normal file
105
test/bun.js/escapeHTML.test.js
Normal file
@@ -0,0 +1,105 @@
|
||||
import { describe, it, expect } from "bun:test";
|
||||
import { gcTick } from "./gc";
|
||||
import { escapeHTML } from "bun";
|
||||
|
||||
describe("escapeHTML", () => {
|
||||
// The matrix of cases we need to test for:
|
||||
// 1. Works with short strings
|
||||
// 2. Works with long strings
|
||||
// 3. Works with latin1 strings
|
||||
// 4. Works with utf16 strings
|
||||
// 5. Works when the text to escape is somewhere in the middle
|
||||
// 6. Works when the text to escape is in the beginning
|
||||
// 7. Works when the text to escape is in the end
|
||||
// 8. Returns the same string when there's no need to escape
|
||||
it("works", () => {
|
||||
expect(escapeHTML("absolutely nothing to do here")).toBe(
|
||||
"absolutely nothing to do here"
|
||||
);
|
||||
expect(escapeHTML("<script>alert(1)</script>")).toBe(
|
||||
"<script>alert(1)</script>"
|
||||
);
|
||||
expect(escapeHTML("<")).toBe("<");
|
||||
expect(escapeHTML(">")).toBe(">");
|
||||
expect(escapeHTML("&")).toBe("&");
|
||||
expect(escapeHTML("'")).toBe("'");
|
||||
expect(escapeHTML('"')).toBe(""");
|
||||
expect(escapeHTML("\n")).toBe("\n");
|
||||
expect(escapeHTML("\r")).toBe("\r");
|
||||
expect(escapeHTML("\t")).toBe("\t");
|
||||
expect(escapeHTML("\f")).toBe("\f");
|
||||
expect(escapeHTML("\v")).toBe("\v");
|
||||
expect(escapeHTML("\b")).toBe("\b");
|
||||
expect(escapeHTML("\u00A0")).toBe("\u00A0");
|
||||
expect(escapeHTML("<script>ab")).toBe("<script>ab");
|
||||
expect(escapeHTML("<script>")).toBe("<script>");
|
||||
expect(escapeHTML("<script><script>")).toBe("<script><script>");
|
||||
|
||||
expect(escapeHTML("lalala" + "<script>alert(1)</script>" + "lalala")).toBe(
|
||||
"lalala<script>alert(1)</script>lalala"
|
||||
);
|
||||
|
||||
expect(escapeHTML("<script>alert(1)</script>" + "lalala")).toBe(
|
||||
"<script>alert(1)</script>lalala"
|
||||
);
|
||||
expect(escapeHTML("lalala" + "<script>alert(1)</script>")).toBe(
|
||||
"lalala" + "<script>alert(1)</script>"
|
||||
);
|
||||
|
||||
expect(escapeHTML("What does 😊 mean?")).toBe("What does 😊 mean?");
|
||||
const output = escapeHTML("<What does 😊");
|
||||
expect(output).toBe("<What does 😊");
|
||||
expect(escapeHTML("<div>What does 😊 mean in text?")).toBe(
|
||||
"<div>What does 😊 mean in text?"
|
||||
);
|
||||
|
||||
expect(
|
||||
escapeHTML(
|
||||
("lalala" + "<script>alert(1)</script>" + "lalala").repeat(900)
|
||||
)
|
||||
).toBe("lalala<script>alert(1)</script>lalala".repeat(900));
|
||||
expect(
|
||||
escapeHTML(("<script>alert(1)</script>" + "lalala").repeat(900))
|
||||
).toBe("<script>alert(1)</script>lalala".repeat(900));
|
||||
expect(
|
||||
escapeHTML(("lalala" + "<script>alert(1)</script>").repeat(900))
|
||||
).toBe(("lalala" + "<script>alert(1)</script>").repeat(900));
|
||||
|
||||
// the positions of the unicode codepoint are important
|
||||
// our simd code for U16 is at 8 bytes, so we need to especially check the boundaries
|
||||
expect(
|
||||
escapeHTML("😊lalala" + "<script>alert(1)</script>" + "lalala")
|
||||
).toBe("😊lalala<script>alert(1)</script>lalala");
|
||||
expect(escapeHTML("<script>😊alert(1)</script>" + "lalala")).toBe(
|
||||
"<script>😊alert(1)</script>lalala"
|
||||
);
|
||||
expect(escapeHTML("<script>alert(1)😊</script>" + "lalala")).toBe(
|
||||
"<script>alert(1)😊</script>lalala"
|
||||
);
|
||||
expect(escapeHTML("<script>alert(1)</script>" + "😊lalala")).toBe(
|
||||
"<script>alert(1)</script>😊lalala"
|
||||
);
|
||||
expect(escapeHTML("<script>alert(1)</script>" + "lal😊ala")).toBe(
|
||||
"<script>alert(1)</script>lal😊ala"
|
||||
);
|
||||
expect(
|
||||
escapeHTML("<script>alert(1)</script>" + "lal😊ala".repeat(10))
|
||||
).toBe("<script>alert(1)</script>" + "lal😊ala".repeat(10));
|
||||
|
||||
for (let i = 1; i < 10; i++)
|
||||
expect(escapeHTML("<script>alert(1)</script>" + "la😊".repeat(i))).toBe(
|
||||
"<script>alert(1)</script>" + "la😊".repeat(i)
|
||||
);
|
||||
|
||||
expect(escapeHTML("la😊" + "<script>alert(1)</script>")).toBe(
|
||||
"la😊" + "<script>alert(1)</script>"
|
||||
);
|
||||
expect(
|
||||
escapeHTML(("lalala" + "<script>alert(1)</script>😊").repeat(1))
|
||||
).toBe(("lalala" + "<script>alert(1)</script>😊").repeat(1));
|
||||
|
||||
expect(escapeHTML("😊".repeat(100))).toBe("😊".repeat(100));
|
||||
expect(escapeHTML("😊<".repeat(100))).toBe("😊<".repeat(100));
|
||||
expect(escapeHTML("<😊>".repeat(100))).toBe("<😊>".repeat(100));
|
||||
});
|
||||
});
|
||||
8
test/bun.js/esm/first.mjs
Normal file
8
test/bun.js/esm/first.mjs
Normal file
@@ -0,0 +1,8 @@
|
||||
import { end, start } from "./startEnd.mjs";
|
||||
|
||||
start("First");
|
||||
|
||||
import "./second.mjs";
|
||||
import "./third.mjs";
|
||||
|
||||
end("First");
|
||||
5
test/bun.js/esm/second-child.mjs
Normal file
5
test/bun.js/esm/second-child.mjs
Normal file
@@ -0,0 +1,5 @@
|
||||
import { start, end } from "./startEnd.mjs";
|
||||
|
||||
start("Second (nested import)");
|
||||
|
||||
end("Second (nested import)");
|
||||
7
test/bun.js/esm/second.mjs
Normal file
7
test/bun.js/esm/second.mjs
Normal file
@@ -0,0 +1,7 @@
|
||||
import { start, end } from "./startEnd.mjs";
|
||||
|
||||
start("Second");
|
||||
|
||||
import "./second-child.mjs";
|
||||
|
||||
end("Second");
|
||||
6
test/bun.js/esm/startEnd.mjs
Normal file
6
test/bun.js/esm/startEnd.mjs
Normal file
@@ -0,0 +1,6 @@
|
||||
export function start(name) {
|
||||
console.log(`[start] ${name}`);
|
||||
}
|
||||
export function end(name) {
|
||||
console.log(`[end] ${name}`);
|
||||
}
|
||||
4
test/bun.js/esm/third.mjs
Normal file
4
test/bun.js/esm/third.mjs
Normal file
@@ -0,0 +1,4 @@
|
||||
import { end, start } from "./startEnd.mjs";
|
||||
|
||||
start("Third");
|
||||
end("Third");
|
||||
2
test/bun.js/exit.js
Normal file
2
test/bun.js/exit.js
Normal file
@@ -0,0 +1,2 @@
|
||||
process.exit(0);
|
||||
throw new Error("Well that didn't work");
|
||||
46
test/bun.js/fetch.js.txt
Normal file
46
test/bun.js/fetch.js.txt
Normal file
@@ -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>
|
||||
440
test/bun.js/fetch.test.js
Normal file
440
test/bun.js/fetch.test.js
Normal file
@@ -0,0 +1,440 @@
|
||||
import { it, describe, expect } from "bun:test";
|
||||
import fs from "fs";
|
||||
import { gc } from "./gc";
|
||||
|
||||
describe("fetch", () => {
|
||||
const urls = ["https://example.com", "http://example.com"];
|
||||
for (let url of urls) {
|
||||
gc();
|
||||
it(url, async () => {
|
||||
gc();
|
||||
const response = await fetch(url);
|
||||
gc();
|
||||
const text = await response.text();
|
||||
gc();
|
||||
expect(
|
||||
fs.readFileSync(
|
||||
import.meta.path.substring(0, import.meta.path.lastIndexOf("/")) +
|
||||
"/fetch.js.txt",
|
||||
"utf8"
|
||||
)
|
||||
).toBe(text);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
function testBlobInterface(blobbyConstructor, hasBlobFn) {
|
||||
for (let withGC of [false, true]) {
|
||||
for (let jsonObject of [
|
||||
{ hello: true },
|
||||
{
|
||||
hello:
|
||||
"😀 😃 😄 😁 😆 😅 😂 🤣 🥲 ☺️ 😊 😇 🙂 🙃 😉 😌 😍 🥰 😘 😗 😙 😚 😋 😛 😝 😜 🤪 🤨 🧐 🤓 😎 🥸 🤩 🥳",
|
||||
},
|
||||
]) {
|
||||
it(`${jsonObject.hello === true ? "latin1" : "utf16"} json${
|
||||
withGC ? " (with gc) " : ""
|
||||
}`, async () => {
|
||||
if (withGC) gc();
|
||||
var response = blobbyConstructor(JSON.stringify(jsonObject));
|
||||
if (withGC) gc();
|
||||
expect(JSON.stringify(await response.json())).toBe(
|
||||
JSON.stringify(jsonObject)
|
||||
);
|
||||
if (withGC) gc();
|
||||
});
|
||||
|
||||
it(`${
|
||||
jsonObject.hello === true ? "latin1" : "utf16"
|
||||
} arrayBuffer -> json${withGC ? " (with gc) " : ""}`, async () => {
|
||||
if (withGC) gc();
|
||||
var response = blobbyConstructor(
|
||||
new TextEncoder().encode(JSON.stringify(jsonObject))
|
||||
);
|
||||
if (withGC) gc();
|
||||
expect(JSON.stringify(await response.json())).toBe(
|
||||
JSON.stringify(jsonObject)
|
||||
);
|
||||
if (withGC) gc();
|
||||
});
|
||||
|
||||
it(`${jsonObject.hello === true ? "latin1" : "utf16"} text${
|
||||
withGC ? " (with gc) " : ""
|
||||
}`, async () => {
|
||||
if (withGC) gc();
|
||||
var response = blobbyConstructor(JSON.stringify(jsonObject));
|
||||
if (withGC) gc();
|
||||
expect(await response.text()).toBe(JSON.stringify(jsonObject));
|
||||
if (withGC) gc();
|
||||
});
|
||||
|
||||
it(`${
|
||||
jsonObject.hello === true ? "latin1" : "utf16"
|
||||
} arrayBuffer -> text${withGC ? " (with gc) " : ""}`, async () => {
|
||||
if (withGC) gc();
|
||||
var response = blobbyConstructor(
|
||||
new TextEncoder().encode(JSON.stringify(jsonObject))
|
||||
);
|
||||
if (withGC) gc();
|
||||
expect(await response.text()).toBe(JSON.stringify(jsonObject));
|
||||
if (withGC) gc();
|
||||
});
|
||||
|
||||
it(`${jsonObject.hello === true ? "latin1" : "utf16"} arrayBuffer${
|
||||
withGC ? " (with gc) " : ""
|
||||
}`, async () => {
|
||||
if (withGC) gc();
|
||||
|
||||
var response = blobbyConstructor(JSON.stringify(jsonObject));
|
||||
if (withGC) gc();
|
||||
|
||||
const bytes = new TextEncoder().encode(JSON.stringify(jsonObject));
|
||||
if (withGC) gc();
|
||||
|
||||
const compare = new Uint8Array(await response.arrayBuffer());
|
||||
if (withGC) gc();
|
||||
|
||||
for (let i = 0; i < compare.length; i++) {
|
||||
if (withGC) gc();
|
||||
|
||||
expect(compare[i]).toBe(bytes[i]);
|
||||
if (withGC) gc();
|
||||
}
|
||||
if (withGC) gc();
|
||||
});
|
||||
|
||||
it(`${
|
||||
jsonObject.hello === true ? "latin1" : "utf16"
|
||||
} arrayBuffer -> arrayBuffer${withGC ? " (with gc) " : ""}`, async () => {
|
||||
if (withGC) gc();
|
||||
|
||||
var response = blobbyConstructor(
|
||||
new TextEncoder().encode(JSON.stringify(jsonObject))
|
||||
);
|
||||
if (withGC) gc();
|
||||
|
||||
const bytes = new TextEncoder().encode(JSON.stringify(jsonObject));
|
||||
if (withGC) gc();
|
||||
|
||||
const compare = new Uint8Array(await response.arrayBuffer());
|
||||
if (withGC) gc();
|
||||
|
||||
for (let i = 0; i < compare.length; i++) {
|
||||
if (withGC) gc();
|
||||
|
||||
expect(compare[i]).toBe(bytes[i]);
|
||||
if (withGC) gc();
|
||||
}
|
||||
if (withGC) gc();
|
||||
});
|
||||
|
||||
hasBlobFn &&
|
||||
it(`${jsonObject.hello === true ? "latin1" : "utf16"} blob${
|
||||
withGC ? " (with gc) " : ""
|
||||
}`, async () => {
|
||||
if (withGC) gc();
|
||||
const text = JSON.stringify(jsonObject);
|
||||
var response = blobbyConstructor(text);
|
||||
if (withGC) gc();
|
||||
const size = new TextEncoder().encode(text).byteLength;
|
||||
if (withGC) gc();
|
||||
const blobed = await response.blob();
|
||||
if (withGC) gc();
|
||||
expect(blobed instanceof Blob).toBe(true);
|
||||
if (withGC) gc();
|
||||
expect(blobed.size).toBe(size);
|
||||
if (withGC) gc();
|
||||
expect(blobed.type).toBe("");
|
||||
if (withGC) gc();
|
||||
blobed.type = "application/json";
|
||||
if (withGC) gc();
|
||||
expect(blobed.type).toBe("application/json");
|
||||
if (withGC) gc();
|
||||
const out = await blobed.text();
|
||||
expect(out).toBe(text);
|
||||
if (withGC) gc();
|
||||
await new Promise((resolve) => setTimeout(resolve, 1));
|
||||
if (withGC) gc();
|
||||
expect(out).toBe(text);
|
||||
const first = await blobed.arrayBuffer();
|
||||
const initial = first[0];
|
||||
first[0] = 254;
|
||||
const second = await blobed.arrayBuffer();
|
||||
expect(second[0]).toBe(initial);
|
||||
expect(first[0]).toBe(254);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
describe("Blob", () => {
|
||||
testBlobInterface((data) => new Blob([data]));
|
||||
|
||||
var blobConstructorValues = [
|
||||
["123", "456"],
|
||||
["123", 456],
|
||||
["123", "456", "789"],
|
||||
["123", 456, 789],
|
||||
[1, 2, 3, 4, 5, 6, 7, 8, 9],
|
||||
[Uint8Array.from([1, 2, 3, 4, 5, 6, 7, 9])],
|
||||
[Uint8Array.from([1, 2, 3, 4]), "5678", 9],
|
||||
[new Blob([Uint8Array.from([1, 2, 3, 4])]), "5678", 9],
|
||||
[
|
||||
new Blob([
|
||||
new TextEncoder().encode(
|
||||
"😀 😃 😄 😁 😆 😅 😂 🤣 🥲 ☺️ 😊 😇 🙂 🙃 😉 😌 😍 🥰 😘 😗 😙 😚 😋 😛 😝 😜 🤪 🤨 🧐 🤓 😎 🥸 🤩 🥳"
|
||||
),
|
||||
]),
|
||||
],
|
||||
[
|
||||
new TextEncoder().encode(
|
||||
"😀 😃 😄 😁 😆 😅 😂 🤣 🥲 ☺️ 😊 😇 🙂 🙃 😉 😌 😍 🥰 😘 😗 😙 😚 😋 😛 😝 😜 🤪 🤨 🧐 🤓 😎 🥸 🤩 🥳"
|
||||
),
|
||||
],
|
||||
];
|
||||
|
||||
var expected = [
|
||||
"123456",
|
||||
"123456",
|
||||
"123456789",
|
||||
"123456789",
|
||||
"123456789",
|
||||
"\x01\x02\x03\x04\x05\x06\x07\t",
|
||||
"\x01\x02\x03\x0456789",
|
||||
"\x01\x02\x03\x0456789",
|
||||
"😀 😃 😄 😁 😆 😅 😂 🤣 🥲 ☺️ 😊 😇 🙂 🙃 😉 😌 😍 🥰 😘 😗 😙 😚 😋 😛 😝 😜 🤪 🤨 🧐 🤓 😎 🥸 🤩 🥳",
|
||||
"😀 😃 😄 😁 😆 😅 😂 🤣 🥲 ☺️ 😊 😇 🙂 🙃 😉 😌 😍 🥰 😘 😗 😙 😚 😋 😛 😝 😜 🤪 🤨 🧐 🤓 😎 🥸 🤩 🥳",
|
||||
];
|
||||
|
||||
it(`blobConstructorValues`, async () => {
|
||||
for (let i = 0; i < blobConstructorValues.length; i++) {
|
||||
var response = new Blob(blobConstructorValues[i]);
|
||||
const res = await response.text();
|
||||
if (res !== expected[i]) {
|
||||
throw new Error(
|
||||
`Failed: ${expected[i]
|
||||
.split("")
|
||||
.map((a) => a.charCodeAt(0))}, received: ${res
|
||||
.split("")
|
||||
.map((a) => a.charCodeAt(0))}`
|
||||
);
|
||||
}
|
||||
|
||||
expect(res).toBe(expected[i]);
|
||||
}
|
||||
});
|
||||
|
||||
for (let withGC of [false, true]) {
|
||||
it(`Blob.slice() ${withGC ? " with gc" : ""}`, async () => {
|
||||
var parts = ["hello", " ", "world"];
|
||||
if (withGC) gc();
|
||||
var str = parts.join("");
|
||||
if (withGC) gc();
|
||||
var combined = new Blob(parts);
|
||||
if (withGC) gc();
|
||||
for (let part of parts) {
|
||||
if (withGC) gc();
|
||||
expect(
|
||||
await combined
|
||||
.slice(str.indexOf(part), str.indexOf(part) + part.length)
|
||||
.text()
|
||||
).toBe(part);
|
||||
if (withGC) gc();
|
||||
}
|
||||
if (withGC) gc();
|
||||
for (let part of parts) {
|
||||
if (withGC) gc();
|
||||
expect(
|
||||
await combined
|
||||
.slice(str.indexOf(part), str.indexOf(part) + part.length)
|
||||
.text()
|
||||
).toBe(part);
|
||||
if (withGC) gc();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe("Response", () => {
|
||||
describe("Response.json", () => {
|
||||
it("works", async () => {
|
||||
const inputs = [
|
||||
"hellooo",
|
||||
[[123], 456, 789],
|
||||
{ hello: "world" },
|
||||
{ ok: "😉 😌 😍 🥰 😘 " },
|
||||
];
|
||||
for (let input of inputs) {
|
||||
const output = JSON.stringify(input);
|
||||
expect(await Response.json(input).text()).toBe(output);
|
||||
}
|
||||
// JSON.stringify() returns undefined
|
||||
expect(await Response.json().text()).toBe("");
|
||||
// JSON.stringify("") returns '""'
|
||||
expect(await Response.json("").text()).toBe('""');
|
||||
});
|
||||
it("sets the content-type header", () => {
|
||||
let response = Response.json("hello");
|
||||
expect(response.type).toBe("basic");
|
||||
expect(response.headers.get("content-type")).toBe(
|
||||
"application/json;charset=utf-8"
|
||||
);
|
||||
expect(response.status).toBe(200);
|
||||
});
|
||||
it("supports number status code", () => {
|
||||
let response = Response.json("hello", 407);
|
||||
expect(response.type).toBe("basic");
|
||||
expect(response.headers.get("content-type")).toBe(
|
||||
"application/json;charset=utf-8"
|
||||
);
|
||||
expect(response.status).toBe(407);
|
||||
});
|
||||
|
||||
it("supports headers", () => {
|
||||
var response = Response.json("hello", {
|
||||
headers: {
|
||||
"content-type": "potato",
|
||||
"x-hello": "world",
|
||||
},
|
||||
status: 408,
|
||||
});
|
||||
|
||||
expect(response.headers.get("x-hello")).toBe("world");
|
||||
expect(response.status).toBe(408);
|
||||
});
|
||||
});
|
||||
describe("Response.redirect", () => {
|
||||
it("works", () => {
|
||||
const inputs = [
|
||||
"http://example.com",
|
||||
"http://example.com/",
|
||||
"http://example.com/hello",
|
||||
"http://example.com/hello/",
|
||||
"http://example.com/hello/world",
|
||||
"http://example.com/hello/world/",
|
||||
];
|
||||
for (let input of inputs) {
|
||||
expect(Response.redirect(input).headers.get("Location")).toBe(input);
|
||||
}
|
||||
});
|
||||
|
||||
it("supports headers", () => {
|
||||
var response = Response.redirect("https://example.com", {
|
||||
headers: {
|
||||
"content-type": "potato",
|
||||
"x-hello": "world",
|
||||
Location: "https://wrong.com",
|
||||
},
|
||||
status: 408,
|
||||
});
|
||||
expect(response.headers.get("x-hello")).toBe("world");
|
||||
expect(response.headers.get("Location")).toBe("https://example.com");
|
||||
expect(response.status).toBe(302);
|
||||
expect(response.type).toBe("basic");
|
||||
expect(response.ok).toBe(false);
|
||||
});
|
||||
});
|
||||
describe("Response.error", () => {
|
||||
it("works", () => {
|
||||
expect(Response.error().type).toBe("error");
|
||||
expect(Response.error().ok).toBe(false);
|
||||
expect(Response.error().status).toBe(0);
|
||||
});
|
||||
});
|
||||
it("clone", async () => {
|
||||
gc();
|
||||
var body = new Response("<div>hello</div>", {
|
||||
headers: {
|
||||
"content-type": "text/html; charset=utf-8",
|
||||
},
|
||||
});
|
||||
gc();
|
||||
var clone = body.clone();
|
||||
gc();
|
||||
body.headers.set("content-type", "text/plain");
|
||||
gc();
|
||||
expect(clone.headers.get("content-type")).toBe("text/html; charset=utf-8");
|
||||
gc();
|
||||
expect(body.headers.get("content-type")).toBe("text/plain");
|
||||
gc();
|
||||
expect(await clone.text()).toBe("<div>hello</div>");
|
||||
gc();
|
||||
});
|
||||
it("invalid json", async () => {
|
||||
gc();
|
||||
var body = new Response("<div>hello</div>", {
|
||||
headers: {
|
||||
"content-type": "text/html; charset=utf-8",
|
||||
},
|
||||
});
|
||||
try {
|
||||
await body.json();
|
||||
expect(false).toBe(true);
|
||||
} catch (exception) {
|
||||
expect(exception instanceof SyntaxError);
|
||||
}
|
||||
});
|
||||
|
||||
testBlobInterface((data) => new Response(data), true);
|
||||
});
|
||||
|
||||
describe("Request", () => {
|
||||
it("clone", async () => {
|
||||
gc();
|
||||
var body = new Request("https://hello.com", {
|
||||
headers: {
|
||||
"content-type": "text/html; charset=utf-8",
|
||||
},
|
||||
body: "<div>hello</div>",
|
||||
});
|
||||
gc();
|
||||
expect(body.headers.get("content-type")).toBe("text/html; charset=utf-8");
|
||||
gc();
|
||||
var clone = body.clone();
|
||||
gc();
|
||||
body.headers.set("content-type", "text/plain");
|
||||
gc();
|
||||
expect(clone.headers.get("content-type")).toBe("text/html; charset=utf-8");
|
||||
gc();
|
||||
expect(body.headers.get("content-type")).toBe("text/plain");
|
||||
gc();
|
||||
expect(await clone.text()).toBe("<div>hello</div>");
|
||||
gc();
|
||||
});
|
||||
|
||||
testBlobInterface(
|
||||
(data) => new Request("https://hello.com", { body: data }),
|
||||
true
|
||||
);
|
||||
});
|
||||
|
||||
describe("Headers", () => {
|
||||
it("writes", async () => {
|
||||
var headers = new Headers({
|
||||
"content-type": "text/html; charset=utf-8",
|
||||
});
|
||||
gc();
|
||||
expect(headers.get("content-type")).toBe("text/html; charset=utf-8");
|
||||
gc();
|
||||
headers.delete("content-type");
|
||||
gc();
|
||||
expect(headers.get("content-type")).toBe(null);
|
||||
gc();
|
||||
headers.append("content-type", "text/plain");
|
||||
gc();
|
||||
expect(headers.get("content-type")).toBe("text/plain");
|
||||
gc();
|
||||
headers.append("content-type", "text/plain");
|
||||
gc();
|
||||
expect(headers.get("content-type")).toBe("text/plain, text/plain");
|
||||
gc();
|
||||
headers.set("content-type", "text/html; charset=utf-8");
|
||||
gc();
|
||||
expect(headers.get("content-type")).toBe("text/html; charset=utf-8");
|
||||
|
||||
headers.delete("content-type");
|
||||
gc();
|
||||
expect(headers.get("content-type")).toBe(null);
|
||||
gc();
|
||||
});
|
||||
});
|
||||
129
test/bun.js/ffi-test.c
Normal file
129
test/bun.js/ffi-test.c
Normal file
@@ -0,0 +1,129 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
bool returns_true();
|
||||
bool returns_false();
|
||||
char returns_42_char();
|
||||
float returns_42_float();
|
||||
double returns_42_double();
|
||||
uint8_t returns_42_uint8_t();
|
||||
int8_t returns_neg_42_int8_t();
|
||||
uint16_t returns_42_uint16_t();
|
||||
uint32_t returns_42_uint32_t();
|
||||
uint64_t returns_42_uint64_t();
|
||||
int16_t returns_neg_42_int16_t();
|
||||
int32_t returns_neg_42_int32_t();
|
||||
int64_t returns_neg_42_int64_t();
|
||||
|
||||
bool cb_identity_true(bool (*cb)());
|
||||
bool cb_identity_false(bool (*cb)());
|
||||
char cb_identity_42_char(char (*cb)());
|
||||
float cb_identity_42_float(float (*cb)());
|
||||
double cb_identity_42_double(double (*cb)());
|
||||
uint8_t cb_identity_42_uint8_t(uint8_t (*cb)());
|
||||
int8_t cb_identity_neg_42_int8_t(int8_t (*cb)());
|
||||
uint16_t cb_identity_42_uint16_t(uint16_t (*cb)());
|
||||
uint32_t cb_identity_42_uint32_t(uint32_t (*cb)());
|
||||
uint64_t cb_identity_42_uint64_t(uint64_t (*cb)());
|
||||
int16_t cb_identity_neg_42_int16_t(int16_t (*cb)());
|
||||
int32_t cb_identity_neg_42_int32_t(int32_t (*cb)());
|
||||
int64_t cb_identity_neg_42_int64_t(int64_t (*cb)());
|
||||
|
||||
bool identity_bool_true();
|
||||
bool identity_bool_false();
|
||||
char identity_char(char a);
|
||||
float identity_float(float a);
|
||||
bool identity_bool(bool ident);
|
||||
double identity_double(double a);
|
||||
int8_t identity_int8_t(int8_t a);
|
||||
int16_t identity_int16_t(int16_t a);
|
||||
int32_t identity_int32_t(int32_t a);
|
||||
int64_t identity_int64_t(int64_t a);
|
||||
uint8_t identity_uint8_t(uint8_t a);
|
||||
uint16_t identity_uint16_t(uint16_t a);
|
||||
uint32_t identity_uint32_t(uint32_t a);
|
||||
uint64_t identity_uint64_t(uint64_t a);
|
||||
|
||||
char add_char(char a, char b);
|
||||
float add_float(float a, float b);
|
||||
double add_double(double a, double b);
|
||||
int8_t add_int8_t(int8_t a, int8_t b);
|
||||
int16_t add_int16_t(int16_t a, int16_t b);
|
||||
int32_t add_int32_t(int32_t a, int32_t b);
|
||||
int64_t add_int64_t(int64_t a, int64_t b);
|
||||
uint8_t add_uint8_t(uint8_t a, uint8_t b);
|
||||
uint16_t add_uint16_t(uint16_t a, uint16_t b);
|
||||
uint32_t add_uint32_t(uint32_t a, uint32_t b);
|
||||
uint64_t add_uint64_t(uint64_t a, uint64_t b);
|
||||
|
||||
bool returns_false() { return false; }
|
||||
bool returns_true() { return true; }
|
||||
char returns_42_char() { return '*'; }
|
||||
double returns_42_double() { return (double)42.42; }
|
||||
float returns_42_float() { return 42.42f; }
|
||||
int16_t returns_neg_42_int16_t() { return -42; }
|
||||
int32_t returns_neg_42_int32_t() { return -42; }
|
||||
int64_t returns_neg_42_int64_t() { return -42; }
|
||||
int8_t returns_neg_42_int8_t() { return -42; }
|
||||
uint16_t returns_42_uint16_t() { return 42; }
|
||||
uint32_t returns_42_uint32_t() { return 42; }
|
||||
uint64_t returns_42_uint64_t() { return 42; }
|
||||
uint8_t returns_42_uint8_t() { return (uint8_t)42; }
|
||||
|
||||
char identity_char(char a) { return a; }
|
||||
float identity_float(float a) { return a; }
|
||||
double identity_double(double a) { return a; }
|
||||
int8_t identity_int8_t(int8_t a) { return a; }
|
||||
int16_t identity_int16_t(int16_t a) { return a; }
|
||||
int32_t identity_int32_t(int32_t a) { return a; }
|
||||
int64_t identity_int64_t(int64_t a) { return a; }
|
||||
uint8_t identity_uint8_t(uint8_t a) { return a; }
|
||||
uint16_t identity_uint16_t(uint16_t a) { return a; }
|
||||
uint32_t identity_uint32_t(uint32_t a) { return a; }
|
||||
uint64_t identity_uint64_t(uint64_t a) { return a; }
|
||||
bool identity_bool(bool ident) { return ident; }
|
||||
void *identity_ptr(void *ident) { return ident; }
|
||||
|
||||
char add_char(char a, char b) { return a + b; }
|
||||
float add_float(float a, float b) { return a + b; }
|
||||
double add_double(double a, double b) { return a + b; }
|
||||
int8_t add_int8_t(int8_t a, int8_t b) { return a + b; }
|
||||
int16_t add_int16_t(int16_t a, int16_t b) { return a + b; }
|
||||
int32_t add_int32_t(int32_t a, int32_t b) { return a + b; }
|
||||
int64_t add_int64_t(int64_t a, int64_t b) { return a + b; }
|
||||
uint8_t add_uint8_t(uint8_t a, uint8_t b) { return a + b; }
|
||||
uint16_t add_uint16_t(uint16_t a, uint16_t b) { return a + b; }
|
||||
uint32_t add_uint32_t(uint32_t a, uint32_t b) { return a + b; }
|
||||
uint64_t add_uint64_t(uint64_t a, uint64_t b) { return a + b; }
|
||||
|
||||
void *ptr_should_point_to_42_as_int32_t();
|
||||
void *ptr_should_point_to_42_as_int32_t() {
|
||||
int32_t *ptr = malloc(sizeof(int32_t));
|
||||
*ptr = 42;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
bool does_pointer_equal_42_as_int32_t(int32_t *ptr);
|
||||
bool does_pointer_equal_42_as_int32_t(int32_t *ptr) { return *ptr == 42; }
|
||||
|
||||
void *return_a_function_ptr_to_function_that_returns_true();
|
||||
void *return_a_function_ptr_to_function_that_returns_true() {
|
||||
return (void *)&returns_true;
|
||||
}
|
||||
|
||||
bool cb_identity_true(bool (*cb)()) { return cb(); }
|
||||
|
||||
bool cb_identity_false(bool (*cb)()) { return cb(); }
|
||||
char cb_identity_42_char(char (*cb)()) { return cb(); }
|
||||
float cb_identity_42_float(float (*cb)()) { return cb(); }
|
||||
double cb_identity_42_double(double (*cb)()) { return cb(); }
|
||||
uint8_t cb_identity_42_uint8_t(uint8_t (*cb)()) { return cb(); }
|
||||
int8_t cb_identity_neg_42_int8_t(int8_t (*cb)()) { return cb(); }
|
||||
uint16_t cb_identity_42_uint16_t(uint16_t (*cb)()) { return cb(); }
|
||||
uint32_t cb_identity_42_uint32_t(uint32_t (*cb)()) { return cb(); }
|
||||
uint64_t cb_identity_42_uint64_t(uint64_t (*cb)()) { return cb(); }
|
||||
int16_t cb_identity_neg_42_int16_t(int16_t (*cb)()) { return cb(); }
|
||||
int32_t cb_identity_neg_42_int32_t(int32_t (*cb)()) { return cb(); }
|
||||
int64_t cb_identity_neg_42_int64_t(int64_t (*cb)()) { return cb(); }
|
||||
270
test/bun.js/ffi.test.fixture.callback.c
Normal file
270
test/bun.js/ffi.test.fixture.callback.c
Normal file
@@ -0,0 +1,270 @@
|
||||
#define IS_CALLBACK 1
|
||||
// This file is part of Bun!
|
||||
// You can find the original source:
|
||||
// https://github.com/Jarred-Sumner/bun/blob/main/src/bun.js/api/FFI.h#L2
|
||||
//
|
||||
// clang-format off
|
||||
// This file is only compatible with 64 bit CPUs
|
||||
// It must be kept in sync with JSCJSValue.h
|
||||
// https://github.com/Jarred-Sumner/WebKit/blob/72c2052b781cbfd4af867ae79ac9de460e392fba/Source/JavaScriptCore/runtime/JSCJSValue.h#L455-L458
|
||||
#ifdef IS_CALLBACK
|
||||
#define INJECT_BEFORE int c = 500; // This is a callback, so we need to inject code before the call
|
||||
#endif
|
||||
#define IS_BIG_ENDIAN 0
|
||||
#define USE_JSVALUE64 1
|
||||
#define USE_JSVALUE32_64 0
|
||||
|
||||
|
||||
// /* 7.18.1.1 Exact-width integer types */
|
||||
typedef unsigned char uint8_t;
|
||||
typedef signed char int8_t;
|
||||
typedef short int16_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef int int32_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef long long int64_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
typedef unsigned long long size_t;
|
||||
typedef long intptr_t;
|
||||
typedef uint64_t uintptr_t;
|
||||
typedef _Bool bool;
|
||||
|
||||
#define true 1
|
||||
#define false 0
|
||||
|
||||
|
||||
#ifdef INJECT_BEFORE
|
||||
// #include <stdint.h>
|
||||
#endif
|
||||
// #include <tcclib.h>
|
||||
|
||||
// This value is 2^49, used to encode doubles such that the encoded value will
|
||||
// begin with a 15-bit pattern within the range 0x0002..0xFFFC.
|
||||
#define DoubleEncodeOffsetBit 49
|
||||
#define DoubleEncodeOffset (1ll << DoubleEncodeOffsetBit)
|
||||
#define OtherTag 0x2
|
||||
#define BoolTag 0x4
|
||||
#define UndefinedTag 0x8
|
||||
#define TagValueFalse (OtherTag | BoolTag | false)
|
||||
#define TagValueTrue (OtherTag | BoolTag | true)
|
||||
#define TagValueUndefined (OtherTag | UndefinedTag)
|
||||
#define TagValueNull (OtherTag)
|
||||
#define NotCellMask NumberTag | OtherTag
|
||||
|
||||
#define MAX_INT32 2147483648
|
||||
#define MAX_INT52 9007199254740991
|
||||
|
||||
// If all bits in the mask are set, this indicates an integer number,
|
||||
// if any but not all are set this value is a double precision number.
|
||||
#define NumberTag 0xfffe000000000000ll
|
||||
|
||||
typedef void* JSCell;
|
||||
|
||||
typedef union EncodedJSValue {
|
||||
int64_t asInt64;
|
||||
|
||||
#if USE_JSVALUE64
|
||||
JSCell *ptr;
|
||||
#endif
|
||||
|
||||
#if IS_BIG_ENDIAN
|
||||
struct {
|
||||
int32_t tag;
|
||||
int32_t payload;
|
||||
} asBits;
|
||||
#else
|
||||
struct {
|
||||
int32_t payload;
|
||||
int32_t tag;
|
||||
} asBits;
|
||||
#endif
|
||||
|
||||
void* asPtr;
|
||||
double asDouble;
|
||||
} EncodedJSValue;
|
||||
|
||||
EncodedJSValue ValueUndefined = { TagValueUndefined };
|
||||
EncodedJSValue ValueTrue = { TagValueTrue };
|
||||
|
||||
typedef void* JSContext;
|
||||
|
||||
// Bun_FFI_PointerOffsetToArgumentsList is injected into the build
|
||||
// The value is generated in `make sizegen`
|
||||
// The value is 6.
|
||||
// On ARM64_32, the value is something else but it really doesn't matter for our case
|
||||
// However, I don't want this to subtly break amidst future upgrades to JavaScriptCore
|
||||
#define LOAD_ARGUMENTS_FROM_CALL_FRAME \
|
||||
int64_t *argsPtr = (int64_t*)((size_t*)callFrame + Bun_FFI_PointerOffsetToArgumentsList)
|
||||
|
||||
|
||||
#ifdef IS_CALLBACK
|
||||
extern int64_t bun_call(JSContext, void* func, void* thisValue, size_t len, const EncodedJSValue args[], void* exception);
|
||||
JSContext cachedJSContext;
|
||||
void* cachedCallbackFunction;
|
||||
#endif
|
||||
|
||||
static bool JSVALUE_IS_CELL(EncodedJSValue val) __attribute__((__always_inline__));
|
||||
static bool JSVALUE_IS_INT32(EncodedJSValue val) __attribute__((__always_inline__));
|
||||
static bool JSVALUE_IS_NUMBER(EncodedJSValue val) __attribute__((__always_inline__));
|
||||
|
||||
static uint64_t JSVALUE_TO_UINT64(void* globalObject, EncodedJSValue value) __attribute__((__always_inline__));
|
||||
static int64_t JSVALUE_TO_INT64(EncodedJSValue value) __attribute__((__always_inline__));
|
||||
uint64_t JSVALUE_TO_UINT64_SLOW(void* globalObject, EncodedJSValue value);
|
||||
int64_t JSVALUE_TO_INT64_SLOW(EncodedJSValue value);
|
||||
|
||||
EncodedJSValue UINT64_TO_JSVALUE_SLOW(void* globalObject, uint64_t val);
|
||||
EncodedJSValue INT64_TO_JSVALUE_SLOW(void* globalObject, int64_t val);
|
||||
static EncodedJSValue UINT64_TO_JSVALUE(void* globalObject, uint64_t val) __attribute__((__always_inline__));
|
||||
static EncodedJSValue INT64_TO_JSVALUE(void* globalObject, int64_t val) __attribute__((__always_inline__));
|
||||
|
||||
|
||||
static EncodedJSValue INT32_TO_JSVALUE(int32_t val) __attribute__((__always_inline__));
|
||||
static EncodedJSValue DOUBLE_TO_JSVALUE(double val) __attribute__((__always_inline__));
|
||||
static EncodedJSValue FLOAT_TO_JSVALUE(float val) __attribute__((__always_inline__));
|
||||
static EncodedJSValue BOOLEAN_TO_JSVALUE(bool val) __attribute__((__always_inline__));
|
||||
static EncodedJSValue PTR_TO_JSVALUE(void* ptr) __attribute__((__always_inline__));
|
||||
|
||||
static void* JSVALUE_TO_PTR(EncodedJSValue val) __attribute__((__always_inline__));
|
||||
static int32_t JSVALUE_TO_INT32(EncodedJSValue val) __attribute__((__always_inline__));
|
||||
static float JSVALUE_TO_FLOAT(EncodedJSValue val) __attribute__((__always_inline__));
|
||||
static double JSVALUE_TO_DOUBLE(EncodedJSValue val) __attribute__((__always_inline__));
|
||||
static bool JSVALUE_TO_BOOL(EncodedJSValue val) __attribute__((__always_inline__));
|
||||
|
||||
static bool JSVALUE_IS_CELL(EncodedJSValue val) {
|
||||
return !(val.asInt64 & NotCellMask);
|
||||
}
|
||||
|
||||
static bool JSVALUE_IS_INT32(EncodedJSValue val) {
|
||||
return (val.asInt64 & NumberTag) == NumberTag;
|
||||
}
|
||||
|
||||
static bool JSVALUE_IS_NUMBER(EncodedJSValue val) {
|
||||
return val.asInt64 & NumberTag;
|
||||
}
|
||||
|
||||
|
||||
static void* JSVALUE_TO_PTR(EncodedJSValue val) {
|
||||
// must be a double
|
||||
return (void*)(val.asInt64 - DoubleEncodeOffset);
|
||||
}
|
||||
|
||||
static EncodedJSValue PTR_TO_JSVALUE(void* ptr) {
|
||||
EncodedJSValue val;
|
||||
val.asInt64 = (int64_t)ptr + DoubleEncodeOffset;
|
||||
return val;
|
||||
}
|
||||
|
||||
static int32_t JSVALUE_TO_INT32(EncodedJSValue val) {
|
||||
return val.asInt64;
|
||||
}
|
||||
|
||||
static EncodedJSValue INT32_TO_JSVALUE(int32_t val) {
|
||||
EncodedJSValue res;
|
||||
res.asInt64 = NumberTag | (uint32_t)val;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static EncodedJSValue DOUBLE_TO_JSVALUE(double val) {
|
||||
EncodedJSValue res;
|
||||
res.asDouble = val;
|
||||
res.asInt64 += DoubleEncodeOffset;
|
||||
return res;
|
||||
}
|
||||
|
||||
static EncodedJSValue FLOAT_TO_JSVALUE(float val) {
|
||||
return DOUBLE_TO_JSVALUE((double)val);
|
||||
}
|
||||
|
||||
static EncodedJSValue BOOLEAN_TO_JSVALUE(bool val) {
|
||||
EncodedJSValue res;
|
||||
res.asInt64 = val ? TagValueTrue : TagValueFalse;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static double JSVALUE_TO_DOUBLE(EncodedJSValue val) {
|
||||
val.asInt64 -= DoubleEncodeOffset;
|
||||
return val.asDouble;
|
||||
}
|
||||
|
||||
static float JSVALUE_TO_FLOAT(EncodedJSValue val) {
|
||||
return (float)JSVALUE_TO_DOUBLE(val);
|
||||
}
|
||||
|
||||
static bool JSVALUE_TO_BOOL(EncodedJSValue val) {
|
||||
return val.asInt64 == TagValueTrue;
|
||||
}
|
||||
|
||||
|
||||
static uint64_t JSVALUE_TO_UINT64(void* globalObject, EncodedJSValue value) {
|
||||
if (JSVALUE_IS_INT32(value)) {
|
||||
return (uint64_t)JSVALUE_TO_INT32(value);
|
||||
}
|
||||
|
||||
if (JSVALUE_IS_NUMBER(value)) {
|
||||
return (uint64_t)JSVALUE_TO_DOUBLE(value);
|
||||
}
|
||||
|
||||
return JSVALUE_TO_UINT64_SLOW(globalObject, value);
|
||||
}
|
||||
static int64_t JSVALUE_TO_INT64(EncodedJSValue value) {
|
||||
if (JSVALUE_IS_INT32(value)) {
|
||||
return (int64_t)JSVALUE_TO_INT32(value);
|
||||
}
|
||||
|
||||
if (JSVALUE_IS_NUMBER(value)) {
|
||||
return (int64_t)JSVALUE_TO_DOUBLE(value);
|
||||
}
|
||||
|
||||
return JSVALUE_TO_INT64_SLOW(value);
|
||||
}
|
||||
|
||||
static EncodedJSValue UINT64_TO_JSVALUE(void* globalObject, uint64_t val) {
|
||||
if (val < MAX_INT32) {
|
||||
return INT32_TO_JSVALUE((int32_t)val);
|
||||
}
|
||||
|
||||
if (val < MAX_INT52) {
|
||||
return DOUBLE_TO_JSVALUE((double)val);
|
||||
}
|
||||
|
||||
return UINT64_TO_JSVALUE_SLOW(globalObject, val);
|
||||
}
|
||||
|
||||
static EncodedJSValue INT64_TO_JSVALUE(void* globalObject, int64_t val) {
|
||||
if (val >= -MAX_INT32 && val <= MAX_INT32) {
|
||||
return INT32_TO_JSVALUE((int32_t)val);
|
||||
}
|
||||
|
||||
if (val >= -MAX_INT52 && val <= MAX_INT52) {
|
||||
return DOUBLE_TO_JSVALUE((double)val);
|
||||
}
|
||||
|
||||
return INT64_TO_JSVALUE_SLOW(globalObject, val);
|
||||
}
|
||||
|
||||
#ifndef IS_CALLBACK
|
||||
void* JSFunctionCall(void* globalObject, void* callFrame);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// --- Generated Code ---
|
||||
|
||||
|
||||
/* --- The Callback Function */
|
||||
/* --- The Callback Function */
|
||||
bool my_callback_function(void* arg0);
|
||||
|
||||
bool my_callback_function(void* arg0) {
|
||||
#ifdef INJECT_BEFORE
|
||||
INJECT_BEFORE;
|
||||
#endif
|
||||
EncodedJSValue arguments[1] = {
|
||||
PTR_TO_JSVALUE(arg0)
|
||||
};
|
||||
EncodedJSValue return_value = {bun_call(cachedJSContext, cachedCallbackFunction, (void*)0, 1, &arguments[0], (void*)0)};
|
||||
return JSVALUE_TO_BOOL(return_value);
|
||||
}
|
||||
|
||||
268
test/bun.js/ffi.test.fixture.receiver.c
Normal file
268
test/bun.js/ffi.test.fixture.receiver.c
Normal file
@@ -0,0 +1,268 @@
|
||||
#define HAS_ARGUMENTS
|
||||
#define USES_FLOAT 1
|
||||
// This file is part of Bun!
|
||||
// You can find the original source:
|
||||
// https://github.com/Jarred-Sumner/bun/blob/main/src/bun.js/api/FFI.h#L2
|
||||
//
|
||||
// clang-format off
|
||||
// This file is only compatible with 64 bit CPUs
|
||||
// It must be kept in sync with JSCJSValue.h
|
||||
// https://github.com/Jarred-Sumner/WebKit/blob/72c2052b781cbfd4af867ae79ac9de460e392fba/Source/JavaScriptCore/runtime/JSCJSValue.h#L455-L458
|
||||
#ifdef IS_CALLBACK
|
||||
#define INJECT_BEFORE int c = 500; // This is a callback, so we need to inject code before the call
|
||||
#endif
|
||||
#define IS_BIG_ENDIAN 0
|
||||
#define USE_JSVALUE64 1
|
||||
#define USE_JSVALUE32_64 0
|
||||
|
||||
|
||||
// /* 7.18.1.1 Exact-width integer types */
|
||||
typedef unsigned char uint8_t;
|
||||
typedef signed char int8_t;
|
||||
typedef short int16_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef int int32_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef long long int64_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
typedef unsigned long long size_t;
|
||||
typedef long intptr_t;
|
||||
typedef uint64_t uintptr_t;
|
||||
typedef _Bool bool;
|
||||
|
||||
#define true 1
|
||||
#define false 0
|
||||
|
||||
|
||||
#ifdef INJECT_BEFORE
|
||||
// #include <stdint.h>
|
||||
#endif
|
||||
// #include <tcclib.h>
|
||||
|
||||
// This value is 2^49, used to encode doubles such that the encoded value will
|
||||
// begin with a 15-bit pattern within the range 0x0002..0xFFFC.
|
||||
#define DoubleEncodeOffsetBit 49
|
||||
#define DoubleEncodeOffset (1ll << DoubleEncodeOffsetBit)
|
||||
#define OtherTag 0x2
|
||||
#define BoolTag 0x4
|
||||
#define UndefinedTag 0x8
|
||||
#define TagValueFalse (OtherTag | BoolTag | false)
|
||||
#define TagValueTrue (OtherTag | BoolTag | true)
|
||||
#define TagValueUndefined (OtherTag | UndefinedTag)
|
||||
#define TagValueNull (OtherTag)
|
||||
#define NotCellMask NumberTag | OtherTag
|
||||
|
||||
#define MAX_INT32 2147483648
|
||||
#define MAX_INT52 9007199254740991
|
||||
|
||||
// If all bits in the mask are set, this indicates an integer number,
|
||||
// if any but not all are set this value is a double precision number.
|
||||
#define NumberTag 0xfffe000000000000ll
|
||||
|
||||
typedef void* JSCell;
|
||||
|
||||
typedef union EncodedJSValue {
|
||||
int64_t asInt64;
|
||||
|
||||
#if USE_JSVALUE64
|
||||
JSCell *ptr;
|
||||
#endif
|
||||
|
||||
#if IS_BIG_ENDIAN
|
||||
struct {
|
||||
int32_t tag;
|
||||
int32_t payload;
|
||||
} asBits;
|
||||
#else
|
||||
struct {
|
||||
int32_t payload;
|
||||
int32_t tag;
|
||||
} asBits;
|
||||
#endif
|
||||
|
||||
void* asPtr;
|
||||
double asDouble;
|
||||
} EncodedJSValue;
|
||||
|
||||
EncodedJSValue ValueUndefined = { TagValueUndefined };
|
||||
EncodedJSValue ValueTrue = { TagValueTrue };
|
||||
|
||||
typedef void* JSContext;
|
||||
|
||||
// Bun_FFI_PointerOffsetToArgumentsList is injected into the build
|
||||
// The value is generated in `make sizegen`
|
||||
// The value is 6.
|
||||
// On ARM64_32, the value is something else but it really doesn't matter for our case
|
||||
// However, I don't want this to subtly break amidst future upgrades to JavaScriptCore
|
||||
#define LOAD_ARGUMENTS_FROM_CALL_FRAME \
|
||||
int64_t *argsPtr = (int64_t*)((size_t*)callFrame + Bun_FFI_PointerOffsetToArgumentsList)
|
||||
|
||||
|
||||
#ifdef IS_CALLBACK
|
||||
extern int64_t bun_call(JSContext, void* func, void* thisValue, size_t len, const EncodedJSValue args[], void* exception);
|
||||
JSContext cachedJSContext;
|
||||
void* cachedCallbackFunction;
|
||||
#endif
|
||||
|
||||
static bool JSVALUE_IS_CELL(EncodedJSValue val) __attribute__((__always_inline__));
|
||||
static bool JSVALUE_IS_INT32(EncodedJSValue val) __attribute__((__always_inline__));
|
||||
static bool JSVALUE_IS_NUMBER(EncodedJSValue val) __attribute__((__always_inline__));
|
||||
|
||||
static uint64_t JSVALUE_TO_UINT64(void* globalObject, EncodedJSValue value) __attribute__((__always_inline__));
|
||||
static int64_t JSVALUE_TO_INT64(EncodedJSValue value) __attribute__((__always_inline__));
|
||||
uint64_t JSVALUE_TO_UINT64_SLOW(void* globalObject, EncodedJSValue value);
|
||||
int64_t JSVALUE_TO_INT64_SLOW(EncodedJSValue value);
|
||||
|
||||
EncodedJSValue UINT64_TO_JSVALUE_SLOW(void* globalObject, uint64_t val);
|
||||
EncodedJSValue INT64_TO_JSVALUE_SLOW(void* globalObject, int64_t val);
|
||||
static EncodedJSValue UINT64_TO_JSVALUE(void* globalObject, uint64_t val) __attribute__((__always_inline__));
|
||||
static EncodedJSValue INT64_TO_JSVALUE(void* globalObject, int64_t val) __attribute__((__always_inline__));
|
||||
|
||||
|
||||
static EncodedJSValue INT32_TO_JSVALUE(int32_t val) __attribute__((__always_inline__));
|
||||
static EncodedJSValue DOUBLE_TO_JSVALUE(double val) __attribute__((__always_inline__));
|
||||
static EncodedJSValue FLOAT_TO_JSVALUE(float val) __attribute__((__always_inline__));
|
||||
static EncodedJSValue BOOLEAN_TO_JSVALUE(bool val) __attribute__((__always_inline__));
|
||||
static EncodedJSValue PTR_TO_JSVALUE(void* ptr) __attribute__((__always_inline__));
|
||||
|
||||
static void* JSVALUE_TO_PTR(EncodedJSValue val) __attribute__((__always_inline__));
|
||||
static int32_t JSVALUE_TO_INT32(EncodedJSValue val) __attribute__((__always_inline__));
|
||||
static float JSVALUE_TO_FLOAT(EncodedJSValue val) __attribute__((__always_inline__));
|
||||
static double JSVALUE_TO_DOUBLE(EncodedJSValue val) __attribute__((__always_inline__));
|
||||
static bool JSVALUE_TO_BOOL(EncodedJSValue val) __attribute__((__always_inline__));
|
||||
|
||||
static bool JSVALUE_IS_CELL(EncodedJSValue val) {
|
||||
return !(val.asInt64 & NotCellMask);
|
||||
}
|
||||
|
||||
static bool JSVALUE_IS_INT32(EncodedJSValue val) {
|
||||
return (val.asInt64 & NumberTag) == NumberTag;
|
||||
}
|
||||
|
||||
static bool JSVALUE_IS_NUMBER(EncodedJSValue val) {
|
||||
return val.asInt64 & NumberTag;
|
||||
}
|
||||
|
||||
|
||||
static void* JSVALUE_TO_PTR(EncodedJSValue val) {
|
||||
// must be a double
|
||||
return (void*)(val.asInt64 - DoubleEncodeOffset);
|
||||
}
|
||||
|
||||
static EncodedJSValue PTR_TO_JSVALUE(void* ptr) {
|
||||
EncodedJSValue val;
|
||||
val.asInt64 = (int64_t)ptr + DoubleEncodeOffset;
|
||||
return val;
|
||||
}
|
||||
|
||||
static int32_t JSVALUE_TO_INT32(EncodedJSValue val) {
|
||||
return val.asInt64;
|
||||
}
|
||||
|
||||
static EncodedJSValue INT32_TO_JSVALUE(int32_t val) {
|
||||
EncodedJSValue res;
|
||||
res.asInt64 = NumberTag | (uint32_t)val;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static EncodedJSValue DOUBLE_TO_JSVALUE(double val) {
|
||||
EncodedJSValue res;
|
||||
res.asDouble = val;
|
||||
res.asInt64 += DoubleEncodeOffset;
|
||||
return res;
|
||||
}
|
||||
|
||||
static EncodedJSValue FLOAT_TO_JSVALUE(float val) {
|
||||
return DOUBLE_TO_JSVALUE((double)val);
|
||||
}
|
||||
|
||||
static EncodedJSValue BOOLEAN_TO_JSVALUE(bool val) {
|
||||
EncodedJSValue res;
|
||||
res.asInt64 = val ? TagValueTrue : TagValueFalse;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static double JSVALUE_TO_DOUBLE(EncodedJSValue val) {
|
||||
val.asInt64 -= DoubleEncodeOffset;
|
||||
return val.asDouble;
|
||||
}
|
||||
|
||||
static float JSVALUE_TO_FLOAT(EncodedJSValue val) {
|
||||
return (float)JSVALUE_TO_DOUBLE(val);
|
||||
}
|
||||
|
||||
static bool JSVALUE_TO_BOOL(EncodedJSValue val) {
|
||||
return val.asInt64 == TagValueTrue;
|
||||
}
|
||||
|
||||
|
||||
static uint64_t JSVALUE_TO_UINT64(void* globalObject, EncodedJSValue value) {
|
||||
if (JSVALUE_IS_INT32(value)) {
|
||||
return (uint64_t)JSVALUE_TO_INT32(value);
|
||||
}
|
||||
|
||||
if (JSVALUE_IS_NUMBER(value)) {
|
||||
return (uint64_t)JSVALUE_TO_DOUBLE(value);
|
||||
}
|
||||
|
||||
return JSVALUE_TO_UINT64_SLOW(globalObject, value);
|
||||
}
|
||||
static int64_t JSVALUE_TO_INT64(EncodedJSValue value) {
|
||||
if (JSVALUE_IS_INT32(value)) {
|
||||
return (int64_t)JSVALUE_TO_INT32(value);
|
||||
}
|
||||
|
||||
if (JSVALUE_IS_NUMBER(value)) {
|
||||
return (int64_t)JSVALUE_TO_DOUBLE(value);
|
||||
}
|
||||
|
||||
return JSVALUE_TO_INT64_SLOW(value);
|
||||
}
|
||||
|
||||
static EncodedJSValue UINT64_TO_JSVALUE(void* globalObject, uint64_t val) {
|
||||
if (val < MAX_INT32) {
|
||||
return INT32_TO_JSVALUE((int32_t)val);
|
||||
}
|
||||
|
||||
if (val < MAX_INT52) {
|
||||
return DOUBLE_TO_JSVALUE((double)val);
|
||||
}
|
||||
|
||||
return UINT64_TO_JSVALUE_SLOW(globalObject, val);
|
||||
}
|
||||
|
||||
static EncodedJSValue INT64_TO_JSVALUE(void* globalObject, int64_t val) {
|
||||
if (val >= -MAX_INT32 && val <= MAX_INT32) {
|
||||
return INT32_TO_JSVALUE((int32_t)val);
|
||||
}
|
||||
|
||||
if (val >= -MAX_INT52 && val <= MAX_INT52) {
|
||||
return DOUBLE_TO_JSVALUE((double)val);
|
||||
}
|
||||
|
||||
return INT64_TO_JSVALUE_SLOW(globalObject, val);
|
||||
}
|
||||
|
||||
#ifndef IS_CALLBACK
|
||||
void* JSFunctionCall(void* globalObject, void* callFrame);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// --- Generated Code ---
|
||||
/* --- The Function To Call */
|
||||
float not_a_callback(float arg0);
|
||||
|
||||
|
||||
/* ---- Your Wrapper Function ---- */
|
||||
void* JSFunctionCall(void* globalObject, void* callFrame) {
|
||||
LOAD_ARGUMENTS_FROM_CALL_FRAME;
|
||||
EncodedJSValue arg0;
|
||||
arg0.asInt64 = *argsPtr;
|
||||
float return_value = not_a_callback( JSVALUE_TO_FLOAT(arg0));
|
||||
|
||||
return FLOAT_TO_JSVALUE(return_value).asPtr;
|
||||
}
|
||||
|
||||
543
test/bun.js/ffi.test.js
Normal file
543
test/bun.js/ffi.test.js
Normal file
@@ -0,0 +1,543 @@
|
||||
// import { describe, it, expect } from "bun:test";
|
||||
// import { unsafe } from "bun";
|
||||
// //
|
||||
// import {
|
||||
// native,
|
||||
// viewSource,
|
||||
// dlopen,
|
||||
// CString,
|
||||
// ptr,
|
||||
// toBuffer,
|
||||
// toArrayBuffer,
|
||||
// FFIType,
|
||||
// callback,
|
||||
// CFunction,
|
||||
// } from "bun:ffi";
|
||||
|
||||
// it("ffi print", async () => {
|
||||
// await Bun.write(
|
||||
// import.meta.dir + "/ffi.test.fixture.callback.c",
|
||||
// viewSource(
|
||||
// {
|
||||
// returns: "bool",
|
||||
// args: ["ptr"],
|
||||
// },
|
||||
// true
|
||||
// )
|
||||
// );
|
||||
// await Bun.write(
|
||||
// import.meta.dir + "/ffi.test.fixture.receiver.c",
|
||||
// viewSource(
|
||||
// {
|
||||
// not_a_callback: {
|
||||
// returns: "float",
|
||||
// args: ["float"],
|
||||
// },
|
||||
// },
|
||||
// false
|
||||
// )[0]
|
||||
// );
|
||||
// expect(
|
||||
// viewSource(
|
||||
// {
|
||||
// returns: "int8_t",
|
||||
// args: [],
|
||||
// },
|
||||
// true
|
||||
// ).length > 0
|
||||
// ).toBe(true);
|
||||
// expect(
|
||||
// viewSource(
|
||||
// {
|
||||
// a: {
|
||||
// returns: "int8_t",
|
||||
// args: [],
|
||||
// },
|
||||
// },
|
||||
// false
|
||||
// ).length > 0
|
||||
// ).toBe(true);
|
||||
// });
|
||||
|
||||
// function getTypes(fast) {
|
||||
// const int64_t = fast ? "i64_fast" : "int64_t";
|
||||
// const uint64_t = fast ? "u64_fast" : "uint64_t";
|
||||
// return {
|
||||
// returns_true: {
|
||||
// returns: "bool",
|
||||
// args: [],
|
||||
// },
|
||||
// returns_false: {
|
||||
// returns: "bool",
|
||||
// args: [],
|
||||
// },
|
||||
// returns_42_char: {
|
||||
// returns: "char",
|
||||
// args: [],
|
||||
// },
|
||||
// returns_42_float: {
|
||||
// returns: "float",
|
||||
// args: [],
|
||||
// },
|
||||
// returns_42_double: {
|
||||
// returns: "double",
|
||||
// args: [],
|
||||
// },
|
||||
// returns_42_uint8_t: {
|
||||
// returns: "uint8_t",
|
||||
// args: [],
|
||||
// },
|
||||
// returns_neg_42_int8_t: {
|
||||
// returns: "int8_t",
|
||||
// args: [],
|
||||
// },
|
||||
// returns_42_uint16_t: {
|
||||
// returns: "uint16_t",
|
||||
// args: [],
|
||||
// },
|
||||
// returns_42_uint32_t: {
|
||||
// returns: "uint32_t",
|
||||
// args: [],
|
||||
// },
|
||||
// returns_42_uint64_t: {
|
||||
// returns: uint64_t,
|
||||
// args: [],
|
||||
// },
|
||||
// returns_neg_42_int16_t: {
|
||||
// returns: "int16_t",
|
||||
// args: [],
|
||||
// },
|
||||
// returns_neg_42_int32_t: {
|
||||
// returns: "int32_t",
|
||||
// args: [],
|
||||
// },
|
||||
// returns_neg_42_int64_t: {
|
||||
// returns: int64_t,
|
||||
// args: [],
|
||||
// },
|
||||
|
||||
// identity_char: {
|
||||
// returns: "char",
|
||||
// args: ["char"],
|
||||
// },
|
||||
// identity_float: {
|
||||
// returns: "float",
|
||||
// args: ["float"],
|
||||
// },
|
||||
// identity_bool: {
|
||||
// returns: "bool",
|
||||
// args: ["bool"],
|
||||
// },
|
||||
// identity_double: {
|
||||
// returns: "double",
|
||||
// args: ["double"],
|
||||
// },
|
||||
// identity_int8_t: {
|
||||
// returns: "int8_t",
|
||||
// args: ["int8_t"],
|
||||
// },
|
||||
// identity_int16_t: {
|
||||
// returns: "int16_t",
|
||||
// args: ["int16_t"],
|
||||
// },
|
||||
// identity_int32_t: {
|
||||
// returns: "int32_t",
|
||||
// args: ["int32_t"],
|
||||
// },
|
||||
// identity_int64_t: {
|
||||
// returns: int64_t,
|
||||
// args: [int64_t],
|
||||
// },
|
||||
// identity_uint8_t: {
|
||||
// returns: "uint8_t",
|
||||
// args: ["uint8_t"],
|
||||
// },
|
||||
// identity_uint16_t: {
|
||||
// returns: "uint16_t",
|
||||
// args: ["uint16_t"],
|
||||
// },
|
||||
// identity_uint32_t: {
|
||||
// returns: "uint32_t",
|
||||
// args: ["uint32_t"],
|
||||
// },
|
||||
// identity_uint64_t: {
|
||||
// returns: uint64_t,
|
||||
// args: [uint64_t],
|
||||
// },
|
||||
|
||||
// add_char: {
|
||||
// returns: "char",
|
||||
// args: ["char", "char"],
|
||||
// },
|
||||
// add_float: {
|
||||
// returns: "float",
|
||||
// args: ["float", "float"],
|
||||
// },
|
||||
// add_double: {
|
||||
// returns: "double",
|
||||
// args: ["double", "double"],
|
||||
// },
|
||||
// add_int8_t: {
|
||||
// returns: "int8_t",
|
||||
// args: ["int8_t", "int8_t"],
|
||||
// },
|
||||
// add_int16_t: {
|
||||
// returns: "int16_t",
|
||||
// args: ["int16_t", "int16_t"],
|
||||
// },
|
||||
// add_int32_t: {
|
||||
// returns: "int32_t",
|
||||
// args: ["int32_t", "int32_t"],
|
||||
// },
|
||||
// add_int64_t: {
|
||||
// returns: int64_t,
|
||||
// args: [int64_t, int64_t],
|
||||
// },
|
||||
// add_uint8_t: {
|
||||
// returns: "uint8_t",
|
||||
// args: ["uint8_t", "uint8_t"],
|
||||
// },
|
||||
// add_uint16_t: {
|
||||
// returns: "uint16_t",
|
||||
// args: ["uint16_t", "uint16_t"],
|
||||
// },
|
||||
// add_uint32_t: {
|
||||
// returns: "uint32_t",
|
||||
// args: ["uint32_t", "uint32_t"],
|
||||
// },
|
||||
|
||||
// does_pointer_equal_42_as_int32_t: {
|
||||
// returns: "bool",
|
||||
// args: ["ptr"],
|
||||
// },
|
||||
|
||||
// ptr_should_point_to_42_as_int32_t: {
|
||||
// returns: "ptr",
|
||||
// args: [],
|
||||
// },
|
||||
// identity_ptr: {
|
||||
// returns: "ptr",
|
||||
// args: ["ptr"],
|
||||
// },
|
||||
// add_uint64_t: {
|
||||
// returns: uint64_t,
|
||||
// args: [uint64_t, uint64_t],
|
||||
// },
|
||||
|
||||
// cb_identity_true: {
|
||||
// returns: "bool",
|
||||
// args: ["ptr"],
|
||||
// },
|
||||
// cb_identity_false: {
|
||||
// returns: "bool",
|
||||
// args: ["ptr"],
|
||||
// },
|
||||
// cb_identity_42_char: {
|
||||
// returns: "char",
|
||||
// args: ["ptr"],
|
||||
// },
|
||||
// cb_identity_42_float: {
|
||||
// returns: "float",
|
||||
// args: ["ptr"],
|
||||
// },
|
||||
// cb_identity_42_double: {
|
||||
// returns: "double",
|
||||
// args: ["ptr"],
|
||||
// },
|
||||
// cb_identity_42_uint8_t: {
|
||||
// returns: "uint8_t",
|
||||
// args: ["ptr"],
|
||||
// },
|
||||
// cb_identity_neg_42_int8_t: {
|
||||
// returns: "int8_t",
|
||||
// args: ["ptr"],
|
||||
// },
|
||||
// cb_identity_42_uint16_t: {
|
||||
// returns: "uint16_t",
|
||||
// args: ["ptr"],
|
||||
// },
|
||||
// cb_identity_42_uint32_t: {
|
||||
// returns: "uint32_t",
|
||||
// args: ["ptr"],
|
||||
// },
|
||||
// cb_identity_42_uint64_t: {
|
||||
// returns: uint64_t,
|
||||
// args: ["ptr"],
|
||||
// },
|
||||
// cb_identity_neg_42_int16_t: {
|
||||
// returns: "int16_t",
|
||||
// args: ["ptr"],
|
||||
// },
|
||||
// cb_identity_neg_42_int32_t: {
|
||||
// returns: "int32_t",
|
||||
// args: ["ptr"],
|
||||
// },
|
||||
// cb_identity_neg_42_int64_t: {
|
||||
// returns: int64_t,
|
||||
// args: ["ptr"],
|
||||
// },
|
||||
|
||||
// return_a_function_ptr_to_function_that_returns_true: {
|
||||
// returns: "ptr",
|
||||
// args: [],
|
||||
// },
|
||||
// };
|
||||
// }
|
||||
|
||||
// function ffiRunner(types) {
|
||||
// const {
|
||||
// symbols: {
|
||||
// returns_true,
|
||||
// returns_false,
|
||||
// return_a_function_ptr_to_function_that_returns_true,
|
||||
// returns_42_char,
|
||||
// returns_42_float,
|
||||
// returns_42_double,
|
||||
// returns_42_uint8_t,
|
||||
// returns_neg_42_int8_t,
|
||||
// returns_42_uint16_t,
|
||||
// returns_42_uint32_t,
|
||||
// returns_42_uint64_t,
|
||||
// returns_neg_42_int16_t,
|
||||
// returns_neg_42_int32_t,
|
||||
// returns_neg_42_int64_t,
|
||||
// identity_char,
|
||||
// identity_float,
|
||||
// identity_bool,
|
||||
// identity_double,
|
||||
// identity_int8_t,
|
||||
// identity_int16_t,
|
||||
// identity_int32_t,
|
||||
// identity_int64_t,
|
||||
// identity_uint8_t,
|
||||
// identity_uint16_t,
|
||||
// identity_uint32_t,
|
||||
// identity_uint64_t,
|
||||
// add_char,
|
||||
// add_float,
|
||||
// add_double,
|
||||
// add_int8_t,
|
||||
// add_int16_t,
|
||||
// add_int32_t,
|
||||
// add_int64_t,
|
||||
// add_uint8_t,
|
||||
// add_uint16_t,
|
||||
// identity_ptr,
|
||||
// add_uint32_t,
|
||||
// add_uint64_t,
|
||||
// does_pointer_equal_42_as_int32_t,
|
||||
// ptr_should_point_to_42_as_int32_t,
|
||||
// cb_identity_true,
|
||||
// cb_identity_false,
|
||||
// cb_identity_42_char,
|
||||
// cb_identity_42_float,
|
||||
// cb_identity_42_double,
|
||||
// cb_identity_42_uint8_t,
|
||||
// cb_identity_neg_42_int8_t,
|
||||
// cb_identity_42_uint16_t,
|
||||
// cb_identity_42_uint32_t,
|
||||
// cb_identity_42_uint64_t,
|
||||
// cb_identity_neg_42_int16_t,
|
||||
// cb_identity_neg_42_int32_t,
|
||||
// cb_identity_neg_42_int64_t,
|
||||
// },
|
||||
// close,
|
||||
// } = dlopen("/tmp/bun-ffi-test.dylib", types);
|
||||
|
||||
// expect(returns_true()).toBe(true);
|
||||
|
||||
// expect(returns_false()).toBe(false);
|
||||
|
||||
// expect(returns_42_char()).toBe(42);
|
||||
// console.log(
|
||||
// returns_42_uint64_t().valueOf(),
|
||||
// returns_42_uint64_t(),
|
||||
// returns_42_uint64_t().valueOf() === returns_42_uint64_t()
|
||||
// );
|
||||
// expect(returns_42_uint64_t().valueOf()).toBe(42);
|
||||
|
||||
// expect(Math.fround(returns_42_float())).toBe(Math.fround(42.41999804973602));
|
||||
// expect(returns_42_double()).toBe(42.42);
|
||||
// expect(returns_42_uint8_t()).toBe(42);
|
||||
// expect(returns_neg_42_int8_t()).toBe(-42);
|
||||
// expect(returns_42_uint16_t()).toBe(42);
|
||||
// expect(returns_42_uint32_t()).toBe(42);
|
||||
// expect(returns_42_uint64_t()).toBe(42);
|
||||
// expect(returns_neg_42_int16_t()).toBe(-42);
|
||||
// expect(returns_neg_42_int32_t()).toBe(-42);
|
||||
// expect(identity_int32_t(10)).toBe(10);
|
||||
// expect(returns_neg_42_int64_t()).toBe(-42);
|
||||
|
||||
// expect(identity_char(10)).toBe(10);
|
||||
|
||||
// expect(identity_float(10.199999809265137)).toBe(10.199999809265137);
|
||||
|
||||
// expect(identity_bool(true)).toBe(true);
|
||||
|
||||
// expect(identity_bool(false)).toBe(false);
|
||||
// expect(identity_double(10.100000000000364)).toBe(10.100000000000364);
|
||||
|
||||
// expect(identity_int8_t(10)).toBe(10);
|
||||
// expect(identity_int16_t(10)).toBe(10);
|
||||
// expect(identity_int64_t(10)).toBe(10);
|
||||
// expect(identity_uint8_t(10)).toBe(10);
|
||||
// expect(identity_uint16_t(10)).toBe(10);
|
||||
// expect(identity_uint32_t(10)).toBe(10);
|
||||
// expect(identity_uint64_t(10)).toBe(10);
|
||||
|
||||
// var bigArray = new BigUint64Array(8);
|
||||
// new Uint8Array(bigArray.buffer).fill(255);
|
||||
// var bigIntArray = new BigInt64Array(bigArray.buffer);
|
||||
// expect(identity_uint64_t(bigArray[0])).toBe(bigArray[0]);
|
||||
// expect(identity_uint64_t(bigArray[0] - BigInt(1))).toBe(
|
||||
// bigArray[0] - BigInt(1)
|
||||
// );
|
||||
|
||||
// expect(add_uint64_t(BigInt(-1) * bigArray[0], bigArray[0])).toBe(0);
|
||||
// expect(add_uint64_t(BigInt(-1) * bigArray[0] + BigInt(10), bigArray[0])).toBe(
|
||||
// 10
|
||||
// );
|
||||
// expect(identity_uint64_t(0)).toBe(0);
|
||||
// expect(identity_uint64_t(100)).toBe(100);
|
||||
// expect(identity_uint64_t(BigInt(100))).toBe(100);
|
||||
// expect(identity_int64_t(bigIntArray[0])).toBe(bigIntArray[0]);
|
||||
// expect(identity_int64_t(bigIntArray[0] - BigInt(1))).toBe(
|
||||
// bigIntArray[0] - BigInt(1)
|
||||
// );
|
||||
|
||||
// expect(add_char(1, 1)).toBe(2);
|
||||
// expect(add_float(2.4, 2.8)).toBe(Math.fround(5.2));
|
||||
// expect(add_double(4.2, 0.1)).toBe(4.3);
|
||||
// expect(add_int8_t(1, 1)).toBe(2);
|
||||
// expect(add_int16_t(1, 1)).toBe(2);
|
||||
// expect(add_int32_t(1, 1)).toBe(2);
|
||||
// expect(add_int64_t(1, 1)).toBe(2);
|
||||
// expect(add_uint8_t(1, 1)).toBe(2);
|
||||
// expect(add_uint16_t(1, 1)).toBe(2);
|
||||
// expect(add_uint32_t(1, 1)).toBe(2);
|
||||
|
||||
// const cptr = ptr_should_point_to_42_as_int32_t();
|
||||
// expect(cptr != 0).toBe(true);
|
||||
// expect(typeof cptr === "number").toBe(true);
|
||||
// expect(does_pointer_equal_42_as_int32_t(cptr)).toBe(true);
|
||||
// const buffer = toBuffer(cptr, 0, 4);
|
||||
// expect(buffer.readInt32(0)).toBe(42);
|
||||
// expect(new DataView(toArrayBuffer(cptr, 0, 4), 0, 4).getInt32(0, true)).toBe(
|
||||
// 42
|
||||
// );
|
||||
// expect(ptr(buffer)).toBe(cptr);
|
||||
// expect(new CString(cptr, 0, 1).toString()).toBe("*");
|
||||
// expect(identity_ptr(cptr)).toBe(cptr);
|
||||
// const second_ptr = ptr(new Buffer(8));
|
||||
// expect(identity_ptr(second_ptr)).toBe(second_ptr);
|
||||
|
||||
// var myCFunction = new CFunction({
|
||||
// ptr: return_a_function_ptr_to_function_that_returns_true(),
|
||||
// returns: "bool",
|
||||
// });
|
||||
// expect(myCFunction()).toBe(true);
|
||||
|
||||
// // function identityBool() {
|
||||
// // return true;
|
||||
// // }
|
||||
// // globalThis.identityBool = identityBool;
|
||||
|
||||
// // const first = native.callback(
|
||||
// // {
|
||||
// // returns: "bool",
|
||||
// // },
|
||||
// // identityBool
|
||||
// // );
|
||||
// // expect(
|
||||
// // cb_identity_true()
|
||||
// // ).toBe(true);
|
||||
|
||||
// // expect(cb_identity_true(first)).toBe(true);
|
||||
|
||||
// // expect(
|
||||
// // cb_identity_false(
|
||||
// // callback(
|
||||
// // {
|
||||
// // returns: "bool",
|
||||
// // },
|
||||
// // () => false
|
||||
// // )
|
||||
// // )
|
||||
// // ).toBe(false);
|
||||
|
||||
// // expect(
|
||||
// // cb_identity_42_char(
|
||||
// // callback(
|
||||
// // {
|
||||
// // returns: "char",
|
||||
// // },
|
||||
// // () => 42
|
||||
// // )
|
||||
// // )
|
||||
// // ).toBe(42);
|
||||
// // expect(
|
||||
// // cb_identity_42_uint8_t(
|
||||
// // callback(
|
||||
// // {
|
||||
// // returns: "uint8_t",
|
||||
// // },
|
||||
// // () => 42
|
||||
// // )
|
||||
// // )
|
||||
// // ).toBe(42);
|
||||
|
||||
// // cb_identity_neg_42_int8_t(
|
||||
// // callback(
|
||||
// // {
|
||||
// // returns: "int8_t",
|
||||
// // },
|
||||
// // () => -42
|
||||
// // )
|
||||
// // ).toBe(-42);
|
||||
|
||||
// // cb_identity_42_uint16_t(
|
||||
// // callback(
|
||||
// // {
|
||||
// // returns: "uint16_t",
|
||||
// // },
|
||||
// // () => 42
|
||||
// // )
|
||||
// // ).toBe(42);
|
||||
|
||||
// // cb_identity_42_uint32_t(
|
||||
// // callback(
|
||||
// // {
|
||||
// // returns: "uint32_t",
|
||||
// // },
|
||||
// // () => 42
|
||||
// // )
|
||||
// // ).toBe(42);
|
||||
|
||||
// // cb_identity_neg_42_int16_t(
|
||||
// // callback(
|
||||
// // {
|
||||
// // returns: "int16_t",
|
||||
// // },
|
||||
// // () => -42
|
||||
// // )
|
||||
// // ).toBe(-42);
|
||||
|
||||
// // cb_identity_neg_42_int32_t(
|
||||
// // callback(
|
||||
// // {
|
||||
// // returns: "int32_t",
|
||||
// // },
|
||||
// // () => -42
|
||||
// // )
|
||||
// // ).toBe(-42);
|
||||
|
||||
// close();
|
||||
// }
|
||||
|
||||
// it("run ffi fast", () => {
|
||||
// ffiRunner(getTypes(true));
|
||||
// });
|
||||
|
||||
// it("run ffi", () => {
|
||||
// ffiRunner(getTypes(false));
|
||||
// });
|
||||
23
test/bun.js/fs-stream.js
Normal file
23
test/bun.js/fs-stream.js
Normal file
@@ -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);
|
||||
}
|
||||
});
|
||||
});
|
||||
244
test/bun.js/fs.test.js
Normal file
244
test/bun.js/fs.test.js
Normal file
@@ -0,0 +1,244 @@
|
||||
import { gc } from "bun";
|
||||
import { describe, expect, it } from "bun:test";
|
||||
import {
|
||||
closeSync,
|
||||
existsSync,
|
||||
mkdirSync,
|
||||
openSync,
|
||||
readdirSync,
|
||||
readFile,
|
||||
readFileSync,
|
||||
readSync,
|
||||
writeFileSync,
|
||||
writeSync,
|
||||
} from "node:fs";
|
||||
|
||||
const Buffer = globalThis.Buffer || Uint8Array;
|
||||
|
||||
if (!import.meta.dir) {
|
||||
import.meta.dir = ".";
|
||||
}
|
||||
|
||||
describe("mkdirSync", () => {
|
||||
it("should create a directory", () => {
|
||||
const tempdir = `/tmp/fs.test.js/${Date.now()}/1234/hi`;
|
||||
expect(existsSync(tempdir)).toBe(false);
|
||||
expect(tempdir.includes(mkdirSync(tempdir, { recursive: true }))).toBe(
|
||||
true
|
||||
);
|
||||
expect(existsSync(tempdir)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
it("readdirSync on import.meta.dir", () => {
|
||||
const dirs = readdirSync(import.meta.dir);
|
||||
expect(dirs.length > 0).toBe(true);
|
||||
var match = false;
|
||||
gc(true);
|
||||
for (let i = 0; i < dirs.length; i++) {
|
||||
if (dirs[i] === import.meta.file) {
|
||||
match = true;
|
||||
}
|
||||
}
|
||||
gc(true);
|
||||
expect(match).toBe(true);
|
||||
});
|
||||
|
||||
it("readdirSync on import.meta.dir with trailing slash", () => {
|
||||
const dirs = readdirSync(import.meta.dir + "/");
|
||||
expect(dirs.length > 0).toBe(true);
|
||||
// this file should exist in it
|
||||
var match = false;
|
||||
for (let i = 0; i < dirs.length; i++) {
|
||||
if (dirs[i] === import.meta.file) {
|
||||
match = true;
|
||||
}
|
||||
}
|
||||
expect(match).toBe(true);
|
||||
});
|
||||
|
||||
it("readdirSync works on empty directories", () => {
|
||||
const path = `/tmp/fs-test-empty-dir-${(
|
||||
Math.random() * 100000 +
|
||||
100
|
||||
).toString(32)}`;
|
||||
mkdirSync(path, { recursive: true });
|
||||
expect(readdirSync(path).length).toBe(0);
|
||||
});
|
||||
|
||||
it("readdirSync works on directories with under 32 files", () => {
|
||||
const path = `/tmp/fs-test-one-dir-${(Math.random() * 100000 + 100).toString(
|
||||
32
|
||||
)}`;
|
||||
mkdirSync(path, { recursive: true });
|
||||
writeFileSync(`${path}/a`, "a");
|
||||
const results = readdirSync(path);
|
||||
expect(results.length).toBe(1);
|
||||
expect(results[0]).toBe("a");
|
||||
});
|
||||
|
||||
it("readdirSync throws when given a file path", () => {
|
||||
try {
|
||||
readdirSync(import.meta.path);
|
||||
throw new Error("should not get here");
|
||||
} catch (exception) {
|
||||
expect(exception.name).toBe("ENOTDIR");
|
||||
}
|
||||
});
|
||||
|
||||
it("readdirSync throws when given a path that doesn't exist", () => {
|
||||
try {
|
||||
readdirSync(import.meta.path + "/does-not-exist/really");
|
||||
throw new Error("should not get here");
|
||||
} catch (exception) {
|
||||
expect(exception.name).toBe("ENOTDIR");
|
||||
}
|
||||
});
|
||||
|
||||
it("readdirSync throws when given a file path with trailing slash", () => {
|
||||
try {
|
||||
readdirSync(import.meta.path + "/");
|
||||
throw new Error("should not get here");
|
||||
} catch (exception) {
|
||||
expect(exception.name).toBe("ENOTDIR");
|
||||
}
|
||||
});
|
||||
|
||||
describe("readSync", () => {
|
||||
const firstFourBytes = new Uint32Array(
|
||||
new TextEncoder().encode("File").buffer
|
||||
)[0];
|
||||
it("works with a position set to 0", () => {
|
||||
const fd = openSync(import.meta.dir + "/readFileSync.txt", "r");
|
||||
const four = new Uint8Array(4);
|
||||
|
||||
{
|
||||
const count = readSync(fd, four, 0, 4, 0);
|
||||
const u32 = new Uint32Array(four.buffer)[0];
|
||||
expect(u32).toBe(firstFourBytes);
|
||||
expect(count).toBe(4);
|
||||
}
|
||||
closeSync(fd);
|
||||
});
|
||||
it("works without position set", () => {
|
||||
const fd = openSync(import.meta.dir + "/readFileSync.txt", "r");
|
||||
const four = new Uint8Array(4);
|
||||
{
|
||||
const count = readSync(fd, four);
|
||||
const u32 = new Uint32Array(four.buffer)[0];
|
||||
expect(u32).toBe(firstFourBytes);
|
||||
expect(count).toBe(4);
|
||||
}
|
||||
closeSync(fd);
|
||||
});
|
||||
});
|
||||
|
||||
describe("writeSync", () => {
|
||||
it("works with a position set to 0", () => {
|
||||
const fd = openSync(import.meta.dir + "/writeFileSync.txt", "w+");
|
||||
const four = new Uint8Array(4);
|
||||
|
||||
{
|
||||
const count = writeSync(fd, new TextEncoder().encode("File"), 0, 4, 0);
|
||||
expect(count).toBe(4);
|
||||
}
|
||||
closeSync(fd);
|
||||
});
|
||||
it("works without position set", () => {
|
||||
const fd = openSync(import.meta.dir + "/writeFileSync.txt", "w+");
|
||||
const four = new Uint8Array(4);
|
||||
{
|
||||
const count = writeSync(fd, new TextEncoder().encode("File"));
|
||||
expect(count).toBe(4);
|
||||
}
|
||||
closeSync(fd);
|
||||
});
|
||||
});
|
||||
|
||||
describe("readFileSync", () => {
|
||||
it("works", () => {
|
||||
const text = readFileSync(import.meta.dir + "/readFileSync.txt", "utf8");
|
||||
expect(text).toBe("File read successfully");
|
||||
});
|
||||
|
||||
it("works with a file url", () => {
|
||||
const text = readFileSync(
|
||||
new URL("file://" + import.meta.dir + "/readFileSync.txt"),
|
||||
"utf8"
|
||||
);
|
||||
expect(text).toBe("File read successfully");
|
||||
});
|
||||
|
||||
it("returning Buffer works", () => {
|
||||
const text = readFileSync(import.meta.dir + "/readFileSync.txt");
|
||||
const encoded = [
|
||||
70, 105, 108, 101, 32, 114, 101, 97, 100, 32, 115, 117, 99, 99, 101, 115,
|
||||
115, 102, 117, 108, 108, 121,
|
||||
];
|
||||
for (let i = 0; i < encoded.length; i++) {
|
||||
expect(text[i]).toBe(encoded[i]);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("readFile", () => {
|
||||
it("works", async () => {
|
||||
await new Promise((resolve, reject) => {
|
||||
readFile(import.meta.dir + "/readFileSync.txt", "utf8", (err, text) => {
|
||||
expect(text).toBe("File read successfully");
|
||||
resolve(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("returning Buffer works", async () => {
|
||||
await new Promise((resolve, reject) => {
|
||||
readFile(import.meta.dir + "/readFileSync.txt", (err, text) => {
|
||||
const encoded = [
|
||||
70, 105, 108, 101, 32, 114, 101, 97, 100, 32, 115, 117, 99, 99, 101,
|
||||
115, 115, 102, 117, 108, 108, 121,
|
||||
];
|
||||
for (let i = 0; i < encoded.length; i++) {
|
||||
expect(text[i]).toBe(encoded[i]);
|
||||
}
|
||||
resolve(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("writeFileSync", () => {
|
||||
it("works", () => {
|
||||
const path = `/tmp/${Date.now()}.writeFileSync.txt`;
|
||||
writeFileSync(path, "File written successfully", "utf8");
|
||||
|
||||
expect(readFileSync(path, "utf8")).toBe("File written successfully");
|
||||
});
|
||||
|
||||
it("returning Buffer works", () => {
|
||||
const buffer = new Buffer([
|
||||
70, 105, 108, 101, 32, 119, 114, 105, 116, 116, 101, 110, 32, 115, 117,
|
||||
99, 99, 101, 115, 115, 102, 117, 108, 108, 121,
|
||||
]);
|
||||
const path = `/tmp/${Date.now()}.blob.writeFileSync.txt`;
|
||||
writeFileSync(path, buffer);
|
||||
const out = readFileSync(path);
|
||||
|
||||
for (let i = 0; i < buffer.length; i++) {
|
||||
expect(buffer[i]).toBe(out[i]);
|
||||
}
|
||||
});
|
||||
it("returning ArrayBuffer works", () => {
|
||||
const buffer = new Buffer([
|
||||
70, 105, 108, 101, 32, 119, 114, 105, 116, 116, 101, 110, 32, 115, 117,
|
||||
99, 99, 101, 115, 115, 102, 117, 108, 108, 121,
|
||||
]);
|
||||
const path = `/tmp/${Date.now()}.blob2.writeFileSync.txt`;
|
||||
writeFileSync(path, buffer);
|
||||
const out = readFileSync(path);
|
||||
|
||||
for (let i = 0; i < buffer.length; i++) {
|
||||
expect(buffer[i]).toBe(out[i]);
|
||||
}
|
||||
});
|
||||
});
|
||||
15
test/bun.js/gc.js
Normal file
15
test/bun.js/gc.js
Normal file
@@ -0,0 +1,15 @@
|
||||
export function gc() {
|
||||
// console.trace("GC");
|
||||
Bun.gc(true);
|
||||
}
|
||||
|
||||
// we must ensure that finalizers are run
|
||||
// so that the reference-counting logic is exercised
|
||||
export function gcTick(trace = false) {
|
||||
trace && console.trace("");
|
||||
// console.trace("hello");
|
||||
gc();
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(resolve, 0);
|
||||
});
|
||||
}
|
||||
39
test/bun.js/globals.test.js
Normal file
39
test/bun.js/globals.test.js
Normal file
@@ -0,0 +1,39 @@
|
||||
import { it, describe, expect } from "bun:test";
|
||||
|
||||
it("extendable", () => {
|
||||
const classes = [
|
||||
Blob,
|
||||
TextDecoder,
|
||||
TextEncoder,
|
||||
Request,
|
||||
Response,
|
||||
Headers,
|
||||
HTMLRewriter,
|
||||
Bun.Transpiler,
|
||||
];
|
||||
// None of these should error
|
||||
for (let Class of classes) {
|
||||
var Foo = class extends Class {};
|
||||
var bar = new Foo();
|
||||
expect(bar instanceof Class).toBe(true);
|
||||
expect(!!Class.prototype).toBe(true);
|
||||
expect(typeof Class.prototype).toBe("object");
|
||||
}
|
||||
expect(true).toBe(true);
|
||||
});
|
||||
|
||||
it("name", () => {
|
||||
const classes = [
|
||||
["Blob", Blob],
|
||||
["TextDecoder", TextDecoder],
|
||||
["TextEncoder", TextEncoder],
|
||||
["Request", Request],
|
||||
["Response", Response],
|
||||
["Headers", Headers],
|
||||
["HTMLRewriter", HTMLRewriter],
|
||||
["Transpiler", Bun.Transpiler],
|
||||
];
|
||||
for (let [name, Class] of classes) {
|
||||
expect(Class.name).toBe(name);
|
||||
}
|
||||
});
|
||||
36
test/bun.js/hash.test.js
Normal file
36
test/bun.js/hash.test.js
Normal file
@@ -0,0 +1,36 @@
|
||||
import fs from "fs";
|
||||
import { it, expect } from "bun:test";
|
||||
import path from "path";
|
||||
|
||||
it(`Bun.hash()`, () => {
|
||||
Bun.hash("hello world");
|
||||
Bun.hash(new TextEncoder().encode("hello world"));
|
||||
});
|
||||
it(`Bun.hash.wyhash()`, () => {
|
||||
Bun.hash.wyhash("hello world");
|
||||
Bun.hash.wyhash(new TextEncoder().encode("hello world"));
|
||||
});
|
||||
it(`Bun.hash.adler32()`, () => {
|
||||
Bun.hash.adler32("hello world");
|
||||
Bun.hash.adler32(new TextEncoder().encode("hello world"));
|
||||
});
|
||||
it(`Bun.hash.crc32()`, () => {
|
||||
Bun.hash.crc32("hello world");
|
||||
Bun.hash.crc32(new TextEncoder().encode("hello world"));
|
||||
});
|
||||
it(`Bun.hash.cityHash32()`, () => {
|
||||
Bun.hash.cityHash32("hello world");
|
||||
Bun.hash.cityHash32(new TextEncoder().encode("hello world"));
|
||||
});
|
||||
it(`Bun.hash.cityHash64()`, () => {
|
||||
Bun.hash.cityHash64("hello world");
|
||||
Bun.hash.cityHash64(new TextEncoder().encode("hello world"));
|
||||
});
|
||||
it(`Bun.hash.murmur32v3()`, () => {
|
||||
Bun.hash.murmur32v3("hello world");
|
||||
Bun.hash.murmur32v3(new TextEncoder().encode("hello world"));
|
||||
});
|
||||
it(`Bun.hash.murmur64v2()`, () => {
|
||||
Bun.hash.murmur64v2("hello world");
|
||||
Bun.hash.murmur64v2(new TextEncoder().encode("hello world"));
|
||||
});
|
||||
293
test/bun.js/html-rewriter.test.js
Normal file
293
test/bun.js/html-rewriter.test.js
Normal file
@@ -0,0 +1,293 @@
|
||||
import { describe, it, expect } from "bun:test";
|
||||
import { gcTick } from "./gc";
|
||||
|
||||
var setTimeoutAsync = (fn, delay) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
try {
|
||||
resolve(fn());
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
}, delay);
|
||||
});
|
||||
};
|
||||
|
||||
describe("HTMLRewriter", () => {
|
||||
it("HTMLRewriter: async replacement", async () => {
|
||||
await gcTick();
|
||||
const res = new HTMLRewriter()
|
||||
.on("div", {
|
||||
async element(element) {
|
||||
await setTimeoutAsync(() => {
|
||||
element.setInnerContent("<span>replace</span>", { html: true });
|
||||
}, 5);
|
||||
},
|
||||
})
|
||||
.transform(new Response("<div>example.com</div>"));
|
||||
await gcTick();
|
||||
expect(await res.text()).toBe("<div><span>replace</span></div>");
|
||||
await gcTick();
|
||||
});
|
||||
|
||||
it("supports element handlers", async () => {
|
||||
var rewriter = new HTMLRewriter();
|
||||
rewriter.on("div", {
|
||||
element(element) {
|
||||
element.setInnerContent("<blink>it worked!</blink>", { html: true });
|
||||
},
|
||||
});
|
||||
var input = new Response("<div>hello</div>");
|
||||
var output = rewriter.transform(input);
|
||||
expect(await output.text()).toBe("<div><blink>it worked!</blink></div>");
|
||||
});
|
||||
|
||||
it("(from file) supports element handlers", async () => {
|
||||
var rewriter = new HTMLRewriter();
|
||||
rewriter.on("div", {
|
||||
element(element) {
|
||||
element.setInnerContent("<blink>it worked!</blink>", { html: true });
|
||||
},
|
||||
});
|
||||
await Bun.write("/tmp/html-rewriter.txt.js", "<div>hello</div>");
|
||||
var input = new Response(Bun.file("/tmp/html-rewriter.txt.js"));
|
||||
var output = rewriter.transform(input);
|
||||
expect(await output.text()).toBe("<div><blink>it worked!</blink></div>");
|
||||
});
|
||||
|
||||
it("supports attribute iterator", async () => {
|
||||
var rewriter = new HTMLRewriter();
|
||||
var expected = [
|
||||
["first", ""],
|
||||
["second", "alrihgt"],
|
||||
["third", "123"],
|
||||
["fourth", "5"],
|
||||
["fifth", "helloooo"],
|
||||
];
|
||||
rewriter.on("div", {
|
||||
element(element2) {
|
||||
for (let attr of element2.attributes) {
|
||||
const stack = expected.shift();
|
||||
expect(stack[0]).toBe(attr[0]);
|
||||
expect(stack[1]).toBe(attr[1]);
|
||||
}
|
||||
},
|
||||
});
|
||||
var input = new Response(
|
||||
'<div first second="alrihgt" third="123" fourth=5 fifth=helloooo>hello</div>'
|
||||
);
|
||||
var output = rewriter.transform(input);
|
||||
expect(await output.text()).toBe(
|
||||
'<div first second="alrihgt" third="123" fourth=5 fifth=helloooo>hello</div>'
|
||||
);
|
||||
expect(expected.length).toBe(0);
|
||||
});
|
||||
|
||||
it("handles element specific mutations", async () => {
|
||||
// prepend/append
|
||||
let res = new HTMLRewriter()
|
||||
.on("p", {
|
||||
element(element) {
|
||||
element.prepend("<span>prepend</span>");
|
||||
element.prepend("<span>prepend html</span>", { html: true });
|
||||
element.append("<span>append</span>");
|
||||
element.append("<span>append html</span>", { html: true });
|
||||
},
|
||||
})
|
||||
.transform(new Response("<p>test</p>"));
|
||||
expect(await res.text()).toBe(
|
||||
[
|
||||
"<p>",
|
||||
"<span>prepend html</span>",
|
||||
"<span>prepend</span>",
|
||||
"test",
|
||||
"<span>append</span>",
|
||||
"<span>append html</span>",
|
||||
"</p>",
|
||||
].join("")
|
||||
);
|
||||
|
||||
// setInnerContent
|
||||
res = new HTMLRewriter()
|
||||
.on("p", {
|
||||
element(element) {
|
||||
element.setInnerContent("<span>replace</span>");
|
||||
},
|
||||
})
|
||||
.transform(new Response("<p>test</p>"));
|
||||
expect(await res.text()).toBe("<p><span>replace</span></p>");
|
||||
res = new HTMLRewriter()
|
||||
.on("p", {
|
||||
element(element) {
|
||||
element.setInnerContent("<span>replace</span>", { html: true });
|
||||
},
|
||||
})
|
||||
.transform(new Response("<p>test</p>"));
|
||||
expect(await res.text()).toBe("<p><span>replace</span></p>");
|
||||
|
||||
// removeAndKeepContent
|
||||
res = new HTMLRewriter()
|
||||
.on("p", {
|
||||
element(element) {
|
||||
element.removeAndKeepContent();
|
||||
},
|
||||
})
|
||||
.transform(new Response("<p>test</p>"));
|
||||
expect(await res.text()).toBe("test");
|
||||
});
|
||||
|
||||
it("handles element class properties", async () => {
|
||||
class Handler {
|
||||
constructor(content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
element(element) {
|
||||
element.setInnerContent(this.content);
|
||||
}
|
||||
}
|
||||
const res = new HTMLRewriter()
|
||||
.on("p", new Handler("new"))
|
||||
.transform(new Response("<p>test</p>"));
|
||||
expect(await res.text()).toBe("<p>new</p>");
|
||||
});
|
||||
|
||||
const commentsMutationsInput = "<p><!--test--></p>";
|
||||
const commentsMutationsExpected = {
|
||||
beforeAfter: [
|
||||
"<p>",
|
||||
"<span>before</span>",
|
||||
"<span>before html</span>",
|
||||
"<!--test-->",
|
||||
"<span>after html</span>",
|
||||
"<span>after</span>",
|
||||
"</p>",
|
||||
].join(""),
|
||||
replace: "<p><span>replace</span></p>",
|
||||
replaceHtml: "<p><span>replace</span></p>",
|
||||
remove: "<p></p>",
|
||||
};
|
||||
|
||||
const commentPropertiesMacro = async (func) => {
|
||||
const res = func(new HTMLRewriter(), (comment) => {
|
||||
expect(comment.removed).toBe(false);
|
||||
expect(comment.text).toBe("test");
|
||||
comment.text = "new";
|
||||
expect(comment.text).toBe("new");
|
||||
}).transform(new Response("<p><!--test--></p>"));
|
||||
expect(await res.text()).toBe("<p><!--new--></p>");
|
||||
};
|
||||
|
||||
it("HTMLRewriter: handles comment properties", () =>
|
||||
commentPropertiesMacro((rw, comments) => {
|
||||
rw.on("p", { comments });
|
||||
return rw;
|
||||
}));
|
||||
|
||||
it("selector tests", async () => {
|
||||
const checkSelector = async (selector, input, expected) => {
|
||||
const res = new HTMLRewriter()
|
||||
.on(selector, {
|
||||
element(element) {
|
||||
element.setInnerContent("new");
|
||||
},
|
||||
})
|
||||
.transform(new Response(input));
|
||||
expect(await res.text()).toBe(expected);
|
||||
};
|
||||
|
||||
await checkSelector("*", "<h1>1</h1><p>2</p>", "<h1>new</h1><p>new</p>");
|
||||
await checkSelector("p", "<h1>1</h1><p>2</p>", "<h1>1</h1><p>new</p>");
|
||||
await checkSelector(
|
||||
"p:nth-child(2)",
|
||||
"<div><p>1</p><p>2</p><p>3</p></div>",
|
||||
"<div><p>1</p><p>new</p><p>3</p></div>"
|
||||
);
|
||||
await checkSelector(
|
||||
"p:first-child",
|
||||
"<div><p>1</p><p>2</p><p>3</p></div>",
|
||||
"<div><p>new</p><p>2</p><p>3</p></div>"
|
||||
);
|
||||
await checkSelector(
|
||||
"p:nth-of-type(2)",
|
||||
"<div><p>1</p><h1>2</h1><p>3</p><h1>4</h1><p>5</p></div>",
|
||||
"<div><p>1</p><h1>2</h1><p>new</p><h1>4</h1><p>5</p></div>"
|
||||
);
|
||||
await checkSelector(
|
||||
"p:first-of-type",
|
||||
"<div><h1>1</h1><p>2</p><p>3</p></div>",
|
||||
"<div><h1>1</h1><p>new</p><p>3</p></div>"
|
||||
);
|
||||
await checkSelector(
|
||||
"p:not(:first-child)",
|
||||
"<div><p>1</p><p>2</p><p>3</p></div>",
|
||||
"<div><p>1</p><p>new</p><p>new</p></div>"
|
||||
);
|
||||
await checkSelector(
|
||||
"p.red",
|
||||
'<p class="red">1</p><p>2</p>',
|
||||
'<p class="red">new</p><p>2</p>'
|
||||
);
|
||||
await checkSelector(
|
||||
"h1#header",
|
||||
'<h1 id="header">1</h1><h1>2</h1>',
|
||||
'<h1 id="header">new</h1><h1>2</h1>'
|
||||
);
|
||||
await checkSelector(
|
||||
"p[data-test]",
|
||||
"<p data-test>1</p><p>2</p>",
|
||||
"<p data-test>new</p><p>2</p>"
|
||||
);
|
||||
await checkSelector(
|
||||
'p[data-test="one"]',
|
||||
'<p data-test="one">1</p><p data-test="two">2</p>',
|
||||
'<p data-test="one">new</p><p data-test="two">2</p>'
|
||||
);
|
||||
await checkSelector(
|
||||
'p[data-test="one" i]',
|
||||
'<p data-test="one">1</p><p data-test="OnE">2</p><p data-test="two">3</p>',
|
||||
'<p data-test="one">new</p><p data-test="OnE">new</p><p data-test="two">3</p>'
|
||||
);
|
||||
await checkSelector(
|
||||
'p[data-test="one" s]',
|
||||
'<p data-test="one">1</p><p data-test="OnE">2</p><p data-test="two">3</p>',
|
||||
'<p data-test="one">new</p><p data-test="OnE">2</p><p data-test="two">3</p>'
|
||||
);
|
||||
await checkSelector(
|
||||
'p[data-test~="two"]',
|
||||
'<p data-test="one two three">1</p><p data-test="one two">2</p><p data-test="one">3</p>',
|
||||
'<p data-test="one two three">new</p><p data-test="one two">new</p><p data-test="one">3</p>'
|
||||
);
|
||||
await checkSelector(
|
||||
'p[data-test^="a"]',
|
||||
'<p data-test="a1">1</p><p data-test="a2">2</p><p data-test="b1">3</p>',
|
||||
'<p data-test="a1">new</p><p data-test="a2">new</p><p data-test="b1">3</p>'
|
||||
);
|
||||
await checkSelector(
|
||||
'p[data-test$="1"]',
|
||||
'<p data-test="a1">1</p><p data-test="a2">2</p><p data-test="b1">3</p>',
|
||||
'<p data-test="a1">new</p><p data-test="a2">2</p><p data-test="b1">new</p>'
|
||||
);
|
||||
await checkSelector(
|
||||
'p[data-test*="b"]',
|
||||
'<p data-test="abc">1</p><p data-test="ab">2</p><p data-test="a">3</p>',
|
||||
'<p data-test="abc">new</p><p data-test="ab">new</p><p data-test="a">3</p>'
|
||||
);
|
||||
await checkSelector(
|
||||
'p[data-test|="a"]',
|
||||
'<p data-test="a">1</p><p data-test="a-1">2</p><p data-test="a2">3</p>',
|
||||
'<p data-test="a">new</p><p data-test="a-1">new</p><p data-test="a2">3</p>'
|
||||
);
|
||||
await checkSelector(
|
||||
"div span",
|
||||
"<div><h1><span>1</span></h1><span>2</span><b>3</b></div>",
|
||||
"<div><h1><span>new</span></h1><span>new</span><b>3</b></div>"
|
||||
);
|
||||
await checkSelector(
|
||||
"div > span",
|
||||
"<div><h1><span>1</span></h1><span>2</span><b>3</b></div>",
|
||||
"<div><h1><span>1</span></h1><span>new</span><b>3</b></div>"
|
||||
);
|
||||
});
|
||||
});
|
||||
33
test/bun.js/import-meta.test.js
Normal file
33
test/bun.js/import-meta.test.js
Normal file
@@ -0,0 +1,33 @@
|
||||
import { it, expect } from "bun:test";
|
||||
import * as Module from "node:module";
|
||||
import sync from "./require-json.json";
|
||||
|
||||
const { path, dir } = import.meta;
|
||||
|
||||
it("import.meta.resolveSync", () => {
|
||||
expect(
|
||||
import.meta.resolveSync("./" + import.meta.file, import.meta.path)
|
||||
).toBe(path);
|
||||
const require = Module.createRequire(import.meta.path);
|
||||
expect(require.resolve(import.meta.path)).toBe(path);
|
||||
expect(require.resolve("./" + import.meta.file)).toBe(path);
|
||||
|
||||
// check it works with URL objects
|
||||
expect(
|
||||
Module.createRequire(new URL(import.meta.url)).resolve(import.meta.path)
|
||||
).toBe(import.meta.path);
|
||||
});
|
||||
|
||||
it("import.meta.require", () => {
|
||||
expect(import.meta.require("./require-json.json").hello).toBe(sync.hello);
|
||||
const require = Module.createRequire(import.meta.path);
|
||||
expect(require("./require-json.json").hello).toBe(sync.hello);
|
||||
});
|
||||
|
||||
it("import.meta.dir", () => {
|
||||
expect(dir.endsWith("/bun/test/bun.js")).toBe(true);
|
||||
});
|
||||
|
||||
it("import.meta.path", () => {
|
||||
expect(path.endsWith("/bun/test/bun.js/import-meta.test.js")).toBe(true);
|
||||
});
|
||||
3
test/bun.js/inline.macro.js
Normal file
3
test/bun.js/inline.macro.js
Normal file
@@ -0,0 +1,3 @@
|
||||
export function whatDidIPass(expr, ctx) {
|
||||
return ctx;
|
||||
}
|
||||
96
test/bun.js/inspect.test.js
Normal file
96
test/bun.js/inspect.test.js
Normal file
@@ -0,0 +1,96 @@
|
||||
import { it, expect } from "bun:test";
|
||||
|
||||
it("jsx with two elements", () => {
|
||||
const input = Bun.inspect(
|
||||
<div hello="quoted">
|
||||
<input type="text" value={"123"} />
|
||||
string inside child
|
||||
</div>
|
||||
);
|
||||
|
||||
const output = `<div hello="quoted">
|
||||
<input type="text" value="123" />
|
||||
string inside child
|
||||
</div>`;
|
||||
|
||||
expect(input).toBe(output);
|
||||
});
|
||||
|
||||
const Foo = () => <div hello="quoted">foo</div>;
|
||||
|
||||
it("jsx with anon component", () => {
|
||||
const input = Bun.inspect(<Foo />);
|
||||
|
||||
const output = `<NoName />`;
|
||||
|
||||
expect(input).toBe(output);
|
||||
});
|
||||
|
||||
it("jsx with fragment", () => {
|
||||
const input = Bun.inspect(<>foo bar</>);
|
||||
|
||||
const output = `<>foo bar</>`;
|
||||
|
||||
expect(input).toBe(output);
|
||||
});
|
||||
|
||||
it("inspect", () => {
|
||||
expect(Bun.inspect(new TypeError("what")).includes("TypeError: what")).toBe(
|
||||
true
|
||||
);
|
||||
expect("hi").toBe("hi");
|
||||
expect(Bun.inspect(1)).toBe("1");
|
||||
expect(Bun.inspect(1, "hi")).toBe("1 hi");
|
||||
expect(Bun.inspect([])).toBe("[]");
|
||||
expect(Bun.inspect({})).toBe("{ }");
|
||||
expect(Bun.inspect({ hello: 1 })).toBe("{ hello: 1 }");
|
||||
expect(Bun.inspect({ hello: 1, there: 2 })).toBe("{ hello: 1, there: 2 }");
|
||||
expect(Bun.inspect({ hello: "1", there: 2 })).toBe(
|
||||
'{ hello: "1", there: 2 }'
|
||||
);
|
||||
expect(Bun.inspect({ 'hello-"there': "1", there: 2 })).toBe(
|
||||
'{ "hello-\\"there": "1", there: 2 }'
|
||||
);
|
||||
var str = "123";
|
||||
while (str.length < 4096) {
|
||||
str += "123";
|
||||
}
|
||||
expect(Bun.inspect(str)).toBe(str);
|
||||
// expect(Bun.inspect(new Headers())).toBe("Headers (0 KB) {}");
|
||||
expect(Bun.inspect(new Response()).length > 0).toBe(true);
|
||||
// expect(
|
||||
// JSON.stringify(
|
||||
// new Headers({
|
||||
// hi: "ok",
|
||||
// })
|
||||
// )
|
||||
// ).toBe('{"hi":"ok"}');
|
||||
expect(Bun.inspect(new Set())).toBe("Set {}");
|
||||
expect(Bun.inspect(new Map())).toBe("Map {}");
|
||||
expect(Bun.inspect(new Map([["foo", "bar"]]))).toBe(
|
||||
'Map(1) {\n "foo": "bar",\n}'
|
||||
);
|
||||
expect(Bun.inspect(new Set(["bar"]))).toBe('Set(1) {\n "bar",\n}');
|
||||
expect(Bun.inspect(<div>foo</div>)).toBe("<div>foo</div>");
|
||||
expect(Bun.inspect(<div hello>foo</div>)).toBe("<div hello=true>foo</div>");
|
||||
expect(Bun.inspect(<div hello={1}>foo</div>)).toBe("<div hello=1>foo</div>");
|
||||
expect(Bun.inspect(<div hello={123}>hi</div>)).toBe(
|
||||
"<div hello=123>hi</div>"
|
||||
);
|
||||
expect(Bun.inspect(<div hello="quoted">quoted</div>)).toBe(
|
||||
'<div hello="quoted">quoted</div>'
|
||||
);
|
||||
expect(
|
||||
Bun.inspect(
|
||||
<div hello="quoted">
|
||||
<input type="text" value={"123"} />
|
||||
</div>
|
||||
)
|
||||
).toBe(
|
||||
`
|
||||
<div hello="quoted">
|
||||
<input type="text" value="123" />
|
||||
</div>`.trim()
|
||||
);
|
||||
expect(Bun.inspect(BigInt(32))).toBe("32n");
|
||||
});
|
||||
7
test/bun.js/macro-check.js
Normal file
7
test/bun.js/macro-check.js
Normal file
@@ -0,0 +1,7 @@
|
||||
export function keepSecondArgument(bacon1234) {
|
||||
return bacon1234.arguments[1];
|
||||
}
|
||||
|
||||
export function bacon(heloooo) {
|
||||
return heloooo.arguments[1];
|
||||
}
|
||||
80
test/bun.js/microtask.test.js
Normal file
80
test/bun.js/microtask.test.js
Normal file
@@ -0,0 +1,80 @@
|
||||
import { it } from "bun:test";
|
||||
|
||||
it("queueMicrotask", async () => {
|
||||
// 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"
|
||||
);
|
||||
}
|
||||
});
|
||||
69
test/bun.js/mmap.test.js
Normal file
69
test/bun.js/mmap.test.js
Normal file
@@ -0,0 +1,69 @@
|
||||
import { describe, it, expect } from "bun:test";
|
||||
import { gcTick } from "./gc";
|
||||
|
||||
describe("Bun.mmap", async () => {
|
||||
await gcTick();
|
||||
const path = `/tmp/bun-mmap-test_${Math.random()}.txt`;
|
||||
await gcTick();
|
||||
await Bun.write(path, "hello");
|
||||
await gcTick();
|
||||
|
||||
it("mmap finalizer", async () => {
|
||||
let map = Bun.mmap(path);
|
||||
await gcTick();
|
||||
const map2 = Bun.mmap(path);
|
||||
|
||||
map = null;
|
||||
await gcTick();
|
||||
});
|
||||
|
||||
it("mmap passed to other syscalls", async () => {
|
||||
const map = Bun.mmap(path);
|
||||
await gcTick();
|
||||
await Bun.write(path + "1", map);
|
||||
await gcTick();
|
||||
const text = await (await Bun.file(path + "1")).text();
|
||||
await gcTick();
|
||||
|
||||
expect(text).toBe(new TextDecoder().decode(map));
|
||||
});
|
||||
|
||||
it("mmap sync", async () => {
|
||||
const map = Bun.mmap(path);
|
||||
await gcTick();
|
||||
const map2 = Bun.mmap(path);
|
||||
await gcTick();
|
||||
|
||||
const old = map[0];
|
||||
await gcTick();
|
||||
map[0] = 0;
|
||||
await gcTick();
|
||||
expect(map2[0]).toBe(0);
|
||||
|
||||
map2[0] = old;
|
||||
await gcTick();
|
||||
expect(map[0]).toBe(old);
|
||||
await gcTick();
|
||||
await Bun.write(path, "olleh");
|
||||
await gcTick();
|
||||
expect(new TextDecoder().decode(map)).toBe("olleh");
|
||||
await gcTick();
|
||||
});
|
||||
|
||||
it("mmap private", async () => {
|
||||
await gcTick();
|
||||
const map = Bun.mmap(path, { shared: true });
|
||||
await gcTick();
|
||||
const map2 = Bun.mmap(path, { shared: false });
|
||||
await gcTick();
|
||||
const old = map[0];
|
||||
|
||||
await gcTick();
|
||||
map2[0] = 0;
|
||||
await gcTick();
|
||||
expect(map2[0]).toBe(0);
|
||||
await gcTick();
|
||||
expect(map[0]).toBe(old);
|
||||
await gcTick();
|
||||
});
|
||||
});
|
||||
16
test/bun.js/node-builtins.test.js
Normal file
16
test/bun.js/node-builtins.test.js
Normal file
@@ -0,0 +1,16 @@
|
||||
import { describe, it, expect } from "bun:test";
|
||||
|
||||
import { EventEmitter } from "events";
|
||||
|
||||
describe("EventEmitter", () => {
|
||||
it("should emit events", () => {
|
||||
const emitter = new EventEmitter();
|
||||
var called = false;
|
||||
const listener = () => {
|
||||
called = true;
|
||||
};
|
||||
emitter.on("test", listener);
|
||||
emitter.emit("test");
|
||||
expect(called).toBe(true);
|
||||
});
|
||||
});
|
||||
457
test/bun.js/path.test.js
Normal file
457
test/bun.js/path.test.js
Normal file
@@ -0,0 +1,457 @@
|
||||
const { file } = import.meta;
|
||||
|
||||
import { describe, it, expect } from "bun:test";
|
||||
import * as path from "node:path";
|
||||
import assert from "assert";
|
||||
|
||||
const strictEqual = (...args) => {
|
||||
assert.strictEqual(...args);
|
||||
expect(true).toBe(true);
|
||||
};
|
||||
|
||||
it("path.basename", () => {
|
||||
strictEqual(path.basename(file), "path.test.js");
|
||||
strictEqual(path.basename(file, ".js"), "path.test");
|
||||
strictEqual(path.basename(".js", ".js"), "");
|
||||
strictEqual(path.basename(""), "");
|
||||
strictEqual(path.basename("/dir/basename.ext"), "basename.ext");
|
||||
strictEqual(path.basename("/basename.ext"), "basename.ext");
|
||||
strictEqual(path.basename("basename.ext"), "basename.ext");
|
||||
strictEqual(path.basename("basename.ext/"), "basename.ext");
|
||||
strictEqual(path.basename("basename.ext//"), "basename.ext");
|
||||
strictEqual(path.basename("aaa/bbb", "/bbb"), "bbb");
|
||||
strictEqual(path.basename("aaa/bbb", "a/bbb"), "bbb");
|
||||
strictEqual(path.basename("aaa/bbb", "bbb"), "bbb");
|
||||
strictEqual(path.basename("aaa/bbb//", "bbb"), "bbb");
|
||||
strictEqual(path.basename("aaa/bbb", "bb"), "b");
|
||||
strictEqual(path.basename("aaa/bbb", "b"), "bb");
|
||||
strictEqual(path.basename("/aaa/bbb", "/bbb"), "bbb");
|
||||
strictEqual(path.basename("/aaa/bbb", "a/bbb"), "bbb");
|
||||
strictEqual(path.basename("/aaa/bbb", "bbb"), "bbb");
|
||||
strictEqual(path.basename("/aaa/bbb//", "bbb"), "bbb");
|
||||
strictEqual(path.basename("/aaa/bbb", "bb"), "b");
|
||||
strictEqual(path.basename("/aaa/bbb", "b"), "bb");
|
||||
strictEqual(path.basename("/aaa/bbb"), "bbb");
|
||||
strictEqual(path.basename("/aaa/"), "aaa");
|
||||
strictEqual(path.basename("/aaa/b"), "b");
|
||||
strictEqual(path.basename("/a/b"), "b");
|
||||
strictEqual(path.basename("//a"), "a");
|
||||
strictEqual(path.basename("a", "a"), "");
|
||||
|
||||
// // On Windows a backslash acts as a path separator.
|
||||
strictEqual(path.win32.basename("\\dir\\basename.ext"), "basename.ext");
|
||||
strictEqual(path.win32.basename("\\basename.ext"), "basename.ext");
|
||||
strictEqual(path.win32.basename("basename.ext"), "basename.ext");
|
||||
strictEqual(path.win32.basename("basename.ext\\"), "basename.ext");
|
||||
strictEqual(path.win32.basename("basename.ext\\\\"), "basename.ext");
|
||||
strictEqual(path.win32.basename("foo"), "foo");
|
||||
strictEqual(path.win32.basename("aaa\\bbb", "\\bbb"), "bbb");
|
||||
strictEqual(path.win32.basename("aaa\\bbb", "a\\bbb"), "bbb");
|
||||
strictEqual(path.win32.basename("aaa\\bbb", "bbb"), "bbb");
|
||||
strictEqual(path.win32.basename("aaa\\bbb\\\\\\\\", "bbb"), "bbb");
|
||||
strictEqual(path.win32.basename("aaa\\bbb", "bb"), "b");
|
||||
strictEqual(path.win32.basename("aaa\\bbb", "b"), "bb");
|
||||
strictEqual(path.win32.basename("C:"), "");
|
||||
strictEqual(path.win32.basename("C:."), ".");
|
||||
strictEqual(path.win32.basename("C:\\"), "");
|
||||
strictEqual(path.win32.basename("C:\\dir\\base.ext"), "base.ext");
|
||||
strictEqual(path.win32.basename("C:\\basename.ext"), "basename.ext");
|
||||
strictEqual(path.win32.basename("C:basename.ext"), "basename.ext");
|
||||
strictEqual(path.win32.basename("C:basename.ext\\"), "basename.ext");
|
||||
strictEqual(path.win32.basename("C:basename.ext\\\\"), "basename.ext");
|
||||
strictEqual(path.win32.basename("C:foo"), "foo");
|
||||
strictEqual(path.win32.basename("file:stream"), "file:stream");
|
||||
strictEqual(path.win32.basename("a", "a"), "");
|
||||
|
||||
// On unix a backslash is just treated as any other character.
|
||||
strictEqual(
|
||||
path.posix.basename("\\dir\\basename.ext"),
|
||||
"\\dir\\basename.ext"
|
||||
);
|
||||
strictEqual(path.posix.basename("\\basename.ext"), "\\basename.ext");
|
||||
strictEqual(path.posix.basename("basename.ext"), "basename.ext");
|
||||
strictEqual(path.posix.basename("basename.ext\\"), "basename.ext\\");
|
||||
strictEqual(path.posix.basename("basename.ext\\\\"), "basename.ext\\\\");
|
||||
strictEqual(path.posix.basename("foo"), "foo");
|
||||
|
||||
// POSIX filenames may include control characters
|
||||
// c.f. http://www.dwheeler.com/essays/fixing-unix-linux-filenames.html
|
||||
const controlCharFilename = `Icon${String.fromCharCode(13)}`;
|
||||
strictEqual(
|
||||
path.posix.basename(`/a/b/${controlCharFilename}`),
|
||||
controlCharFilename
|
||||
);
|
||||
});
|
||||
|
||||
it("path.join", () => {
|
||||
const failures = [];
|
||||
const backslashRE = /\\/g;
|
||||
|
||||
const joinTests = [
|
||||
[
|
||||
[path.posix.join],
|
||||
// Arguments result
|
||||
[
|
||||
[[".", "x/b", "..", "/b/c.js"], "x/b/c.js"],
|
||||
// [[], '.'],
|
||||
[["/.", "x/b", "..", "/b/c.js"], "/x/b/c.js"],
|
||||
[["/foo", "../../../bar"], "/bar"],
|
||||
[["foo", "../../../bar"], "../../bar"],
|
||||
[["foo/", "../../../bar"], "../../bar"],
|
||||
[["foo/x", "../../../bar"], "../bar"],
|
||||
[["foo/x", "./bar"], "foo/x/bar"],
|
||||
[["foo/x/", "./bar"], "foo/x/bar"],
|
||||
[["foo/x/", ".", "bar"], "foo/x/bar"],
|
||||
[["./"], "./"],
|
||||
[[".", "./"], "./"],
|
||||
[[".", ".", "."], "."],
|
||||
[[".", "./", "."], "."],
|
||||
[[".", "/./", "."], "."],
|
||||
[[".", "/////./", "."], "."],
|
||||
[["."], "."],
|
||||
[["", "."], "."],
|
||||
[["", "foo"], "foo"],
|
||||
[["foo", "/bar"], "foo/bar"],
|
||||
[["", "/foo"], "/foo"],
|
||||
[["", "", "/foo"], "/foo"],
|
||||
[["", "", "foo"], "foo"],
|
||||
[["foo", ""], "foo"],
|
||||
[["foo/", ""], "foo/"],
|
||||
[["foo", "", "/bar"], "foo/bar"],
|
||||
[["./", "..", "/foo"], "../foo"],
|
||||
[["./", "..", "..", "/foo"], "../../foo"],
|
||||
[[".", "..", "..", "/foo"], "../../foo"],
|
||||
[["", "..", "..", "/foo"], "../../foo"],
|
||||
[["/"], "/"],
|
||||
[["/", "."], "/"],
|
||||
[["/", ".."], "/"],
|
||||
[["/", "..", ".."], "/"],
|
||||
[[""], "."],
|
||||
[["", ""], "."],
|
||||
[[" /foo"], " /foo"],
|
||||
[[" ", "foo"], " /foo"],
|
||||
[[" ", "."], " "],
|
||||
[[" ", "/"], " /"],
|
||||
[[" ", ""], " "],
|
||||
[["/", "foo"], "/foo"],
|
||||
[["/", "/foo"], "/foo"],
|
||||
[["/", "//foo"], "/foo"],
|
||||
[["/", "", "/foo"], "/foo"],
|
||||
[["", "/", "foo"], "/foo"],
|
||||
[["", "/", "/foo"], "/foo"],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
// // Windows-specific join tests
|
||||
// joinTests.push([
|
||||
// path.win32.join,
|
||||
// joinTests[0][1].slice(0).concat([
|
||||
// // Arguments result
|
||||
// // UNC path expected
|
||||
// [["//foo/bar"], "\\\\foo\\bar\\"],
|
||||
// [["\\/foo/bar"], "\\\\foo\\bar\\"],
|
||||
// [["\\\\foo/bar"], "\\\\foo\\bar\\"],
|
||||
// // UNC path expected - server and share separate
|
||||
// [["//foo", "bar"], "\\\\foo\\bar\\"],
|
||||
// [["//foo/", "bar"], "\\\\foo\\bar\\"],
|
||||
// [["//foo", "/bar"], "\\\\foo\\bar\\"],
|
||||
// // UNC path expected - questionable
|
||||
// [["//foo", "", "bar"], "\\\\foo\\bar\\"],
|
||||
// [["//foo/", "", "bar"], "\\\\foo\\bar\\"],
|
||||
// [["//foo/", "", "/bar"], "\\\\foo\\bar\\"],
|
||||
// // UNC path expected - even more questionable
|
||||
// [["", "//foo", "bar"], "\\\\foo\\bar\\"],
|
||||
// [["", "//foo/", "bar"], "\\\\foo\\bar\\"],
|
||||
// [["", "//foo/", "/bar"], "\\\\foo\\bar\\"],
|
||||
// // No UNC path expected (no double slash in first component)
|
||||
// [["\\", "foo/bar"], "\\foo\\bar"],
|
||||
// [["\\", "/foo/bar"], "\\foo\\bar"],
|
||||
// [["", "/", "/foo/bar"], "\\foo\\bar"],
|
||||
// // No UNC path expected (no non-slashes in first component -
|
||||
// // questionable)
|
||||
// [["//", "foo/bar"], "\\foo\\bar"],
|
||||
// [["//", "/foo/bar"], "\\foo\\bar"],
|
||||
// [["\\\\", "/", "/foo/bar"], "\\foo\\bar"],
|
||||
// [["//"], "\\"],
|
||||
// // No UNC path expected (share name missing - questionable).
|
||||
// [["//foo"], "\\foo"],
|
||||
// [["//foo/"], "\\foo\\"],
|
||||
// [["//foo", "/"], "\\foo\\"],
|
||||
// [["//foo", "", "/"], "\\foo\\"],
|
||||
// // No UNC path expected (too many leading slashes - questionable)
|
||||
// [["///foo/bar"], "\\foo\\bar"],
|
||||
// [["////foo", "bar"], "\\foo\\bar"],
|
||||
// [["\\\\\\/foo/bar"], "\\foo\\bar"],
|
||||
// // Drive-relative vs drive-absolute paths. This merely describes the
|
||||
// // status quo, rather than being obviously right
|
||||
// [["c:"], "c:."],
|
||||
// [["c:."], "c:."],
|
||||
// [["c:", ""], "c:."],
|
||||
// [["", "c:"], "c:."],
|
||||
// [["c:.", "/"], "c:.\\"],
|
||||
// [["c:.", "file"], "c:file"],
|
||||
// [["c:", "/"], "c:\\"],
|
||||
// [["c:", "file"], "c:\\file"],
|
||||
// ]),
|
||||
// ]);
|
||||
joinTests.forEach((test) => {
|
||||
if (!Array.isArray(test[0])) test[0] = [test[0]];
|
||||
test[0].forEach((join) => {
|
||||
test[1].forEach((test) => {
|
||||
const actual = join.apply(null, test[0]);
|
||||
const expected = test[1];
|
||||
// For non-Windows specific tests with the Windows join(), we need to try
|
||||
// replacing the slashes since the non-Windows specific tests' `expected`
|
||||
// use forward slashes
|
||||
let actualAlt;
|
||||
let os;
|
||||
if (join === path.win32.join) {
|
||||
actualAlt = actual.replace(backslashRE, "/");
|
||||
os = "win32";
|
||||
} else {
|
||||
os = "posix";
|
||||
}
|
||||
if (actual !== expected && actualAlt !== expected) {
|
||||
const delimiter = test[0].map(JSON.stringify).join(",");
|
||||
const message = `path.${os}.join(${delimiter})\n expect=${JSON.stringify(
|
||||
expected
|
||||
)}\n actual=${JSON.stringify(actual)}`;
|
||||
failures.push(`\n${message}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
strictEqual(failures.length, 0, failures.join(""));
|
||||
});
|
||||
|
||||
it("path.relative", () => {
|
||||
const failures = [];
|
||||
|
||||
const relativeTests = [
|
||||
// [
|
||||
// path.win32.relative,
|
||||
// // Arguments result
|
||||
// [
|
||||
// ["c:/blah\\blah", "d:/games", "d:\\games"],
|
||||
// ["c:/aaaa/bbbb", "c:/aaaa", ".."],
|
||||
// ["c:/aaaa/bbbb", "c:/cccc", "..\\..\\cccc"],
|
||||
// ["c:/aaaa/bbbb", "c:/aaaa/bbbb", ""],
|
||||
// ["c:/aaaa/bbbb", "c:/aaaa/cccc", "..\\cccc"],
|
||||
// ["c:/aaaa/", "c:/aaaa/cccc", "cccc"],
|
||||
// ["c:/", "c:\\aaaa\\bbbb", "aaaa\\bbbb"],
|
||||
// ["c:/aaaa/bbbb", "d:\\", "d:\\"],
|
||||
// ["c:/AaAa/bbbb", "c:/aaaa/bbbb", ""],
|
||||
// ["c:/aaaaa/", "c:/aaaa/cccc", "..\\aaaa\\cccc"],
|
||||
// ["C:\\foo\\bar\\baz\\quux", "C:\\", "..\\..\\..\\.."],
|
||||
// [
|
||||
// "C:\\foo\\test",
|
||||
// "C:\\foo\\test\\bar\\package.json",
|
||||
// "bar\\package.json",
|
||||
// ],
|
||||
// ["C:\\foo\\bar\\baz-quux", "C:\\foo\\bar\\baz", "..\\baz"],
|
||||
// ["C:\\foo\\bar\\baz", "C:\\foo\\bar\\baz-quux", "..\\baz-quux"],
|
||||
// ["\\\\foo\\bar", "\\\\foo\\bar\\baz", "baz"],
|
||||
// ["\\\\foo\\bar\\baz", "\\\\foo\\bar", ".."],
|
||||
// ["\\\\foo\\bar\\baz-quux", "\\\\foo\\bar\\baz", "..\\baz"],
|
||||
// ["\\\\foo\\bar\\baz", "\\\\foo\\bar\\baz-quux", "..\\baz-quux"],
|
||||
// ["C:\\baz-quux", "C:\\baz", "..\\baz"],
|
||||
// ["C:\\baz", "C:\\baz-quux", "..\\baz-quux"],
|
||||
// ["\\\\foo\\baz-quux", "\\\\foo\\baz", "..\\baz"],
|
||||
// ["\\\\foo\\baz", "\\\\foo\\baz-quux", "..\\baz-quux"],
|
||||
// ["C:\\baz", "\\\\foo\\bar\\baz", "\\\\foo\\bar\\baz"],
|
||||
// ["\\\\foo\\bar\\baz", "C:\\baz", "C:\\baz"],
|
||||
// ],
|
||||
// ],
|
||||
[
|
||||
path.posix.relative,
|
||||
// Arguments result
|
||||
[
|
||||
["/var/lib", "/var", ".."],
|
||||
["/var/lib", "/bin", "../../bin"],
|
||||
["/var/lib", "/var/lib", ""],
|
||||
["/var/lib", "/var/apache", "../apache"],
|
||||
["/var/", "/var/lib", "lib"],
|
||||
["/", "/var/lib", "var/lib"],
|
||||
["/foo/test", "/foo/test/bar/package.json", "bar/package.json"],
|
||||
["/Users/a/web/b/test/mails", "/Users/a/web/b", "../.."],
|
||||
["/foo/bar/baz-quux", "/foo/bar/baz", "../baz"],
|
||||
["/foo/bar/baz", "/foo/bar/baz-quux", "../baz-quux"],
|
||||
["/baz-quux", "/baz", "../baz"],
|
||||
["/baz", "/baz-quux", "../baz-quux"],
|
||||
["/page1/page2/foo", "/", "../../.."],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
relativeTests.forEach((test) => {
|
||||
const relative = test[0];
|
||||
test[1].forEach((test) => {
|
||||
const actual = relative(test[0], test[1]);
|
||||
const expected = test[2];
|
||||
if (actual !== expected) {
|
||||
const os = relative === path.win32.relative ? "win32" : "posix";
|
||||
const message = `path.${os}.relative(${test
|
||||
.slice(0, 2)
|
||||
.map(JSON.stringify)
|
||||
.join(",")})\n expect=${JSON.stringify(
|
||||
expected
|
||||
)}\n actual=${JSON.stringify(actual)}`;
|
||||
failures.push(`\n${message}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
strictEqual(failures.length, 0, failures.join(""));
|
||||
expect(true).toBe(true);
|
||||
});
|
||||
|
||||
it("path.normalize", () => {
|
||||
// strictEqual(
|
||||
// path.win32.normalize("./fixtures///b/../b/c.js"),
|
||||
// "fixtures\\b\\c.js"
|
||||
// );
|
||||
// strictEqual(path.win32.normalize("/foo/../../../bar"), "\\bar");
|
||||
// strictEqual(path.win32.normalize("a//b//../b"), "a\\b");
|
||||
// strictEqual(path.win32.normalize("a//b//./c"), "a\\b\\c");
|
||||
// strictEqual(path.win32.normalize("a//b//."), "a\\b");
|
||||
// strictEqual(
|
||||
// path.win32.normalize("//server/share/dir/file.ext"),
|
||||
// "\\\\server\\share\\dir\\file.ext"
|
||||
// );
|
||||
// strictEqual(path.win32.normalize("/a/b/c/../../../x/y/z"), "\\x\\y\\z");
|
||||
// strictEqual(path.win32.normalize("C:"), "C:.");
|
||||
// strictEqual(path.win32.normalize("C:..\\abc"), "C:..\\abc");
|
||||
// strictEqual(path.win32.normalize("C:..\\..\\abc\\..\\def"), "C:..\\..\\def");
|
||||
// strictEqual(path.win32.normalize("C:\\."), "C:\\");
|
||||
// strictEqual(path.win32.normalize("file:stream"), "file:stream");
|
||||
// strictEqual(path.win32.normalize("bar\\foo..\\..\\"), "bar\\");
|
||||
// strictEqual(path.win32.normalize("bar\\foo..\\.."), "bar");
|
||||
// strictEqual(path.win32.normalize("bar\\foo..\\..\\baz"), "bar\\baz");
|
||||
// strictEqual(path.win32.normalize("bar\\foo..\\"), "bar\\foo..\\");
|
||||
// strictEqual(path.win32.normalize("bar\\foo.."), "bar\\foo..");
|
||||
// strictEqual(path.win32.normalize("..\\foo..\\..\\..\\bar"), "..\\..\\bar");
|
||||
// strictEqual(
|
||||
// path.win32.normalize("..\\...\\..\\.\\...\\..\\..\\bar"),
|
||||
// "..\\..\\bar"
|
||||
// );
|
||||
// strictEqual(
|
||||
// path.win32.normalize("../../../foo/../../../bar"),
|
||||
// "..\\..\\..\\..\\..\\bar"
|
||||
// );
|
||||
// strictEqual(
|
||||
// path.win32.normalize("../../../foo/../../../bar/../../"),
|
||||
// "..\\..\\..\\..\\..\\..\\"
|
||||
// );
|
||||
// strictEqual(
|
||||
// path.win32.normalize("../foobar/barfoo/foo/../../../bar/../../"),
|
||||
// "..\\..\\"
|
||||
// );
|
||||
// strictEqual(
|
||||
// path.win32.normalize("../.../../foobar/../../../bar/../../baz"),
|
||||
// "..\\..\\..\\..\\baz"
|
||||
// );
|
||||
// strictEqual(path.win32.normalize("foo/bar\\baz"), "foo\\bar\\baz");
|
||||
|
||||
strictEqual(
|
||||
path.posix.normalize("./fixtures///b/../b/c.js"),
|
||||
"fixtures/b/c.js"
|
||||
);
|
||||
strictEqual(path.posix.normalize("/foo/../../../bar"), "/bar");
|
||||
strictEqual(path.posix.normalize("a//b//../b"), "a/b");
|
||||
strictEqual(path.posix.normalize("a//b//./c"), "a/b/c");
|
||||
strictEqual(path.posix.normalize("a//b//."), "a/b");
|
||||
strictEqual(path.posix.normalize("/a/b/c/../../../x/y/z"), "/x/y/z");
|
||||
strictEqual(path.posix.normalize("///..//./foo/.//bar"), "/foo/bar");
|
||||
strictEqual(path.posix.normalize("bar/foo../../"), "bar/");
|
||||
strictEqual(path.posix.normalize("bar/foo../.."), "bar");
|
||||
strictEqual(path.posix.normalize("bar/foo../../baz"), "bar/baz");
|
||||
strictEqual(path.posix.normalize("bar/foo../"), "bar/foo../");
|
||||
strictEqual(path.posix.normalize("bar/foo.."), "bar/foo..");
|
||||
console.log("A");
|
||||
strictEqual(path.posix.normalize("../foo../../../bar"), "../../bar");
|
||||
console.log("B");
|
||||
strictEqual(path.posix.normalize("../.../.././.../../../bar"), "../../bar");
|
||||
strictEqual(
|
||||
path.posix.normalize("../../../foo/../../../bar"),
|
||||
"../../../../../bar"
|
||||
);
|
||||
strictEqual(
|
||||
path.posix.normalize("../../../foo/../../../bar/../../"),
|
||||
"../../../../../../"
|
||||
);
|
||||
strictEqual(
|
||||
path.posix.normalize("../foobar/barfoo/foo/../../../bar/../../"),
|
||||
"../../"
|
||||
);
|
||||
strictEqual(
|
||||
path.posix.normalize("../.../../foobar/../../../bar/../../baz"),
|
||||
"../../../../baz"
|
||||
);
|
||||
strictEqual(path.posix.normalize("foo/bar\\baz"), "foo/bar\\baz");
|
||||
});
|
||||
|
||||
it("path.resolve", () => {
|
||||
const failures = [];
|
||||
const slashRE = /\//g;
|
||||
const backslashRE = /\\/g;
|
||||
|
||||
const resolveTests = [
|
||||
// [
|
||||
// path.win32.resolve,
|
||||
// // Arguments result
|
||||
// [
|
||||
// [["c:/blah\\blah", "d:/games", "c:../a"], "c:\\blah\\a"],
|
||||
// [["c:/ignore", "d:\\a/b\\c/d", "\\e.exe"], "d:\\e.exe"],
|
||||
// [["c:/ignore", "c:/some/file"], "c:\\some\\file"],
|
||||
// [["d:/ignore", "d:some/dir//"], "d:\\ignore\\some\\dir"],
|
||||
// [["."], process.cwd()],
|
||||
// [["//server/share", "..", "relative\\"], "\\\\server\\share\\relative"],
|
||||
// [["c:/", "//"], "c:\\"],
|
||||
// [["c:/", "//dir"], "c:\\dir"],
|
||||
// [["c:/", "//server/share"], "\\\\server\\share\\"],
|
||||
// [["c:/", "//server//share"], "\\\\server\\share\\"],
|
||||
// [["c:/", "///some//dir"], "c:\\some\\dir"],
|
||||
// [
|
||||
// ["C:\\foo\\tmp.3\\", "..\\tmp.3\\cycles\\root.js"],
|
||||
// "C:\\foo\\tmp.3\\cycles\\root.js",
|
||||
// ],
|
||||
// ],
|
||||
// ],
|
||||
[
|
||||
path.posix.resolve,
|
||||
// Arguments result
|
||||
[
|
||||
[["/var/lib", "../", "file/"], "/var/file"],
|
||||
[["/var/lib", "/../", "file/"], "/file"],
|
||||
[["a/b/c/", "../../.."], process.cwd()],
|
||||
[["."], process.cwd()],
|
||||
[["/some/dir", ".", "/absolute/"], "/absolute"],
|
||||
[
|
||||
["/foo/tmp.3/", "../tmp.3/cycles/root.js"],
|
||||
"/foo/tmp.3/cycles/root.js",
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
const isWindows = false;
|
||||
resolveTests.forEach(([resolve, tests]) => {
|
||||
tests.forEach(([test, expected]) => {
|
||||
const actual = resolve.apply(null, test);
|
||||
let actualAlt;
|
||||
const os = resolve === path.win32.resolve ? "win32" : "posix";
|
||||
if (resolve === path.win32.resolve && !isWindows)
|
||||
actualAlt = actual.replace(backslashRE, "/");
|
||||
else if (resolve !== path.win32.resolve && isWindows)
|
||||
actualAlt = actual.replace(slashRE, "\\");
|
||||
|
||||
const message = `path.${os}.resolve(${test
|
||||
.map(JSON.stringify)
|
||||
.join(",")})\n expect=${JSON.stringify(
|
||||
expected
|
||||
)}\n actual=${JSON.stringify(actual)}`;
|
||||
if (actual !== expected && actualAlt !== expected) failures.push(message);
|
||||
});
|
||||
});
|
||||
strictEqual(failures.length, 0, failures.join("\n"));
|
||||
});
|
||||
18
test/bun.js/performance.test.js
Normal file
18
test/bun.js/performance.test.js
Normal file
@@ -0,0 +1,18 @@
|
||||
import { expect, it } from "bun:test";
|
||||
|
||||
it("performance.now() should be monotonic", () => {
|
||||
const first = performance.now();
|
||||
const second = performance.now();
|
||||
const third = performance.now();
|
||||
const fourth = performance.now();
|
||||
const fifth = performance.now();
|
||||
const sixth = performance.now();
|
||||
expect(first < second).toBe(true);
|
||||
expect(second < third).toBe(true);
|
||||
expect(third < fourth).toBe(true);
|
||||
expect(fourth < fifth).toBe(true);
|
||||
expect(fifth < sixth).toBe(true);
|
||||
expect(Bun.nanoseconds() > 0).toBe(true);
|
||||
expect(Bun.nanoseconds() > sixth).toBe(true);
|
||||
expect(typeof Bun.nanoseconds() === "number").toBe(true);
|
||||
});
|
||||
91
test/bun.js/process-nexttick.js
Normal file
91
test/bun.js/process-nexttick.js
Normal file
@@ -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"
|
||||
);
|
||||
});
|
||||
93
test/bun.js/process-nexttick.test.js
Normal file
93
test/bun.js/process-nexttick.test.js
Normal file
@@ -0,0 +1,93 @@
|
||||
import { it } from "bun:test";
|
||||
|
||||
it("process.nextTick", async () => {
|
||||
// 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) => {
|
||||
if (first !== 12345 || second !== "hello")
|
||||
reject(new Error("process.nextTick called with wrong arguments"));
|
||||
resolve(true);
|
||||
},
|
||||
12345,
|
||||
"hello"
|
||||
);
|
||||
});
|
||||
});
|
||||
54
test/bun.js/process.test.js
Normal file
54
test/bun.js/process.test.js
Normal file
@@ -0,0 +1,54 @@
|
||||
import { describe, it } from "bun:test";
|
||||
|
||||
it("process", () => {
|
||||
// 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());
|
||||
});
|
||||
1
test/bun.js/readFileSync.txt
Normal file
1
test/bun.js/readFileSync.txt
Normal file
@@ -0,0 +1 @@
|
||||
File read successfully
|
||||
9
test/bun.js/readdir.js
Normal file
9
test/bun.js/readdir.js
Normal file
@@ -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("."));
|
||||
25
test/bun.js/reportError.test.js
Normal file
25
test/bun.js/reportError.test.js
Normal file
@@ -0,0 +1,25 @@
|
||||
import { it } from "bun:test";
|
||||
|
||||
it("reportError", () => {
|
||||
console.log("---BEGIN REPORT ERROR TEST--");
|
||||
// make sure we don't crash when given non-sensical types
|
||||
reportError(new Error("reportError Test!"));
|
||||
reportError(true);
|
||||
reportError(false);
|
||||
reportError(null);
|
||||
reportError(123);
|
||||
reportError(Infinity);
|
||||
reportError(NaN);
|
||||
reportError(-NaN);
|
||||
reportError("");
|
||||
reportError(new Uint8Array(1));
|
||||
reportError(new Uint8Array(0));
|
||||
reportError(new ArrayBuffer(0));
|
||||
reportError(new ArrayBuffer(1));
|
||||
reportError("string");
|
||||
reportError([]);
|
||||
reportError([123, null]);
|
||||
reportError({});
|
||||
reportError([{}]);
|
||||
console.log("---END REPORT ERROR TEST--");
|
||||
});
|
||||
3
test/bun.js/require-json.json
Normal file
3
test/bun.js/require-json.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"hello": -123
|
||||
}
|
||||
1
test/bun.js/resolve-typescript-file.tsx
Normal file
1
test/bun.js/resolve-typescript-file.tsx
Normal file
@@ -0,0 +1 @@
|
||||
export default {};
|
||||
100
test/bun.js/resolve.test.js
Normal file
100
test/bun.js/resolve.test.js
Normal file
@@ -0,0 +1,100 @@
|
||||
import { it, expect } from "bun:test";
|
||||
import { mkdirSync, writeFileSync } from "fs";
|
||||
import { join } from "path";
|
||||
|
||||
it("import.meta.resolve", async () => {
|
||||
expect(await import.meta.resolve("./resolve.test.js")).toBe(import.meta.path);
|
||||
|
||||
expect(await import.meta.resolve("./resolve.test.js", import.meta.path)).toBe(
|
||||
import.meta.path
|
||||
);
|
||||
|
||||
expect(
|
||||
// optional second param can be any path, including a dir
|
||||
await import.meta.resolve(
|
||||
"./bun.js/resolve.test.js",
|
||||
join(import.meta.path, "../")
|
||||
)
|
||||
).toBe(import.meta.path);
|
||||
|
||||
// can be a package path
|
||||
expect(
|
||||
(await import.meta.resolve("react", import.meta.path)).length > 0
|
||||
).toBe(true);
|
||||
|
||||
// file extensions are optional
|
||||
expect(await import.meta.resolve("./resolve.test")).toBe(import.meta.path);
|
||||
|
||||
// works with tsconfig.json "paths"
|
||||
expect(await import.meta.resolve("foo/bar")).toBe(
|
||||
join(import.meta.path, "../baz.js")
|
||||
);
|
||||
|
||||
// works with package.json "exports"
|
||||
writePackageJSONExportsFixture();
|
||||
expect(await import.meta.resolve("package-json-exports/baz")).toBe(
|
||||
join(import.meta.path, "../node_modules/package-json-exports/foo/bar.js")
|
||||
);
|
||||
|
||||
// works with TypeScript compiler edgecases like:
|
||||
// - If the file ends with .js and it doesn't exist, try again with .ts and .tsx
|
||||
expect(await import.meta.resolve("./resolve-typescript-file.js")).toBe(
|
||||
join(import.meta.path, "../resolve-typescript-file.tsx")
|
||||
);
|
||||
expect(await import.meta.resolve("./resolve-typescript-file.tsx")).toBe(
|
||||
join(import.meta.path, "../resolve-typescript-file.tsx")
|
||||
);
|
||||
|
||||
// throws a ResolveError on failure
|
||||
try {
|
||||
await import.meta.resolve("THIS FILE DOESNT EXIST");
|
||||
throw new Error("Test failed");
|
||||
} catch (exception) {
|
||||
expect(exception instanceof ResolveError).toBe(true);
|
||||
expect(exception.referrer).toBe(import.meta.path);
|
||||
expect(exception.name).toBe("ResolveError");
|
||||
}
|
||||
});
|
||||
|
||||
// the slightly lower level API, which doesn't prefill the second param
|
||||
// and expects a directory instead of a filepath
|
||||
it("Bun.resolve", async () => {
|
||||
expect(await Bun.resolve("./resolve.test.js", import.meta.dir)).toBe(
|
||||
import.meta.path
|
||||
);
|
||||
});
|
||||
|
||||
// synchronous
|
||||
it("Bun.resolveSync", () => {
|
||||
expect(Bun.resolveSync("./resolve.test.js", import.meta.dir)).toBe(
|
||||
import.meta.path
|
||||
);
|
||||
});
|
||||
|
||||
function writePackageJSONExportsFixture() {
|
||||
try {
|
||||
mkdirSync(
|
||||
join(import.meta.dir, "./node_modules/package-json-exports/foo"),
|
||||
{
|
||||
recursive: true,
|
||||
}
|
||||
);
|
||||
} catch (exception) {}
|
||||
writeFileSync(
|
||||
join(import.meta.dir, "./node_modules/package-json-exports/foo/bar.js"),
|
||||
"export const bar = 1;"
|
||||
);
|
||||
writeFileSync(
|
||||
join(import.meta.dir, "./node_modules/package-json-exports/package.json"),
|
||||
JSON.stringify(
|
||||
{
|
||||
name: "package-json-exports",
|
||||
exports: {
|
||||
"./baz": "./foo/bar.js",
|
||||
},
|
||||
},
|
||||
null,
|
||||
2
|
||||
)
|
||||
);
|
||||
}
|
||||
218
test/bun.js/response.file.test.js
Normal file
218
test/bun.js/response.file.test.js
Normal file
@@ -0,0 +1,218 @@
|
||||
import fs from "fs";
|
||||
import { it, expect } from "bun:test";
|
||||
import path from "path";
|
||||
import { gcTick } from "./gc";
|
||||
|
||||
it("Bun.file not found returns ENOENT", async () => {
|
||||
try {
|
||||
await gcTick();
|
||||
await Bun.file("/does/not/exist.txt").text();
|
||||
await gcTick();
|
||||
} catch (exception) {
|
||||
expect(exception.code).toBe("ENOENT");
|
||||
}
|
||||
await gcTick();
|
||||
});
|
||||
|
||||
it("Bun.write('out.txt', 'string')", async () => {
|
||||
for (let erase of [true, false]) {
|
||||
if (erase) {
|
||||
try {
|
||||
fs.unlinkSync(path.join("/tmp", "out.txt"));
|
||||
} catch (e) {}
|
||||
}
|
||||
await gcTick();
|
||||
expect(await Bun.write("/tmp/out.txt", "string")).toBe("string".length);
|
||||
await gcTick();
|
||||
const out = Bun.file("/tmp/out.txt");
|
||||
await gcTick();
|
||||
expect(await out.text()).toBe("string");
|
||||
await gcTick();
|
||||
expect(await out.text()).toBe(fs.readFileSync("/tmp/out.txt", "utf8"));
|
||||
await gcTick();
|
||||
}
|
||||
});
|
||||
|
||||
it("Bun.write blob", async () => {
|
||||
await Bun.write(
|
||||
Bun.file("/tmp/response-file.test.txt"),
|
||||
Bun.file(path.join(import.meta.dir, "fetch.js.txt"))
|
||||
);
|
||||
await gcTick();
|
||||
await Bun.write(Bun.file("/tmp/response-file.test.txt"), "blah blah blha");
|
||||
await gcTick();
|
||||
await Bun.write(
|
||||
Bun.file("/tmp/response-file.test.txt"),
|
||||
new Uint32Array(1024)
|
||||
);
|
||||
await gcTick();
|
||||
await Bun.write("/tmp/response-file.test.txt", new Uint32Array(1024));
|
||||
await gcTick();
|
||||
expect(
|
||||
await Bun.write(
|
||||
new TextEncoder().encode("/tmp/response-file.test.txt"),
|
||||
new Uint32Array(1024)
|
||||
)
|
||||
).toBe(new Uint32Array(1024).byteLength);
|
||||
await gcTick();
|
||||
});
|
||||
|
||||
it("Bun.file -> Bun.file", async () => {
|
||||
try {
|
||||
fs.unlinkSync(path.join("/tmp", "fetch.js.in"));
|
||||
} catch (e) {}
|
||||
await gcTick();
|
||||
try {
|
||||
fs.unlinkSync(path.join("/tmp", "fetch.js.out"));
|
||||
} catch (e) {}
|
||||
await gcTick();
|
||||
const file = path.join(import.meta.dir, "fetch.js.txt");
|
||||
await gcTick();
|
||||
const text = fs.readFileSync(file, "utf8");
|
||||
fs.writeFileSync("/tmp/fetch.js.in", text);
|
||||
await gcTick();
|
||||
{
|
||||
const result = await Bun.write(
|
||||
Bun.file("/tmp/fetch.js.out"),
|
||||
Bun.file("/tmp/fetch.js.in")
|
||||
);
|
||||
await gcTick();
|
||||
expect(await Bun.file("/tmp/fetch.js.out").text()).toBe(text);
|
||||
await gcTick();
|
||||
}
|
||||
|
||||
{
|
||||
await Bun.write(
|
||||
Bun.file("/tmp/fetch.js.in").slice(0, (text.length / 2) | 0),
|
||||
Bun.file("/tmp/fetch.js.out")
|
||||
);
|
||||
expect(await Bun.file("/tmp/fetch.js.in").text()).toBe(
|
||||
text.substring(0, (text.length / 2) | 0)
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
await gcTick();
|
||||
await Bun.write("/tmp/fetch.js.in", Bun.file("/tmp/fetch.js.out"));
|
||||
await gcTick();
|
||||
expect(await Bun.file("/tmp/fetch.js.in").text()).toBe(text);
|
||||
}
|
||||
});
|
||||
|
||||
it("Bun.file", async () => {
|
||||
const file = path.join(import.meta.dir, "fetch.js.txt");
|
||||
await gcTick();
|
||||
expect(await Bun.file(file).text()).toBe(fs.readFileSync(file, "utf8"));
|
||||
await gcTick();
|
||||
});
|
||||
|
||||
it("Bun.file as a Blob", async () => {
|
||||
const filePath = path.join(import.meta.path, "../fetch.js.txt");
|
||||
const fixture = fs.readFileSync(filePath, "utf8");
|
||||
// this is a Blob object with the same interface as the one returned by fetch
|
||||
// internally, instead of a byte array, it stores the file path!
|
||||
// this enables several performance optimizations
|
||||
var blob = Bun.file(filePath);
|
||||
await gcTick();
|
||||
|
||||
// no size because we haven't read it from disk yet
|
||||
expect(blob.size).toBe(0);
|
||||
await gcTick();
|
||||
// now it reads "./fetch.js.txt" from the filesystem
|
||||
// it's lazy, only loads once we ask for it
|
||||
// if it fails, the promise will reject at this point
|
||||
expect(await blob.text()).toBe(fixture);
|
||||
await gcTick();
|
||||
// now that it's loaded, the size updates
|
||||
expect(blob.size).toBe(fixture.length);
|
||||
await gcTick();
|
||||
// and it only loads once for _all_ blobs pointing to that file path
|
||||
// until all references are released
|
||||
expect((await blob.arrayBuffer()).byteLength).toBe(fixture.length);
|
||||
await gcTick();
|
||||
|
||||
const array = new Uint8Array(await blob.arrayBuffer());
|
||||
await gcTick();
|
||||
const text = fixture;
|
||||
for (let i = 0; i < text.length; i++) {
|
||||
expect(array[i]).toBe(text.charCodeAt(i));
|
||||
}
|
||||
await gcTick();
|
||||
expect(blob.size).toBe(fixture.length);
|
||||
blob = null;
|
||||
await gcTick();
|
||||
await new Promise((resolve) => setTimeout(resolve, 1));
|
||||
// now we're back
|
||||
var blob = Bun.file(filePath);
|
||||
expect(blob.size).toBe(0);
|
||||
});
|
||||
|
||||
it("Response -> Bun.file", async () => {
|
||||
const file = path.join(import.meta.dir, "fetch.js.txt");
|
||||
await gcTick();
|
||||
const text = fs.readFileSync(file, "utf8");
|
||||
await gcTick();
|
||||
const response = new Response(Bun.file(file));
|
||||
await gcTick();
|
||||
expect(await response.text()).toBe(text);
|
||||
await gcTick();
|
||||
});
|
||||
|
||||
it("Bun.file -> Response", async () => {
|
||||
// ensure the file doesn't already exist
|
||||
try {
|
||||
fs.unlinkSync("/tmp/fetch.js.out");
|
||||
} catch {}
|
||||
await gcTick();
|
||||
const file = path.join(import.meta.dir, "fetch.js.txt");
|
||||
await gcTick();
|
||||
const text = fs.readFileSync(file, "utf8");
|
||||
await gcTick();
|
||||
const resp = await fetch("https://example.com");
|
||||
await gcTick();
|
||||
|
||||
expect(await Bun.write("/tmp/fetch.js.out", resp)).toBe(text.length);
|
||||
await gcTick();
|
||||
expect(await Bun.file("/tmp/fetch.js.out").text()).toBe(text);
|
||||
await gcTick();
|
||||
});
|
||||
|
||||
it("Response -> Bun.file -> Response -> text", async () => {
|
||||
await gcTick();
|
||||
const file = path.join(import.meta.dir, "fetch.js.txt");
|
||||
await gcTick();
|
||||
const text = fs.readFileSync(file, "utf8");
|
||||
await gcTick();
|
||||
const response = new Response(Bun.file(file));
|
||||
await gcTick();
|
||||
const response2 = response.clone();
|
||||
await gcTick();
|
||||
expect(await response2.text()).toBe(text);
|
||||
await gcTick();
|
||||
});
|
||||
|
||||
// If you write nothing to a file, it shouldn't modify it
|
||||
// If you want to truncate a file, it should be more explicit
|
||||
it("Bun.write('output.html', '')", async () => {
|
||||
await Bun.write("/tmp/output.html", "lalalala");
|
||||
expect(await Bun.write("/tmp/output.html", "")).toBe(0);
|
||||
expect(await Bun.file("/tmp/output.html").text()).toBe("lalalala");
|
||||
});
|
||||
|
||||
// Since Bun.file is resolved lazily, this needs to specifically be checked
|
||||
it("Bun.write('output.html', HTMLRewriter.transform(Bun.file)))", async () => {
|
||||
var rewriter = new HTMLRewriter();
|
||||
rewriter.on("div", {
|
||||
element(element) {
|
||||
element.setInnerContent("<blink>it worked!</blink>", { html: true });
|
||||
},
|
||||
});
|
||||
await Bun.write("/tmp/html-rewriter.txt.js", "<div>hello</div>");
|
||||
var input = new Response(Bun.file("/tmp/html-rewriter.txt.js"));
|
||||
var output = rewriter.transform(input);
|
||||
const outpath = `/tmp/html-rewriter.${Date.now()}.html`;
|
||||
await Bun.write(outpath, output);
|
||||
expect(await Bun.file(outpath).text()).toBe(
|
||||
"<div><blink>it worked!</blink></div>"
|
||||
);
|
||||
});
|
||||
82
test/bun.js/serve.test.ts
Normal file
82
test/bun.js/serve.test.ts
Normal file
@@ -0,0 +1,82 @@
|
||||
import { file, serve } from "bun";
|
||||
import { expect, it } from "bun:test";
|
||||
import { readFileSync } from "fs";
|
||||
import { resolve } from "path";
|
||||
|
||||
var port = 40000;
|
||||
|
||||
it("should work for a hello world", async () => {
|
||||
const server = serve({
|
||||
port: port++,
|
||||
fetch(req) {
|
||||
return new Response(`Hello, world!`);
|
||||
},
|
||||
});
|
||||
const response = await fetch(`http://localhost:${server.port}`);
|
||||
expect(await response.text()).toBe("Hello, world!");
|
||||
server.stop();
|
||||
});
|
||||
|
||||
it("should work for a file", async () => {
|
||||
const fixture = resolve(import.meta.dir, "./fetch.js.txt");
|
||||
const textToExpect = readFileSync(fixture, "utf-8");
|
||||
|
||||
const server = serve({
|
||||
port: port++,
|
||||
fetch(req) {
|
||||
return new Response(file(fixture));
|
||||
},
|
||||
});
|
||||
const response = await fetch(`http://localhost:${server.port}`);
|
||||
expect(await response.text()).toBe(textToExpect);
|
||||
server.stop();
|
||||
});
|
||||
|
||||
it("fetch should work with headers", async () => {
|
||||
const fixture = resolve(import.meta.dir, "./fetch.js.txt");
|
||||
|
||||
const server = serve({
|
||||
port: port++,
|
||||
fetch(req) {
|
||||
if (req.headers.get("X-Foo") !== "bar") {
|
||||
return new Response("X-Foo header not set", { status: 500 });
|
||||
}
|
||||
return new Response(file(fixture), {
|
||||
headers: { "X-Both-Ways": "1" },
|
||||
});
|
||||
},
|
||||
});
|
||||
const response = await fetch(`http://localhost:${server.port}`, {
|
||||
headers: {
|
||||
"X-Foo": "bar",
|
||||
},
|
||||
});
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.headers.get("X-Both-Ways")).toBe("1");
|
||||
server.stop();
|
||||
});
|
||||
|
||||
var count = 200;
|
||||
it(`should work for a file ${count} times`, async () => {
|
||||
const fixture = resolve(import.meta.dir, "./fetch.js.txt");
|
||||
const textToExpect = readFileSync(fixture, "utf-8");
|
||||
var ran = 0;
|
||||
const server = serve({
|
||||
port: port++,
|
||||
async fetch(req) {
|
||||
return new Response(file(fixture));
|
||||
},
|
||||
});
|
||||
|
||||
// this gets stuck if run about 200 times awaiting all the promises
|
||||
// when the promises are run altogether, instead of one at a time
|
||||
// it's hard to say if this only happens here due to some weird stuff with the test runner
|
||||
// or if it's "real" issue
|
||||
for (let i = 0; i < count; i++) {
|
||||
const response = await fetch(`http://localhost:${server.port}`);
|
||||
expect(await response.text()).toBe(textToExpect);
|
||||
}
|
||||
|
||||
server.stop();
|
||||
});
|
||||
35
test/bun.js/setInterval.test.js
Normal file
35
test/bun.js/setInterval.test.js
Normal file
@@ -0,0 +1,35 @@
|
||||
import { it, expect } from "bun:test";
|
||||
|
||||
it("setInterval", async () => {
|
||||
var counter = 0;
|
||||
var start;
|
||||
const result = await new Promise((resolve, reject) => {
|
||||
start = performance.now();
|
||||
|
||||
var id = setInterval(() => {
|
||||
counter++;
|
||||
if (counter === 10) {
|
||||
resolve(counter);
|
||||
clearInterval(id);
|
||||
}
|
||||
}, 1);
|
||||
});
|
||||
|
||||
expect(result).toBe(10);
|
||||
expect(performance.now() - start >= 10).toBe(true);
|
||||
});
|
||||
|
||||
it("clearInterval", async () => {
|
||||
var called = false;
|
||||
const id = setInterval(() => {
|
||||
called = true;
|
||||
expect(false).toBe(true);
|
||||
}, 1);
|
||||
clearInterval(id);
|
||||
await new Promise((resolve, reject) => {
|
||||
setInterval(() => {
|
||||
resolve();
|
||||
}, 10);
|
||||
});
|
||||
expect(called).toBe(false);
|
||||
});
|
||||
39
test/bun.js/setTimeout.test.js
Normal file
39
test/bun.js/setTimeout.test.js
Normal file
@@ -0,0 +1,39 @@
|
||||
import { it, expect } from "bun:test";
|
||||
|
||||
it("setTimeout", async () => {
|
||||
var lastID = -1;
|
||||
const result = await new Promise((resolve, reject) => {
|
||||
var numbers = [];
|
||||
|
||||
for (let i = 1; i < 100; i++) {
|
||||
const id = setTimeout(() => {
|
||||
numbers.push(i);
|
||||
if (i === 99) {
|
||||
resolve(numbers);
|
||||
}
|
||||
}, i);
|
||||
expect(id > lastID).toBe(true);
|
||||
lastID = id;
|
||||
}
|
||||
});
|
||||
|
||||
for (let j = 0; j < result.length; j++) {
|
||||
expect(result[j]).toBe(j + 1);
|
||||
}
|
||||
expect(result.length).toBe(99);
|
||||
});
|
||||
|
||||
it("clearTimeout", async () => {
|
||||
var called = false;
|
||||
const id = setTimeout(() => {
|
||||
called = true;
|
||||
expect(false).toBe(true);
|
||||
}, 1);
|
||||
clearTimeout(id);
|
||||
await new Promise((resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
resolve();
|
||||
}, 10);
|
||||
});
|
||||
expect(called).toBe(false);
|
||||
});
|
||||
10
test/bun.js/shadow.test.js
Normal file
10
test/bun.js/shadow.test.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import { describe, it, expect } from "bun:test";
|
||||
|
||||
it("shadow realm works", () => {
|
||||
const red = new ShadowRealm();
|
||||
globalThis.someValue = 1;
|
||||
// Affects only the ShadowRealm's global
|
||||
const result = red.evaluate("globalThis.someValue = 2;");
|
||||
expect(globalThis.someValue).toBe(1);
|
||||
expect(result).toBe(2);
|
||||
});
|
||||
10
test/bun.js/sleep.js
Normal file
10
test/bun.js/sleep.js
Normal file
@@ -0,0 +1,10 @@
|
||||
const interval = 0.01;
|
||||
const now = performance.now();
|
||||
console.time("Slept");
|
||||
Bun.sleepSync(interval);
|
||||
const elapsed = performance.now() - now;
|
||||
if (elapsed < interval) {
|
||||
throw new Error("Didn't sleep");
|
||||
}
|
||||
|
||||
console.timeEnd("Slept");
|
||||
74
test/bun.js/solid-dom-fixtures/SVG/code.js
Normal file
74
test/bun.js/solid-dom-fixtures/SVG/code.js
Normal file
@@ -0,0 +1,74 @@
|
||||
const template = (
|
||||
<svg width="400" height="180">
|
||||
<rect
|
||||
stroke-width="2"
|
||||
x="50"
|
||||
y="20"
|
||||
rx="20"
|
||||
ry="20"
|
||||
width="150"
|
||||
height="150"
|
||||
style="fill:red;stroke:black;stroke-width:5;opacity:0.5"
|
||||
/>
|
||||
<linearGradient gradientTransform="rotate(25)">
|
||||
<stop offset="0%"></stop>
|
||||
</linearGradient>
|
||||
</svg>
|
||||
);
|
||||
|
||||
const template2 = (
|
||||
<svg width="400" height="180">
|
||||
<rect
|
||||
className={state.name}
|
||||
stroke-width={state.width}
|
||||
x={state.x}
|
||||
y={state.y}
|
||||
rx="20"
|
||||
ry="20"
|
||||
width="150"
|
||||
height="150"
|
||||
style={{
|
||||
fill: "red",
|
||||
stroke: "black",
|
||||
"stroke-width": props.stroke,
|
||||
opacity: 0.5,
|
||||
}}
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
|
||||
const template3 = (
|
||||
<svg width="400" height="180">
|
||||
<rect {...props} />
|
||||
</svg>
|
||||
);
|
||||
|
||||
const template4 = <rect x="50" y="20" width="150" height="150" />;
|
||||
|
||||
const template5 = (
|
||||
<>
|
||||
<rect x="50" y="20" width="150" height="150" />
|
||||
</>
|
||||
);
|
||||
|
||||
const template6 = (
|
||||
<Component>
|
||||
<rect x="50" y="20" width="150" height="150" />
|
||||
</Component>
|
||||
);
|
||||
|
||||
const template7 = (
|
||||
<svg viewBox={"0 0 160 40"} xmlns="http://www.w3.org/2000/svg">
|
||||
<a xlink:href={url}>
|
||||
<text x="10" y="25">
|
||||
MDN Web Docs
|
||||
</text>
|
||||
</a>
|
||||
</svg>
|
||||
);
|
||||
|
||||
const template8 = (
|
||||
<svg viewBox={"0 0 160 40"} xmlns="http://www.w3.org/2000/svg">
|
||||
<text x="10" y="25" textContent={text} />
|
||||
</svg>
|
||||
);
|
||||
33
test/bun.js/solid-dom-fixtures/SVG/output.bun.js
Normal file
33
test/bun.js/solid-dom-fixtures/SVG/output.bun.js
Normal file
@@ -0,0 +1,33 @@
|
||||
var _tmpl$1 = _template$('<svg width="400" height="180"><rect stroke-width="2" x="50" y="20" rx="20" ry="20" width="150" height="150"/><linearGradient gradientTransform="rotate(25)"><stop offset="0%"/></linearGradient></svg>', 4), _tmpl$2 = _template$('<svg width="400" height="180"><rect rx="20" ry="20" width="150" height="150"/></svg>', 2), _tmpl$3 = _template$('<svg width="400" height="180"><rect/></svg>', 2), _tmpl$4 = _template$('<rect x="50" y="20" width="150" height="150"/>', 0), _tmpl$5 = _template$('<svg viewBox="0 0 160 40" xmlns="http://www.w3.org/2000/svg"><a><text x="10" y="25">MDN Web Docs</text></a></svg>', 6), _tmpl$6 = _template$('<svg viewBox="0 0 160 40" xmlns="http://www.w3.org/2000/svg"><text x="10" y="25"/></svg>', 2);
|
||||
const template = _tmpl$1.cloneNode(true);
|
||||
const template2 = () => {
|
||||
var _el = _tmpl$1.cloneNode(true);
|
||||
effect(() => {
|
||||
return setAttribute(_el, "className", state.name);
|
||||
});
|
||||
effect(() => {
|
||||
return setAttribute(_el, "stroke-width", state.width);
|
||||
});
|
||||
effect(() => {
|
||||
return setAttribute(_el, "x", state.x);
|
||||
});
|
||||
effect(() => {
|
||||
return setAttribute(_el, "y", state.y);
|
||||
});
|
||||
;
|
||||
return _el;
|
||||
};
|
||||
const template3 = _tmpl$3.cloneNode(true);
|
||||
const template4 = _tmpl$4.cloneNode(true);
|
||||
const template5 = ;
|
||||
const template6 = createComponent(Component, {});
|
||||
const template7 = () => {
|
||||
var _el = _tmpl$4.cloneNode(true);
|
||||
setAttribute(_el, "xlink:href", url);
|
||||
return _el;
|
||||
};
|
||||
const template8 = () => {
|
||||
var _el = _tmpl$5.cloneNode(true);
|
||||
setAttribute(_el, "textContent", text);
|
||||
return _el;
|
||||
};
|
||||
108
test/bun.js/solid-dom-fixtures/SVG/output.js
Normal file
108
test/bun.js/solid-dom-fixtures/SVG/output.js
Normal file
@@ -0,0 +1,108 @@
|
||||
import { template as _$template } from "r-dom";
|
||||
import { setAttributeNS as _$setAttributeNS } from "r-dom";
|
||||
import { createComponent as _$createComponent } from "r-dom";
|
||||
import { spread as _$spread } from "r-dom";
|
||||
import { setAttribute as _$setAttribute } from "r-dom";
|
||||
import { effect as _$effect } from "r-dom";
|
||||
|
||||
const _tmpl$ = /*#__PURE__*/ _$template(
|
||||
`<svg width="400" height="180"><rect stroke-width="2" x="50" y="20" rx="20" ry="20" width="150" height="150" style="fill:red;stroke:black;stroke-width:5;opacity:0.5"></rect><linearGradient gradientTransform="rotate(25)"><stop offset="0%"></stop></linearGradient></svg>`,
|
||||
8
|
||||
),
|
||||
_tmpl$2 = /*#__PURE__*/ _$template(
|
||||
`<svg width="400" height="180"><rect rx="20" ry="20" width="150" height="150"></rect></svg>`,
|
||||
4
|
||||
),
|
||||
_tmpl$3 = /*#__PURE__*/ _$template(
|
||||
`<svg width="400" height="180"><rect></rect></svg>`,
|
||||
4
|
||||
),
|
||||
_tmpl$4 = /*#__PURE__*/ _$template(
|
||||
`<svg><rect x="50" y="20" width="150" height="150"></rect></svg>`,
|
||||
4,
|
||||
true
|
||||
),
|
||||
_tmpl$5 = /*#__PURE__*/ _$template(
|
||||
`<svg viewBox="0 0 160 40" xmlns="http://www.w3.org/2000/svg"><a><text x="10" y="25">MDN Web Docs</text></a></svg>`,
|
||||
6
|
||||
),
|
||||
_tmpl$6 = /*#__PURE__*/ _$template(
|
||||
`<svg viewBox="0 0 160 40" xmlns="http://www.w3.org/2000/svg"><text x="10" y="25"></text></svg>`,
|
||||
4
|
||||
);
|
||||
|
||||
const template = _tmpl$.cloneNode(true);
|
||||
|
||||
const template2 = (() => {
|
||||
const _el$2 = _tmpl$2.cloneNode(true),
|
||||
_el$3 = _el$2.firstChild;
|
||||
|
||||
_el$3.style.setProperty("fill", "red");
|
||||
|
||||
_el$3.style.setProperty("stroke", "black");
|
||||
|
||||
_el$3.style.setProperty("opacity", "0.5");
|
||||
|
||||
_$effect(
|
||||
(_p$) => {
|
||||
const _v$ = state.name,
|
||||
_v$2 = state.width,
|
||||
_v$3 = state.x,
|
||||
_v$4 = state.y,
|
||||
_v$5 = props.stroke;
|
||||
_v$ !== _p$._v$ && _$setAttribute(_el$3, "class", (_p$._v$ = _v$));
|
||||
_v$2 !== _p$._v$2 &&
|
||||
_$setAttribute(_el$3, "stroke-width", (_p$._v$2 = _v$2));
|
||||
_v$3 !== _p$._v$3 && _$setAttribute(_el$3, "x", (_p$._v$3 = _v$3));
|
||||
_v$4 !== _p$._v$4 && _$setAttribute(_el$3, "y", (_p$._v$4 = _v$4));
|
||||
_v$5 !== _p$._v$5 &&
|
||||
_el$3.style.setProperty("stroke-width", (_p$._v$5 = _v$5));
|
||||
return _p$;
|
||||
},
|
||||
{
|
||||
_v$: undefined,
|
||||
_v$2: undefined,
|
||||
_v$3: undefined,
|
||||
_v$4: undefined,
|
||||
_v$5: undefined,
|
||||
}
|
||||
);
|
||||
|
||||
return _el$2;
|
||||
})();
|
||||
|
||||
const template3 = (() => {
|
||||
const _el$4 = _tmpl$3.cloneNode(true),
|
||||
_el$5 = _el$4.firstChild;
|
||||
|
||||
_$spread(_el$5, props, true, false);
|
||||
|
||||
return _el$4;
|
||||
})();
|
||||
|
||||
const template4 = _tmpl$4.cloneNode(true);
|
||||
|
||||
const template5 = _tmpl$4.cloneNode(true);
|
||||
|
||||
const template6 = _$createComponent(Component, {
|
||||
get children() {
|
||||
return _tmpl$4.cloneNode(true);
|
||||
},
|
||||
});
|
||||
|
||||
const template7 = (() => {
|
||||
const _el$9 = _tmpl$5.cloneNode(true),
|
||||
_el$10 = _el$9.firstChild;
|
||||
|
||||
_$setAttributeNS(_el$10, "http://www.w3.org/1999/xlink", "xlink:href", url);
|
||||
|
||||
return _el$9;
|
||||
})();
|
||||
|
||||
const template8 = (() => {
|
||||
const _el$11 = _tmpl$6.cloneNode(true),
|
||||
_el$12 = _el$11.firstChild;
|
||||
|
||||
_el$12.textContent = text;
|
||||
return _el$11;
|
||||
})();
|
||||
115
test/bun.js/solid-dom-fixtures/attributeExpressions/code.js
Normal file
115
test/bun.js/solid-dom-fixtures/attributeExpressions/code.js
Normal file
@@ -0,0 +1,115 @@
|
||||
const selected = true;
|
||||
let id = "my-h1";
|
||||
let link;
|
||||
const template = (
|
||||
<div
|
||||
id="main"
|
||||
{...results}
|
||||
classList={{ selected: unknown }}
|
||||
style={{ color }}
|
||||
>
|
||||
<h1
|
||||
class="base"
|
||||
id={id}
|
||||
{...results()}
|
||||
disabled
|
||||
readonly=""
|
||||
title={welcoming()}
|
||||
style={{ "background-color": color(), "margin-right": "40px" }}
|
||||
classList={{ dynamic: dynamic(), selected }}
|
||||
>
|
||||
<a href={"/"} ref={link} classList={{ "ccc ddd": true }} readonly={value}>
|
||||
Welcome
|
||||
</a>
|
||||
</h1>
|
||||
</div>
|
||||
);
|
||||
|
||||
const template2 = (
|
||||
<div {...getProps("test")}>
|
||||
<div textContent={rowId} />
|
||||
<div textContent={row.label} />
|
||||
<div innerHTML={"<div/>"} />
|
||||
</div>
|
||||
);
|
||||
|
||||
const template3 = (
|
||||
<div
|
||||
id={/*@once*/ state.id}
|
||||
style={/*@once*/ { "background-color": state.color }}
|
||||
name={state.name}
|
||||
textContent={/*@once*/ state.content}
|
||||
/>
|
||||
);
|
||||
|
||||
const template4 = (
|
||||
<div class="hi" className={state.class} classList={{ "ccc:ddd": true }} />
|
||||
);
|
||||
|
||||
const template5 = <div class="a" className="b"></div>;
|
||||
|
||||
const template6 = <div style={someStyle()} textContent="Hi" />;
|
||||
|
||||
const template7 = (
|
||||
<div
|
||||
style={{
|
||||
"background-color": color(),
|
||||
"margin-right": "40px",
|
||||
...props.style,
|
||||
}}
|
||||
style:padding-top={props.top}
|
||||
class:my-class={props.active}
|
||||
/>
|
||||
);
|
||||
|
||||
let refTarget;
|
||||
const template8 = <div ref={refTarget} />;
|
||||
|
||||
const template9 = <div ref={(e) => console.log(e)} />;
|
||||
|
||||
const template10 = <div ref={refFactory()} />;
|
||||
|
||||
const template11 = <div use:something use:another={thing} use:zero={0} />;
|
||||
|
||||
const template12 = <div prop:htmlFor={thing} />;
|
||||
|
||||
const template13 = <input type="checkbox" checked={true} />;
|
||||
|
||||
const template14 = <input type="checkbox" checked={state.visible} />;
|
||||
|
||||
const template15 = <div class="`a">`$`</div>;
|
||||
|
||||
const template16 = (
|
||||
<button
|
||||
class="static"
|
||||
classList={{
|
||||
hi: "k",
|
||||
}}
|
||||
type="button"
|
||||
>
|
||||
Write
|
||||
</button>
|
||||
);
|
||||
|
||||
const template17 = (
|
||||
<button
|
||||
classList={{
|
||||
a: true,
|
||||
b: true,
|
||||
c: true,
|
||||
}}
|
||||
onClick={increment}
|
||||
>
|
||||
Hi
|
||||
</button>
|
||||
);
|
||||
|
||||
const template18 = (
|
||||
<div
|
||||
{...{
|
||||
get [key()]() {
|
||||
return props.value;
|
||||
},
|
||||
}}
|
||||
/>
|
||||
);
|
||||
@@ -0,0 +1,155 @@
|
||||
var _tmpl = _template$(
|
||||
'<div id="main"><h1 class="base" disabled readonly><a href="/">Welcome</a></h1></div>',
|
||||
6
|
||||
),
|
||||
_tmpl$2 = _template$(
|
||||
'<div><div/><div/><div innerHTML="<div/>"/></div>',
|
||||
2
|
||||
),
|
||||
_tmpl$2 = _template$("<div/>", 0),
|
||||
_tmpl$3 = _template$('<div class="hi"/>', 0),
|
||||
_tmpl$5 = _template$('<div class="a" class="b"/>', 0),
|
||||
_tmpl$5 = _template$('<div textContent="Hi"/>', 0),
|
||||
_tmpl$6 = _template$("<div use:something use:zero=0/>", 0),
|
||||
_tmpl$8 = _template$('<input type="checkbox" checked/>', 0),
|
||||
_tmpl$8 = _template$('<input type="checkbox"/>', 0),
|
||||
_tmpl$10 = _template$('<div class="`a">`$`</div>', 2),
|
||||
_tmpl$10 = _template$(
|
||||
'<button class="static" type="button">Write</button>',
|
||||
2
|
||||
),
|
||||
_tmpl$11 = _template$("<button>Hi</button>", 2);
|
||||
const selected = true;
|
||||
let id = "my-h1";
|
||||
let link;
|
||||
const template = () => {
|
||||
var _el = _tmpl.cloneNode(true),
|
||||
_el$1 = _el.firstChild,
|
||||
_el$2 = _el$1.nextSibling;
|
||||
effect(() => {
|
||||
return setAttribute(_el, "classList", { selected: unknown });
|
||||
});
|
||||
setAttribute(_el$1, "id", id);
|
||||
effect(() => {
|
||||
return setAttribute(_el$1, "title", welcoming());
|
||||
});
|
||||
effect(() => {
|
||||
return setAttribute(_el$1, "classList", { dynamic: dynamic(), selected });
|
||||
});
|
||||
setAttribute(_el$2, "ref", link);
|
||||
effect(() => {
|
||||
return setAttribute(_el$2, "classList", { "ccc ddd": true });
|
||||
});
|
||||
setAttribute(_el$2, "readonly", value);
|
||||
return _el;
|
||||
};
|
||||
const template2 = () => {
|
||||
var _el = _tmpl$1.cloneNode(true),
|
||||
_el$1 = _el.firstChild;
|
||||
setAttribute(_el, "textContent", rowId);
|
||||
effect(() => {
|
||||
return setAttribute(_el$1, "textContent", row.label);
|
||||
});
|
||||
return _el;
|
||||
};
|
||||
const template3 = () => {
|
||||
var _el = _tmpl$2.cloneNode(true);
|
||||
effect(() => {
|
||||
return setAttribute(_el, "id", state.id);
|
||||
});
|
||||
effect(() => {
|
||||
return setAttribute(_el, "name", state.name);
|
||||
});
|
||||
effect(() => {
|
||||
return setAttribute(_el, "textContent", state.content);
|
||||
});
|
||||
return _el;
|
||||
};
|
||||
const template4 = () => {
|
||||
var _el = _tmpl$3.cloneNode(true);
|
||||
effect(() => {
|
||||
return setAttribute(_el, "className", state.class);
|
||||
});
|
||||
effect(() => {
|
||||
return setAttribute(_el, "classList", { "ccc:ddd": true });
|
||||
});
|
||||
return _el;
|
||||
};
|
||||
const template5 = _tmpl$5.cloneNode(true);
|
||||
const template6 = () => {
|
||||
var _el = _tmpl$5.cloneNode(true);
|
||||
return _el;
|
||||
};
|
||||
const template7 = () => {
|
||||
var _el = _tmpl$2.cloneNode(true);
|
||||
effect(() => {
|
||||
return setAttribute(_el, "style:padding-top", props.top);
|
||||
});
|
||||
effect(() => {
|
||||
return setAttribute(_el, "class:my-class", props.active);
|
||||
});
|
||||
return _el;
|
||||
};
|
||||
let refTarget;
|
||||
const template8 = () => {
|
||||
var _el = _tmpl$2.cloneNode(true);
|
||||
setAttribute(_el, "ref", refTarget);
|
||||
return _el;
|
||||
};
|
||||
const template9 = () => {
|
||||
var _el = _tmpl$2.cloneNode(true);
|
||||
effect(() => {
|
||||
return setAttribute(_el, "ref", (e) => console.log(e));
|
||||
});
|
||||
return _el;
|
||||
};
|
||||
const template10 = () => {
|
||||
var _el = _tmpl$2.cloneNode(true);
|
||||
effect(() => {
|
||||
return setAttribute(_el, "ref", refFactory());
|
||||
});
|
||||
return _el;
|
||||
};
|
||||
const template11 = () => {
|
||||
var _el = _tmpl$6.cloneNode(true);
|
||||
setAttribute(_el, "use:another", thing);
|
||||
return _el;
|
||||
};
|
||||
const template12 = () => {
|
||||
var _el = _tmpl$2.cloneNode(true);
|
||||
setAttribute(_el, "prop:htmlFor", thing);
|
||||
return _el;
|
||||
};
|
||||
const template13 = _tmpl$8.cloneNode(true);
|
||||
const template14 = () => {
|
||||
var _el = _tmpl$8.cloneNode(true);
|
||||
effect(() => {
|
||||
return setAttribute(_el, "checked", state.visible);
|
||||
});
|
||||
return _el;
|
||||
};
|
||||
const template15 = _tmpl$10.cloneNode(true);
|
||||
const template16 = () => {
|
||||
var _el = _tmpl$10.cloneNode(true);
|
||||
effect(() => {
|
||||
return setAttribute(_el, "classList", {
|
||||
hi: "k",
|
||||
});
|
||||
});
|
||||
return _el;
|
||||
};
|
||||
const template17 = () => {
|
||||
var _el = _tmpl$11.cloneNode(true);
|
||||
effect(() => {
|
||||
return setAttribute(_el, "classList", {
|
||||
a: true,
|
||||
b: true,
|
||||
c: true,
|
||||
});
|
||||
});
|
||||
effect(() => {
|
||||
return (_el.$$click = increment);
|
||||
});
|
||||
return _el;
|
||||
};
|
||||
const template18 = _tmpl$2.cloneNode(true);
|
||||
241
test/bun.js/solid-dom-fixtures/attributeExpressions/output.js
Normal file
241
test/bun.js/solid-dom-fixtures/attributeExpressions/output.js
Normal file
@@ -0,0 +1,241 @@
|
||||
const _tmpl$ = /*#__PURE__*/ _$template(
|
||||
`<div id="main"><h1 class="base selected" id="my-h1" disabled readonly=""><a href="/">Welcome</a></h1></div>`,
|
||||
6
|
||||
),
|
||||
_tmpl$2 = /*#__PURE__*/ _$template(
|
||||
`<div><div></div><div> </div><div></div></div>`,
|
||||
8
|
||||
),
|
||||
_tmpl$3 = /*#__PURE__*/ _$template(`<div></div>`, 2),
|
||||
_tmpl$4 = /*#__PURE__*/ _$template(`<div class="a b"></div>`, 2),
|
||||
_tmpl$5 = /*#__PURE__*/ _$template(`<input type="checkbox">`, 1),
|
||||
_tmpl$6 = /*#__PURE__*/ _$template(`<div class="\`a">\`$\`</div>`, 2),
|
||||
_tmpl$7 = /*#__PURE__*/ _$template(
|
||||
`<button class="static hi" type="button">Write</button>`,
|
||||
2
|
||||
),
|
||||
_tmpl$8 = /*#__PURE__*/ _$template(`<button class="a b c">Hi</button>`, 2);
|
||||
|
||||
const selected = true;
|
||||
let id = "my-h1";
|
||||
let link;
|
||||
|
||||
const template = (() => {
|
||||
const _el$ = _tmpl$.cloneNode(true),
|
||||
_el$2 = _el$.firstChild,
|
||||
_el$3 = _el$2.firstChild;
|
||||
|
||||
_$spread(_el$, results, false, true);
|
||||
|
||||
_el$.classList.toggle("selected", unknown);
|
||||
|
||||
_el$.style.setProperty("color", color);
|
||||
|
||||
_$spread(_el$2, results, false, true);
|
||||
|
||||
_el$2.style.setProperty("margin-right", "40px");
|
||||
|
||||
const _ref$ = link;
|
||||
typeof _ref$ === "function" ? _ref$(_el$3) : (link = _el$3);
|
||||
|
||||
_$classList(_el$3, {
|
||||
"ccc ddd": true,
|
||||
});
|
||||
|
||||
_el$3.readOnly = value;
|
||||
|
||||
_$effect(
|
||||
(_p$) => {
|
||||
const _v$ = welcoming(),
|
||||
_v$2 = color(),
|
||||
_v$3 = !!dynamic();
|
||||
|
||||
_v$ !== _p$._v$ && _$setAttribute(_el$2, "title", (_p$._v$ = _v$));
|
||||
_v$2 !== _p$._v$2 &&
|
||||
_el$2.style.setProperty("background-color", (_p$._v$2 = _v$2));
|
||||
_v$3 !== _p$._v$3 && _el$2.classList.toggle("dynamic", (_p$._v$3 = _v$3));
|
||||
return _p$;
|
||||
},
|
||||
{
|
||||
_v$: undefined,
|
||||
_v$2: undefined,
|
||||
_v$3: undefined,
|
||||
}
|
||||
);
|
||||
|
||||
return _el$;
|
||||
})();
|
||||
|
||||
const template2 = (() => {
|
||||
const _el$4 = _tmpl$2.cloneNode(true),
|
||||
_el$5 = _el$4.firstChild,
|
||||
_el$6 = _el$5.nextSibling,
|
||||
_el$7 = _el$6.firstChild,
|
||||
_el$8 = _el$6.nextSibling;
|
||||
|
||||
_$spread(_el$4, () => getProps("test"), false, true);
|
||||
|
||||
_el$5.textContent = rowId;
|
||||
_el$8.innerHTML = "<div/>";
|
||||
|
||||
_$effect(() => (_el$7.data = row.label));
|
||||
|
||||
return _el$4;
|
||||
})();
|
||||
|
||||
const template3 = (() => {
|
||||
const _el$9 = _tmpl$3.cloneNode(true);
|
||||
|
||||
_$setAttribute(_el$9, "id", state.id);
|
||||
|
||||
_el$9.style.setProperty("background-color", state.color);
|
||||
|
||||
_el$9.textContent = state.content;
|
||||
|
||||
_$effect(() => _$setAttribute(_el$9, "name", state.name));
|
||||
|
||||
return _el$9;
|
||||
})();
|
||||
|
||||
const template4 = (() => {
|
||||
const _el$10 = _tmpl$3.cloneNode(true);
|
||||
|
||||
_$classList(_el$10, {
|
||||
"ccc:ddd": true,
|
||||
});
|
||||
|
||||
_$effect(() => _$className(_el$10, `hi ${state.class || ""}`));
|
||||
|
||||
return _el$10;
|
||||
})();
|
||||
|
||||
const template5 = _tmpl$4.cloneNode(true);
|
||||
|
||||
const template6 = (() => {
|
||||
const _el$12 = _tmpl$3.cloneNode(true);
|
||||
|
||||
_el$12.textContent = "Hi";
|
||||
|
||||
_$effect((_$p) => _$style(_el$12, someStyle(), _$p));
|
||||
|
||||
return _el$12;
|
||||
})();
|
||||
|
||||
const template7 = (() => {
|
||||
const _el$13 = _tmpl$3.cloneNode(true);
|
||||
|
||||
_$effect(
|
||||
(_p$) => {
|
||||
const _v$4 = {
|
||||
"background-color": color(),
|
||||
"margin-right": "40px",
|
||||
...props.style,
|
||||
},
|
||||
_v$5 = props.top,
|
||||
_v$6 = !!props.active;
|
||||
|
||||
_p$._v$4 = _$style(_el$13, _v$4, _p$._v$4);
|
||||
_v$5 !== _p$._v$5 &&
|
||||
_el$13.style.setProperty("padding-top", (_p$._v$5 = _v$5));
|
||||
_v$6 !== _p$._v$6 &&
|
||||
_el$13.classList.toggle("my-class", (_p$._v$6 = _v$6));
|
||||
return _p$;
|
||||
},
|
||||
{
|
||||
_v$4: undefined,
|
||||
_v$5: undefined,
|
||||
_v$6: undefined,
|
||||
}
|
||||
);
|
||||
|
||||
return _el$13;
|
||||
})();
|
||||
|
||||
let refTarget;
|
||||
|
||||
const template8 = (() => {
|
||||
const _el$14 = _tmpl$3.cloneNode(true);
|
||||
|
||||
const _ref$2 = refTarget;
|
||||
typeof _ref$2 === "function" ? _ref$2(_el$14) : (refTarget = _el$14);
|
||||
return _el$14;
|
||||
})();
|
||||
|
||||
const template9 = (() => {
|
||||
const _el$15 = _tmpl$3.cloneNode(true);
|
||||
|
||||
((e) => console.log(e))(_el$15);
|
||||
|
||||
return _el$15;
|
||||
})();
|
||||
|
||||
const template10 = (() => {
|
||||
const _el$16 = _tmpl$3.cloneNode(true);
|
||||
|
||||
const _ref$3 = refFactory();
|
||||
|
||||
typeof _ref$3 === "function" && _ref$3(_el$16);
|
||||
return _el$16;
|
||||
})();
|
||||
|
||||
const template11 = (() => {
|
||||
const _el$17 = _tmpl$3.cloneNode(true);
|
||||
|
||||
zero(_el$17, () => 0);
|
||||
another(_el$17, () => thing);
|
||||
something(_el$17, () => true);
|
||||
return _el$17;
|
||||
})();
|
||||
|
||||
const template12 = (() => {
|
||||
const _el$18 = _tmpl$3.cloneNode(true);
|
||||
|
||||
_el$18.htmlFor = thing;
|
||||
return _el$18;
|
||||
})();
|
||||
|
||||
const template13 = (() => {
|
||||
const _el$19 = _tmpl$5.cloneNode(true);
|
||||
|
||||
_el$19.checked = true;
|
||||
return _el$19;
|
||||
})();
|
||||
|
||||
const template14 = (() => {
|
||||
const _el$20 = _tmpl$5.cloneNode(true);
|
||||
|
||||
_$effect(() => (_el$20.checked = state.visible));
|
||||
|
||||
return _el$20;
|
||||
})();
|
||||
|
||||
const template15 = _tmpl$6.cloneNode(true);
|
||||
|
||||
const template16 = _tmpl$7.cloneNode(true);
|
||||
|
||||
const template17 = (() => {
|
||||
const _el$23 = _tmpl$8.cloneNode(true);
|
||||
|
||||
_$addEventListener(_el$23, "click", increment, true);
|
||||
|
||||
return _el$23;
|
||||
})();
|
||||
|
||||
const template18 = (() => {
|
||||
const _el$24 = _tmpl$3.cloneNode(true);
|
||||
|
||||
_$spread(
|
||||
_el$24,
|
||||
() => ({
|
||||
get [key()]() {
|
||||
return props.value;
|
||||
},
|
||||
}),
|
||||
false,
|
||||
false
|
||||
);
|
||||
|
||||
return _el$24;
|
||||
})();
|
||||
|
||||
_$delegateEvents(["click"]);
|
||||
161
test/bun.js/solid-dom-fixtures/components/code.js
Normal file
161
test/bun.js/solid-dom-fixtures/components/code.js
Normal file
@@ -0,0 +1,161 @@
|
||||
import { Show } from "somewhere";
|
||||
|
||||
const Child = (props) => {
|
||||
const [s, set] = createSignal();
|
||||
return (
|
||||
<>
|
||||
<div ref={props.ref}>Hello {props.name}</div>
|
||||
<div ref={set}>{props.children}</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const template = (props) => {
|
||||
let childRef;
|
||||
const { content } = props;
|
||||
return (
|
||||
<div>
|
||||
<Child name="John" {...props} ref={childRef} booleanProperty>
|
||||
<div>From Parent</div>
|
||||
</Child>
|
||||
<Child name="Jason" {...dynamicSpread()} ref={props.ref}>
|
||||
{/* Comment Node */}
|
||||
<div>{content}</div>
|
||||
</Child>
|
||||
<Context.Consumer ref={props.consumerRef()}>
|
||||
{(context) => context}
|
||||
</Context.Consumer>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const template2 = (
|
||||
<Child
|
||||
name="Jake"
|
||||
dynamic={state.data}
|
||||
stale={/*@once*/ state.data}
|
||||
handleClick={clickHandler}
|
||||
hyphen-ated={state.data}
|
||||
ref={(el) => (e = el)}
|
||||
/>
|
||||
);
|
||||
|
||||
const template3 = (
|
||||
<Child>
|
||||
<div />
|
||||
<div />
|
||||
<div />
|
||||
After
|
||||
</Child>
|
||||
);
|
||||
|
||||
const [s, set] = createSignal();
|
||||
const template4 = <Child ref={set}>{<div />}</Child>;
|
||||
|
||||
const template5 = <Child dynamic={state.dynamic}>{state.dynamic}</Child>;
|
||||
|
||||
// builtIns
|
||||
const template6 = (
|
||||
<For each={state.list} fallback={<Loading />}>
|
||||
{(item) => <Show when={state.condition}>{item}</Show>}
|
||||
</For>
|
||||
);
|
||||
|
||||
const template7 = (
|
||||
<Child>
|
||||
<div />
|
||||
{state.dynamic}
|
||||
</Child>
|
||||
);
|
||||
|
||||
const template8 = (
|
||||
<Child>
|
||||
{(item) => item}
|
||||
{(item) => item}
|
||||
</Child>
|
||||
);
|
||||
|
||||
const template9 = <_garbage>Hi</_garbage>;
|
||||
|
||||
const template10 = (
|
||||
<div>
|
||||
<Link>new</Link>
|
||||
{" | "}
|
||||
<Link>comments</Link>
|
||||
{" | "}
|
||||
<Link>show</Link>
|
||||
{" | "}
|
||||
<Link>ask</Link>
|
||||
{" | "}
|
||||
<Link>jobs</Link>
|
||||
{" | "}
|
||||
<Link>submit</Link>
|
||||
</div>
|
||||
);
|
||||
|
||||
const template11 = (
|
||||
<div>
|
||||
<Link>new</Link>
|
||||
{" | "}
|
||||
<Link>comments</Link>
|
||||
<Link>show</Link>
|
||||
{" | "}
|
||||
<Link>ask</Link>
|
||||
<Link>jobs</Link>
|
||||
{" | "}
|
||||
<Link>submit</Link>
|
||||
</div>
|
||||
);
|
||||
|
||||
const template12 = (
|
||||
<div>
|
||||
{" | "}
|
||||
<Link>comments</Link>
|
||||
{" | "}
|
||||
{" | "}
|
||||
{" | "}
|
||||
<Link>show</Link>
|
||||
{" | "}
|
||||
</div>
|
||||
);
|
||||
|
||||
class Template13 {
|
||||
render() {
|
||||
<Component prop={this.something} onClick={() => this.shouldStay}>
|
||||
<Nested prop={this.data}>{this.content}</Nested>
|
||||
</Component>;
|
||||
}
|
||||
}
|
||||
|
||||
const Template14 = <Component>{data()}</Component>;
|
||||
|
||||
const Template15 = <Component {...props} />;
|
||||
|
||||
const Template16 = <Component something={something} {...props} />;
|
||||
|
||||
const Template17 = (
|
||||
<Pre>
|
||||
<span>1</span> <span>2</span> <span>3</span>
|
||||
</Pre>
|
||||
);
|
||||
const Template18 = (
|
||||
<Pre>
|
||||
<span>1</span>
|
||||
<span>2</span>
|
||||
<span>3</span>
|
||||
</Pre>
|
||||
);
|
||||
|
||||
const Template19 = <Component {...s.dynamic()} />;
|
||||
|
||||
const Template20 = <Component class={prop.red ? "red" : "green"} />;
|
||||
|
||||
const template21 = (
|
||||
<Component
|
||||
{...{
|
||||
get [key()]() {
|
||||
return props.value;
|
||||
},
|
||||
}}
|
||||
/>
|
||||
);
|
||||
205
test/bun.js/solid-dom-fixtures/components/output.bun.js
Normal file
205
test/bun.js/solid-dom-fixtures/components/output.bun.js
Normal file
@@ -0,0 +1,205 @@
|
||||
var _tmpl = _template$("<div><div>From Parent</div><div</div></div>", 9), _tmpl$1 = _template$("<div> | | | | | </div>", 8), _tmpl$2 = _template$("<div> | | | </div>", 8);
|
||||
import {Show} from "somewhere";
|
||||
const Child = (props) => {
|
||||
const [s, set] = createSignal();
|
||||
return ;
|
||||
};
|
||||
const template = (props) => {
|
||||
let childRef;
|
||||
const { content } = props;
|
||||
return () => {
|
||||
var _tmpl = _tmpl.cloneNode(true);
|
||||
insert(_tmpl, createComponent(Child, {
|
||||
name: "John",
|
||||
ref: childRef,
|
||||
booleanProperty: true
|
||||
}), null);
|
||||
insert(_tmpl, content, null);
|
||||
insert(_tmpl, createComponent(Child, {
|
||||
name: "Jason",
|
||||
ref: props.ref
|
||||
}), null);
|
||||
insert(_tmpl, createComponent(Context.Consumer, {
|
||||
ref: props.consumerRef(),
|
||||
get children: [
|
||||
(context) => context
|
||||
]
|
||||
}), null);
|
||||
return _tmpl;
|
||||
};
|
||||
};
|
||||
const template2 = createComponent(Child, {
|
||||
name: "Jake",
|
||||
dynamic: state.data,
|
||||
stale: state.data,
|
||||
handleClick: clickHandler,
|
||||
"hyphen-ated": state.data,
|
||||
get ref: () => {
|
||||
return (el) => e = el;
|
||||
}
|
||||
});
|
||||
const template3 = createComponent(Child, {
|
||||
get children: [
|
||||
"After"
|
||||
]
|
||||
});
|
||||
const [s, set] = createSignal();
|
||||
const template4 = createComponent(Child, {
|
||||
ref: set
|
||||
});
|
||||
const template5 = createComponent(Child, {
|
||||
dynamic: state.dynamic,
|
||||
get children: [
|
||||
state.dynamic
|
||||
]
|
||||
});
|
||||
const template6 = createComponent(For, {
|
||||
each: state.list,
|
||||
fallback: ,
|
||||
get children: [
|
||||
(item) => createComponent(Show, {
|
||||
when: state.condition,
|
||||
get children: [
|
||||
item
|
||||
]
|
||||
})
|
||||
]
|
||||
});
|
||||
const template7 = createComponent(Child, {
|
||||
get children: [
|
||||
state.dynamic
|
||||
]
|
||||
});
|
||||
const template8 = createComponent(Child, {
|
||||
get children: [
|
||||
(item) => item,
|
||||
(item) => item
|
||||
]
|
||||
});
|
||||
const template9 = createComponent(_garbage, {
|
||||
get children: [
|
||||
"Hi"
|
||||
]
|
||||
});
|
||||
const template10 = () => {
|
||||
var _tmpl$1 = _tmpl$1.cloneNode(true);
|
||||
insert(_tmpl$1, createComponent(Link, {
|
||||
get children: [
|
||||
"new"
|
||||
]
|
||||
}), null);
|
||||
insert(_tmpl$1, createComponent(Link, {
|
||||
get children: [
|
||||
"comments"
|
||||
]
|
||||
}), null);
|
||||
insert(_tmpl$1, createComponent(Link, {
|
||||
get children: [
|
||||
"show"
|
||||
]
|
||||
}), null);
|
||||
insert(_tmpl$1, createComponent(Link, {
|
||||
get children: [
|
||||
"ask"
|
||||
]
|
||||
}), null);
|
||||
insert(_tmpl$1, createComponent(Link, {
|
||||
get children: [
|
||||
"jobs"
|
||||
]
|
||||
}), null);
|
||||
insert(_tmpl$1, createComponent(Link, {
|
||||
get children: [
|
||||
"submit"
|
||||
]
|
||||
}), null);
|
||||
return _tmpl$1;
|
||||
};
|
||||
const template11 = () => {
|
||||
var _tmpl$2 = _tmpl$2.cloneNode(true);
|
||||
insert(_tmpl$2, createComponent(Link, {
|
||||
get children: [
|
||||
"new"
|
||||
]
|
||||
}), null);
|
||||
insert(_tmpl$2, createComponent(Link, {
|
||||
get children: [
|
||||
"comments"
|
||||
]
|
||||
}), null);
|
||||
insert(_tmpl$2, createComponent(Link, {
|
||||
get children: [
|
||||
"show"
|
||||
]
|
||||
}), null);
|
||||
insert(_tmpl$2, createComponent(Link, {
|
||||
get children: [
|
||||
"ask"
|
||||
]
|
||||
}), null);
|
||||
insert(_tmpl$2, createComponent(Link, {
|
||||
get children: [
|
||||
"jobs"
|
||||
]
|
||||
}), null);
|
||||
insert(_tmpl$2, createComponent(Link, {
|
||||
get children: [
|
||||
"submit"
|
||||
]
|
||||
}), null);
|
||||
return _tmpl$2;
|
||||
};
|
||||
const template12 = () => {
|
||||
var _tmpl$1 = _tmpl$1.cloneNode(true);
|
||||
insert(_tmpl$1, createComponent(Link, {
|
||||
get children: [
|
||||
"comments"
|
||||
]
|
||||
}), null);
|
||||
insert(_tmpl$1, createComponent(Link, {
|
||||
get children: [
|
||||
"show"
|
||||
]
|
||||
}), null);
|
||||
return _tmpl$1;
|
||||
};
|
||||
|
||||
class Template13 {
|
||||
render() {
|
||||
createComponent(Component, {
|
||||
prop: this.something,
|
||||
get onClick: () => {
|
||||
return () => this.shouldStay;
|
||||
},
|
||||
get children: [
|
||||
createComponent(Nested, {
|
||||
prop: this.data,
|
||||
get children: [
|
||||
this.content
|
||||
]
|
||||
})
|
||||
]
|
||||
});
|
||||
}
|
||||
}
|
||||
const Template14 = createComponent(Component, {
|
||||
get children: [
|
||||
data()
|
||||
]
|
||||
});
|
||||
const Template15 = createComponent(Component, {});
|
||||
const Template16 = createComponent(Component, {
|
||||
something
|
||||
});
|
||||
const Template17 = createComponent(Pre, {
|
||||
get children: [
|
||||
" ",
|
||||
" "
|
||||
]
|
||||
});
|
||||
const Template18 = createComponent(Pre, {});
|
||||
const Template19 = createComponent(Component, {});
|
||||
const Template20 = createComponent(Component, {
|
||||
class: prop.red ? "red" : "green"
|
||||
});
|
||||
const template21 = createComponent(Component, {});
|
||||
443
test/bun.js/solid-dom-fixtures/components/output.js
Normal file
443
test/bun.js/solid-dom-fixtures/components/output.js
Normal file
@@ -0,0 +1,443 @@
|
||||
import { template as _$template } from "r-dom";
|
||||
import { memo as _$memo } from "r-dom";
|
||||
import { For as _$For } from "r-dom";
|
||||
import { createComponent as _$createComponent } from "r-dom";
|
||||
import { mergeProps as _$mergeProps } from "r-dom";
|
||||
import { insert as _$insert } from "r-dom";
|
||||
|
||||
const _tmpl$ = /*#__PURE__*/ _$template(`<div>Hello </div>`, 2),
|
||||
_tmpl$2 = /*#__PURE__*/ _$template(`<div></div>`, 2),
|
||||
_tmpl$3 = /*#__PURE__*/ _$template(`<div>From Parent</div>`, 2),
|
||||
_tmpl$4 = /*#__PURE__*/ _$template(
|
||||
`<div> | <!> | <!> | <!> | <!> | </div>`,
|
||||
6
|
||||
),
|
||||
_tmpl$5 = /*#__PURE__*/ _$template(`<div> | <!> | <!> | </div>`, 4),
|
||||
_tmpl$6 = /*#__PURE__*/ _$template(`<div> | <!> | | | <!> | </div>`, 4),
|
||||
_tmpl$7 = /*#__PURE__*/ _$template(`<span>1</span>`, 2),
|
||||
_tmpl$8 = /*#__PURE__*/ _$template(`<span>2</span>`, 2),
|
||||
_tmpl$9 = /*#__PURE__*/ _$template(`<span>3</span>`, 2);
|
||||
|
||||
import { Show } from "somewhere";
|
||||
|
||||
const Child = (props) => {
|
||||
const [s, set] = createSignal();
|
||||
return [
|
||||
(() => {
|
||||
const _el$ = _tmpl$.cloneNode(true),
|
||||
_el$2 = _el$.firstChild;
|
||||
|
||||
const _ref$ = props.ref;
|
||||
typeof _ref$ === "function" ? _ref$(_el$) : (props.ref = _el$);
|
||||
|
||||
_$insert(_el$, () => props.name, null);
|
||||
|
||||
return _el$;
|
||||
})(),
|
||||
(() => {
|
||||
const _el$3 = _tmpl$2.cloneNode(true);
|
||||
|
||||
set(_el$3);
|
||||
|
||||
_$insert(_el$3, () => props.children);
|
||||
|
||||
return _el$3;
|
||||
})(),
|
||||
];
|
||||
};
|
||||
|
||||
const template = (props) => {
|
||||
let childRef;
|
||||
const { content } = props;
|
||||
return (() => {
|
||||
const _el$4 = _tmpl$2.cloneNode(true);
|
||||
|
||||
_$insert(
|
||||
_el$4,
|
||||
_$createComponent(
|
||||
Child,
|
||||
_$mergeProps(
|
||||
{
|
||||
name: "John",
|
||||
},
|
||||
props,
|
||||
{
|
||||
ref(r$) {
|
||||
const _ref$2 = childRef;
|
||||
typeof _ref$2 === "function" ? _ref$2(r$) : (childRef = r$);
|
||||
},
|
||||
|
||||
booleanProperty: true,
|
||||
|
||||
get children() {
|
||||
return _tmpl$3.cloneNode(true);
|
||||
},
|
||||
}
|
||||
)
|
||||
),
|
||||
null
|
||||
);
|
||||
|
||||
_$insert(
|
||||
_el$4,
|
||||
_$createComponent(
|
||||
Child,
|
||||
_$mergeProps(
|
||||
{
|
||||
name: "Jason",
|
||||
},
|
||||
dynamicSpread,
|
||||
{
|
||||
ref(r$) {
|
||||
const _ref$3 = props.ref;
|
||||
typeof _ref$3 === "function" ? _ref$3(r$) : (props.ref = r$);
|
||||
},
|
||||
|
||||
get children() {
|
||||
const _el$6 = _tmpl$2.cloneNode(true);
|
||||
|
||||
_$insert(_el$6, content);
|
||||
|
||||
return _el$6;
|
||||
},
|
||||
}
|
||||
)
|
||||
),
|
||||
null
|
||||
);
|
||||
|
||||
_$insert(
|
||||
_el$4,
|
||||
_$createComponent(Context.Consumer, {
|
||||
ref(r$) {
|
||||
const _ref$4 = props.consumerRef();
|
||||
|
||||
typeof _ref$4 === "function" && _ref$4(r$);
|
||||
},
|
||||
|
||||
children: (context) => context,
|
||||
}),
|
||||
null
|
||||
);
|
||||
|
||||
return _el$4;
|
||||
})();
|
||||
};
|
||||
|
||||
const template2 = _$createComponent(Child, {
|
||||
name: "Jake",
|
||||
|
||||
get dynamic() {
|
||||
return state.data;
|
||||
},
|
||||
|
||||
stale: state.data,
|
||||
handleClick: clickHandler,
|
||||
|
||||
get ["hyphen-ated"]() {
|
||||
return state.data;
|
||||
},
|
||||
|
||||
ref: (el) => (e = el),
|
||||
});
|
||||
|
||||
const template3 = _$createComponent(Child, {
|
||||
get children() {
|
||||
return [
|
||||
_tmpl$2.cloneNode(true),
|
||||
_tmpl$2.cloneNode(true),
|
||||
_tmpl$2.cloneNode(true),
|
||||
"After",
|
||||
];
|
||||
},
|
||||
});
|
||||
|
||||
const [s, set] = createSignal();
|
||||
|
||||
const template4 = _$createComponent(Child, {
|
||||
ref: set,
|
||||
|
||||
get children() {
|
||||
return _tmpl$2.cloneNode(true);
|
||||
},
|
||||
});
|
||||
|
||||
const template5 = _$createComponent(Child, {
|
||||
get dynamic() {
|
||||
return state.dynamic;
|
||||
},
|
||||
|
||||
get children() {
|
||||
return state.dynamic;
|
||||
},
|
||||
}); // builtIns
|
||||
|
||||
const template6 = _$createComponent(_$For, {
|
||||
get each() {
|
||||
return state.list;
|
||||
},
|
||||
|
||||
get fallback() {
|
||||
return _$createComponent(Loading, {});
|
||||
},
|
||||
|
||||
children: (item) =>
|
||||
_$createComponent(Show, {
|
||||
get when() {
|
||||
return state.condition;
|
||||
},
|
||||
|
||||
children: item,
|
||||
}),
|
||||
});
|
||||
|
||||
const template7 = _$createComponent(Child, {
|
||||
get children() {
|
||||
return [_tmpl$2.cloneNode(true), _$memo(() => state.dynamic)];
|
||||
},
|
||||
});
|
||||
|
||||
const template8 = _$createComponent(Child, {
|
||||
get children() {
|
||||
return [(item) => item, (item) => item];
|
||||
},
|
||||
});
|
||||
|
||||
const template9 = _$createComponent(_garbage, {
|
||||
children: "Hi",
|
||||
});
|
||||
|
||||
const template10 = (() => {
|
||||
const _el$12 = _tmpl$4.cloneNode(true),
|
||||
_el$13 = _el$12.firstChild,
|
||||
_el$18 = _el$13.nextSibling,
|
||||
_el$14 = _el$18.nextSibling,
|
||||
_el$19 = _el$14.nextSibling,
|
||||
_el$15 = _el$19.nextSibling,
|
||||
_el$20 = _el$15.nextSibling,
|
||||
_el$16 = _el$20.nextSibling,
|
||||
_el$21 = _el$16.nextSibling,
|
||||
_el$17 = _el$21.nextSibling;
|
||||
|
||||
_$insert(
|
||||
_el$12,
|
||||
_$createComponent(Link, {
|
||||
children: "new",
|
||||
}),
|
||||
_el$13
|
||||
);
|
||||
|
||||
_$insert(
|
||||
_el$12,
|
||||
_$createComponent(Link, {
|
||||
children: "comments",
|
||||
}),
|
||||
_el$18
|
||||
);
|
||||
|
||||
_$insert(
|
||||
_el$12,
|
||||
_$createComponent(Link, {
|
||||
children: "show",
|
||||
}),
|
||||
_el$19
|
||||
);
|
||||
|
||||
_$insert(
|
||||
_el$12,
|
||||
_$createComponent(Link, {
|
||||
children: "ask",
|
||||
}),
|
||||
_el$20
|
||||
);
|
||||
|
||||
_$insert(
|
||||
_el$12,
|
||||
_$createComponent(Link, {
|
||||
children: "jobs",
|
||||
}),
|
||||
_el$21
|
||||
);
|
||||
|
||||
_$insert(
|
||||
_el$12,
|
||||
_$createComponent(Link, {
|
||||
children: "submit",
|
||||
}),
|
||||
null
|
||||
);
|
||||
|
||||
return _el$12;
|
||||
})();
|
||||
|
||||
const template11 = (() => {
|
||||
const _el$22 = _tmpl$5.cloneNode(true),
|
||||
_el$23 = _el$22.firstChild,
|
||||
_el$26 = _el$23.nextSibling,
|
||||
_el$24 = _el$26.nextSibling,
|
||||
_el$27 = _el$24.nextSibling,
|
||||
_el$25 = _el$27.nextSibling;
|
||||
|
||||
_$insert(
|
||||
_el$22,
|
||||
_$createComponent(Link, {
|
||||
children: "new",
|
||||
}),
|
||||
_el$23
|
||||
);
|
||||
|
||||
_$insert(
|
||||
_el$22,
|
||||
_$createComponent(Link, {
|
||||
children: "comments",
|
||||
}),
|
||||
_el$26
|
||||
);
|
||||
|
||||
_$insert(
|
||||
_el$22,
|
||||
_$createComponent(Link, {
|
||||
children: "show",
|
||||
}),
|
||||
_el$26
|
||||
);
|
||||
|
||||
_$insert(
|
||||
_el$22,
|
||||
_$createComponent(Link, {
|
||||
children: "ask",
|
||||
}),
|
||||
_el$27
|
||||
);
|
||||
|
||||
_$insert(
|
||||
_el$22,
|
||||
_$createComponent(Link, {
|
||||
children: "jobs",
|
||||
}),
|
||||
_el$27
|
||||
);
|
||||
|
||||
_$insert(
|
||||
_el$22,
|
||||
_$createComponent(Link, {
|
||||
children: "submit",
|
||||
}),
|
||||
null
|
||||
);
|
||||
|
||||
return _el$22;
|
||||
})();
|
||||
|
||||
const template12 = (() => {
|
||||
const _el$28 = _tmpl$6.cloneNode(true),
|
||||
_el$29 = _el$28.firstChild,
|
||||
_el$34 = _el$29.nextSibling,
|
||||
_el$30 = _el$34.nextSibling,
|
||||
_el$35 = _el$30.nextSibling,
|
||||
_el$33 = _el$35.nextSibling;
|
||||
|
||||
_$insert(
|
||||
_el$28,
|
||||
_$createComponent(Link, {
|
||||
children: "comments",
|
||||
}),
|
||||
_el$34
|
||||
);
|
||||
|
||||
_$insert(
|
||||
_el$28,
|
||||
_$createComponent(Link, {
|
||||
children: "show",
|
||||
}),
|
||||
_el$35
|
||||
);
|
||||
|
||||
return _el$28;
|
||||
})();
|
||||
|
||||
class Template13 {
|
||||
render() {
|
||||
const _self$ = this;
|
||||
|
||||
_$createComponent(Component, {
|
||||
get prop() {
|
||||
return _self$.something;
|
||||
},
|
||||
|
||||
onClick: () => _self$.shouldStay,
|
||||
|
||||
get children() {
|
||||
return _$createComponent(Nested, {
|
||||
get prop() {
|
||||
return _self$.data;
|
||||
},
|
||||
|
||||
get children() {
|
||||
return _self$.content;
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const Template14 = _$createComponent(Component, {
|
||||
get children() {
|
||||
return data();
|
||||
},
|
||||
});
|
||||
|
||||
const Template15 = _$createComponent(Component, props);
|
||||
|
||||
const Template16 = _$createComponent(
|
||||
Component,
|
||||
_$mergeProps(
|
||||
{
|
||||
something: something,
|
||||
},
|
||||
props
|
||||
)
|
||||
);
|
||||
|
||||
const Template17 = _$createComponent(Pre, {
|
||||
get children() {
|
||||
return [
|
||||
_tmpl$7.cloneNode(true),
|
||||
" ",
|
||||
_tmpl$8.cloneNode(true),
|
||||
" ",
|
||||
_tmpl$9.cloneNode(true),
|
||||
];
|
||||
},
|
||||
});
|
||||
|
||||
const Template18 = _$createComponent(Pre, {
|
||||
get children() {
|
||||
return [
|
||||
_tmpl$7.cloneNode(true),
|
||||
_tmpl$8.cloneNode(true),
|
||||
_tmpl$9.cloneNode(true),
|
||||
];
|
||||
},
|
||||
});
|
||||
|
||||
const Template19 = _$createComponent(
|
||||
Component,
|
||||
_$mergeProps(() => s.dynamic())
|
||||
);
|
||||
|
||||
const Template20 = _$createComponent(Component, {
|
||||
get ["class"]() {
|
||||
return prop.red ? "red" : "green";
|
||||
},
|
||||
});
|
||||
|
||||
const template21 = _$createComponent(
|
||||
Component,
|
||||
_$mergeProps(() => ({
|
||||
get [key()]() {
|
||||
return props.value;
|
||||
},
|
||||
}))
|
||||
);
|
||||
@@ -0,0 +1,71 @@
|
||||
const template1 = <div>{simple}</div>;
|
||||
|
||||
const template2 = <div>{state.dynamic}</div>;
|
||||
|
||||
const template3 = <div>{simple ? good : bad}</div>;
|
||||
|
||||
const template4 = <div>{simple ? good() : bad}</div>;
|
||||
|
||||
const template5 = <div>{state.dynamic ? good() : bad}</div>;
|
||||
|
||||
const template6 = <div>{state.dynamic && good()}</div>;
|
||||
|
||||
const template7 = (
|
||||
<div>{state.count > 5 ? (state.dynamic ? best : good()) : bad}</div>
|
||||
);
|
||||
|
||||
const template8 = <div>{state.dynamic && state.something && good()}</div>;
|
||||
|
||||
const template9 = <div>{(state.dynamic && good()) || bad}</div>;
|
||||
|
||||
const template10 = (
|
||||
<div>{state.a ? "a" : state.b ? "b" : state.c ? "c" : "fallback"}</div>
|
||||
);
|
||||
|
||||
const template11 = (
|
||||
<div>{state.a ? a() : state.b ? b() : state.c ? "c" : "fallback"}</div>
|
||||
);
|
||||
|
||||
const template12 = <Comp render={state.dynamic ? good() : bad} />;
|
||||
|
||||
// no dynamic predicate
|
||||
const template13 = <Comp render={state.dynamic ? good : bad} />;
|
||||
|
||||
const template14 = <Comp render={state.dynamic && good()} />;
|
||||
|
||||
// no dynamic predicate
|
||||
const template15 = <Comp render={state.dynamic && good} />;
|
||||
|
||||
const template16 = <Comp render={state.dynamic || good()} />;
|
||||
|
||||
const template17 = <Comp render={state.dynamic ? <Comp /> : <Comp />} />;
|
||||
|
||||
const template18 = <Comp>{state.dynamic ? <Comp /> : <Comp />}</Comp>;
|
||||
|
||||
const template19 = <div innerHTML={state.dynamic ? <Comp /> : <Comp />} />;
|
||||
|
||||
const template20 = <div>{state.dynamic ? <Comp /> : <Comp />}</div>;
|
||||
|
||||
const template21 = <Comp render={state?.dynamic ? "a" : "b"} />;
|
||||
|
||||
const template22 = <Comp>{state?.dynamic ? "a" : "b"}</Comp>;
|
||||
|
||||
const template23 = <div innerHTML={state?.dynamic ? "a" : "b"} />;
|
||||
|
||||
const template24 = <div>{state?.dynamic ? "a" : "b"}</div>;
|
||||
|
||||
const template25 = <Comp render={state.dynamic ?? <Comp />} />;
|
||||
|
||||
const template26 = <Comp>{state.dynamic ?? <Comp />}</Comp>;
|
||||
|
||||
const template27 = <div innerHTML={state.dynamic ?? <Comp />} />;
|
||||
|
||||
const template28 = <div>{state.dynamic ?? <Comp />}</div>;
|
||||
|
||||
const template29 = <div>{(thing() && thing1()) ?? thing2() ?? thing3()}</div>;
|
||||
|
||||
const template30 = <div>{thing() || thing1() || thing2()}</div>;
|
||||
|
||||
const template31 = (
|
||||
<Comp value={count() ? (count() ? count() : count()) : count()} />
|
||||
);
|
||||
@@ -0,0 +1,144 @@
|
||||
var _tmpl = template("<div</div>", 2), _tmpl$1 = template("<div/>", 0);
|
||||
const template1 = () => {
|
||||
var _tmpl = _tmpl.cloneNode(true);
|
||||
insert(_tmpl, simple, null);
|
||||
return _tmpl;
|
||||
};
|
||||
const template2 = () => {
|
||||
var _tmpl = _tmpl.cloneNode(true);
|
||||
insert(_tmpl, state.dynamic, null);
|
||||
return _tmpl;
|
||||
};
|
||||
const template3 = () => {
|
||||
var _tmpl = _tmpl.cloneNode(true);
|
||||
insert(_tmpl, simple ? good : bad, null);
|
||||
return _tmpl;
|
||||
};
|
||||
const template4 = () => {
|
||||
var _tmpl = _tmpl.cloneNode(true);
|
||||
insert(_tmpl, simple ? good() : bad, null);
|
||||
return _tmpl;
|
||||
};
|
||||
const template5 = () => {
|
||||
var _tmpl = _tmpl.cloneNode(true);
|
||||
insert(_tmpl, state.dynamic ? good() : bad, null);
|
||||
return _tmpl;
|
||||
};
|
||||
const template6 = () => {
|
||||
var _tmpl = _tmpl.cloneNode(true);
|
||||
insert(_tmpl, state.dynamic && good(), null);
|
||||
return _tmpl;
|
||||
};
|
||||
const template7 = () => {
|
||||
var _tmpl = _tmpl.cloneNode(true);
|
||||
insert(_tmpl, state.count > 5 ? state.dynamic ? best : good() : bad, null);
|
||||
return _tmpl;
|
||||
};
|
||||
const template8 = () => {
|
||||
var _tmpl = _tmpl.cloneNode(true);
|
||||
insert(_tmpl, state.dynamic && state.something && good(), null);
|
||||
return _tmpl;
|
||||
};
|
||||
const template9 = () => {
|
||||
var _tmpl = _tmpl.cloneNode(true);
|
||||
insert(_tmpl, state.dynamic && good() || bad, null);
|
||||
return _tmpl;
|
||||
};
|
||||
const template10 = () => {
|
||||
var _tmpl = _tmpl.cloneNode(true);
|
||||
insert(_tmpl, state.a ? "a" : state.b ? "b" : state.c ? "c" : "fallback", null);
|
||||
return _tmpl;
|
||||
};
|
||||
const template11 = () => {
|
||||
var _tmpl = _tmpl.cloneNode(true);
|
||||
insert(_tmpl, state.a ? a() : state.b ? b() : state.c ? "c" : "fallback", null);
|
||||
return _tmpl;
|
||||
};
|
||||
const template12 = createComponent(Comp, {
|
||||
render: state.dynamic ? good() : bad
|
||||
});
|
||||
const template13 = createComponent(Comp, {
|
||||
render: state.dynamic ? good : bad
|
||||
});
|
||||
const template14 = createComponent(Comp, {
|
||||
render: state.dynamic && good()
|
||||
});
|
||||
const template15 = createComponent(Comp, {
|
||||
render: state.dynamic && good
|
||||
});
|
||||
const template16 = createComponent(Comp, {
|
||||
render: state.dynamic || good()
|
||||
});
|
||||
const template17 = createComponent(Comp, {
|
||||
render: state.dynamic ? createComponent(Comp, {}) : createComponent(Comp, {})
|
||||
});
|
||||
const template18 = createComponent(Comp, {
|
||||
get children: [
|
||||
state.dynamic ? createComponent(Comp, {}) : createComponent(Comp, {})
|
||||
]
|
||||
});
|
||||
const template19 = () => {
|
||||
var _el = _tmpl$1.cloneNode(true);
|
||||
effect(() => {
|
||||
return setAttribute(_el, "innerHTML", state.dynamic ? createComponent(Comp, {}) : createComponent(Comp, {}));
|
||||
});
|
||||
return _el;
|
||||
};
|
||||
const template20 = () => {
|
||||
var _tmpl = _tmpl.cloneNode(true);
|
||||
insert(_tmpl, state.dynamic ? createComponent(Comp, {}) : createComponent(Comp, {}), null);
|
||||
return _tmpl;
|
||||
};
|
||||
const template21 = createComponent(Comp, {
|
||||
render: state?.dynamic ? "a" : "b"
|
||||
});
|
||||
const template22 = createComponent(Comp, {
|
||||
get children: [
|
||||
state?.dynamic ? "a" : "b"
|
||||
]
|
||||
});
|
||||
const template23 = () => {
|
||||
var _el = _tmpl$1.cloneNode(true);
|
||||
effect(() => {
|
||||
return setAttribute(_el, "innerHTML", state?.dynamic ? "a" : "b");
|
||||
});
|
||||
return _el;
|
||||
};
|
||||
const template24 = () => {
|
||||
var _tmpl = _tmpl.cloneNode(true);
|
||||
insert(_tmpl, state?.dynamic ? "a" : "b", null);
|
||||
return _tmpl;
|
||||
};
|
||||
const template25 = createComponent(Comp, {
|
||||
render: state.dynamic ?? createComponent(Comp, {})
|
||||
});
|
||||
const template26 = createComponent(Comp, {
|
||||
get children: [
|
||||
state.dynamic ?? createComponent(Comp, {})
|
||||
]
|
||||
});
|
||||
const template27 = () => {
|
||||
var _el = _tmpl$1.cloneNode(true);
|
||||
effect(() => {
|
||||
return setAttribute(_el, "innerHTML", state.dynamic ?? createComponent(Comp, {}));
|
||||
});
|
||||
return _el;
|
||||
};
|
||||
const template28 = () => {
|
||||
var _tmpl = _tmpl.cloneNode(true);
|
||||
insert(_tmpl, state.dynamic ?? createComponent(Comp, {}), null);
|
||||
return _tmpl;
|
||||
};
|
||||
const template29 = () => {
|
||||
var _tmpl = _tmpl.cloneNode(true);
|
||||
insert(_tmpl, (thing() && thing1()) ?? thing2() ?? thing3(), null);
|
||||
return _tmpl;
|
||||
};
|
||||
const template30 = () => {
|
||||
var _tmpl = _tmpl.cloneNode(true);
|
||||
insert(_tmpl, thing() || thing1() || thing2(), null);
|
||||
return _tmpl;
|
||||
};
|
||||
const template31 = createComponent(Comp, {
|
||||
value: count() ? count() ? count() : count() : count()
|
||||
});
|
||||
319
test/bun.js/solid-dom-fixtures/conditionalExpressions/output.js
Normal file
319
test/bun.js/solid-dom-fixtures/conditionalExpressions/output.js
Normal file
@@ -0,0 +1,319 @@
|
||||
import { template as _$template } from "r-dom";
|
||||
import { effect as _$effect } from "r-dom";
|
||||
import { createComponent as _$createComponent } from "r-dom";
|
||||
import { memo as _$memo } from "r-dom";
|
||||
import { insert as _$insert } from "r-dom";
|
||||
|
||||
const _tmpl$ = /*#__PURE__*/ _$template(`<div></div>`, 2);
|
||||
|
||||
const template1 = (() => {
|
||||
const _el$ = _tmpl$.cloneNode(true);
|
||||
|
||||
_$insert(_el$, simple);
|
||||
|
||||
return _el$;
|
||||
})();
|
||||
|
||||
const template2 = (() => {
|
||||
const _el$2 = _tmpl$.cloneNode(true);
|
||||
|
||||
_$insert(_el$2, () => state.dynamic);
|
||||
|
||||
return _el$2;
|
||||
})();
|
||||
|
||||
const template3 = (() => {
|
||||
const _el$3 = _tmpl$.cloneNode(true);
|
||||
|
||||
_$insert(_el$3, simple ? good : bad);
|
||||
|
||||
return _el$3;
|
||||
})();
|
||||
|
||||
const template4 = (() => {
|
||||
const _el$4 = _tmpl$.cloneNode(true);
|
||||
|
||||
_$insert(_el$4, () => (simple ? good() : bad));
|
||||
|
||||
return _el$4;
|
||||
})();
|
||||
|
||||
const template5 = (() => {
|
||||
const _el$5 = _tmpl$.cloneNode(true);
|
||||
|
||||
_$insert(
|
||||
_el$5,
|
||||
(() => {
|
||||
const _c$ = _$memo(() => !!state.dynamic, true);
|
||||
|
||||
return () => (_c$() ? good() : bad);
|
||||
})()
|
||||
);
|
||||
|
||||
return _el$5;
|
||||
})();
|
||||
|
||||
const template6 = (() => {
|
||||
const _el$6 = _tmpl$.cloneNode(true);
|
||||
|
||||
_$insert(
|
||||
_el$6,
|
||||
(() => {
|
||||
const _c$2 = _$memo(() => !!state.dynamic, true);
|
||||
|
||||
return () => _c$2() && good();
|
||||
})()
|
||||
);
|
||||
|
||||
return _el$6;
|
||||
})();
|
||||
|
||||
const template7 = (() => {
|
||||
const _el$7 = _tmpl$.cloneNode(true);
|
||||
|
||||
_$insert(
|
||||
_el$7,
|
||||
(() => {
|
||||
const _c$3 = _$memo(() => state.count > 5, true);
|
||||
|
||||
return () =>
|
||||
_c$3()
|
||||
? (() => {
|
||||
const _c$4 = _$memo(() => !!state.dynamic, true);
|
||||
|
||||
return () => (_c$4() ? best : good());
|
||||
})()
|
||||
: bad;
|
||||
})()
|
||||
);
|
||||
|
||||
return _el$7;
|
||||
})();
|
||||
|
||||
const template8 = (() => {
|
||||
const _el$8 = _tmpl$.cloneNode(true);
|
||||
|
||||
_$insert(
|
||||
_el$8,
|
||||
(() => {
|
||||
const _c$5 = _$memo(() => !!(state.dynamic && state.something), true);
|
||||
|
||||
return () => _c$5() && good();
|
||||
})()
|
||||
);
|
||||
|
||||
return _el$8;
|
||||
})();
|
||||
|
||||
const template9 = (() => {
|
||||
const _el$9 = _tmpl$.cloneNode(true);
|
||||
|
||||
_$insert(
|
||||
_el$9,
|
||||
(() => {
|
||||
const _c$6 = _$memo(() => !!state.dynamic, true);
|
||||
|
||||
return () => (_c$6() && good()) || bad;
|
||||
})()
|
||||
);
|
||||
|
||||
return _el$9;
|
||||
})();
|
||||
|
||||
const template10 = (() => {
|
||||
const _el$10 = _tmpl$.cloneNode(true);
|
||||
|
||||
_$insert(_el$10, () =>
|
||||
state.a ? "a" : state.b ? "b" : state.c ? "c" : "fallback"
|
||||
);
|
||||
|
||||
return _el$10;
|
||||
})();
|
||||
|
||||
const template11 = (() => {
|
||||
const _el$11 = _tmpl$.cloneNode(true);
|
||||
|
||||
_$insert(
|
||||
_el$11,
|
||||
(() => {
|
||||
const _c$7 = _$memo(() => !!state.a, true);
|
||||
|
||||
return () =>
|
||||
_c$7()
|
||||
? a()
|
||||
: (() => {
|
||||
const _c$8 = _$memo(() => !!state.b, true);
|
||||
|
||||
return () => (_c$8() ? b() : state.c ? "c" : "fallback");
|
||||
})();
|
||||
})()
|
||||
);
|
||||
|
||||
return _el$11;
|
||||
})();
|
||||
|
||||
const template12 = _$createComponent(Comp, {
|
||||
get render() {
|
||||
return _$memo(() => !!state.dynamic, true)() ? good() : bad;
|
||||
},
|
||||
}); // no dynamic predicate
|
||||
|
||||
const template13 = _$createComponent(Comp, {
|
||||
get render() {
|
||||
return state.dynamic ? good : bad;
|
||||
},
|
||||
});
|
||||
|
||||
const template14 = _$createComponent(Comp, {
|
||||
get render() {
|
||||
return _$memo(() => !!state.dynamic, true)() && good();
|
||||
},
|
||||
}); // no dynamic predicate
|
||||
|
||||
const template15 = _$createComponent(Comp, {
|
||||
get render() {
|
||||
return state.dynamic && good;
|
||||
},
|
||||
});
|
||||
|
||||
const template16 = _$createComponent(Comp, {
|
||||
get render() {
|
||||
return state.dynamic || good();
|
||||
},
|
||||
});
|
||||
|
||||
const template17 = _$createComponent(Comp, {
|
||||
get render() {
|
||||
return _$memo(() => !!state.dynamic, true)()
|
||||
? _$createComponent(Comp, {})
|
||||
: _$createComponent(Comp, {});
|
||||
},
|
||||
});
|
||||
|
||||
const template18 = _$createComponent(Comp, {
|
||||
get children() {
|
||||
return _$memo(() => !!state.dynamic, true)()
|
||||
? _$createComponent(Comp, {})
|
||||
: _$createComponent(Comp, {});
|
||||
},
|
||||
});
|
||||
|
||||
const template19 = (() => {
|
||||
const _el$12 = _tmpl$.cloneNode(true);
|
||||
|
||||
_$effect(
|
||||
() =>
|
||||
(_el$12.innerHTML = state.dynamic
|
||||
? _$createComponent(Comp, {})
|
||||
: _$createComponent(Comp, {}))
|
||||
);
|
||||
|
||||
return _el$12;
|
||||
})();
|
||||
|
||||
const template20 = (() => {
|
||||
const _el$13 = _tmpl$.cloneNode(true);
|
||||
|
||||
_$insert(
|
||||
_el$13,
|
||||
(() => {
|
||||
const _c$9 = _$memo(() => !!state.dynamic, true);
|
||||
|
||||
return () =>
|
||||
_c$9() ? _$createComponent(Comp, {}) : _$createComponent(Comp, {});
|
||||
})()
|
||||
);
|
||||
|
||||
return _el$13;
|
||||
})();
|
||||
|
||||
const template21 = _$createComponent(Comp, {
|
||||
get render() {
|
||||
return state?.dynamic ? "a" : "b";
|
||||
},
|
||||
});
|
||||
|
||||
const template22 = _$createComponent(Comp, {
|
||||
get children() {
|
||||
return state?.dynamic ? "a" : "b";
|
||||
},
|
||||
});
|
||||
|
||||
const template23 = (() => {
|
||||
const _el$14 = _tmpl$.cloneNode(true);
|
||||
|
||||
_$effect(() => (_el$14.innerHTML = state?.dynamic ? "a" : "b"));
|
||||
|
||||
return _el$14;
|
||||
})();
|
||||
|
||||
const template24 = (() => {
|
||||
const _el$15 = _tmpl$.cloneNode(true);
|
||||
|
||||
_$insert(_el$15, () => (state?.dynamic ? "a" : "b"));
|
||||
|
||||
return _el$15;
|
||||
})();
|
||||
|
||||
const template25 = _$createComponent(Comp, {
|
||||
get render() {
|
||||
return state.dynamic ?? _$createComponent(Comp, {});
|
||||
},
|
||||
});
|
||||
|
||||
const template26 = _$createComponent(Comp, {
|
||||
get children() {
|
||||
return state.dynamic ?? _$createComponent(Comp, {});
|
||||
},
|
||||
});
|
||||
|
||||
const template27 = (() => {
|
||||
const _el$16 = _tmpl$.cloneNode(true);
|
||||
|
||||
_$effect(
|
||||
() => (_el$16.innerHTML = state.dynamic ?? _$createComponent(Comp, {}))
|
||||
);
|
||||
|
||||
return _el$16;
|
||||
})();
|
||||
|
||||
const template28 = (() => {
|
||||
const _el$17 = _tmpl$.cloneNode(true);
|
||||
|
||||
_$insert(_el$17, () => state.dynamic ?? _$createComponent(Comp, {}));
|
||||
|
||||
return _el$17;
|
||||
})();
|
||||
|
||||
const template29 = (() => {
|
||||
const _el$18 = _tmpl$.cloneNode(true);
|
||||
|
||||
_$insert(
|
||||
_el$18,
|
||||
(() => {
|
||||
const _c$10 = _$memo(() => !!thing(), true);
|
||||
|
||||
return () => (_c$10() && thing1()) ?? thing2() ?? thing3();
|
||||
})()
|
||||
);
|
||||
|
||||
return _el$18;
|
||||
})();
|
||||
|
||||
const template30 = (() => {
|
||||
const _el$19 = _tmpl$.cloneNode(true);
|
||||
|
||||
_$insert(_el$19, () => thing() || thing1() || thing2());
|
||||
|
||||
return _el$19;
|
||||
})();
|
||||
|
||||
const template31 = _$createComponent(Comp, {
|
||||
get value() {
|
||||
return _$memo(() => !!count(), true)()
|
||||
? _$memo(() => !!count(), true)()
|
||||
? count()
|
||||
: count()
|
||||
: count();
|
||||
},
|
||||
});
|
||||
29
test/bun.js/solid-dom-fixtures/customElements/code.js
Normal file
29
test/bun.js/solid-dom-fixtures/customElements/code.js
Normal file
@@ -0,0 +1,29 @@
|
||||
const template = (
|
||||
<my-element
|
||||
some-attr={name}
|
||||
notProp={data}
|
||||
attr:my-attr={data}
|
||||
prop:someProp={data}
|
||||
/>
|
||||
);
|
||||
|
||||
const template2 = (
|
||||
<my-element
|
||||
some-attr={state.name}
|
||||
notProp={state.data}
|
||||
attr:my-attr={state.data}
|
||||
prop:someProp={state.data}
|
||||
/>
|
||||
);
|
||||
|
||||
const template3 = (
|
||||
<my-element>
|
||||
<header slot="head">Title</header>
|
||||
</my-element>
|
||||
);
|
||||
|
||||
const template4 = (
|
||||
<>
|
||||
<slot name="head"></slot>
|
||||
</>
|
||||
);
|
||||
27
test/bun.js/solid-dom-fixtures/customElements/output.bun.js
Normal file
27
test/bun.js/solid-dom-fixtures/customElements/output.bun.js
Normal file
@@ -0,0 +1,27 @@
|
||||
var _tmpl = _template$("<my-element/>", 0), _tmpl$2 = _template$('<my-element><header slot="head">Title</header></my-element>', 4);
|
||||
const template = () => {
|
||||
var _el = _tmpl.cloneNode(true);
|
||||
setAttribute(_el, "some-attr", name);
|
||||
setAttribute(_el, "notProp", data);
|
||||
setAttribute(_el, "attr:my-attr", data);
|
||||
setAttribute(_el, "prop:someProp", data);
|
||||
return _el;
|
||||
};
|
||||
const template2 = () => {
|
||||
var _el = _tmpl.cloneNode(true);
|
||||
effect(() => {
|
||||
return setAttribute(_el, "some-attr", state.name);
|
||||
});
|
||||
effect(() => {
|
||||
return setAttribute(_el, "notProp", state.data);
|
||||
});
|
||||
effect(() => {
|
||||
return setAttribute(_el, "attr:my-attr", state.data);
|
||||
});
|
||||
effect(() => {
|
||||
return setAttribute(_el, "prop:someProp", state.data);
|
||||
});
|
||||
return _el;
|
||||
};
|
||||
const template3 = _tmpl$2.cloneNode(true);
|
||||
const template4 = ;
|
||||
66
test/bun.js/solid-dom-fixtures/customElements/output.js
Normal file
66
test/bun.js/solid-dom-fixtures/customElements/output.js
Normal file
@@ -0,0 +1,66 @@
|
||||
import { template as _$template } from "r-dom";
|
||||
import { effect as _$effect } from "r-dom";
|
||||
import { getOwner as _$getOwner } from "r-dom";
|
||||
import { setAttribute as _$setAttribute } from "r-dom";
|
||||
|
||||
const _tmpl$ = /*#__PURE__*/ _$template(`<my-element></my-element>`, 2),
|
||||
_tmpl$2 = /*#__PURE__*/ _$template(
|
||||
`<my-element><header slot="head">Title</header></my-element>`,
|
||||
4
|
||||
),
|
||||
_tmpl$3 = /*#__PURE__*/ _$template(`<slot name="head"></slot>`, 2);
|
||||
|
||||
const template = (() => {
|
||||
const _el$ = document.importNode(_tmpl$, true);
|
||||
|
||||
_el$.someAttr = name;
|
||||
_el$.notprop = data;
|
||||
|
||||
_$setAttribute(_el$, "my-attr", data);
|
||||
|
||||
_el$.someProp = data;
|
||||
_el$._$owner = _$getOwner();
|
||||
return _el$;
|
||||
})();
|
||||
|
||||
const template2 = (() => {
|
||||
const _el$2 = document.importNode(_tmpl$, true);
|
||||
|
||||
_el$2._$owner = _$getOwner();
|
||||
|
||||
_$effect(
|
||||
(_p$) => {
|
||||
const _v$ = state.name,
|
||||
_v$2 = state.data,
|
||||
_v$3 = state.data,
|
||||
_v$4 = state.data;
|
||||
_v$ !== _p$._v$ && (_el$2.someAttr = _p$._v$ = _v$);
|
||||
_v$2 !== _p$._v$2 && (_el$2.notprop = _p$._v$2 = _v$2);
|
||||
_v$3 !== _p$._v$3 && _$setAttribute(_el$2, "my-attr", (_p$._v$3 = _v$3));
|
||||
_v$4 !== _p$._v$4 && (_el$2.someProp = _p$._v$4 = _v$4);
|
||||
return _p$;
|
||||
},
|
||||
{
|
||||
_v$: undefined,
|
||||
_v$2: undefined,
|
||||
_v$3: undefined,
|
||||
_v$4: undefined,
|
||||
}
|
||||
);
|
||||
|
||||
return _el$2;
|
||||
})();
|
||||
|
||||
const template3 = (() => {
|
||||
const _el$3 = document.importNode(_tmpl$2, true);
|
||||
|
||||
_el$3._$owner = _$getOwner();
|
||||
return _el$3;
|
||||
})();
|
||||
|
||||
const template4 = (() => {
|
||||
const _el$4 = _tmpl$3.cloneNode(true);
|
||||
|
||||
_el$4._$owner = _$getOwner();
|
||||
return _el$4;
|
||||
})();
|
||||
32
test/bun.js/solid-dom-fixtures/eventExpressions/code.js
Normal file
32
test/bun.js/solid-dom-fixtures/eventExpressions/code.js
Normal file
@@ -0,0 +1,32 @@
|
||||
function hoisted1() {
|
||||
console.log("hoisted");
|
||||
}
|
||||
const hoisted2 = () => console.log("hoisted delegated");
|
||||
|
||||
const template = (
|
||||
<div id="main">
|
||||
<button onchange={() => console.log("bound")}>Change Bound</button>
|
||||
<button onChange={[(id) => console.log("bound", id), id]}>
|
||||
Change Bound
|
||||
</button>
|
||||
<button onchange={handler}>Change Bound</button>
|
||||
<button onchange={[handler]}>Change Bound</button>
|
||||
<button onchange={hoisted1}>Change Bound</button>
|
||||
<button onclick={() => console.log("delegated")}>Click Delegated</button>
|
||||
<button onClick={[(id) => console.log("delegated", id), rowId]}>
|
||||
Click Delegated
|
||||
</button>
|
||||
<button onClick={handler}>Click Delegated</button>
|
||||
<button onClick={[handler]}>Click Delegated</button>
|
||||
<button onClick={hoisted2}>Click Delegated</button>
|
||||
<button
|
||||
on:click={() => console.log("listener")}
|
||||
on:CAPS-ev={() => console.log("custom")}
|
||||
>
|
||||
Click Listener
|
||||
</button>
|
||||
<button oncapture:camelClick={() => console.log("listener")}>
|
||||
Click Capture
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
@@ -0,0 +1,57 @@
|
||||
var _tmpl$1 = _template$(
|
||||
'<div id="main"><button>Change Bound</button><button>Change Bound</button><button>Change Bound</button><button>Change Bound</button><button>Change Bound</button><button>Click Delegated</button><button>Click Delegated</button><button>Click Delegated</button><button>Click Delegated</button><button>Click Delegated</button><button>Click Listener</button><button>Click Capture</button></div>',
|
||||
26
|
||||
);
|
||||
function hoisted1() {
|
||||
console.log("hoisted");
|
||||
}
|
||||
const hoisted2 = () => console.log("hoisted delegated");
|
||||
const template = () => {
|
||||
var _el = _tmpl.cloneNode(true),
|
||||
_el$1 = _el.firstChild,
|
||||
_el$2 = _el$1.nextSibling,
|
||||
_el$3 = _el$2.nextSibling,
|
||||
_el$4 = _el$3.nextSibling,
|
||||
_el$5 = _el$4.nextSibling,
|
||||
_el$6 = _el$5.nextSibling,
|
||||
_el$7 = _el$6.nextSibling,
|
||||
_el$8 = _el$7.nextSibling,
|
||||
_el$9 = _el$8.nextSibling,
|
||||
_el$10 = _el$9.nextSibling,
|
||||
_el$11 = _el$10.nextSibling;
|
||||
effect(() => {
|
||||
return setAttribute(_el, "onchange", () => console.log("bound"));
|
||||
});
|
||||
effect(() => {
|
||||
return setAttribute(_el$1, "onChange", [
|
||||
(id) => console.log("bound", id),
|
||||
id,
|
||||
]);
|
||||
});
|
||||
setAttribute(_el$2, "onchange", handler);
|
||||
effect(() => {
|
||||
return setAttribute(_el$3, "onchange", [handler]);
|
||||
});
|
||||
setAttribute(_el$4, "onchange", hoisted1);
|
||||
_el$5.$$click = () => console.log("delegated");
|
||||
effect(() => {
|
||||
return (_el$6.$$click = [(id) => console.log("delegated", id), rowId]);
|
||||
});
|
||||
effect(() => {
|
||||
return (_el$7.$$click = handler);
|
||||
});
|
||||
effect(() => {
|
||||
return (_el$8.$$click = [handler]);
|
||||
});
|
||||
effect(() => {
|
||||
return (_el$9.$$click = hoisted2);
|
||||
});
|
||||
_el$10.addEventListener("click", () => console.log("listener"));
|
||||
_el$10.addEventListener("CAPS-ev", () => console.log("custom"));
|
||||
_el$11.addEventListener(
|
||||
"apture:camelClick",
|
||||
() => console.log("listener"),
|
||||
true
|
||||
);
|
||||
return _el;
|
||||
};
|
||||
63
test/bun.js/solid-dom-fixtures/eventExpressions/output.js
Normal file
63
test/bun.js/solid-dom-fixtures/eventExpressions/output.js
Normal file
@@ -0,0 +1,63 @@
|
||||
import { template as _$template } from "r-dom";
|
||||
import { delegateEvents as _$delegateEvents } from "r-dom";
|
||||
import { addEventListener as _$addEventListener } from "r-dom";
|
||||
|
||||
const _tmpl$ = /*#__PURE__*/ _$template(
|
||||
`<div id="main"><button>Change Bound</button><button>Change Bound</button><button>Change Bound</button><button>Change Bound</button><button>Change Bound</button><button>Click Delegated</button><button>Click Delegated</button><button>Click Delegated</button><button>Click Delegated</button><button>Click Delegated</button><button>Click Listener</button><button>Click Capture</button></div>`,
|
||||
26
|
||||
);
|
||||
|
||||
function hoisted1() {
|
||||
console.log("hoisted");
|
||||
}
|
||||
|
||||
const hoisted2 = () => console.log("hoisted delegated");
|
||||
|
||||
const template = (() => {
|
||||
const _el$ = _tmpl$.cloneNode(true),
|
||||
_el$2 = _el$.firstChild,
|
||||
_el$3 = _el$2.nextSibling,
|
||||
_el$4 = _el$3.nextSibling,
|
||||
_el$5 = _el$4.nextSibling,
|
||||
_el$6 = _el$5.nextSibling,
|
||||
_el$7 = _el$6.nextSibling,
|
||||
_el$8 = _el$7.nextSibling,
|
||||
_el$9 = _el$8.nextSibling,
|
||||
_el$10 = _el$9.nextSibling,
|
||||
_el$11 = _el$10.nextSibling,
|
||||
_el$12 = _el$11.nextSibling,
|
||||
_el$13 = _el$12.nextSibling;
|
||||
|
||||
_el$2.addEventListener("change", () => console.log("bound"));
|
||||
|
||||
_el$3.addEventListener("change", (e) =>
|
||||
((id) => console.log("bound", id))(id, e)
|
||||
);
|
||||
|
||||
_$addEventListener(_el$4, "change", handler);
|
||||
|
||||
_el$5.addEventListener("change", handler);
|
||||
|
||||
_el$6.addEventListener("change", hoisted1);
|
||||
|
||||
_el$7.$$click = () => console.log("delegated");
|
||||
|
||||
_el$8.$$click = (id) => console.log("delegated", id);
|
||||
|
||||
_el$8.$$clickData = rowId;
|
||||
|
||||
_$addEventListener(_el$9, "click", handler, true);
|
||||
|
||||
_el$10.$$click = handler;
|
||||
_el$11.$$click = hoisted2;
|
||||
|
||||
_el$12.addEventListener("click", () => console.log("listener"));
|
||||
|
||||
_el$12.addEventListener("CAPS-ev", () => console.log("custom"));
|
||||
|
||||
_el$13.addEventListener("camelClick", () => console.log("listener"), true);
|
||||
|
||||
return _el$;
|
||||
})();
|
||||
|
||||
_$delegateEvents(["click"]);
|
||||
83
test/bun.js/solid-dom-fixtures/fragments/code.js
Normal file
83
test/bun.js/solid-dom-fixtures/fragments/code.js
Normal file
@@ -0,0 +1,83 @@
|
||||
const multiStatic = (
|
||||
<>
|
||||
<div>First</div>
|
||||
<div>Last</div>
|
||||
</>
|
||||
);
|
||||
|
||||
const multiExpression = (
|
||||
<>
|
||||
<div>First</div>
|
||||
{inserted}
|
||||
<div>Last</div>
|
||||
After
|
||||
</>
|
||||
);
|
||||
|
||||
const multiDynamic = (
|
||||
<>
|
||||
<div id={state.first}>First</div>
|
||||
{state.inserted}
|
||||
<div id={state.last}>Last</div>
|
||||
After
|
||||
</>
|
||||
);
|
||||
|
||||
const singleExpression = <>{inserted}</>;
|
||||
|
||||
const singleDynamic = <>{inserted()}</>;
|
||||
|
||||
const firstStatic = (
|
||||
<>
|
||||
{inserted}
|
||||
<div />
|
||||
</>
|
||||
);
|
||||
|
||||
const firstDynamic = (
|
||||
<>
|
||||
{inserted()}
|
||||
<div />
|
||||
</>
|
||||
);
|
||||
|
||||
const firstComponent = (
|
||||
<>
|
||||
<Component />
|
||||
<div />
|
||||
</>
|
||||
);
|
||||
|
||||
const lastStatic = (
|
||||
<>
|
||||
<div />
|
||||
{inserted}
|
||||
</>
|
||||
);
|
||||
|
||||
const lastDynamic = (
|
||||
<>
|
||||
<div />
|
||||
{inserted()}
|
||||
</>
|
||||
);
|
||||
|
||||
const lastComponent = (
|
||||
<>
|
||||
<div />
|
||||
<Component />
|
||||
</>
|
||||
);
|
||||
|
||||
const spaces = (
|
||||
<>
|
||||
<span>1</span> <span>2</span> <span>3</span>
|
||||
</>
|
||||
);
|
||||
const multiLineTrailing = (
|
||||
<>
|
||||
<span>1</span>
|
||||
<span>2</span>
|
||||
<span>3</span>
|
||||
</>
|
||||
);
|
||||
13
test/bun.js/solid-dom-fixtures/fragments/output.bun.js
Normal file
13
test/bun.js/solid-dom-fixtures/fragments/output.bun.js
Normal file
@@ -0,0 +1,13 @@
|
||||
const multiStatic = ;
|
||||
const multiExpression = ;
|
||||
const multiDynamic = ;
|
||||
const singleExpression = ;
|
||||
const singleDynamic = ;
|
||||
const firstStatic = ;
|
||||
const firstDynamic = ;
|
||||
const firstComponent = ;
|
||||
const lastStatic = ;
|
||||
const lastDynamic = ;
|
||||
const lastComponent = ;
|
||||
const spaces = ;
|
||||
const multiLineTrailing = ;
|
||||
66
test/bun.js/solid-dom-fixtures/fragments/output.js
Normal file
66
test/bun.js/solid-dom-fixtures/fragments/output.js
Normal file
@@ -0,0 +1,66 @@
|
||||
import { template as _$template } from "r-dom";
|
||||
import { createComponent as _$createComponent } from "r-dom";
|
||||
import { memo as _$memo } from "r-dom";
|
||||
import { setAttribute as _$setAttribute } from "r-dom";
|
||||
import { effect as _$effect } from "r-dom";
|
||||
|
||||
const _tmpl$ = /*#__PURE__*/ _$template(`<div>First</div>`, 2),
|
||||
_tmpl$2 = /*#__PURE__*/ _$template(`<div>Last</div>`, 2),
|
||||
_tmpl$3 = /*#__PURE__*/ _$template(`<div></div>`, 2),
|
||||
_tmpl$4 = /*#__PURE__*/ _$template(`<span>1</span>`, 2),
|
||||
_tmpl$5 = /*#__PURE__*/ _$template(`<span>2</span>`, 2),
|
||||
_tmpl$6 = /*#__PURE__*/ _$template(`<span>3</span>`, 2);
|
||||
|
||||
const multiStatic = [_tmpl$.cloneNode(true), _tmpl$2.cloneNode(true)];
|
||||
const multiExpression = [
|
||||
_tmpl$.cloneNode(true),
|
||||
inserted,
|
||||
_tmpl$2.cloneNode(true),
|
||||
"After",
|
||||
];
|
||||
const multiDynamic = [
|
||||
(() => {
|
||||
const _el$5 = _tmpl$.cloneNode(true);
|
||||
|
||||
_$effect(() => _$setAttribute(_el$5, "id", state.first));
|
||||
|
||||
return _el$5;
|
||||
})(),
|
||||
_$memo(() => state.inserted),
|
||||
(() => {
|
||||
const _el$6 = _tmpl$2.cloneNode(true);
|
||||
|
||||
_$effect(() => _$setAttribute(_el$6, "id", state.last));
|
||||
|
||||
return _el$6;
|
||||
})(),
|
||||
"After",
|
||||
];
|
||||
const singleExpression = inserted;
|
||||
|
||||
const singleDynamic = _$memo(inserted);
|
||||
|
||||
const firstStatic = [inserted, _tmpl$3.cloneNode(true)];
|
||||
const firstDynamic = [_$memo(inserted), _tmpl$3.cloneNode(true)];
|
||||
const firstComponent = [
|
||||
_$createComponent(Component, {}),
|
||||
_tmpl$3.cloneNode(true),
|
||||
];
|
||||
const lastStatic = [_tmpl$3.cloneNode(true), inserted];
|
||||
const lastDynamic = [_tmpl$3.cloneNode(true), _$memo(inserted)];
|
||||
const lastComponent = [
|
||||
_tmpl$3.cloneNode(true),
|
||||
_$createComponent(Component, {}),
|
||||
];
|
||||
const spaces = [
|
||||
_tmpl$4.cloneNode(true),
|
||||
" ",
|
||||
_tmpl$5.cloneNode(true),
|
||||
" ",
|
||||
_tmpl$6.cloneNode(true),
|
||||
];
|
||||
const multiLineTrailing = [
|
||||
_tmpl$4.cloneNode(true),
|
||||
_tmpl$5.cloneNode(true),
|
||||
_tmpl$6.cloneNode(true),
|
||||
];
|
||||
36
test/bun.js/solid-dom-fixtures/insertChildren/code.js
Normal file
36
test/bun.js/solid-dom-fixtures/insertChildren/code.js
Normal file
@@ -0,0 +1,36 @@
|
||||
const children = <div />;
|
||||
const dynamic = {
|
||||
children,
|
||||
};
|
||||
const template = <Module children={children} />;
|
||||
const template2 = <module children={children} />;
|
||||
const template3 = <module children={children}>Hello</module>;
|
||||
const template4 = (
|
||||
<module children={children}>
|
||||
<Hello />
|
||||
</module>
|
||||
);
|
||||
const template5 = <module children={dynamic.children} />;
|
||||
const template6 = <Module children={dynamic.children} />;
|
||||
const template7 = <module {...dynamic} />;
|
||||
const template8 = <module {...dynamic}>Hello</module>;
|
||||
const template9 = <module {...dynamic}>{dynamic.children}</module>;
|
||||
const template10 = <Module {...dynamic}>Hello</Module>;
|
||||
const template11 = <module children={/*@once*/ state.children} />;
|
||||
const template12 = <Module children={/*@once*/ state.children} />;
|
||||
const template13 = <module>{...children}</module>;
|
||||
const template14 = <Module>{...children}</Module>;
|
||||
const template15 = <module>{...dynamic.children}</module>;
|
||||
const template16 = <Module>{...dynamic.children}</Module>;
|
||||
const template18 = <module>Hi {...children}</module>;
|
||||
const template19 = <Module>Hi {...children}</Module>;
|
||||
const template20 = <module>{children()}</module>;
|
||||
const template21 = <Module>{children()}</Module>;
|
||||
const template22 = <module>{state.children()}</module>;
|
||||
const template23 = <Module>{state.children()}</Module>;
|
||||
|
||||
const tiles = [];
|
||||
tiles.push(<div>Test 1</div>);
|
||||
const template24 = <div>{tiles}</div>;
|
||||
|
||||
const comma = <div>{(expression(), "static")}</div>;
|
||||
185
test/bun.js/solid-dom-fixtures/insertChildren/output.js
Normal file
185
test/bun.js/solid-dom-fixtures/insertChildren/output.js
Normal file
@@ -0,0 +1,185 @@
|
||||
import { template as _$template } from "r-dom";
|
||||
import { mergeProps as _$mergeProps } from "r-dom";
|
||||
import { spread as _$spread } from "r-dom";
|
||||
import { insert as _$insert } from "r-dom";
|
||||
import { createComponent as _$createComponent } from "r-dom";
|
||||
|
||||
const _tmpl$ = /*#__PURE__*/ _$template(`<div></div>`, 2),
|
||||
_tmpl$2 = /*#__PURE__*/ _$template(`<module></module>`, 2),
|
||||
_tmpl$3 = /*#__PURE__*/ _$template(`<module>Hello</module>`, 2),
|
||||
_tmpl$4 = /*#__PURE__*/ _$template(`<module>Hi </module>`, 2),
|
||||
_tmpl$5 = /*#__PURE__*/ _$template(`<div>Test 1</div>`, 2);
|
||||
|
||||
const children = _tmpl$.cloneNode(true);
|
||||
|
||||
const dynamic = {
|
||||
children,
|
||||
};
|
||||
|
||||
const template = _$createComponent(Module, {
|
||||
children: children,
|
||||
});
|
||||
|
||||
const template2 = (() => {
|
||||
const _el$2 = _tmpl$2.cloneNode(true);
|
||||
|
||||
_$insert(_el$2, children);
|
||||
|
||||
return _el$2;
|
||||
})();
|
||||
|
||||
const template3 = _tmpl$3.cloneNode(true);
|
||||
|
||||
const template4 = (() => {
|
||||
const _el$4 = _tmpl$2.cloneNode(true);
|
||||
|
||||
_$insert(_el$4, _$createComponent(Hello, {}));
|
||||
|
||||
return _el$4;
|
||||
})();
|
||||
|
||||
const template5 = (() => {
|
||||
const _el$5 = _tmpl$2.cloneNode(true);
|
||||
|
||||
_$insert(_el$5, () => dynamic.children);
|
||||
|
||||
return _el$5;
|
||||
})();
|
||||
|
||||
const template6 = _$createComponent(Module, {
|
||||
get children() {
|
||||
return dynamic.children;
|
||||
},
|
||||
});
|
||||
|
||||
const template7 = (() => {
|
||||
const _el$6 = _tmpl$2.cloneNode(true);
|
||||
|
||||
_$spread(_el$6, dynamic, false, false);
|
||||
|
||||
return _el$6;
|
||||
})();
|
||||
|
||||
const template8 = (() => {
|
||||
const _el$7 = _tmpl$3.cloneNode(true);
|
||||
|
||||
_$spread(_el$7, dynamic, false, true);
|
||||
|
||||
return _el$7;
|
||||
})();
|
||||
|
||||
const template9 = (() => {
|
||||
const _el$8 = _tmpl$2.cloneNode(true);
|
||||
|
||||
_$spread(_el$8, dynamic, false, true);
|
||||
|
||||
_$insert(_el$8, () => dynamic.children);
|
||||
|
||||
return _el$8;
|
||||
})();
|
||||
|
||||
const template10 = _$createComponent(
|
||||
Module,
|
||||
_$mergeProps(dynamic, {
|
||||
children: "Hello",
|
||||
})
|
||||
);
|
||||
|
||||
const template11 = (() => {
|
||||
const _el$9 = _tmpl$2.cloneNode(true);
|
||||
|
||||
_$insert(_el$9, state.children);
|
||||
|
||||
return _el$9;
|
||||
})();
|
||||
|
||||
const template12 = _$createComponent(Module, {
|
||||
children: state.children,
|
||||
});
|
||||
|
||||
const template13 = (() => {
|
||||
const _el$10 = _tmpl$2.cloneNode(true);
|
||||
|
||||
_$insert(_el$10, children);
|
||||
|
||||
return _el$10;
|
||||
})();
|
||||
|
||||
const template14 = _$createComponent(Module, {
|
||||
children: children,
|
||||
});
|
||||
|
||||
const template15 = (() => {
|
||||
const _el$11 = _tmpl$2.cloneNode(true);
|
||||
|
||||
_$insert(_el$11, () => dynamic.children);
|
||||
|
||||
return _el$11;
|
||||
})();
|
||||
|
||||
const template16 = _$createComponent(Module, {
|
||||
get children() {
|
||||
return dynamic.children;
|
||||
},
|
||||
});
|
||||
|
||||
const template18 = (() => {
|
||||
const _el$12 = _tmpl$4.cloneNode(true);
|
||||
|
||||
_$insert(_el$12, children, null);
|
||||
|
||||
return _el$12;
|
||||
})();
|
||||
|
||||
const template19 = _$createComponent(Module, {
|
||||
get children() {
|
||||
return ["Hi ", children];
|
||||
},
|
||||
});
|
||||
|
||||
const template20 = (() => {
|
||||
const _el$13 = _tmpl$2.cloneNode(true);
|
||||
|
||||
_$insert(_el$13, children);
|
||||
|
||||
return _el$13;
|
||||
})();
|
||||
|
||||
const template21 = _$createComponent(Module, {
|
||||
get children() {
|
||||
return children();
|
||||
},
|
||||
});
|
||||
|
||||
const template22 = (() => {
|
||||
const _el$14 = _tmpl$2.cloneNode(true);
|
||||
|
||||
_$insert(_el$14, () => state.children());
|
||||
|
||||
return _el$14;
|
||||
})();
|
||||
|
||||
const template23 = _$createComponent(Module, {
|
||||
get children() {
|
||||
return state.children();
|
||||
},
|
||||
});
|
||||
|
||||
const tiles = [];
|
||||
tiles.push(_tmpl$5.cloneNode(true));
|
||||
|
||||
const template24 = (() => {
|
||||
const _el$16 = _tmpl$.cloneNode(true);
|
||||
|
||||
_$insert(_el$16, tiles);
|
||||
|
||||
return _el$16;
|
||||
})();
|
||||
|
||||
const comma = (() => {
|
||||
const _el$17 = _tmpl$.cloneNode(true);
|
||||
|
||||
_$insert(_el$17, () => (expression(), "static"));
|
||||
|
||||
return _el$17;
|
||||
})();
|
||||
6
test/bun.js/solid-dom-fixtures/namespaceElements/code.js
Normal file
6
test/bun.js/solid-dom-fixtures/namespaceElements/code.js
Normal file
@@ -0,0 +1,6 @@
|
||||
const template = <module.A />;
|
||||
const template2 = <module.a.B />;
|
||||
const template3 = <module.A.B />;
|
||||
const template4 = <module.a-b />;
|
||||
const template5 = <module.a-b.c-d />;
|
||||
const template6 = <namespace:tag />;
|
||||
16
test/bun.js/solid-dom-fixtures/namespaceElements/output.js
Normal file
16
test/bun.js/solid-dom-fixtures/namespaceElements/output.js
Normal file
@@ -0,0 +1,16 @@
|
||||
import { template as _$template } from "r-dom";
|
||||
import { createComponent as _$createComponent } from "r-dom";
|
||||
|
||||
const _tmpl$ = /*#__PURE__*/ _$template(`<namespace:tag></namespace:tag>`, 2);
|
||||
|
||||
const template = _$createComponent(module.A, {});
|
||||
|
||||
const template2 = _$createComponent(module.a.B, {});
|
||||
|
||||
const template3 = _$createComponent(module.A.B, {});
|
||||
|
||||
const template4 = _$createComponent(module["a-b"], {});
|
||||
|
||||
const template5 = _$createComponent(module["a-b"]["c-d"], {});
|
||||
|
||||
const template6 = _tmpl$.cloneNode(true);
|
||||
9
test/bun.js/solid-dom-fixtures/simpleElements/code.js
Normal file
9
test/bun.js/solid-dom-fixtures/simpleElements/code.js
Normal file
@@ -0,0 +1,9 @@
|
||||
const template = (
|
||||
<div id="main">
|
||||
<style>{"div { color: red; }"}</style>
|
||||
<h1>Welcome</h1>
|
||||
<label for={"entry"}>Edit:</label>
|
||||
<input id="entry" type="text" />
|
||||
{/* Comment Node */}
|
||||
</div>
|
||||
);
|
||||
@@ -0,0 +1,5 @@
|
||||
var _tmpl$1 = _template$(
|
||||
'<div id="main"><style>div { color: red; }</style><h1>Welcome</h1><label for="entry">Edit:</label><input id="entry" type="text"/></div>',
|
||||
8
|
||||
);
|
||||
const template = _tmpl$1.cloneNode(true);
|
||||
8
test/bun.js/solid-dom-fixtures/simpleElements/output.js
Normal file
8
test/bun.js/solid-dom-fixtures/simpleElements/output.js
Normal file
@@ -0,0 +1,8 @@
|
||||
import { template as _$template } from "r-dom";
|
||||
|
||||
const _tmpl$ = /*#__PURE__*/ _$template(
|
||||
`<div id="main"><style>div { color: red; }</style><h1>Welcome</h1><label for="entry">Edit:</label><input id="entry" type="text"></div>`,
|
||||
9
|
||||
);
|
||||
|
||||
const template = _tmpl$.cloneNode(true);
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user