Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use cases: Read stdin to V8's d8 shell in a Native Messaging host #45

Open
guest271314 opened this issue Jul 17, 2024 · 0 comments
Open

Comments

@guest271314
Copy link

[Use case 1]
[Provide example code snippets and diagrams explaining how the API would be used to solve the given problem]

Read standard input from Chromium or Firefox browsers to V8's d8 shell that is a Native Messaging host.

This is the Native Messaging protocol:

Native messaging protocol (Chrome Developers)

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.

This is why V8's d8's shell readline() function does not read "32-bit message length in native byte order" and proceed with reading the JSON content Implement reading STDIN to an ArrayBuffer. Precedent: writeFile("/proc/self/fd/1")

That's OK. As I told you before, d8 isn't trying to be a general-purpose shell; it's a tool for developing V8. If you want a V8-embedding shell that does more than d8 offers, find one or write your own.

What I'm currently doing with bash, which is really dash on the Linux machine I'm on

function getMessage(pid) {
  try {
    // readline() doesn't read past the Uint32Array equivalent message length
    // V8 authors are not interested in reading STDIN to an ArrayBuffer in d8
    // https://groups.google.com/g/v8-users/c/NsnStT6bx3Y/m/Yr_Z1FwgAQAJ
    // Use dd https://pubs.opengroup.org/onlinepubs/9699919799/utilities/dd.html
    // or GNU Coreutils head https://www.gnu.org/software/coreutils/manual/html_node/head-invocation.html
    // # length=$(head -q -z --bytes=4 /proc/${pid}/fd/0 | od -An -td4 -)
    // # message=$(head -q -z --bytes=$((length)) /proc/${pid}/fd/0)
    // to get message length and return message from Bash script
    const stdin = (os.system("bash", [
      "--posix",
      "-c",
      `
  length=$(dd iflag=fullblock oflag=nocache conv=notrunc,fdatasync bs=4 count=1 if=/proc/${pid}/fd/0 | od -An -td4 -)
  message=$(dd iflag=fullblock oflag=nocache conv=notrunc,fdatasync bs=$((length)) count=1 if=/proc/${pid}/fd/0)
  echo "$message"`,
    ])).trim();
    if (stdin != undefined && stdin != null && stdin.length) {
      const message = encodeMessage(stdin.trim());
      // https://stackoverflow.com/a/58288413
      // const header = new Uint32Array([
      //  ((uint32) =>
      //    (uint32[3] << 24) |
      //    (uint32[2] << 16) |
      //    (uint32[1] << 8) |
      //    (uint32[0]))(Array.from({
      //    length: 4,
      //    }, (_, index) => (message.length >> (index * 8)) & 0xff)),
      // ]);
      // writeFile("messageLength.txt", encodeMessage(JSON.stringify(header)));
      return encodeMessage(stdin);
    } else {
      return;
    }
  } catch (e) {
    writeFile("getMessageError.txt", encodeMessage(e.message));
  }
}

Some prior art using WASI-SDK to compile C Native Messaging host to WASM and using wasmtime as the executable, https://github.com/guest271314/native-messaging-webassembly/blob/main/nm_c_wasm.sh, and WAT embedded in https://github.com/guest271314/native-messaging-webassembly/blob/main/nm_c_wat.sh.

Ideally this could be run using WebAssembly.compile() in a non-browser JavaScript engine shell or runtime environment; to read stardard input and write to standard output, without necessarily relying on an executable such as wasmtime, wasmer, or javy. Not sure if that is possible.

Just providing a use case for the placeholder. I've got some reading to do on "the Component Model wit language" to try to implement this in that format.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant