Skip to main content
We’ve updated our Terms of Service. A new AI Addendum clarifies how Stack Overflow utilizes AI interactions.
added 2 characters in body
Source Link
toolic
  • 16.1k
  • 6
  • 29
  • 220
#!/usr/bin/env -S JS_STDERR=err.txt /home/user/.esvu/engines/jsshell/js
// SpiderMonkey Shell Native Messaging host (W.I.P.)
// guest271314 7-7-2023, 6-16-2024
function encodeMessage(str) {
  return new Uint8Array([...str].map((s) => s.codePointAt()));
}
// Call readline() N times to catch `\r\n\r\n"` from 2d port.postMessage()
let done = false;

let reads = 0;

function getMessage() {
  let stdin;
  while (true) {
    stdin = readline();
    if (stdin !== null) {
      break;
    }
  }

  let data = `${stdin}`.replace(/[\r\n]+|\\x([0-9A-Fa-f]{2,4})/gu, "")
    .replace(/[^A-Za-z0-9\s\[,\]\{\}:_"]+/igu, "")
    .replace(/^"rnrn/gu, "")
    .replace(/^[#\r\n\}_]+(?=\[)/gu, "")
    .replace(/^"(?=["\{]+)|^"(?!"$)/gu, "")
    .replace(/^\[(?=\[(?!.*\]{2}$))/gu, "")
    .replace(/^\{(?!\}|.+\}$)/gu, "")
    .replace(/^[0-9A-Z]+(?=[\[\{"])/igu, "")
    .replace(/^[\]\}](?=\[)/i, "")
    .trimStart().trim();

  return encodeMessage(data);
}

function sendMessage(message) {
  os.file.writeTypedArrayToFile(
    "/proc/self/fd/1",
    new Uint32Array([message.length]),
  );
  os.file.writeTypedArrayToFile("/proc/self/fd/1", message);
}

function main() {
  while (true) {
    const message = getMessage();
    sendMessage(message);
  }
}

try {
  main();
} catch (e) {
  os.file.writeTypedArrayToFile(
    "caught.txt",
    encodeMessage(JSON.stringify(e.message)),
  );
  quit();
}

```
#!/usr/bin/env -S JS_STDERR=err.txt /home/user/.esvu/engines/jsshell/js
// SpiderMonkey Shell Native Messaging host (W.I.P.)
// guest271314 7-7-2023, 6-16-2024
function encodeMessage(str) {
  return new Uint8Array([...str].map((s) => s.codePointAt()));
}
// Call readline() N times to catch `\r\n\r\n"` from 2d port.postMessage()
let done = false;

let reads = 0;

function getMessage() {
  let stdin;
  while (true) {
    stdin = readline();
    if (stdin !== null) {
      break;
    }
  }

  let data = `${stdin}`.replace(/[\r\n]+|\\x([0-9A-Fa-f]{2,4})/gu, "")
    .replace(/[^A-Za-z0-9\s\[,\]\{\}:_"]+/igu, "")
    .replace(/^"rnrn/gu, "")
    .replace(/^[#\r\n\}_]+(?=\[)/gu, "")
    .replace(/^"(?=["\{]+)|^"(?!"$)/gu, "")
    .replace(/^\[(?=\[(?!.*\]{2}$))/gu, "")
    .replace(/^\{(?!\}|.+\}$)/gu, "")
    .replace(/^[0-9A-Z]+(?=[\[\{"])/igu, "")
    .replace(/^[\]\}](?=\[)/i, "")
    .trimStart().trim();

  return encodeMessage(data);
}

function sendMessage(message) {
  os.file.writeTypedArrayToFile(
    "/proc/self/fd/1",
    new Uint32Array([message.length]),
  );
  os.file.writeTypedArrayToFile("/proc/self/fd/1", message);
}

function main() {
  while (true) {
    const message = getMessage();
    sendMessage(message);
  }
}

try {
  main();
} catch (e) {
  os.file.writeTypedArrayToFile(
    "caught.txt",
    encodeMessage(JSON.stringify(e.message)),
  );
  quit();
}

```
#!/usr/bin/env -S JS_STDERR=err.txt /home/user/.esvu/engines/jsshell/js
// SpiderMonkey Shell Native Messaging host (W.I.P.)
// guest271314 7-7-2023, 6-16-2024
function encodeMessage(str) {
  return new Uint8Array([...str].map((s) => s.codePointAt()));
}
// Call readline() N times to catch `\r\n\r\n"` from 2d port.postMessage()
let done = false;

let reads = 0;

function getMessage() {
  let stdin;
  while (true) {
    stdin = readline();
    if (stdin !== null) {
      break;
    }
  }

  let data = `${stdin}`.replace(/[\r\n]+|\\x([0-9A-Fa-f]{2,4})/gu, "")
    .replace(/[^A-Za-z0-9\s\[,\]\{\}:_"]+/igu, "")
    .replace(/^"rnrn/gu, "")
    .replace(/^[#\r\n\}_]+(?=\[)/gu, "")
    .replace(/^"(?=["\{]+)|^"(?!"$)/gu, "")
    .replace(/^\[(?=\[(?!.*\]{2}$))/gu, "")
    .replace(/^\{(?!\}|.+\}$)/gu, "")
    .replace(/^[0-9A-Z]+(?=[\[\{"])/igu, "")
    .replace(/^[\]\}](?=\[)/i, "")
    .trimStart().trim();

  return encodeMessage(data);
}

function sendMessage(message) {
  os.file.writeTypedArrayToFile(
    "/proc/self/fd/1",
    new Uint32Array([message.length]),
  );
  os.file.writeTypedArrayToFile("/proc/self/fd/1", message);
}

function main() {
  while (true) {
    const message = getMessage();
    sendMessage(message);
  }
}

try {
  main();
} catch (e) {
  os.file.writeTypedArrayToFile(
    "caught.txt",
    encodeMessage(JSON.stringify(e.message)),
  );
  quit();
}

Source Link
guest271314
  • 738
  • 3
  • 12

SpiderMonkey JavaScript engine Native Messaging host

Native Messaging host using Mozilla SpiderMonkey JavaScript/WebAssembly engine.

Documentations

Native messaging protocol (Chrome Developers)

In pertinent part

Chrome starts each native messaging host in a separate process and communicates with it using standard input (stdin) and standard output (stdout). The same format is used to send messages in both directions; each message is serialized using JSON, UTF-8 encoded and is preceded with 32-bit message length in native byte order. The maximum size of a single message from the native messaging host is 1 MB, mainly to protect Chrome from misbehaving native applications. The maximum size of the message sent to the native messaging host is 4 GB.

Some development background Why is this SpiderMonkey Native Messsaging host not sending stdout to the client?.

ECMA-262 does not specify reading stdin or writing to stdout for JavaScript. At the JavaScript engine level what that means is that a JavaScript engine can, or cannot have I/O implemented and still be perfectly ECMA-262 test conformant. QuickJS includes a way to read stdin and write to stdout. Mozilla SpiderMonkey is little trickier.

  • I have to send an additional "\r\n\r\n" message from the client (browser) to the host (native application) for the host to get the message. So where in other languages and engines I can just send port.postMessage(new Array(209715)), with SpiderMonkey I have to also send and additional message at the end of every message I send port.postMessage("\r\n\r\n").
  • Don't ask me to explain those regular expressions. I read the string that gets to the host and kept creating regular expressions, line-by-line, until I got what I was expecting.
  • Using /proc/self/fd/1 is not ideal, as Apple OS's don't have that, and neither do Microsoft OS's; works on Debian and Ubuntu Linux operating systems.

Note, an Array with 209715 length in JavaScript winds up being 1 MB serialized to JSON, accounting for the null value set at indexes 0-209714.

Here's the working code

#!/usr/bin/env -S JS_STDERR=err.txt /home/user/.esvu/engines/jsshell/js
// SpiderMonkey Shell Native Messaging host (W.I.P.)
// guest271314 7-7-2023, 6-16-2024
function encodeMessage(str) {
  return new Uint8Array([...str].map((s) => s.codePointAt()));
}
// Call readline() N times to catch `\r\n\r\n"` from 2d port.postMessage()
let done = false;

let reads = 0;

function getMessage() {
  let stdin;
  while (true) {
    stdin = readline();
    if (stdin !== null) {
      break;
    }
  }

  let data = `${stdin}`.replace(/[\r\n]+|\\x([0-9A-Fa-f]{2,4})/gu, "")
    .replace(/[^A-Za-z0-9\s\[,\]\{\}:_"]+/igu, "")
    .replace(/^"rnrn/gu, "")
    .replace(/^[#\r\n\}_]+(?=\[)/gu, "")
    .replace(/^"(?=["\{]+)|^"(?!"$)/gu, "")
    .replace(/^\[(?=\[(?!.*\]{2}$))/gu, "")
    .replace(/^\{(?!\}|.+\}$)/gu, "")
    .replace(/^[0-9A-Z]+(?=[\[\{"])/igu, "")
    .replace(/^[\]\}](?=\[)/i, "")
    .trimStart().trim();

  return encodeMessage(data);
}

function sendMessage(message) {
  os.file.writeTypedArrayToFile(
    "/proc/self/fd/1",
    new Uint32Array([message.length]),
  );
  os.file.writeTypedArrayToFile("/proc/self/fd/1", message);
}

function main() {
  while (true) {
    const message = getMessage();
    sendMessage(message);
  }
}

try {
  main();
} catch (e) {
  os.file.writeTypedArrayToFile(
    "caught.txt",
    encodeMessage(JSON.stringify(e.message)),
  );
  quit();
}

```