GiavaScript / docs

Reference

GiavaScript documentation

GiavaScript is an open-source, cross-platform JavaScript runtime. It implements a curated subset of JavaScript and is not ECMAScript-compliant, so this reference describes GiavaScript behavior only.

Getting Started

Install GiavaScript with Homebrew on macOS or Linux:

brew tap GiavaScript/giavascript && brew install giavascript

Update an existing installation:

brew update && brew upgrade giavascript

Run a file with gs path/to/program.js, or start the REPL with gs. The REPL continues open blocks with a ... prompt and supports .help, .history, .exit, and :quit. Run a snippet with gs -e "code", or parse a file without executing it with gs --check path/to/program.js. An empty file is an error. Runtime errors are written to standard error with their source location (file:line:column), the offending source line, and a caret. Any Error: message gives the CLI an exit status of 1.

var name = "GiavaScript";
console.log(`Hello, ${name}`); // stdout: Hello, GiavaScript
gs -e "1 + 1"       // prints 2
gs --check main.js  // exits 1 on syntax errors, runs nothing

Language Basics

Declare variables with var, let, or const. All three are function/global scoped; there is no block scoping. let behaves like var. const requires an initializer and cannot be reassigned or updated.

var a = 1;
let b;
b = 2;
const c = 3; // c = 4 would raise an error
a += 1; // 2
b++; // 3

Declarations and assignments support destructuring. Array patterns bind by position; object patterns bind by key, with renaming ({key: name}), rest (...rest), and defaults. A default applies only when the value is undefined; null is kept. Function and arrow parameter patterns are not supported.

var [first, ...rest] = [1, 2, 3];
first; // 1
rest; // [2, 3]

var {name, age: years = 0} = {name: "Ada"};
name; // Ada
years; // 0

Values are numbers, strings (single or double quotes), true, false, null, undefined, arrays, objects, functions, dates, regular expressions, and errors. Access properties with object.key or object["key"], and index arrays with items[0]. Arrays and objects support spread ([...items], {...source}); non-array and non-object spread values are ignored. Comments are // line and /* block */. Template literals interpolate with ${...}. Statements on separate lines do not need semicolons. A local file can be evaluated with import "path/to/file.js".

Supported operators include arithmetic + - * / %, bitwise & | ^ ~ << >>, comparisons < > <= >=, equality == != === !==, logical && || !, optional chaining ?. (a?.b, a?.[i], a?.(args)), nullish coalescing ??, ternary condition ? left : right, unary +, typeof, and void.

  • == and != coerce; === and !== do not. switch also uses strict matching.
  • && and || short-circuit and return an operand, not necessarily a boolean.
  • ?. short-circuits to undefined when the target is null or undefined instead of raising. ?? falls back only for those two values, keeping 0, "", and false. ?? binds looser than && and ||.
  • Falsy values are false, 0, 0.0, "", null, and undefined. Arrays and objects are truthy.
  • typeof returns "number", "string", "boolean", "object", "function", or "undefined". An undeclared identifier returns "undefined" under typeof.
var total = 4;
total += 3;
total; // 7

var copy = [...[1, 2], 3];
copy; // [1, 2, 3]

var user = {name: "Ada"};
({role: "admin", ...user}).name; // Ada

typeof missing; // undefined
0 || "fallback"; // fallback

var settings = null;
settings?.theme; // undefined

var count = 0;
count ?? 5; // 0
null ?? 5; // 5

Functions

Function declarations, expressions, named expressions, arrows (with implicit or block bodies), recursion, default parameters, rest parameters, and call-argument spread are supported. Functions are first-class values and close over outer variables. Non-callback user function calls require every declared fixed parameter, rest must be the last parameter, and a function without return produces undefined.

function add(left, right) {
  return left + right;
}
add(20, 22); // 42

var double = value => value * 2;
double(21); // 42

function collect(first, ...rest) {
  return rest;
}
collect(1, 2, 3); // [2, 3]

function sum(a, b, c) { return a + b + c; }
sum(...[10, 20, 12]); // 42

Control Flow

Use if/else if/else, C-style for, for...of, for...in, while, do...while, switch, break, continue, throw, try/catch/finally, and return. for...of iterates arrays, strings, and Map/Set values; for...in iterates object keys. break is valid in loops and switch; continue only in loops. Switch cases use strict matching and fall through until break. finally always runs and may override a return or thrown value.

var grade = 82;
if (grade >= 90) {
  "A";
} else if (grade >= 80) {
  "B"; // B
} else {
  "C";
}

var sum = 0;
for (var i = 1; i <= 3; i++) {
  sum += i;
}
sum; // 6

var letters = "";
for (var letter of ["a", "b", "c"]) {
  letters += letter;
}
letters; // abc

var keys = "";
for (var key in {a: 1, b: 2}) {
  keys += key;
}
keys; // ab

var count = 0;
do {
  count++;
} while (count < 1);
count; // 1

var label = "";
switch (2) {
  case 1: label = "one"; break;
  case 2: label = "two"; break;
  default: label = "other";
}
label; // two

try {
  throw new Error("bad input");
} catch (error) {
  error.message; // bad input
} finally {
  // always runs
}

Values and Collections

Arrays support indexing, a mutable length, and the methods in the Array section. Objects support own string-keyed properties, dot and bracket access, and spread. Array and object spread ignore non-array and non-object values.

Map and Set are keyed collections that compare keys with SameValueZero semantics: numbers compare by value (1 and 1.0 are the same key, and NaN equals itself), strings, booleans, null, and undefined compare by value, and objects compare by reference identity. Iteration uses insertion order. Both are iterable with for...of: a Map yields [key, value] pairs and a Set yields values.

new Map()

Creates an empty keyed collection. Returns a Map. Takes no arguments.

var m = new Map();
m.size; // 0

map.set(key, value)

Stores a value under a key. Returns map for chaining.

var m = new Map();
m.set("a", 1);
m.get("a"); // 1

map.get(key)

Returns the value for a key, or undefined when absent.

var m = new Map(); m.set(1, "one");
m.get(1); // "one"
m.get(1.0); // "one"

map.has(key)

Returns a boolean indicating whether the key exists.

var m = new Map(); m.set("a", 1);
m.has("a"); // true
m.has("b"); // false

map.delete(key)

Removes a key. Returns true if it existed, otherwise false.

var m = new Map(); m.set("a", 1);
m.delete("a"); // true
m.delete("a"); // false

map.clear()

Removes every entry. Returns undefined.

var m = new Map(); m.set("a", 1);
m.clear();
m.size; // 0

map.keys(), map.values(), map.entries()

Return new arrays of keys, values, or [key, value] pairs.

var m = new Map(); m.set("a", 1); m.set("b", 2);
m.keys(); // ["a", "b"]
m.values(); // [1, 2]
m.entries(); // [["a", 1], ["b", 2]]

map.forEach(callback)

Runs callback(value, key, map) for each entry. Returns undefined.

var m = new Map(); m.set("a", 1);
m.forEach(function(value, key) { console.log(key + "=" + value); }); // stdout: a=1

map.size

Read-only number of entries in the Map.

var m = new Map(); m.set("a", 1); m.set("b", 2);
m.size; // 2

for...of over a Map

Yields each entry as a [key, value] array.

var m = new Map(); m.set("a", 1); m.set("b", 2);
var out = [];
for (var pair of m) { out.push(pair[0] + pair[1]); }
out; // ["a1", "b2"]

new Set()

Creates an empty collection of unique values. Returns a Set. Takes no arguments.

var s = new Set();
s.size; // 0

set.add(value)

Adds a value if absent. Returns set for chaining.

var s = new Set();
s.add(1); s.add(1);
s.size; // 1

set.has(value)

Returns a boolean indicating whether the value exists.

var s = new Set(); s.add(2);
s.has(2); // true
s.has(3); // false

set.delete(value)

Removes a value. Returns true if it existed, otherwise false.

var s = new Set(); s.add(1);
s.delete(1); // true

set.clear()

Removes every value. Returns undefined.

var s = new Set(); s.add(1);
s.clear();
s.size; // 0

set.values(), set.entries()

Return new arrays of values, or [value, value] pairs.

var s = new Set(); s.add(1); s.add(2);
s.values(); // [1, 2]
s.entries(); // [[1, 1], [2, 2]]

set.forEach(callback)

Runs callback(value, value, set) for each value. Returns undefined.

var s = new Set(); s.add(1);
s.forEach(function(value) { console.log(value); }); // stdout: 1

set.size

Read-only number of values in the Set.

var s = new Set(); s.add(1); s.add(2);
s.size; // 2

for...of over a Set

Yields each stored value.

var s = new Set(); s.add(3); s.add(4);
var out = [];
for (var value of s) { out.push(value); }
out; // [3, 4]

Global APIs

console.log(...values)

Writes space-separated values to stdout. Returns undefined.

console.log("answer:", 42); // stdout: answer: 42

console.warn(...values)

Writes space-separated values to stderr. Returns undefined.

console.warn("careful"); // stderr: careful

console.error(...values)

Writes space-separated values to stderr. Returns undefined.

console.error("failed"); // stderr: failed

parseInt(value, radix?)

Parses an integer prefix. Returns a number, or NaN when there is no valid digit. Radix must be 0 or between 2 and 36.

parseInt("11", 2); // 3
parseInt("nope"); // NaN

parseFloat(value)

Parses a floating-point prefix. Returns a number, Infinity, or NaN.

parseFloat("3.14px"); // 3.14

isNaN(value)

Coerces a value to a number, then reports whether it is NaN. Returns a boolean.

isNaN("nope"); // true
isNaN(42); // false

readLine()

Reads one standard-input line without its newline. Returns the line as a string, or "" at EOF. Result depends on input.

readLine(); // string from stdin, or "" at EOF

fetch(url, options?)

Performs a synchronous HTTP request. Returns an object with status, ok, headers, text, and json. It does not return a Promise.

fetch("https://example.com").status; // HTTP status number

options supports method, headers, and body. response.text() returns the body string. response.json() parses the body or raises an error when it is not valid JSON. Network results depend on the host.

String

Strings are immutable. Indexes are integer character indexes. The length property is read-only.

String.fromCharCode(...codeUnits)

Builds a string from UTF-16 code units. Returns a string.

String.fromCharCode(65, 66); // AB

text.length

Read-only number of characters in the string.

"hello".length; // 5

text.at(index)

Returns the character at an index, supporting negative indexes, or undefined when outside the string.

"abc".at(-1); // c
"abc".at(9); // undefined

text.charAt(index)

Returns the character at an index, or "" when outside the string.

"abc".charAt(1); // b

text.charCodeAt(index)

Returns the character code at an index, or NaN when outside the string.

"A".charCodeAt(0); // 65

text.codePointAt(index)

Returns the Unicode code point at an index, or undefined when outside the string.

"A".codePointAt(0); // 65

text.concat(suffix)

Returns the text with one string suffix appended.

"Giava".concat("Script"); // GiavaScript

text.startsWith(value), text.endsWith(value), text.includes(value)

Test for a string prefix, suffix, or contained string. Each returns a boolean.

"GiavaScript".startsWith("Giava"); // true
"GiavaScript".endsWith("Script"); // true
"GiavaScript".includes("aSc"); // true

text.indexOf(value), text.lastIndexOf(value)

Return the first or last index of a substring, or -1 when absent.

"banana".indexOf("a"); // 1
"banana".lastIndexOf("a"); // 5

text.isWellFormed(), text.toWellFormed()

Return true, and the unchanged string, respectively. GiavaScript strings are always well formed.

"text".isWellFormed(); // true
"text".toWellFormed(); // text

text.localeCompare(other)

Compares strings lexically. Returns -1, 0, or 1.

"a".localeCompare("b"); // -1

text.match(pattern)

Returns a match array or null. A global regular expression returns all whole matches.

"hello".match(/he(.)l/); // ["hell", "l"]

text.matchAll(pattern)

Returns an array of all matches. Regex matches include capture groups.

"a-a".matchAll("a"); // ["a", "a"]

text.padStart(length, fill?), text.padEnd(length, fill?)

Pad the string to a length using fill, or a single space when omitted. Returns a string.

"7".padStart(3, "0"); // 007
"7".padEnd(3, "0"); // 700

text.replace(search, replacement)

Replaces the first match, or all matches when the pattern is a global regular expression. Returns a string.

"a-a".replace("a", "b"); // b-a
"a-a".replace(/a/g, "b"); // b-b

text.replaceAll(search, replacement)

Replaces every string or regex match. Returns a string.

"a-a".replaceAll("a", "b"); // b-b

text.repeat(count)

Repeats the string a non-negative integer number of times. Returns a string.

"ha".repeat(2); // haha

text.search(pattern)

Returns the index of the first match, or -1.

"hello".search(/ll/); // 2

text.slice(start, end?)

Returns characters in [start, end). Negative indexes count from the end.

"hello".slice(-3); // llo
"hello".slice(1, 3); // el

text.split(separator, limit?)

Splits by a string or regular expression. Returns an array, optionally capped by limit.

"a,b,c".split(","); // ["a", "b", "c"]
"a,b,c".split(",", 2); // ["a", "b"]

text.substring(start, end?)

Returns characters in [start, end). Negative indexes become 0, and reversed bounds swap.

"hello".substring(1, 3); // el
"hello".substring(4, 1); // ell

text.toLowerCase(), text.toUpperCase(), text.toLocaleLowerCase(), text.toLocaleUpperCase()

Return a case-converted string.

"Giava".toUpperCase(); // GIAVA
"Giava".toLowerCase(); // giava

text.trim(), text.trimStart(), text.trimEnd()

Return the string with leading, trailing, or both ends of whitespace removed.

"  hi  ".trim(); // hi
"  hi  ".trimStart(); // "hi  "

text.toString(), text.valueOf()

Return the unchanged string.

"text".valueOf(); // text

Array

Arrays have a mutable length. Callbacks receive (value, index, array); reducers receive (accumulator, value, index, array). Mutating methods usually return the array or the new length.

Array.isArray(value)

Returns a boolean indicating whether the value is an array.

Array.isArray([]); // true
Array.isArray({}); // false

Array.of(...values)

Creates a new array from all arguments. Returns an array.

Array.of(1, 2); // [1, 2]

Array.from(arrayOrStringOrArrayLike)

Returns a shallow array copy, the characters of a string, or values from an object with an integer length.

Array.from("ab"); // ["a", "b"]
Array.from({length: 2, "0": "x", "1": "y"}); // ["x", "y"]

items.length

Read-write number of elements. Assigning changes the array size.

var a = [1, 2];
a.length; // 2

items.at(index)

Returns the item at an index, supporting negative indexes, or undefined out of bounds.

[10, 20].at(-1); // 20

items.concat(...values)

Returns a new array with arguments appended; array arguments are flattened one level.

[1].concat([2], 3); // [1, 2, 3]

items.copyWithin(target, start, end?)

Copies a range within the array in place. Returns the array.

var a = [1, 2, 3];
a.copyWithin(1, 0); // [1, 1, 2]

items.entries(), items.keys(), items.values()

Return new arrays of [index, value] pairs, indexes, or values.

["a", "b"].entries(); // [[0, "a"], [1, "b"]]
["a", "b"].keys(); // [0, 1]

items.every(fn), items.some(fn)

Return whether all, or any, callback results are truthy.

[1, 2].every(x => x > 0); // true
[1, 2].some(x => x > 1); // true

items.filter(fn), items.find(fn), items.findIndex(fn), items.findLast(fn), items.findLastIndex(fn)

Return a filtered array; the matching item or undefined; or the matching index or -1.

[1, 2, 3].filter(x => x > 1); // [2, 3]
[1, 2, 3].find(x => x > 1); // 2
[1, 2, 3].findIndex(x => x > 1); // 1

items.fill(value, start?, end?)

Fills [start, end) in place. Returns the array.

var a = [1, 2, 3];
a.fill(0, 1); // [1, 0, 0]

items.flat(depth?), items.flatMap(fn)

Return a new flattened array. flatMap maps then flattens one level.

[1, [2, [3]]].flat(2); // [1, 2, 3]
[1, 2].flatMap(x => [x, x]); // [1, 1, 2, 2]

items.forEach(fn)

Runs a callback for each element. Returns undefined.

var n = 0;
[1, 2].forEach(x => n += x);
n; // 3

items.includes(value, fromIndex?), items.indexOf(value, fromIndex?), items.lastIndexOf(value, fromIndex?)

Return a boolean, or the first/last matching index or -1. includes matches NaN.

[1, 2, 1].includes(2); // true
[1, 2, 1].lastIndexOf(1); // 2

items.join(separator?), items.toString()

Return a string joining the elements with separator, or a comma by default.

[1, 2, 3].join("-"); // 1-2-3
[1, 2, 3].toString(); // 1,2,3

items.map(fn)

Returns a new array of callback results.

[1, 2].map(x => x * 2); // [2, 4]

items.pop(), items.shift()

Remove and return the last or first item, or undefined when empty. Mutate the array.

var a = [1, 2];
a.pop(); // 2

items.push(value), items.unshift(...values)

Append or prepend values in place. Return the new length.

var a = [1];
a.unshift(2, 3); // 3
a; // [2, 3, 1]

items.reduce(fn, initial?), items.reduceRight(fn, initial?)

Return a reduced value. Empty arrays require an initial value, otherwise an error is raised.

[1, 2, 3].reduce((sum, x) => sum + x, 0); // 6

items.reverse()

Reverses in place. Returns the array.

var a = [1, 2];
a.reverse(); // [2, 1]

items.slice(start?, end?)

Returns a new array for [start, end). Supports negative indexes.

[1, 2, 3].slice(1); // [2, 3]

items.sort()

Sorts in place by string representation. Returns the array.

var a = [10, 2];
a.sort(); // [10, 2]

items.splice(start, deleteCount?, ...items)

Changes an array in place and returns the removed items.

var a = [1, 2, 3];
a.splice(1, 1, 9); // [2]
a; // [1, 9, 3]

Object, Number, and Boolean

Object.assign(target, ...sources)

Copies source properties into target. Returns the target object.

Object.assign({a: 1}, {b: 2}); // {"a": 1, "b": 2}

Object.hasOwn(object, property)

Returns a boolean indicating whether the object has an own property.

Object.hasOwn({a: 1}, "a"); // true

Object.keys(object), Object.values(object), Object.entries(object)

Return arrays of own keys, values, or [key, value] pairs.

Object.keys({a: 1, b: 2}); // ["a", "b"]
Object.values({a: 1, b: 2}); // [1, 2]
Object.entries({a: 1}); // [["a", 1]]

object.toString()

Returns a readable object string.

({a: 1}).toString(); // {"a": 1}

Number.isInteger(value)

Returns true only for integer numbers. Does not coerce.

Number.isInteger(42); // true
Number.isInteger("42"); // false

Number.isFinite(value)

Returns true only for finite numeric values. Does not coerce.

Number.isFinite(3.14); // true
Number.isFinite("3.14"); // false

Number.isNaN(value)

Returns true only for numeric NaN. Does not coerce.

Number.isNaN(parseInt("x")); // true

number.toString()

Returns the numeric string.

(42).toString(); // 42

boolean.toString()

Returns the boolean string.

true.toString(); // true

Math

Constants: E, LN10, LN2, LOG10E, LOG2E, PI, SQRT1_2, and SQRT2.

Math.PI; // 3.141592653589793

Every unary method takes one numeric argument and returns a number. Numeric arguments must be numbers.

abs, sqrt, acos, acosh, asin, asinh, atan, atanh, cbrt, ceil, clz32, cos, cosh, exp, expm1, f16round, floor, fround, log, log10, log1p, log2, round, sign, sin, sinh, tan, tanh, trunc.
Math.abs(-42); // 42
Math.sqrt(9); // 3.0

Math.atan2(y, x)

Returns the angle in radians from the positive x-axis to the point (x, y).

Math.atan2(0, 1); // 0.0

Math.hypot(...values)

Returns the square root of the sum of squares, and 0 when called without arguments.

Math.hypot(3, 4); // 5.0
Math.hypot(); // 0.0

Math.imul(left, right)

Returns the signed 32-bit multiplication of two integer values.

Math.imul(2, 21); // 42

Math.max(...values), Math.min(...values)

Return the largest or smallest number. Math.max() is -Infinity; Math.min() is Infinity.

Math.max(3, 7, 4); // 7.0
Math.min(3, 7, 4); // 3.0

Math.pow(base, exponent)

Returns base raised to exponent.

Math.pow(2, 5); // 32.0

Math.random()

Returns a pseudo-random number from 0 inclusive to 1 exclusive. The value is not deterministic.

Math.random(); // pseudo-random number in [0, 1)

Math.sumPrecise(...values)

Returns a compensated floating-point sum of its numeric arguments.

Math.sumPrecise(1, 2, 3); // 6.0

Date and RegExp

Date.now()

Returns the current UTC Unix timestamp in milliseconds. The value is not deterministic.

Date.now(); // current timestamp number

new Date()

Creates a date for the current UTC time. Takes no arguments. Returns a Date.

new Date().getTime(); // current timestamp number

date.getTime()

Returns the stored timestamp in milliseconds.

var d = new Date();
d.getTime(); // timestamp number

date.toString()

Returns a UTC ISO-like string in the form YYYY-MM-DDTHH:mm:ss.SSSZ.

new Date().toString(); // UTC ISO-like string

/pattern/flags

A regular expression literal. Flags are g, i, m, s, and u. Returns a RegExp.

/hello/i.test("HELLO"); // true

new RegExp(patternOrRegex, flags?)

Creates or copies a regular expression. Returns a RegExp.

new RegExp("hello", "i").test("HELLO"); // true

regexp.source, regexp.flags, regexp.global, regexp.ignoreCase, regexp.multiline, regexp.dotAll, regexp.unicode

Read-only pattern metadata and flag booleans.

/hello/gi.flags; // gi
/hello/i.ignoreCase; // true

regexp.test(value)

Returns a boolean indicating whether the pattern matches the value converted to a string.

/\d+/.test("a42"); // true

regexp.exec(value)

Returns a match array with capture groups, or null.

/he(.)l/.exec("hello"); // ["hell", "l"]

regexp.toString()

Returns a literal-style regex string.

/hello/gi.toString(); // /hello/gi

JSON and Errors

JSON.parse(text)

Parses one string into an object, array, number, boolean, null, or string. Raises an error on invalid JSON.

JSON.parse('{"answer":42}').answer; // 42

JSON.stringify(value)

Returns a JSON string for one value, or undefined for a top-level undefined, function, RegExp, or Error.

JSON.stringify({answer: 42}); // {"answer":42}

Unsupported object properties are omitted; unsupported array values become null; non-finite numbers become null; circular arrays or objects raise an error.

new Error(message?), new TypeError(message?), new ReferenceError(message?), new SyntaxError(message?)

Create an Error object with message, name, stack, and toString(). name defaults to the constructor name.

var error = new TypeError("expected a number");
error.name; // TypeError
error.toString(); // TypeError: expected a number

Error objects can be thrown with throw and caught with try/catch. Raw values can also be thrown. An uncaught throw is reported with its value and a source location (file:line:column). When the throw propagates out of user functions, the report also lists the calling frames as at name lines; anonymous functions appear as at anonymous.

File, Process, and Network

These APIs are host-integrated: their inputs, permissions, and results depend on the machine running GiavaScript.

File.read(path)

Reads a UTF-8 file as a string.

File.read("notes.txt"); // file contents string

File.readLines(path)

Reads a file into a string array, normalizing CRLF to LF.

File.readLines("notes.txt"); // array of lines

File.write(path, content)

Writes a string file. Returns undefined.

File.write("out.txt", "hello"); // undefined

File.append(path, content)

Appends a string to a file. Returns undefined.

File.append("out.txt", "\nmore"); // undefined

process.argv

Program argument string array.

process.argv; // argument array

process.env

Read-only snapshot of host environment variables.

process.env["HOME"]; // environment string or undefined

process.exit(code?)

Ends the process with a numeric status, default 0.

process.exit(1); // exits with status 1

process.run(command, args?)

Runs a command synchronously and returns {stdout, stderr, status}.

process.run("echo", ["hello"]).stdout; // hello followed by newline

fetch(url, options?)

Synchronous HTTP request. See Global APIs. Returns {status, ok, headers, text, json}.

fetch("https://example.com").ok; // boolean

Compatibility

GiavaScript is a curated runtime, not an ECMAScript-compliant browser or Node.js environment. These are not available:

  • Browser DOM APIs
  • print() and len()
  • Array.fromAsync, Array.toReversed, Array.toSorted, Array.toSpliced, Array.with, Array.toLocaleString
  • String.substr

There are no promises or browser APIs. Use only the APIs documented here.