mirror of
https://github.com/remko/waforth
synced 2024-12-26 09:59:09 +01:00
parent
674dce6514
commit
a6d71029dc
17 changed files with 3100 additions and 2829 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -5,6 +5,7 @@ src/waforth.bulkmem.wat
|
|||
src/waforth.vanilla.wat
|
||||
src/web/benchmarks/sieve/sieve-c.js
|
||||
build/
|
||||
dist/
|
||||
*.wasm
|
||||
*.wasm.hex
|
||||
*.tmp
|
||||
|
|
61
README.md
61
README.md
|
@ -22,8 +22,60 @@ Words](http://lars.nocrew.org/dpans/dpans6.htm#6.1), and passes most of the
|
|||
[Forth 200x Test Suite](https://forth-standard.org/standard/testsuite)
|
||||
core word tests.
|
||||
|
||||
![WAForth Console](https://mko.re/waforth/console.gif "WAForth Console")
|
||||
|
||||
## Install Dependencies
|
||||
|
||||
## Using WAForth in an application
|
||||
|
||||
You can embed WAForth in any JavaScript application.
|
||||
|
||||
A simple example to illustrate starting WAForth, and binding JavaScript functions:
|
||||
|
||||
```typescript
|
||||
import WAForth from "waforth";
|
||||
|
||||
(async () => {
|
||||
// Create the UI
|
||||
document.body.innerHTML = `<button>Go!</button><pre></pre>`;
|
||||
const btn = document.querySelector("button");
|
||||
const log = document.querySelector("pre");
|
||||
|
||||
// Initialize WAForth
|
||||
const forth = new WAForth();
|
||||
forth.onEmit = (c) =>
|
||||
log.appendChild(document.createTextNode(String.fromCharCode(c)));
|
||||
await forth.load();
|
||||
|
||||
// Bind "prompt" call to a function that pops up a JavaScript prompt, and pushes the entered number back on the stack
|
||||
forth.bind("prompt", (stack) => {
|
||||
const message = stack.popString();
|
||||
const result = window.prompt(message);
|
||||
stack.push(parseInt(result));
|
||||
});
|
||||
|
||||
// Load Forth code to bind the "prompt" call to a word, and call the word
|
||||
forth.interpret(`
|
||||
( Call "prompt" with the given string )
|
||||
: PROMPT ( c-addr u -- n )
|
||||
S" prompt" SCALL
|
||||
;
|
||||
|
||||
( Prompt the user for a number, and write it to output )
|
||||
: ASK-NUMBER ( -- )
|
||||
S" Please enter a number" PROMPT
|
||||
." The number was" SPACE .
|
||||
;
|
||||
`);
|
||||
|
||||
btn.addEventListener("click", () => {
|
||||
forth.interpret("ASK-NUMBER");
|
||||
});
|
||||
})();
|
||||
```
|
||||
|
||||
## Development
|
||||
|
||||
### Install Dependencies
|
||||
|
||||
The build uses the [WebAssembly Binary
|
||||
Toolkit](https://github.com/WebAssembly/wabt) for converting raw WebAssembly
|
||||
|
@ -34,7 +86,7 @@ managing the dependencies of the shell.
|
|||
yarn
|
||||
|
||||
|
||||
## Building & Running
|
||||
### Building & Running
|
||||
|
||||
To build everything:
|
||||
|
||||
|
@ -44,7 +96,7 @@ To run the development server:
|
|||
|
||||
make dev
|
||||
|
||||
## Testing
|
||||
### Testing
|
||||
|
||||
The tests are served from `/waforth/tests` by the development server.
|
||||
|
||||
|
@ -116,11 +168,10 @@ The shell is [a JavaScript
|
|||
class](https://github.com/remko/waforth/blob/master/src/shell/WAForth.js) that
|
||||
wraps the WebAssembly module, and loads it in the browser. It provides the I/O
|
||||
primitives to the WebAssembly module to read and write characters to a
|
||||
terminal, and externally provides a `run()` function to execute a fragment of
|
||||
terminal, and externally provides a `interpret()` function to execute a fragment of
|
||||
Forth code.
|
||||
|
||||
To tie everything together into an interactive system, there's a small
|
||||
console-based interface around this shell to type Forth code, which you can see
|
||||
in action [here](https://mko.re/waforth/).
|
||||
|
||||
![WAForth Console](https://mko.re/waforth/console.gif "WAForth Console")
|
||||
|
|
28
build-package.js
Executable file
28
build-package.js
Executable file
|
@ -0,0 +1,28 @@
|
|||
#!/usr/bin/env node
|
||||
/* eslint-env node */
|
||||
|
||||
const esbuild = require("esbuild");
|
||||
const path = require("path");
|
||||
const { execSync } = require("child_process");
|
||||
const { wasmTextPlugin } = require("./scripts/esbuild/wasm-text");
|
||||
|
||||
let buildConfig = {
|
||||
bundle: true,
|
||||
logLevel: "info",
|
||||
entryPoints: [path.join(__dirname, "src", "web", "WAForth")],
|
||||
outfile: path.join(__dirname, "dist", "index.js"),
|
||||
minify: true,
|
||||
format: "cjs",
|
||||
loader: {
|
||||
".wasm": "binary",
|
||||
},
|
||||
sourcemap: true,
|
||||
plugins: [wasmTextPlugin({ debug: false })],
|
||||
};
|
||||
|
||||
esbuild.build(buildConfig).then(
|
||||
() => {
|
||||
execSync("./node_modules/.bin/tsc --project tsconfig.package.json");
|
||||
},
|
||||
() => process.exit(1)
|
||||
);
|
10
build-web.js
10
build-web.js
|
@ -61,6 +61,7 @@ let buildConfig = {
|
|||
path.join(__dirname, "src", "web", "shell", "shell"),
|
||||
path.join(__dirname, "src", "web", "tests", "tests"),
|
||||
path.join(__dirname, "src", "web", "benchmarks", "benchmarks"),
|
||||
path.join(__dirname, "src", "web", "examples", "prompt", "prompt"),
|
||||
],
|
||||
entryNames: dev ? "[name]" : "[name]-c$[hash]",
|
||||
assetNames: "[name]-c$[hash]",
|
||||
|
@ -99,6 +100,7 @@ async function handleBuildFinished(result) {
|
|||
let index = INDEX_TEMPLATE.replace(/\$BASE/g, "shell");
|
||||
let testIndex = INDEX_TEMPLATE.replace(/\$BASE/g, "tests");
|
||||
let benchmarksIndex = INDEX_TEMPLATE.replace(/\$BASE/g, "benchmarks");
|
||||
let promptIndex = INDEX_TEMPLATE.replace(/\$BASE/g, "prompt");
|
||||
// console.log(JSON.stringify(result.metafile.outputs, undefined, 2));
|
||||
for (const [out] of Object.entries(result.metafile.outputs)) {
|
||||
const outfile = path.basename(out);
|
||||
|
@ -107,6 +109,7 @@ async function handleBuildFinished(result) {
|
|||
index = index.replace(`/${sourcefile}`, `/${outfile}`);
|
||||
testIndex = testIndex.replace(`/${sourcefile}`, `/${outfile}`);
|
||||
benchmarksIndex = benchmarksIndex.replace(`/${sourcefile}`, `/${outfile}`);
|
||||
promptIndex = promptIndex.replace(`/${sourcefile}`, `/${outfile}`);
|
||||
}
|
||||
await fs.promises.writeFile("public/waforth/index.html", index);
|
||||
await fs.promises.mkdir("public/waforth/tests", { recursive: true });
|
||||
|
@ -116,6 +119,13 @@ async function handleBuildFinished(result) {
|
|||
"public/waforth/benchmarks/index.html",
|
||||
benchmarksIndex
|
||||
);
|
||||
await fs.promises.mkdir("public/waforth/examples/prompt", {
|
||||
recursive: true,
|
||||
});
|
||||
await fs.promises.writeFile(
|
||||
"public/waforth/examples/prompt/index.html",
|
||||
promptIndex
|
||||
);
|
||||
}
|
||||
|
||||
if (watch) {
|
||||
|
|
21
package.json
21
package.json
|
@ -1,8 +1,11 @@
|
|||
{
|
||||
"private": true,
|
||||
"name": "waforth",
|
||||
"version": "0.2.0",
|
||||
"license": "MIT",
|
||||
"repository": "github:remko/waforth",
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"@types/node": "^17.0.31",
|
||||
"chai": "^4.3.6",
|
||||
"esbuild": "^0.14.36",
|
||||
"eslint": "^8.13.0",
|
||||
|
@ -14,13 +17,23 @@
|
|||
"mocha": "^9.2.2",
|
||||
"prettier": "^2.6.2",
|
||||
"react": "^18.0.0",
|
||||
"react-dom": "^18.0.0"
|
||||
"react-dom": "^18.0.0",
|
||||
"typescript": "^4.6.4"
|
||||
},
|
||||
"types": "dist/WAForth.d.ts",
|
||||
"main": "dist/index.js",
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "./build-web.js",
|
||||
"dev": "./build-web.js --watch --development",
|
||||
"test": "./test-web.js",
|
||||
"test-watch": "./test-web.js --watch",
|
||||
"lint": "eslint ."
|
||||
}
|
||||
"lint": "eslint .",
|
||||
"prepare": "./build-package.js"
|
||||
},
|
||||
"keywords": [
|
||||
"forth"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -7,11 +7,11 @@ const process = require("process");
|
|||
|
||||
function encodeLE(n, align) {
|
||||
return (
|
||||
"\\u00" +
|
||||
"\\" +
|
||||
_.padStart(n.toString(16), align * 2, "0")
|
||||
.match(/.{2}/g)
|
||||
.reverse()
|
||||
.join("\\u00")
|
||||
.join("\\")
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@ const nextTableIndex = parseInt(process.argv[7]);
|
|||
const dictionaryEntry = [
|
||||
encodeLE(latest, 4),
|
||||
encodeLE(name.length | flags, 1),
|
||||
_.padEnd(name, 4 * Math.floor((name.length + 4) / 4) - 1, "0"),
|
||||
_.padEnd(name, 6 * Math.floor((name.length + 4) / 4) - 1, "\\00"),
|
||||
encodeLE(nextTableIndex, 4),
|
||||
];
|
||||
console.log(
|
||||
|
@ -41,8 +41,6 @@ console.log(
|
|||
console.log("latest: 0x" + here.toString(16));
|
||||
console.log(
|
||||
"here: 0x" +
|
||||
(here + dictionaryEntry.join("").replace(/\\u..../g, "_").length).toString(
|
||||
16
|
||||
)
|
||||
(here + dictionaryEntry.join("").replace(/\\../g, "_").length).toString(16)
|
||||
);
|
||||
console.log("!nextTableIndex: 0x" + (nextTableIndex + 1).toString(16));
|
||||
|
|
5576
src/waforth.wat
5576
src/waforth.wat
File diff suppressed because it is too large
Load diff
|
@ -7,7 +7,7 @@ const isSafari =
|
|||
// eslint-disable-next-line no-unused-vars
|
||||
const arrayToBase64 =
|
||||
typeof Buffer === "undefined"
|
||||
? function arrayToBase64(bytes) {
|
||||
? function arrayToBase64(bytes: Uint8Array) {
|
||||
var binary = "";
|
||||
var len = bytes.byteLength;
|
||||
for (var i = 0; i < len; i++) {
|
||||
|
@ -15,10 +15,17 @@ const arrayToBase64 =
|
|||
}
|
||||
return window.btoa(binary);
|
||||
}
|
||||
: function arrayToBase64(s) {
|
||||
: function arrayToBase64(s: Uint8Array) {
|
||||
return Buffer.from(s).toString("base64");
|
||||
};
|
||||
|
||||
function loadString(memory: WebAssembly.Memory, addr: number, len: number) {
|
||||
return String.fromCharCode.apply(
|
||||
null,
|
||||
new Uint8Array(memory.buffer, addr, len) as any
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Small JavaScript shell around the WAForth WebAssembly module.
|
||||
*
|
||||
|
@ -28,20 +35,28 @@ const arrayToBase64 =
|
|||
* the I/O primitives with the UI.
|
||||
* */
|
||||
class WAForth {
|
||||
constructor() {}
|
||||
core?: WebAssembly.Instance;
|
||||
buffer?: number[];
|
||||
onEmit?: (c: number) => void;
|
||||
fns: Record<string, (v: Stack) => void>;
|
||||
stack?: Stack;
|
||||
|
||||
start() {
|
||||
let table;
|
||||
let memory;
|
||||
constructor() {
|
||||
this.fns = {};
|
||||
}
|
||||
|
||||
async load() {
|
||||
let table: WebAssembly.Table;
|
||||
let memory: WebAssembly.Memory;
|
||||
const buffer = (this.buffer = []);
|
||||
|
||||
return WebAssembly.instantiate(wasmModule, {
|
||||
const instance = await WebAssembly.instantiate(wasmModule, {
|
||||
shell: {
|
||||
////////////////////////////////////////
|
||||
// I/O
|
||||
////////////////////////////////////////
|
||||
|
||||
emit: this.onEmit,
|
||||
emit: this.onEmit ?? (() => {}),
|
||||
|
||||
getc: () => {
|
||||
if (buffer.length === 0) {
|
||||
|
@ -50,20 +65,20 @@ class WAForth {
|
|||
return buffer.pop();
|
||||
},
|
||||
|
||||
debug: (d) => {
|
||||
debug: (d: number) => {
|
||||
console.log("DEBUG: ", d, String.fromCharCode(d));
|
||||
},
|
||||
|
||||
key: () => {
|
||||
let c;
|
||||
let c: string | null = null;
|
||||
while (c == null || c == "") {
|
||||
c = window.prompt("Enter character");
|
||||
}
|
||||
return c.charCodeAt(0);
|
||||
},
|
||||
|
||||
accept: (p, n) => {
|
||||
const input = (window.prompt("Enter text") || "").substr(0, n);
|
||||
accept: (p: number, n: number) => {
|
||||
const input = (window.prompt("Enter text") || "").substring(0, n);
|
||||
const target = new Uint8Array(memory.buffer, p, input.length);
|
||||
for (let i = 0; i < input.length; ++i) {
|
||||
target[i] = input.charCodeAt(i);
|
||||
|
@ -76,9 +91,9 @@ class WAForth {
|
|||
// Loader
|
||||
////////////////////////////////////////
|
||||
|
||||
load: (offset, length, index) => {
|
||||
load: (offset: number, length: number, index: number) => {
|
||||
let data = new Uint8Array(
|
||||
this.core.exports.memory.buffer,
|
||||
(this.core!.exports.memory as WebAssembly.Memory).buffer,
|
||||
offset,
|
||||
length
|
||||
);
|
||||
|
@ -105,30 +120,85 @@ class WAForth {
|
|||
throw e;
|
||||
}
|
||||
},
|
||||
|
||||
////////////////////////////////////////
|
||||
// Generic call
|
||||
////////////////////////////////////////
|
||||
|
||||
call: () => {
|
||||
const len = pop();
|
||||
const addr = pop();
|
||||
const fname = loadString(memory, addr, len);
|
||||
const fn = this.fns[fname];
|
||||
if (!fn) {
|
||||
console.error("Unbound SCALL: %s", fname);
|
||||
} else {
|
||||
fn(this.stack!);
|
||||
}
|
||||
},
|
||||
},
|
||||
}).then((instance) => {
|
||||
this.core = instance.instance;
|
||||
table = this.core.exports.table;
|
||||
memory = this.core.exports.memory;
|
||||
});
|
||||
this.core = instance.instance;
|
||||
|
||||
const pop = (): number => {
|
||||
return (this.core!.exports.pop as any)();
|
||||
};
|
||||
|
||||
const popString = (): string => {
|
||||
const len = pop();
|
||||
const addr = pop();
|
||||
return loadString(memory, addr, len);
|
||||
};
|
||||
|
||||
const push = (n: number): void => {
|
||||
(this.core!.exports.push as any)(n);
|
||||
};
|
||||
|
||||
this.stack = {
|
||||
pop,
|
||||
popString,
|
||||
push,
|
||||
};
|
||||
table = this.core.exports.table as WebAssembly.Table;
|
||||
memory = this.core.exports.memory as WebAssembly.Memory;
|
||||
}
|
||||
|
||||
read(s) {
|
||||
read(s: string) {
|
||||
const data = new TextEncoder().encode(s);
|
||||
for (let i = data.length - 1; i >= 0; --i) {
|
||||
this.buffer.push(data[i]);
|
||||
this.buffer!.push(data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
run(s) {
|
||||
/**
|
||||
* Read data `s` into the input buffer, and interpret.
|
||||
*/
|
||||
interpret(s: string) {
|
||||
this.read(s);
|
||||
try {
|
||||
return this.core.exports.interpret();
|
||||
return (this.core!.exports.interpret as any)();
|
||||
} catch (e) {
|
||||
// Exceptions thrown from the core means QUIT or ABORT is called, or an error
|
||||
// has occurred. Assume what has been done has been done, and ignore here.
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind `name` to SCALL in Forth.
|
||||
*
|
||||
* When an SCALL is done with `name` on the top of the stack, `fn` will be called (with the name popped off the stack).
|
||||
* Use `stack` to pop parameters off the stack, and push results back on the stack.
|
||||
*/
|
||||
bind(name: string, fn: (stack: Stack) => void) {
|
||||
this.fns[name] = fn;
|
||||
}
|
||||
}
|
||||
|
||||
interface Stack {
|
||||
push(n: number): void;
|
||||
|
||||
pop(): number;
|
||||
popString(): string;
|
||||
}
|
||||
|
||||
export default WAForth;
|
|
@ -19,8 +19,8 @@ forth.onEmit = (c) => {
|
|||
outputBuffer.push(String.fromCharCode(c));
|
||||
};
|
||||
setup.push(
|
||||
forth.start().then(() => {
|
||||
forth.run(sieve);
|
||||
forth.load().then(() => {
|
||||
forth.interpret(sieve);
|
||||
})
|
||||
);
|
||||
|
||||
|
@ -44,7 +44,7 @@ const benchmarks = [
|
|||
name: "sieve",
|
||||
fn: () => {
|
||||
outputBuffer = [];
|
||||
forth.run(`${LIMIT} sieve`);
|
||||
forth.interpret(`${LIMIT} sieve`);
|
||||
return outputBuffer.join("");
|
||||
},
|
||||
},
|
||||
|
|
0
src/web/examples/prompt/prompt.css
Normal file
0
src/web/examples/prompt/prompt.css
Normal file
40
src/web/examples/prompt/prompt.ts
Normal file
40
src/web/examples/prompt/prompt.ts
Normal file
|
@ -0,0 +1,40 @@
|
|||
import "./prompt.css";
|
||||
import WAForth from "../../WAForth";
|
||||
|
||||
(async () => {
|
||||
// Create the UI
|
||||
document.body.innerHTML = `<button>Go!</button><pre></pre>`;
|
||||
const btn = document.querySelector("button");
|
||||
const log = document.querySelector("pre");
|
||||
|
||||
// Initialize WAForth
|
||||
const forth = new WAForth();
|
||||
forth.onEmit = (c) =>
|
||||
log.appendChild(document.createTextNode(String.fromCharCode(c)));
|
||||
await forth.load();
|
||||
|
||||
// Bind "prompt" call to a function that pops up a JavaScript prompt, and pushes the entered number back on the stack
|
||||
forth.bind("prompt", (stack) => {
|
||||
const message = stack.popString();
|
||||
const result = window.prompt(message);
|
||||
stack.push(parseInt(result));
|
||||
});
|
||||
|
||||
// Load Forth code to bind the "prompt" call to a word, and call the word
|
||||
forth.interpret(`
|
||||
( Call "prompt" with the given string )
|
||||
: PROMPT ( c-addr u -- n )
|
||||
S" prompt" SCALL
|
||||
;
|
||||
|
||||
( Prompt the user for a number, and write it to output )
|
||||
: ASK-NUMBER ( -- )
|
||||
S" Please enter a number" PROMPT
|
||||
." The number was" SPACE .
|
||||
;
|
||||
`);
|
||||
|
||||
btn.addEventListener("click", () => {
|
||||
forth.interpret("ASK-NUMBER");
|
||||
});
|
||||
})();
|
|
@ -51,7 +51,7 @@ function startConsole() {
|
|||
// console.log("keydown", ev);
|
||||
if (ev.key === "Enter") {
|
||||
output(" ", true);
|
||||
forth.run(inputbuffer.join(""));
|
||||
forth.interpret(inputbuffer.join(""));
|
||||
inputbuffer = [];
|
||||
} else if (ev.key === "Backspace") {
|
||||
if (inputbuffer.length > 0) {
|
||||
|
@ -80,7 +80,7 @@ function startConsole() {
|
|||
for (const command of commands) {
|
||||
output(command, true);
|
||||
output(" ", true);
|
||||
forth.run(inputbuffer.join("") + command);
|
||||
forth.interpret(inputbuffer.join("") + command);
|
||||
inputbuffer = [];
|
||||
}
|
||||
if (newInputBuffer.length > 0) {
|
||||
|
@ -102,14 +102,15 @@ forth.onEmit = (c) => {
|
|||
clearConsole();
|
||||
|
||||
output("Loading core ... ", false);
|
||||
forth.start().then(
|
||||
forth.load().then(
|
||||
() => {
|
||||
output("ok\nLoading sieve ... ", false);
|
||||
forth.run(sieve);
|
||||
forth.interpret(sieve);
|
||||
clearConsole();
|
||||
startConsole();
|
||||
},
|
||||
() => {
|
||||
(e) => {
|
||||
console.error(e);
|
||||
const errorEl = document.createElement("span");
|
||||
errorEl.className = "error";
|
||||
errorEl.innerText = "error";
|
||||
|
|
|
@ -14,7 +14,7 @@ function loadTests() {
|
|||
output = output + String.fromCharCode(c);
|
||||
// console.log(output);
|
||||
};
|
||||
const x = forth.start().then(
|
||||
const x = forth.load().then(
|
||||
() => {
|
||||
core = forth.core.exports;
|
||||
|
||||
|
@ -82,7 +82,7 @@ function loadTests() {
|
|||
function run(ss, expectErrors = false) {
|
||||
ss.split("\n").forEach((s) => {
|
||||
// console.log("Running: ", s);
|
||||
const r = forth.run(s);
|
||||
const r = forth.interpret(s);
|
||||
if (expectErrors) {
|
||||
expect(r).to.be.undefined;
|
||||
output = output.substr(0, output.length);
|
||||
|
@ -1087,6 +1087,7 @@ function loadTests() {
|
|||
it("should fetch", () => {
|
||||
const ptr = here();
|
||||
memory[ptr / 4] = 123456;
|
||||
console.log("SET", ptr.toString(), memory[ptr / 8]);
|
||||
run(ptr.toString());
|
||||
run("@ 5");
|
||||
expect(stackValues()[0]).to.eql(123456);
|
||||
|
@ -1480,19 +1481,19 @@ function loadTests() {
|
|||
it("should work", () => {
|
||||
run(': FOO 0 0 S" 123AB" >NUMBER ;');
|
||||
run("FOO");
|
||||
expect(stackValues()).to.eql([123, 0, 137427, 2]);
|
||||
expect(stackValues()).to.eql([123, 0, 137443, 2]);
|
||||
});
|
||||
|
||||
it("should work with init", () => {
|
||||
run(': FOO 1 0 S" 1" >NUMBER ;');
|
||||
run("FOO");
|
||||
expect(stackValues()).to.eql([11, 0, 137425, 0]);
|
||||
expect(stackValues()).to.eql([11, 0, 137441, 0]);
|
||||
});
|
||||
|
||||
it("should not parse sign", () => {
|
||||
run(': FOO 0 0 S" -" >NUMBER ;');
|
||||
run("FOO");
|
||||
expect(stackValues()).to.eql([0, 0, 137424, 1]);
|
||||
expect(stackValues()).to.eql([0, 0, 137440, 1]);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
4
src/web/types/waforth.d.ts
vendored
Normal file
4
src/web/types/waforth.d.ts
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
declare module "*.wat" {
|
||||
const value: Uint8Array;
|
||||
export default value;
|
||||
}
|
12
tsconfig.json
Normal file
12
tsconfig.json
Normal file
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"noImplicitAny": true,
|
||||
"strict": true,
|
||||
"incremental": true,
|
||||
"typeRoots": ["./src/web/types"],
|
||||
"types": ["node"]
|
||||
},
|
||||
"include": ["src/web"],
|
||||
"exclude": ["node_modules", "dist", "build"]
|
||||
}
|
14
tsconfig.package.json
Normal file
14
tsconfig.package.json
Normal file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"noImplicitAny": true,
|
||||
"strict": true,
|
||||
"incremental": true,
|
||||
"typeRoots": ["./src/web/types"],
|
||||
"types": ["node"],
|
||||
"declaration": true,
|
||||
"emitDeclarationOnly": true
|
||||
},
|
||||
"include": ["src/web/WAForth.ts", "src/web/types"],
|
||||
"exclude": ["node_modules", "dist", "build"]
|
||||
}
|
10
yarn.lock
10
yarn.lock
|
@ -31,6 +31,11 @@
|
|||
resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45"
|
||||
integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==
|
||||
|
||||
"@types/node@^17.0.31":
|
||||
version "17.0.31"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.31.tgz#a5bb84ecfa27eec5e1c802c6bbf8139bdb163a5d"
|
||||
integrity sha512-AR0x5HbXGqkEx9CadRH3EBYx/VkiUgZIhP4wvPn/+5KIsgpNoyFaRlVe0Zlx9gRtg8fA06a9tskE2MSN7TcG4Q==
|
||||
|
||||
"@ungap/promise-all-settled@1.1.2":
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44"
|
||||
|
@ -1475,6 +1480,11 @@ type-fest@^0.20.2:
|
|||
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4"
|
||||
integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==
|
||||
|
||||
typescript@^4.6.4:
|
||||
version "4.6.4"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.4.tgz#caa78bbc3a59e6a5c510d35703f6a09877ce45e9"
|
||||
integrity sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg==
|
||||
|
||||
unbox-primitive@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471"
|
||||
|
|
Loading…
Reference in a new issue