Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

A modest proposal for importing bytes in javascript

License

NotificationsYou must be signed in to change notification settings

tc39/proposal-import-bytes

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

26 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

A modest proposal for importing bytes in JavaScript.

Status

Synopsis

This proposal is built on top ofimport attributes andimmutable arraybuffer to add the ability to import arbitrary bytes with a common syntax across JavaScript environments.

Developers will then be able to import the bytes as follows:

importbytesfrom"./photo.png"with{type:"bytes"};constbytes=awaitimport("./photo.png",{with:{type:"bytes"}});

The bytes are returned as aUint8Array backed by animmutable arraybuffer.

Note: a similar proposal was mentioned inwhatwg/html#9444

Motivation

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 synchronously or asynchronously, regardless of the JavaScript environment.

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 isomorphic tools likesatori.

Today, the developer must detect the platform in order to read the bytes.

asyncfunctiongetBytes(path){if(typeofDeno!=="undefined"){constbytes=awaitDeno.readFile(path);returnbytes;}if(typeofBun!=="undefined"){constbytes=awaitBun.file(path).bytes();returnbytes;}if(typeofrequire!=="undefined"){constfs=require("fs/promises");constbytes=awaitfs.readFile(path);returnbytes;}if(typeofwindow!=="undefined"){constresponse=awaitfetch(path);constbytes=awaitresponse.bytes();returnbytes;}thrownewError("Unsupported runtime");}constbytes=awaitgetBytes("./photo.png");

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

importbytesfrom"./photo.png"with{type:"bytes"};

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.

constbytes=Uint8Array.fromBase64("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkqAcAAIUAgUW0RjgAAAAASUVORK5CYII=")

Proposed semantics and interoperability

If a module import has an attribute with keytype and valuebytes, the host is required to either fail the import, or treat it as a Uint8Array backed by an immutable ArrayBuffer. The Uint8Array object is the default export of the module (which has no named exports).

In browser environments, this will be equivalent tofetch() such thatsec-fetch-dest will be empty. The responsecontent-type will be ignored.

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

All of the import statements in the module graph that address the same module will evaluate to the same Uint8Array object.

FAQ

How would this proposal work with caching?

The determination of whether thetype attribute is part of the module cache key is left up to hosts (as it is for all import attributes).

For example,import "foo" andimport "foo" with { type: "bytes" } may return the same module in one host, and different modules with another host. Both are valid implementations.

However, a dynamic import and a static import with the sametype must return the same module, regardless of host.

See discussion in Issue#4

Is there any prior art?

Deno 2.4 added support inJuly 2025 to inline a Uint8Array

importimageBytesfrom"./image.png"with{type:"bytes"};

Bun 1.1.7 added a similar feature inMay 2024 to inline a string of text

importhtmlfrom"./index.html"with{type:"text"};

webpack addedasset modules to inline a base64 data URI viaurl-loader in 4.x and nowasset/inline in 5.x

importlogofrom"./images/logo.svg"

esbuild added abinary loader to inline a Uint8Array

importuint8arrayfrom"./example.data"

Parcel added adata url scheme to inline a base64 data URI

importbackgroundfrom"data-url:./background.png";

Moddable added aResource class to inline a host buffer for embedded systems

letresource=newResource("logo.bmp");

Why not mutable?

Mutable can be problematic for several reasons:

  • may need multiple copies of the buffer in memory to avoid different underlying bytes forimport(specifier, { type: "json" }) andimport(specifier, { type: "bytes" })
  • may cause unexpected behavior when multiple modules import the same buffer and detach (saypostMessage() ortransferToImmutable()) in one module which would cause it to become detached in the other module too
  • may cause excessive RAM usage for embedded system (immutable could use ROM instead)
  • may cause excessive memory when tracking source maps
  • may cause an undeniable global communication channel

See discussion in Issue#2 and#5

Why Uint8Array?

Uint8Array is compatible withNode.js Buffer which makes it widely compatible with existing JavaScript code.

Why not ArrayBuffer?

ArrayBuffers cannot be read from directly; the developer must create a view, such as a Uint8Array, to read data. Providing a Uint8Array avoids that additional effort.

This pattern is defined in theW3C design principals.

There was some discussion to switch to ArrayBuffer in Issue#5 however the plenary meeting reached concensus that Uint8Array is more desireable and the problems described in that issue can still be solved with Uint8Array, as long as it's backed by an Immutable ArrayBuffer.

Why not Blob?

Blob is part of the W3CFile API, not part of JavaScript, so it is not a viable solution to include in a TC39 Proposal. Furthermore, Blob typically includes a MIME Type but this proposal ignores the type.

Why not ReadableStream?

ReadableStream is part of the WHATWGStreams, not part of JavaScript, so it is not a viable solution to include in a TC39 Proposal. Furthermore, there isno helper method to turn a stream into a buffer so this won't solve the original motivation of writing isomorphic JavaScript.

See discussion in Issue#3

Why not a phase?

This proposal does not attempt to introduce a new phase like thesource orasset proposals.

A new phase would require a syntax change to JavaScript and causeSec-Fetch-Dest to be script instead of empty. It also introduces security implications since importing arbitrary code could be malicious.

See discussion in Issue#16

Whytype: bytes?

Thetype attribute is proposed the same reason that it was introduced withtype: json: to separate from code loading and provide a differentSec-Fetch-Dest.

Thetype: bytes name will be familiar to developers who are already usingResponse.bytes() as well asBlob.bytes() which both returnUint8Array.

About

A modest proposal for importing bytes in javascript

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks


[8]ページ先頭

©2009-2025 Movatter.jp