[gjs/ewlsh/nova-repl] Port to mozjs91
- From: Evan Welsh <ewlsh src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs/ewlsh/nova-repl] Port to mozjs91
- Date: Mon, 17 Jan 2022 03:42:20 +0000 (UTC)
commit 297ed75451501e1b9dc088b0028fb0b78fbbd047
Author: Evan Welsh <contact evanwelsh com>
Date: Sun Jan 16 17:34:39 2022 -0800
Port to mozjs91
js.gresource.xml | 1 -
modules/console.cpp | 4 -
modules/esm/_repl/cliffy.js | 4 +-
modules/esm/_repl/deno.js | 11 ---
modules/esm/repl.js | 211 +++++++++++++++++++++++---------------------
tools/cliffy/transform.js | 4 +-
6 files changed, 111 insertions(+), 124 deletions(-)
---
diff --git a/js.gresource.xml b/js.gresource.xml
index c7b922db..6817f0b3 100644
--- a/js.gresource.xml
+++ b/js.gresource.xml
@@ -17,7 +17,6 @@
<file>modules/esm/_timers.js</file>
- <file>modules/esm/_repl/deno.js</file>
<file>modules/esm/_repl/cliffy.js</file>
<file>modules/esm/cairo.js</file>
diff --git a/modules/console.cpp b/modules/console.cpp
index 4dfaad64..aa80546a 100644
--- a/modules/console.cpp
+++ b/modules/console.cpp
@@ -32,10 +32,6 @@ namespace mozilla {
union Utf8Unit;
}
-static void gjs_console_warning_reporter(JSContext*, JSErrorReport* report) {
- JS::PrintError(stderr, report, /* reportWarnings = */ true);
-}
-
/* Based on js::shell::AutoReportException from SpiderMonkey. */
class AutoReportException {
JSContext *m_cx;
diff --git a/modules/esm/_repl/cliffy.js b/modules/esm/_repl/cliffy.js
index 9c59d47c..0f951ac3 100644
--- a/modules/esm/_repl/cliffy.js
+++ b/modules/esm/_repl/cliffy.js
@@ -2,7 +2,7 @@
// SPDX-FileCopyrightText: 2022 Benjamin Fischer <c4spar gmx de>
// Inject our shim for the Deno global...
-import * as Deno from './deno.js';
+const Deno = { noColor: false, build: { os: 'linux' } };
let globalThis = { Deno };
const base64abc = [
"A",
@@ -561,7 +561,7 @@ function bgRgb24(str, color) {
], 49));
}
const ANSI_PATTERN = new RegExp([
- "[\\u001B\\u009B][[\\]()$;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[-a-zA-Z\\d\\/$&.:=?%@~_]*)*)?\\u0007)",
+ "[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)",
"(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))",
].join("|"), "g");
function stripColor(string) {
diff --git a/modules/esm/repl.js b/modules/esm/repl.js
index b02d9902..7dac78ef 100644
--- a/modules/esm/repl.js
+++ b/modules/esm/repl.js
@@ -9,6 +9,7 @@ import {Ansi, Keycode} from './_repl/cliffy.js';
const Console = import.meta.importSync('_consoleNative');
// TODO: Integrate with new printer once it is merged...
+
/**
* @param {any} value any valid JavaScript value to stringify
*/
@@ -28,10 +29,15 @@ function toString(value) {
return `${value}`;
}
-const sInputHandler = Symbol('input handler');
-const sExitHandler = Symbol('exit handler');
-const sExitWarning = Symbol('exit warning');
class ReplInput {
+ #inputHandler;
+ #exitHandler;
+ #exitWarning;
+
+ #prompt;
+ #cancelling = false;
+ #cancellable = null;
+
/**
* @param {object} _ _
* @param {Gio.UnixOutputStream} _.stdin the input stream to treat as stdin
@@ -45,8 +51,8 @@ class ReplInput {
this.stderr = stderr;
this.enableColor = enableColor;
- this._prompt = this._buildPrompt();
- this._cancelled = false;
+ this.#prompt = this.#buildPrompt();
+ this.#cancelling = false;
/**
* Store previously inputted lines
@@ -76,24 +82,28 @@ class ReplInput {
*/
this.cursorColumn = 0;
- this[sInputHandler] =
+ this.#inputHandler =
/**
* @param {string} _input the inputted line or lines (separated by \n)
*/
_input => { };
- this[sExitWarning] = false;
+ this.#exitWarning = false;
}
[Symbol.toStringTag]() {
return 'Repl';
}
+ get cancelled() {
+ return this.#cancelling;
+ }
+
/**
* @param {string} pointer the pointer to prefix the line with
*/
- _buildPrompt(pointer = '>') {
- const renderedPrompt = `${pointer} `;
+ #buildPrompt(pointer = '>') {
+ const renderedPrompt = `${pointer} `;
const length = renderedPrompt.length;
return {
@@ -146,11 +156,11 @@ class ReplInput {
}
exit() {
- if (this[sExitWarning]) {
- this[sExitWarning] = false;
- this[sExitHandler]?.();
+ if (this.#exitWarning) {
+ this.#exitWarning = false;
+ this.#exitHandler?.();
} else {
- this[sExitWarning] = true;
+ this.#exitWarning = true;
this.writeSync('\n(To exit, press Ctrl+C again or Ctrl+D)\n');
this.flush();
}
@@ -317,8 +327,8 @@ class ReplInput {
if (this.validate(js)) {
// Reset lines before input is triggered
this.pendingInputLines = [];
- this[sExitWarning] = false;
- this[sInputHandler]?.(js);
+ this.#exitWarning = false;
+ this.#inputHandler?.(js);
} else {
// Buffer the input until a compilable unit is found...
this.pendingInputLines.push(value);
@@ -437,7 +447,7 @@ class ReplInput {
return ' '.padStart(4, '.');
}
- return this._prompt.renderedPrompt;
+ return this.#prompt.renderedPrompt;
}
render() {
@@ -476,17 +486,17 @@ class ReplInput {
for (const event of Keycode.parse(bytes)) {
this.handleEvent(event);
- if (this._cancelled)
+ if (this.#cancelling)
break;
this.render();
}
}
- _asyncReadHandler(stream, result) {
- this.cancellable = null;
+ #asyncReadHandler(stream, result) {
+ this.#cancellable = null;
- if (this._cancelled)
+ if (this.#cancelling)
return;
if (result) {
@@ -495,14 +505,15 @@ class ReplInput {
this.handleInput(gbytes.toArray());
}
- this.cancellable = new Gio.Cancellable();
- stream.read_bytes_async(8, 0, this.cancellable, this._asyncReadHandler.bind(this));
+ this.#cancellable = new Gio.Cancellable();
+ stream.read_bytes_async(8, 0, this.#cancellable, this.#asyncReadHandler.bind(this));
}
cancel() {
- this._cancelled = true;
- this.cancellable?.cancel();
- this.cancellable = null;
+ this.#cancelling = true;
+
+ this.#cancellable?.cancel();
+ this.#cancellable = null;
this.writeSync('\n');
this.flush();
@@ -512,7 +523,7 @@ class ReplInput {
this.render();
// Start the async read loop...
- this._asyncReadHandler(this.stdin);
+ this.#asyncReadHandler(this.stdin);
}
/**
@@ -520,13 +531,13 @@ class ReplInput {
* @param {(input: string) => void} inputHandler a callback when new lines are processed
*/
prompt(inputHandler) {
- this[sInputHandler] = inputHandler;
- this._cancelled = false;
+ this.#inputHandler = inputHandler;
+ this.#cancelling = false;
this.read();
}
onExit(exitHandler) {
- this[sExitHandler] = exitHandler;
+ this.#exitHandler = exitHandler;
}
}
@@ -536,10 +547,14 @@ class FallbackReplInput extends ReplInput {
}
read() {
- while (!this._cancelled) {
+ while (!this.cancelled) {
const prompt = this.getPrompt();
this.editValue(() => {
- return Console.interact(prompt).split('');
+ try {
+ return Console.interact(prompt).split('');
+ } catch {
+ return '';
+ }
});
this.processLine();
@@ -559,43 +574,31 @@ class FallbackReplInput extends ReplInput {
flush() { }
}
-const sCheckEnvironment = Symbol('check environment');
-const sSupportsColor = Symbol('supports color');
-const sMainLoop = Symbol('main loop');
-
export class Repl {
+ #lineNumber = 0;
+ #isRaw = false;
+
+ #supportsColor;
+ #mainloop;
+ #version;
+
constructor() {
({Gio} = imports.gi);
- this._version = imports.system.versionString;
- this.lineNumber = 0;
- this.isRaw = false;
-
- Object.defineProperties(this, {
- [sCheckEnvironment]: {
- writable: true,
- enumerable: false,
- configurable: true,
- value: this[sCheckEnvironment].bind(this),
- },
- [sSupportsColor]: {
- writable: true,
- enumerable: false,
- configurable: true,
- value: true,
- },
- [sMainLoop]: {
- writable: true,
- enumerable: false,
- configurable: true,
- value: null,
- },
- });
+ this.#version = imports.system.versionString;
}
- [sCheckEnvironment]() {
- this[sSupportsColor] = GLib.log_writer_supports_color(1);
- this[sSupportsColor] = this[sSupportsColor] && GLib.getenv('NO_COLOR') === null;
+ get lineNumber() {
+ return this.#lineNumber;
+ }
+
+ get isRaw() {
+ return this.#isRaw;
+ }
+
+ #checkEnvironment() {
+ this.#supportsColor = GLib.log_writer_supports_color(1);
+ this.#supportsColor &&= GLib.getenv('NO_COLOR') === null;
let hasUnixStreams = 'UnixInputStream' in Gio;
hasUnixStreams = hasUnixStreams && 'UnixOutputStream' in Gio;
@@ -603,19 +606,37 @@ export class Repl {
if (!hasUnixStreams)
return false;
+ const noMainLoop = GLib.getenv('GJS_REPL_NO_MAINLOOP');
// TODO: Environment variable for testing.
- if (GLib.getenv('GJS_REPL_NO_MAINLOOP'))
+ if (noMainLoop && noMainLoop === 'true')
return false;
return true;
}
- _evaluate(lines) {
+ #registerInputHandler() {
+ this.#print(`GJS v${this.#version}`);
+
+ // Start accepting input and rendering...
+ this.input.prompt(lines => {
+ if (lines.trim().startsWith('exit()'))
+ this.exit();
+ else
+ this.evaluate(lines);
+ });
+ }
+
+ #print(string) {
+ this.input.writeSync(`${string}${this.#isRaw ? '\n' : ''}`);
+ this.input.flush();
+ }
+
+ #evaluateInternal(lines) {
try {
- const result = Console.eval(lines, this.lineNumber);
+ const result = Console.eval(lines, this.#lineNumber);
if (result !== undefined)
- this._print(`${toString(result)}`);
+ this.#print(`${toString(result)}`);
return null;
} catch (error) {
@@ -623,64 +644,50 @@ export class Repl {
}
}
- _printError(error) {
+ #printError(error) {
if (error.message)
- this._print(`Uncaught ${error.name}: ${error.message}`);
+ this.#print(`Uncaught ${error.name}: ${error.message}`);
else
- this._print(`${toString(error)}`);
+ this.#print(`${toString(error)}`);
}
evaluate(lines) {
- this.lineNumber++;
+ this.#lineNumber++;
// TODO(ewlsh): Object/code block detection similar to Node
let wrappedLines = lines.trim();
if (wrappedLines.startsWith('{') &&
- !wrappedLines.endsWith(';'))
+ !wrappedLines.endsWith(';'))
wrappedLines = `(${wrappedLines})\n`;
// Attempt to evaluate any object literals in () first
- let error = this._evaluate(wrappedLines);
+ let error = this.#evaluateInternal(wrappedLines);
if (!error)
return;
- error = this._evaluate(lines);
+ error = this.#evaluateInternal(lines);
if (!error)
return;
- this._printError(error);
- }
-
- _print(string) {
- this.input.writeSync(`${string}${this.isRaw ? '\n' : ''}`);
- this.input.flush();
+ this.#printError(error);
}
- _registerInputHandler() {
- // Start accepting input and rendering...
- this.input.prompt(lines => {
- if (lines.trim().startsWith('exit()'))
- this.exit();
- else
- this.evaluate(lines);
- });
- }
run() {
- if (!this[sCheckEnvironment]()) {
+ if (!this.#checkEnvironment()) {
this.input = new FallbackReplInput();
- this._registerInputHandler();
+ this.#registerInputHandler();
return;
}
try {
- this.isRaw = Console.enableRawMode();
+ this.#isRaw = Console.enableRawMode();
- if (!this.isRaw) {
+ if (!this.#isRaw) {
this.input = new FallbackReplInput();
- this._registerInputHandler();
+ this.#registerInputHandler();
return;
}
@@ -692,16 +699,14 @@ export class Repl {
stdin,
stdout,
stderr,
- enableColor: this[sSupportsColor],
+ enableColor: this.#supportsColor,
});
this.input.onExit(() => {
this.exit();
});
- this._print(`GJS v${this._version}`);
-
- this._registerInputHandler();
+ this.#registerInputHandler();
// Install our default mainloop...
this.replaceMainLoop(() => {
@@ -710,13 +715,13 @@ export class Repl {
imports.mainloop.quit('repl');
});
- let mainloop = this[sMainLoop];
+ let mainloop = this.#mainloop;
while (mainloop) {
const [start] = mainloop;
start();
- mainloop = this[sMainLoop];
+ mainloop = this.#mainloop;
}
} finally {
Console.disableRawMode();
@@ -726,8 +731,8 @@ export class Repl {
exit() {
this.input.cancel();
- const mainloop = this[sMainLoop];
- this[sMainLoop] = null;
+ const mainloop = this.#mainloop;
+ this.#mainloop = null;
if (mainloop) {
const [, quit] = mainloop;
@@ -744,8 +749,8 @@ export class Repl {
if (!(this.input instanceof ReplInput))
return;
- const mainloop = this[sMainLoop];
- this[sMainLoop] = [start, quit];
+ const mainloop = this.#mainloop;
+ this.#mainloop = [start, quit];
if (mainloop) {
const [, previousQuit] = mainloop;
diff --git a/tools/cliffy/transform.js b/tools/cliffy/transform.js
index 2c2a1b90..aa2268c1 100644
--- a/tools/cliffy/transform.js
+++ b/tools/cliffy/transform.js
@@ -8,14 +8,12 @@ const file = Gio.File.new_for_commandline_arg(System.programArgs[0]);
const [, contents] = file.load_contents(null);
let source = new TextDecoder().decode(contents);
-// Remove all private variable names until mozjs91 is supported.
-source = source.replace(/#/g, '$');
source =
`// SPDX-License-Identifier: MIT
// SPDX-FileCopyrightText: 2022 Benjamin Fischer <c4spar gmx de>
// Inject our shim for the Deno global...
-import * as Deno from './deno.js';
+const Deno = { noColor: false, build: { os: 'linux' } };
let globalThis = { Deno };
${source}`;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]