Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Makefile.js

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions Makefile.source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -529,14 +529,14 @@ target["bootstrap-flow"] = function () {

target["new-version-checklist"] = function () {
// eslint-disable-next-line no-constant-condition
if (0) {
if (1) {
console.log(
`
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!! !!!!!!
!!!!!! Write any important message here, and change the !!!!!!
!!!!!! if (0) above to if (1) !!!!!!
!!!!!! Update the minVersion for the immutableUint8Array !!!!!!
!!!!!! helper !!!!!!
!!!!!! !!!!!!
!!!!!! !!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Expand Down
13 changes: 13 additions & 0 deletions packages/babel-helpers/src/helpers-generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -661,6 +661,19 @@ const helpers: Record<string, Helper> = {
dependencies: {},
internal: false,
}),
// size: 119, gzip size: 105
immutableUint8Array: helper(
"8.0.0-rc.2",
"function _immutableUint8Array(r){var t=r.buffer;return new Uint8Array(t.transferToImmutable?t.transferToImmutable():t)}",
{
globals: ["Uint8Array"],
locals: { _immutableUint8Array: ["body.0.id"] },
exportBindingAssignments: [],
exportName: "_immutableUint8Array",
dependencies: {},
internal: false,
},
),
// size: 537, gzip size: 258
importDeferProxy: helper(
"7.23.0",
Expand Down
16 changes: 16 additions & 0 deletions packages/babel-helpers/src/helpers/immutableUint8Array.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/* @minVersion 8.0.0-rc.2 */

declare global {
interface ArrayBuffer {
transferToImmutable?(): ArrayBuffer;
}
}

export default function _immutableUint8Array(
u8orNodeBuffer: Uint8Array<ArrayBuffer>,
) {
var buf = u8orNodeBuffer.buffer;
return new Uint8Array(
buf.transferToImmutable ? buf.transferToImmutable() : buf,
);
}
5 changes: 5 additions & 0 deletions packages/babel-plugin-proposal-bytes-modules/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
src
test
*.log
tsconfig.json
tsconfig.tsbuildinfo
19 changes: 19 additions & 0 deletions packages/babel-plugin-proposal-bytes-modules/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# @babel/plugin-proposal-bytes-modules

> Transform bytes modules imports (`import '...' with { type: 'bytes' }`) to work in browsers and Node.js.

See our website [@babel/plugin-proposal-bytes-modules](https://babeljs.io/docs/babel-plugin-proposal-bytes-modules) for more information.

## Install

Using npm:

```sh
npm install --save-dev @babel/plugin-proposal-bytes-modules
```

or using yarn:

```sh
yarn add @babel/plugin-proposal-bytes-modules --dev
```
51 changes: 51 additions & 0 deletions packages/babel-plugin-proposal-bytes-modules/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
{
"name": "@babel/plugin-proposal-bytes-modules",
"version": "8.0.0-rc.2",
"description": "Transform bytes modules imports (`import '...' with { type: 'bytes' }`) to work in browsers and Node.js.",
"repository": {
"type": "git",
"url": "https://github.com/babel/babel.git",
"directory": "packages/babel-plugin-proposal-bytes-modules"
},
"homepage": "https://babel.dev/docs/en/next/babel-plugin-proposal-bytes-modules",
"license": "MIT",
"publishConfig": {
"access": "public"
},
"main": "./lib/index.js",
"exports": {
".": {
"types": "./lib/index.d.ts",
"default": "./lib/index.js"
},
"./package.json": "./package.json"
},
"keywords": [
"babel-plugin",
"import",
"source",
"phase",
"wasm",
"WebAssembly",
"assertions",
"proposal",
"stage-3"
],
"dependencies": {
"@babel/helper-import-to-platform-api": "workspace:^",
"@babel/helper-plugin-utils": "workspace:^"
},
"peerDependencies": {
"@babel/core": "workspace:^"
},
"devDependencies": {
"@babel/core": "workspace:^",
"@babel/helper-plugin-test-runner": "workspace:^",
"babel-plugin-polyfill-corejs3": "^0.14.0"
},
"engines": {
"node": "^20.19.0 || >=22.12.0"
},
"author": "The Babel Team (https://babel.dev/team)",
"type": "module"
}
117 changes: 117 additions & 0 deletions packages/babel-plugin-proposal-bytes-modules/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import { declare } from "@babel/helper-plugin-utils";
import type { types as t, File } from "@babel/core";
import {
importToPlatformApi,
buildParallelStaticImports,
type Pieces,
type Builders,
} from "@babel/helper-import-to-platform-api";

export default declare(api => {
const { types: t, template } = api;
api.assertVersion(REQUIRED_VERSION("^8.0.0"));

const targets = api.targets();

let helperESM: Builders;
let helperCJS: Builders;

const transformers: Pieces = {
webFetch: (fetch, file) =>
template.expression.ast`
${fetch}.then(r => r.bytes()).then(${file.addHelper("immutableUint8Array")})
`,
nodeFsSync: (buf, file) =>
t.callExpression(file.addHelper("immutableUint8Array"), [buf]),
nodeFsAsync: file => file.addHelper("immutableUint8Array"),
};

const getHelper = (file: File) => {
const modules = file.get("@babel/plugin-transform-modules-*");
if (modules === "commonjs") {
return (helperCJS ??= importToPlatformApi(targets, transformers, true));
}
if (modules == null) {
return (helperESM ??= importToPlatformApi(targets, transformers, false));
}
throw new Error(
`@babel/plugin-proposal-bytes-modules can only be used when not ` +
`compiling modules, or when compiling them to CommonJS.`,
);
};

function getAttributeKey({ key }: t.ImportAttribute): string {
return t.isIdentifier(key) ? key.name : key.value;
}

function hasTypeBytes(attributes: t.ImportAttribute[]) {
return !!attributes?.some(
attr => getAttributeKey(attr) === "type" && attr.value.value === "bytes",
);
}

return {
name: "proposal-bytes-modules",

visitor: {
Program(path) {
if (path.node.sourceType !== "module") return;

const helper = getHelper(this.file);

const data = [];
for (const decl of path.get("body")) {
if (!decl.isImportDeclaration()) continue;
const attributes = decl.node.attributes || undefined;
if (!hasTypeBytes(attributes)) continue;

if (decl.node.phase != null) {
throw decl.buildCodeFrameError(
"Bytes modules do not support phase modifiers.",
);
}
if (attributes.length > 1) {
const paths = decl.get("attributes");
const index = getAttributeKey(attributes[0]) === "type" ? 1 : 0;
throw paths[index].buildCodeFrameError(
"Unknown attribute for bytes modules.",
);
}

let id: t.Identifier;
let needsNS = false;
for (const specifier of decl.get("specifiers")) {
if (specifier.isImportSpecifier()) {
throw specifier.buildCodeFrameError(
"Bytes modules do not support named imports.",
);
}

id = specifier.node.local;
needsNS = specifier.isImportNamespaceSpecifier();
}
id ??= path.scope.generateUidIdentifier("_");

let fetch = helper.buildFetch(decl.node.source, this.file);

if (needsNS) {
if (helper.needsAwait) {
fetch = template.expression.ast`
${fetch}.then(j => ({ default: j }))
`;
} else {
fetch = template.expression.ast`{ default: ${fetch} }`;
}
}

data.push({ id, fetch });
decl.remove();
}
if (data.length === 0) return;

const decl = buildParallelStaticImports(data, helper.needsAwait);
if (decl) path.unshiftContainer("body", decl);
},
},
};
});
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import j from "./x" with { type: "bytes" };
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"sourceType": "module",
"targets": []
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
const j = await (typeof process === "object" && process.versions?.node ? Promise.all([import("fs"), import("module")]).then(([fs, module]) => new Promise((a => (r, j) => fs.readFile(a, (e, d) => e ? j(e) : r(d)))(module.createRequire(import.meta.url).resolve("./x")))).then(_immutableUint8Array) : fetch(import.meta.resolve?.("./x") ?? new URL("./x", import.meta.url)).then(r => r.bytes()).then(_immutableUint8Array));
function _immutableUint8Array(r) { var t = r.buffer; return new Uint8Array(t.transferToImmutable ? t.transferToImmutable() : t); }
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import j from "./x" with { type: "bytes" };
someBody;
import j2 from "./x3" with { type: "bytes" };
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const [j, j2] = await Promise.all([typeof process === "object" && process.versions?.node ? import("fs").then(fs => fs.promises.readFile(new URL(import.meta.resolve("./x")))).then(_immutableUint8Array) : fetch(import.meta.resolve("./x")).then(r => r.bytes()).then(_immutableUint8Array), typeof process === "object" && process.versions?.node ? import("fs").then(fs => fs.promises.readFile(new URL(import.meta.resolve("./x3")))).then(_immutableUint8Array) : fetch(import.meta.resolve("./x3")).then(r => r.bytes()).then(_immutableUint8Array)]);
function _immutableUint8Array(r) { var t = r.buffer; return new Uint8Array(t.transferToImmutable ? t.transferToImmutable() : t); }
someBody;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import * as ns from "./x" with { type: "bytes" };
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
const ns = await (typeof process === "object" && process.versions?.node ? import("fs").then(fs => fs.promises.readFile(new URL(import.meta.resolve("./x")))).then(_immutableUint8Array) : fetch(import.meta.resolve("./x")).then(r => r.bytes()).then(_immutableUint8Array)).then(j => ({
default: j
}));
function _immutableUint8Array(r) { var t = r.buffer; return new Uint8Array(t.transferToImmutable ? t.transferToImmutable() : t); }
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import j from "./x" with { type: "bytes" };
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
const j = await (typeof process === "object" && process.versions?.node ? import("fs").then(fs => fs.promises.readFile(new URL(import.meta.resolve("./x")))).then(_immutableUint8Array) : fetch(import.meta.resolve("./x")).then(r => r.bytes()).then(_immutableUint8Array));
function _immutableUint8Array(r) { var t = r.buffer; return new Uint8Array(t.transferToImmutable ? t.transferToImmutable() : t); }
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// TODO: Not supported yet
let promise = import("./x", { with: { type: "bytes" } });
Comment on lines +1 to +2
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We also do not support this for JSON yet.

Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// TODO: Not supported yet
let promise = import("./x", {
with: {
type: "bytes"
}
});
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import j from "./x" with { type: "bytes" };
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"targets": { "firefox": "90", "node": "20.0" }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
const j = await (typeof process === "object" && process.versions?.node ? Promise.all([import("fs"), import("module")]).then(([fs, module]) => fs.promises.readFile(module.createRequire(import.meta.url).resolve("./x"))).then(_immutableUint8Array) : fetch(import.meta.resolve?.("./x") ?? new URL("./x", import.meta.url)).then(r => r.bytes()).then(_immutableUint8Array));
function _immutableUint8Array(r) { var t = r.buffer; return new Uint8Array(t.transferToImmutable ? t.transferToImmutable() : t); }
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import j from "./x" with { type: "bytes" };
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"targets": { "firefox": "90", "node": "20.6" }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
const j = await (typeof process === "object" && process.versions?.node ? import("fs").then(fs => fs.promises.readFile(new URL(import.meta.resolve("./x")))).then(_immutableUint8Array) : fetch(import.meta.resolve?.("./x") ?? new URL("./x", import.meta.url)).then(r => r.bytes()).then(_immutableUint8Array));
function _immutableUint8Array(r) { var t = r.buffer; return new Uint8Array(t.transferToImmutable ? t.transferToImmutable() : t); }
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import j from "./x" with { type: "bytes" };
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"targets": { "firefox": "110", "node": "20.0" }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
const j = await (typeof process === "object" && process.versions?.node ? Promise.all([import("fs"), import("module")]).then(([fs, module]) => fs.promises.readFile(module.createRequire(import.meta.url).resolve("./x"))).then(_immutableUint8Array) : fetch(import.meta.resolve("./x")).then(r => r.bytes()).then(_immutableUint8Array));
function _immutableUint8Array(r) { var t = r.buffer; return new Uint8Array(t.transferToImmutable ? t.transferToImmutable() : t); }
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import j from "./x" with { type: "bytes" };
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"targets": { "firefox": "110", "node": "9.0" }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
const j = await (typeof process === "object" && process.versions?.node ? Promise.all([import("fs"), import("module")]).then(([fs, module]) => new Promise((a => (r, j) => fs.readFile(a, (e, d) => e ? j(e) : r(d)))(module.createRequire(import.meta.url).resolve("./x")))).then(_immutableUint8Array) : fetch(import.meta.resolve("./x")).then(r => r.bytes()).then(_immutableUint8Array));
function _immutableUint8Array(r) { var t = r.buffer; return new Uint8Array(t.transferToImmutable ? t.transferToImmutable() : t); }
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"sourceType": "module",
"targets": { "firefox": "110", "node": "20.6" },
"plugins": ["proposal-bytes-modules"]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import bytes from "./x" with { type: "bytes" };
import json from "./x" with { type: "json" };
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"sourceType": "module",
"targets": { "firefox": "110", "node": "20.6" },
"plugins": ["proposal-bytes-modules", "transform-json-modules"]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const json = await (typeof process === "object" && process.versions?.node ? import("fs").then(fs => fs.promises.readFile(new URL(import.meta.resolve("./x")))).then(JSON.parse) : fetch(import.meta.resolve("./x")).then(r => r.json()));
const bytes = await (typeof process === "object" && process.versions?.node ? import("fs").then(fs => fs.promises.readFile(new URL(import.meta.resolve("./x")))).then(_immutableUint8Array) : fetch(import.meta.resolve("./x")).then(r => r.bytes()).then(_immutableUint8Array));
function _immutableUint8Array(r) { var t = r.buffer; return new Uint8Array(t.transferToImmutable ? t.transferToImmutable() : t); }
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import j from "./x" with { type: "bytes" };
someBody;
import j2 from "./x2" with { type: "bytes" };
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"throws": "Cannot compile to CommonJS, since it would require top-level await."
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import * as ns from "./x" with { type: "bytes" };
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"throws": "Cannot compile to CommonJS, since it would require top-level await."
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import j from "./x" with { type: "bytes" };
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"throws": "Cannot compile to CommonJS, since it would require top-level await."
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// TODO: Not supported yet
let promise = import("./x", { with: { type: "bytes" } });
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
"use strict";

// TODO: Not supported yet
let promise = import("./x", {
with: {
type: "bytes"
}
});
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import j from "./x" with { type: "bytes" };
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"targets": { "firefox": "90" },
"throws": "Cannot compile to CommonJS, since it would require top-level await."
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"sourceType": "module",
"targets": { "firefox": "110" },
"plugins": ["proposal-bytes-modules", "transform-modules-commonjs"]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import j from "./x" with { type: "bytes" };
someBody;
import j2 from "./x2" with { type: "bytes" };
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const [j, j2] = await Promise.all([fetch(import.meta.resolve("./x")).then(r => r.bytes()).then(_immutableUint8Array), fetch(import.meta.resolve("./x2")).then(r => r.bytes()).then(_immutableUint8Array)]);
function _immutableUint8Array(r) { var t = r.buffer; return new Uint8Array(t.transferToImmutable ? t.transferToImmutable() : t); }
someBody;
Loading
Loading