A partial archive of discourse.wicg.io as of Saturday February 24, 2024.

[Proposal] requestNativeScripts() - Write, reference, execute native (shell) scripts in main thread, Worker, Worklet scope

guest271314
2019-09-29

API to write/read/execute native applications based on the concepts of Native File System, Native Messaging, MutationObserver, PerformanceObserver, inotifywait.

Problem

A problem that cannot current be solved without using a native application, or if preferred, a shell script.

Solution

Select a local directory to store and/or write and modify shell scripts to be executed, including using parameters passed from JavaScript contexts, whether Window, Worker, or Worklet, etc. scopes.

Observe the local directory for changes, for example, using inotifywait or similar directory and file change observing program to monitor (potentially recursively), which ultimately can be incorporated into source code shipped by the implementer.

Built on top of Native File System the user provides a name to the shell script (which can already exist in the directory where permission to read/write is requested). The user writes or modifies the shell script where an event is dispatched for each read/write. The written file is executed. When the supplied output file name is written the directory a Promise is resolved with value set to the output file name. Native File System can then be used to get the output file.

This solution avoids using an extension or app, a local server, or WASM, to execute and get output of native applications.

Example of the current implementation using Native Messaging, which demonstrates how the below algorithm can be implemented in order to omit the need for using Native Messaging

~/native-messaging-mkvmerge/host$ inotifywait -m -r --format ‘%:e %f’ ~/native-messaging-mkvmerge/host
Setting up watches. Beware: since -r was given, this may take a while! Watches established.
OPEN native-messaging-host.js
ACCESS native-messaging-host.js
CLOSE_NOWRITE:CLOSE native-messaging-host.js
OPEN native-messaging-host.js
ACCESS native-messaging-host.js
CLOSE_NOWRITE:CLOSE native-messaging-host.js
OPEN protocol.js
ACCESS protocol.js
CLOSE_NOWRITE:CLOSE protocol.js
OPEN:ISDIR
ACCESS:ISDIR
ACCESS:ISDIR
OPEN mkvmerge
ACCESS mkvmerge
CLOSE_NOWRITE:CLOSE mkvmerge
// …
OPEN merged.webm
ACCESS merged.webm
// …
ACCESS merged.webm
CLOSE_NOWRITE:CLOSE merged.webm
DELETE _YLXYCZLTY0KHJ00O.webm
DELETE _5D67C3V117PB8YCW.webm
OPEN:ISDIR
ACCESS:ISDIR
ACCESS:ISDIR
DELETE _EXGPUXEN6MW17I4A.webm
OPEN:ISDIR
ACCESS:ISDIR
ACCESS:ISDIR
ACCESS:ISDIR
CLOSE_NOWRITE:CLOSE:ISDIR
ACCESS:ISDIR
CLOSE_NOWRITE:CLOSE:ISDIR
OPEN:ISDIR
// …
ACCESS:ISDIR
CLOSE_NOWRITE:CLOSE:ISDIR
DELETE _VENHB8899Q4YRRGW.webm
// … await writeScript.execute() =>
// let dir = await self.chooseFileSystemEntries({type: “openDirectory”}) =>
// let result = await dir.getFile(<${outputFileName /* merged.webm */}>) =>
// done.
DELETE merged.webm

The basic algorithm

Context: Window, WorkerGlobalScope, WorkletGlobalScope

  1. let outputFileName = "file.ext", scriptName = "doStuff"
  2. let nativeScripts = await self.requestNativeScripts(<Map> [[<${scriptName}>, "/path/to/local/directory/sciptName"]])
  3. let writeScript = await nativeScripts.get(<${scriptName}>).write("#!/bin/bash ... doStuff(<${outputFileName}>)")
  4. await writeScript.execute() // when outputFileName is written resolve Promise
  5. let dir = await self.chooseFileSystemEntries({type: "openDirectory"})
  6. let result = await dir.getFile(<${outputFileName}>) // get output of executed native application

Related

Explainer