Skip to content

Commit 49e313e

Browse files
authored
Uint8Array => Immutable ArrayBuffer (#7)
- Closes #2 - Closes #5
1 parent 6d3286f commit 49e313e

File tree

1 file changed

+39
-32
lines changed

1 file changed

+39
-32
lines changed

README.md

Lines changed: 39 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,79 +1,79 @@
1-
# Proposal Import Bytes
1+
# Proposal Import Buffer
22

3-
Champions: Steven ([@styfle](https://github.com/styfle))
3+
Champions: [@styfle](https://github.com/styfle)
44

55
Status: Stage 0.
66

7-
Please leave any feedback you have in the [issues](https://github.com/styfle/proposal-import-bytes/issues)!
7+
Please leave any feedback in the [issues](https://github.com/styfle/proposal-import-bytes/issues), thanks!
88

99
## Synopsis
1010

11-
This proposal is buit on top of the the [import attributes proposal](https://github.com/tc39/proposal-import-attributes) to add the ability to import arbitrary bytes in a common way across JavaScript environments.
11+
This proposal is buit on top of [import attributes](https://github.com/tc39/proposal-import-attributes) and [immutable arraybuffer](https://github.com/tc39/proposal-immutable-arraybuffer) to add the ability to import arbitrary bytes in a common way across JavaScript environments.
1212

13-
Developers will then be able to import bytes as follows:
13+
Developers will then be able to import the buffer as follows:
1414

1515
```js
16-
import bytes from "./photo.png" with { type: "bytes" };
17-
import("photo.png", { with: { type: "bytes" } });
16+
import buffer from "./photo.png" with { type: "buffer" };
17+
import("photo.png", { with: { type: "buffer" } });
1818
```
1919

2020
Note: a similar proposal was mentioned in https://github.com/whatwg/html/issues/9444
2121

2222
## Motivation
2323

24-
In a similar manner to why JSON modules are useful, importing raw bytes is useful to extend this behavior to all files. This provides an isomorphic way to read a file, regardless of the JavaScript environment.
24+
In a similar manner to why JSON modules are useful, importing raw bytes is useful to extend this behavior to all files. This proposal provides an isomorphic way to read a file, regardless of the JavaScript environment.
2525

26-
For example, a developer may want to read a `.png` file to process an image or `.woff` to process a font and pass the bytes into using isomorphic tools like [satori](https://github.com/vercel/satori).
26+
For example, a developer may want to read a `.png` file to process an image or `.woff` to process a font and pass the buffer into isomorphic tools like [satori](https://github.com/vercel/satori).
2727

28-
Today, the developer must detect the platform in order to read the bytes.
28+
Today, the developer must detect the platform in order to read the buffer.
2929

3030
```js
31-
async function getBytes(path) {
31+
async function getBuffer(path) {
3232
if (typeof Deno !== "undefined") {
33-
const bytes = await Deno.readFile(path);
34-
return bytes;
33+
const result = await Deno.readFile(path);
34+
return result.buffer;
3535
}
3636
if (typeof Bun !== "undefined") {
37-
const bytes = await Bun.file(path).bytes();
38-
return bytes;
37+
const buffer = await Bun.file(path).arrayBuffer();
38+
return buffer;
3939
}
4040
if (typeof require !== "undefined") {
4141
const fs = require("fs/promises");
42-
const bytes = await fs.readFile(path);
43-
return bytes;
42+
const result = await fs.readFile(path);
43+
return result.buffer;
4444
}
4545
if (typeof window !== "undefined") {
4646
const response = await fetch(path);
47-
const bytes = await response.bytes();
48-
return bytes;
47+
const buffer = await response.arrayBuffer();
48+
return buffer;
4949
}
5050
throw new Error("Unsupported runtime");
5151
}
5252

53-
const bytes = await getBytes("./photo.png");
53+
const buffer = await getBuffer("./photo.png");
5454
```
5555

5656
We can maximize portability and reduce boilerplate by turning this into a single line of code:
5757

5858
```js
59-
import bytes from "./photo.png" with { type: "bytes" };
59+
import buffer from "./photo.png" with { type: "buffer" };
6060
```
6161

6262
Using an import also provides opportunity for further optimizations when using a bundler. For example, bundlers can statically analyze this import and inline as base64.
6363

6464
```js
65-
const bytes = Uint8Array.fromBase64("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkqAcAAIUAgUW0RjgAAAAASUVORK5CYII=")
65+
const buffer = Uint8Array.fromBase64("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkqAcAAIUAgUW0RjgAAAAASUVORK5CYII=").buffer.transferToImmutable()
6666
```
6767

6868
## Proposed semantics and interoperability
6969

70-
If a module import has an attribute with key `type` and value `bytes`, the host is required to either fail the import, or treat it as a Uint8Array. The Uint8Array object is the default export of the module (which has no named exports).
70+
If a module import has an attribute with key `type` and value `buffer`, the host is required to either fail the import, or treat it as an immutable ArrayBuffer. The ArrayBuffer object is the default export of the module (which has no named exports).
7171

7272
In browser environments, this will be equivalent to `fetch()` such that `sec-fetch-dest` will be empty. The response `content-type` will be ignored.
7373

7474
In "local" desktop/server/embedded, this will be equivalent to a file read. The file extension will be ignored.
7575

76-
All of the import statements in the module graph that address the same module will evaluate to the same mutable Uint8Array object.
76+
All of the import statements in the module graph that address the same module will evaluate to the same immutable ArrayBuffer object.
7777

7878
## FAQ
7979

@@ -119,18 +119,25 @@ Moddable added a [Resource](https://www.moddable.com/documentation/files/files#r
119119
let resource = new Resource("logo.bmp");
120120
```
121121

122-
### What about ArrayBuffer vs Uint8Array?
122+
### Why not mutable?
123123

124-
Both are viable solutions. Uint8Array matches the [Response.bytes()](https://developer.mozilla.org/en-US/docs/Web/API/Response/bytes) method return type as well as [Deno's implementation](https://deno.com/blog/v2.4#importing-text-and-bytes). Uint8Array is also compatible with [Node.js Buffer](https://nodejs.org/api/buffer.html#buffer) which makes it widely compatible with existing JavaScript code.
124+
Mutable can be problematic for several reasons:
125125

126-
This is currently being discussed in https://github.com/styfle/proposal-import-bytes/issues/5
126+
- may need multiple copies of the buffer in memory to avoid different underlying bytes for `import(specifier, { type: "json" })` and `import(specifier, { type: "buffer" })`
127+
- may cause unexpected behavior when multiple modules import the same buffer and detach (say `postMessage()` or `transferToImmutable()`) in one module which would cause it to become detached in the other module too
128+
- may cause excessive RAM usage for embedded system (immutable could use ROM instead)
129+
- may cause excessive memory when tracking source maps
130+
- may cause an undeniable global communication channel
127131

128-
### What about Blob vs Uint8Array?
132+
See discussion in Issue https://github.com/styfle/proposal-import-bytes/issues/2 and https://github.com/styfle/proposal-import-bytes/issues/5
129133

130-
Blob is part of the W3C [File API](https://www.w3.org/TR/FileAPI/), not part of JavaScript so it is not a viable solution to include in a TC39 Proposal. Blob also includes a type and is immutable.
134+
### Why not Uint8Array?
131135

132-
### What about mutable vs immutable?
136+
Uint8Array is one array-like view of an underlying ArrayBuffer, but there are many views (see TypedArray) because there are many different ways that one might want to access the content of the buffer.
133137

134-
Both are viable solutions. Mutable would match the behavior of existing imports from [import attributes proposal](https://github.com/tc39/proposal-import-attributes) but there is still a possibility of making `bytes` default to immutable given the [proposal-immutable-arraybuffer](https://github.com/tc39/proposal-immutable-arraybuffer).
138+
See discussion in Issue https://github.com/styfle/proposal-import-bytes/issues/5
139+
140+
### Why not Blob?
141+
142+
Blob is part of the W3C [File API](https://www.w3.org/TR/FileAPI/), not part of JavaScript so it is not a viable solution to include in a TC39 Proposal.
135143

136-
Ideally there would be a separate proposal for a new `immutable` attribute.

0 commit comments

Comments
 (0)