Update Babel plugin tests (#20053)

This commit is contained in:
fisker Cheung authored and GitHub committed 2026-09-14 20:48:16 +08:00
1 parent 475893a105
commit 733f4e9604
57 files changed
+1308 -2872

No files matched your search

@@ -0,0 +1,41 @@
name: Update Babel plugin tests
on:
workflow_dispatch:
schedule:
# “At 00:00 on day-of-month 1 in July.” https://crontab.guru/#0_0_1_7_*
- cron: "0 0 1 7 *"
permissions:
pull-requests: write
contents: write
jobs:
run:
name: Update Babel plugin tests
if: github.event_name != 'schedule' || github.repository == 'prettier/prettier'
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Setup Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
cache: "yarn"
- name: Install Dependencies
run: yarn install --immutable
- name: Run script
run: node scripts/update-babel-plugin-tests.js
- name: Set current date env
run: echo "CURRENT_DATE=$(date +'%Y-%m-%d')" >> "$GITHUB_ENV"
- uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
with:
commit-message: Update Babel plugin tests (${{ env.CURRENT_DATE }})
branch: automated-cleanup-cspell-${{ env.CURRENT_DATE }}
branch-suffix: timestamp
title: Update Babel plugin tests (${{ env.CURRENT_DATE }})
+148
View File
@@ -0,0 +1,148 @@
#!/usr/bin/env node
import assert from "node:assert/strict";
import fs from "node:fs/promises";
import dashify from "dashify";
import { fromMarkdown } from "mdast-util-from-markdown";
import { gfmFromMarkdown } from "mdast-util-gfm";
import { gfm as gfmSyntax } from "micromark-extension-gfm";
import { outdent } from "outdent";
const testDirectory = new URL(
"../tests/format/js/babel-plugins/",
import.meta.url,
);
const docUrl =
"https://raw.githubusercontent.com/babel/website/HEAD/docs/parser.md";
const cacheFile = new URL("../.tmp/babel-parser-plugins.md", import.meta.url);
async function getDoc() {
let stat;
try {
stat = await fs.stat(cacheFile);
} catch {
// No op
}
if (stat) {
if (Date.now() - stat.mtimeMs < /* 60 minutes */ 60 * 60 * 1000) {
return fs.readFile(cacheFile, "utf8");
}
await fs.rm(cacheFile);
}
const response = await fetch(docUrl);
if (!response.ok) {
throw new Error(`Fetch '${docUrl}' failed.`);
}
const text = await response.text();
await fs.writeFile(cacheFile, text);
return text;
}
function* parseCodeExample(nodes) {
for (let index = 0; index < nodes.length; index++) {
const node = nodes[index];
if (node.type === "inlineCode") {
yield node.value;
} else if (node.type === "html" && node.value === "<code>") {
const valueNode = nodes[++index];
const closingTagNode = nodes[++index];
assert.equal(closingTagNode.type, "html");
assert.equal(closingTagNode.value, "</code>");
assert.equal(valueNode.type, "text");
yield valueNode.value;
} else {
assert.equal(node.type, "text");
assert.equal(node.value.trim(), ",");
}
}
}
function* parsePluginTable(text) {
const tree = fromMarkdown(text, {
extensions: [gfmSyntax()],
mdastExtensions: [gfmFromMarkdown()],
});
assert.equal(tree.children.length, 1);
assert.equal(tree.children[0].type, "table");
const table = tree.children[0];
assert.ok(table.children.length > 2);
for (const row of table.children.slice(1)) {
const [nameCell, exampleCell] = row.children;
assert.equal(nameCell.children[0].type, "inlineCode");
const name = nameCell.children[0].value;
assert.ok(/^[a-z\d]+$/i.test(name), name);
const comment = text
.slice(nameCell.position.start.offset + 1, nameCell.position.end.offset)
.trim();
yield {
name,
comment,
examples: parseCodeExample(exampleCell.children).toArray(),
};
}
}
async function clean() {
const files = await fs.readdir(testDirectory);
await Promise.all(
files
.filter(
(file) => !(file === "format.test.js" || file === "__snapshots__"),
)
.map((file) => fs.rm(new URL(file, testDirectory))),
);
}
function* getExamples(text) {
const matches = text.matchAll(
/(?<=\n)\| Name\s* \| Code Example \s* \|\n.*?(?=\n\n)/gs,
);
for (const [text] of matches) {
for (const { name, comment, examples } of parsePluginTable(text)) {
for (const [index, code] of examples.entries()) {
const filename = `${dashify(name)}${index === 0 ? "" : `-${index + 1}`}.js`;
yield { filename, name, comment, code };
}
}
}
}
async function updateBabelPluginTests() {
const text = await getDoc();
await Promise.all(
getExamples(text).map(({ filename, comment, code }) =>
fs.writeFile(
new URL(filename, testDirectory),
outdent`
/*
${comment}
*/
${code}
` + "\n",
),
),
);
}
await clean();
await updateBabelPluginTests();
+8 -2
View File
@@ -31,8 +31,14 @@ const parseOptions = {
createParenthesizedExpressions: true, createParenthesizedExpressions: true,
attachComment: false, attachComment: false,
plugins: [ plugins: [
// When adding a plugin, please add a test in `tests/format/js/babel-plugins`, /*
// To remove plugins, remove it here and run `yarn test tests/format/js/babel-plugins` to verify Add a plugin:
Please make sure a simple syntax test added in `tests/format/js/babel-plugins/`,
Run `node scripts/update-babel-plugin-tests.js` will add examples
from https://babel.dev/docs/babel-parser#plugins
Remove a plugin:
Remove it here and run `yarn test tests/format/js/babel-plugins` to verify
*/
"doExpressions", "doExpressions",
"exportDefaultFrom", "exportDefaultFrom",
"functionBind", "functionBind",
@@ -61,6 +61,7 @@ const disabledTests = new Map(
"js/await-expression/like-call.js", "js/await-expression/like-call.js",
"jsx/top-level-await/test.jsx", "jsx/top-level-await/test.jsx",
], ],
"babel-flow": ["js/babel-plugins/flow-comments.js"],
typescript: [], typescript: [],
yaml: [ yaml: [
// Bug: https://github.com/eemeli/yaml/issues/646 // Bug: https://github.com/eemeli/yaml/issues/646
File diff suppressed because it is too large. Load diff
@@ -1 +1,5 @@
async do { await requestAPI().json() }; /*
`asyncDoExpressions` ([proposal](https://github.com/tc39/proposal-async-do-expressions))
*/
async do { await requestAPI().json() }
@@ -1,6 +0,0 @@
// https://babeljs.io/docs/babel-plugin-proposal-async-generator-functions
async function* agf() {
await 1;
yield 2;
}
-128
View File
@@ -1,128 +0,0 @@
// https://github.com/tc39/proposal-bigint
const previousMaxSafe = BigInt(Number.MAX_SAFE_INTEGER);
// ↪ 9007199254740991
const maxPlusOne = previousMaxSafe + 1n;
// ↪ 9007199254740992n
const theFuture = previousMaxSafe + 2n;
// ↪ 9007199254740993n, this works now!
const multi = previousMaxSafe * 2n;
// ↪ 18014398509481982n
// `–` is not minus sign,
// SIC https://github.com/tc39/proposal-bigint#operators
// const subtr = multi – 10n;
// ↪ 18014398509481972n
const mod = multi % 10n;
// ↪ 2n
const bigN = 2n ** 54n;
// ↪ 18014398509481984n
bigN * -1n
// ↪ –18014398509481984n
0n === 0
// ↪ false
0n == 0
// ↪ true
1n < 2
// ↪ true
2n > 1
// ↪ true
2 > 2
// ↪ false
2n > 2
// ↪ false
2n >= 2
// ↪ true
const mixed = [4n, 6, -12n, 10, 4, 0, 0n];
// ↪ [4n, 6, -12n, 10, 4, 0, 0n]
mixed.sort();
// ↪ [-12n, 0, 0n, 10, 4n, 4, 6]
if (0n) {
console.log('Hello from the if!');
} else {
console.log('Hello from the else!');
}
// ↪ "Hello from the else!"
0n || 12n
// ↪ 12n
0n && 12n
// ↪ 0n
Boolean(0n)
// ↪ false
Boolean(12n)
// ↪ true
!12n
// ↪ false
!0n
// ↪ true
const view = new BigInt64Array(4);
// ↪ [0n, 0n, 0n, 0n]
view.length;
// ↪ 4
view[0];
// ↪ 0n
view[0] = 42n;
view[0];
// ↪ 42n
// Highest possible BigInt value that can be represented as a
// signed 64-bit integer.
const max = 2n ** (64n - 1n) - 1n;
view[0] = max;
view[0];
// ↪ 9_223_372_036_854_775_807n
view[0] = max + 1n;
view[0];
// ↪ -9_223_372_036_854_775_808n
// ^ negative because of overflow
1n + 2
// ↪ TypeError: Cannot mix BigInt and other types, use explicit conversions
1n * 2
// ↪ TypeError: Cannot mix BigInt and other types, use explicit conversions
+1n
// ↪ TypeError: Cannot convert a BigInt value to a number
Number(1n)
// ↪ 1
1n + '2'
// ↪ "12"
'2' + 1n
// ↪ "21"
const badPrecision = BigInt(9007199254740993);
// ↪9007199254740992n
const goodPrecision = BigInt('9007199254740993');
// ↪9007199254740993n
const alsoGoodPrecision = 9007199254740993n;
// ↪9007199254740993n
@@ -1,26 +0,0 @@
// https://babeljs.io/docs/babel-plugin-proposal-class-properties
class Bork {
//Property initializer syntax
instanceProperty = "bork";
boundFunction = () => {
return this.instanceProperty;
};
//Static class properties
static staticProperty = "babelIsCool";
static staticFunction = function() {
return Bork.staticProperty;
};
}
let myBork = new Bork;
//Property initializers are not on the prototype.
console.log(myBork.__proto__.boundFunction); // > undefined
//Bound functions are bound to the class instance.
console.log(myBork.boundFunction.call(undefined)); // > "bork"
//Static function exists on the class.
console.log(Bork.staticFunction()); // > "babelIsCool"
@@ -1,11 +0,0 @@
class C {
static #x = 42;
static y;
static {
try {
this.y = doSomethingWith(this.#x);
} catch {
this.y = "unknown";
}
}
}
@@ -1,3 +1,5 @@
class C extends HTMLElement { /*
accessor clicked = false; `decoratorAutoAccessors` ([proposal](https://github.com/tc39/proposal-decorators))
} */
class Example { @reactive accessor myBool = false; }
+4 -28
View File
@@ -1,29 +1,5 @@
// https://babeljs.io/docs/babel-plugin-proposal-decorators /*
`decorators` ([proposal](https://github.com/tc39/proposal-decorators)) <br/> `decorators-legacy`
*/
@annotation @a class A {}
class MyClass { }
function annotation(target) {
target.annotated = true;
}
@isTestable(true)
class MyClass { }
function isTestable(value) {
return function decorator(target) {
target.isTestable = value;
}
}
class C {
@enumerable(false)
method() { }
}
function enumerable(value) {
return function (target, key, descriptor) {
descriptor.enumerable = value;
return descriptor;
}
}
@@ -1 +1,5 @@
import defer * as ns from "x"; /*
`deferredImportEvaluation` ([proposal](https://github.com/tc39/proposal-defer-import-eval))
*/
import defer * as ns from "dep";
@@ -1,12 +1,5 @@
class Foo { /*
#x = 1; `destructuringPrivate` ([proposal](https://github.com/tc39/proposal-destructuring-private))
constructor() { */
console.log(this.#x); // => 1
const { #x: x } = this; class Example { #x = 1; method() { const { #x: x } = this; } }
console.log(x); // => 1
}
equals({ #x: otherX }) {
const { #x: currentX } = this;
return currentX === otherX;
}
}
@@ -1 +1,5 @@
const [a, void] = iter; /*
`discardBinding` ([proposal](https://github.com/tc39/proposal-discard-binding))
*/
using void = new Lock(mutex)
@@ -1,11 +1,5 @@
// https://babeljs.io/docs/babel-plugin-proposal-do-expressions /*
`doExpressions` ([proposal](https://github.com/tc39/proposal-do-expressions))
*/
let a = do { var a = do { if (true) { 'hi'; } };
if(x > 10) {
'big';
} else {
'small';
}
};
// is equivalent to:
let a = x > 10 ? 'big' : 'small';
@@ -1,8 +0,0 @@
// https://babeljs.io/docs/babel-plugin-syntax-dynamic-import
// There is no example code on babel website
import('./prettier.mjs');
import(prettier);
import('./prettier.mjs').then(module => console.log(module));
import(prettier).then(module => console.log(module));
@@ -1,12 +0,0 @@
function * g() {
using handle = acquireFileHandle(); // block-scoped critical resource
} // cleanup
{
using obj = g(); // block-scoped declaration
const r = obj.next();
} // calls finally blocks in `g`
{
await using obj = g();
}
@@ -1,4 +1,5 @@
// https://babeljs.io/docs/babel-plugin-proposal-export-default-from /*
`exportDefaultFrom` ([proposal](https://github.com/tc39/ecmascript-export-default-from))
*/
export v from "mod"
export v from 'mod';
@@ -1,3 +0,0 @@
// https://babeljs.io/docs/babel-plugin-proposal-export-namespace-from
export * as ns from 'mod';
@@ -0,0 +1,5 @@
/*
`flowComments` ([docs](https://flow.org/en/docs/types/comments/))
*/
/*:: type Foo = {...}; */
+4 -2
View File
@@ -1,3 +1,5 @@
// https://babeljs.io/docs/babel-preset-flow /*
`flow` ([repo](https://github.com/facebook/flow))
*/
function foo(one: any, two: number, three?): string {} var a: string = "";
+62 -87
View File
@@ -3,149 +3,124 @@
runFormatTest(import.meta, ["babel", "babel-ts", "babel-flow"], { runFormatTest(import.meta, ["babel", "babel-ts", "babel-flow"], {
errors: { errors: {
babel: ["flow.js", "typescript.js"],
__babel_estree: ["flow.js", "typescript.js"],
"babel-flow": [],
"babel-ts": [],
acorn: [ acorn: [
"async-do-expressions.js",
"decorator-auto-accessors.js",
"decorators.js", "decorators.js",
"deferred-import-evaluation.js",
"destructuring-private.js", "destructuring-private.js",
"discard-binding.js",
"do-expressions.js", "do-expressions.js",
"export-default-from.js", "export-default-from.js",
// "flow-comments.js",
"flow.js", "flow.js",
"function-bind.js", "function-bind.js",
"function-bind-2.js",
"function-sent.js", "function-sent.js",
"module-blocks.js",
"optional-chaining-assign.js",
"partial-application.js", "partial-application.js",
"pipeline-operator-fsharp.js", "pipeline-operator.js",
"pipeline-operator-minimal.js", "source-phase-imports.js",
"pipeline-operator-hack.cjs",
"throw-expressions.js", "throw-expressions.js",
"typescript.js", "typescript.js",
"v8intrinsic.js", "v8intrinsic.js",
"module-blocks.js",
"async-do-expressions.js",
"decorator-auto-accessors.js",
"source-phase-imports.js",
"deferred-import-evaluation.js",
"optional-chaining-assignment.js",
"discard-binding.js",
], ],
espree: [ espree: [
"decorators.js",
"destructuring-private.js",
"do-expressions.js",
"export-default-from.js",
"flow.js",
"function-bind.js",
"function-sent.js",
"partial-application.js",
"pipeline-operator-fsharp.js",
"pipeline-operator-minimal.js",
"pipeline-operator-hack.cjs",
"throw-expressions.js",
"typescript.js",
"v8intrinsic.js",
"module-blocks.js",
"async-do-expressions.js", "async-do-expressions.js",
"decorator-auto-accessors.js", "decorator-auto-accessors.js",
"source-phase-imports.js", "decorators.js",
"deferred-import-evaluation.js", "deferred-import-evaluation.js",
"optional-chaining-assignment.js",
"discard-binding.js",
],
meriyah: [
"do-expressions.js",
"destructuring-private.js", "destructuring-private.js",
"discard-binding.js",
"do-expressions.js",
"export-default-from.js", "export-default-from.js",
// "flow-comments.js",
"flow.js", "flow.js",
"function-bind.js", "function-bind.js",
"function-bind-2.js",
"function-sent.js", "function-sent.js",
"module-attributes-dynamic.js", "module-blocks.js",
"module-attributes-static.js", "optional-chaining-assign.js",
"partial-application.js", "partial-application.js",
"pipeline-operator-fsharp.js", "pipeline-operator.js",
"pipeline-operator-minimal.js", "source-phase-imports.js",
"pipeline-operator-hack.cjs",
"throw-expressions.js", "throw-expressions.js",
"typescript.js", "typescript.js",
"v8intrinsic.js", "v8intrinsic.js",
"module-blocks.js", ],
meriyah: [
"async-do-expressions.js", "async-do-expressions.js",
"optional-chaining-assignment.js", // "decorator-auto-accessors.js",
// "decorators.js",
// "deferred-import-evaluation.js",
"destructuring-private.js",
"discard-binding.js", "discard-binding.js",
"do-expressions.js",
"export-default-from.js",
// "flow-comments.js",
"flow.js",
"function-bind.js",
"function-bind-2.js",
"function-sent.js",
"module-blocks.js",
"optional-chaining-assign.js",
"partial-application.js",
"pipeline-operator.js",
// "source-phase-imports.js",
"throw-expressions.js",
"typescript.js",
"v8intrinsic.js",
], ],
oxc: [ oxc: [
"async-do-expressions.js", "async-do-expressions.js",
// "decorator-auto-accessors.js",
// "decorators.js",
// "deferred-import-evaluation.js",
"destructuring-private.js", "destructuring-private.js",
"discard-binding.js",
"do-expressions.js", "do-expressions.js",
"export-default-from.js", "export-default-from.js",
// "flow-comments.js",
"flow.js", "flow.js",
"function-bind.js", "function-bind.js",
"function-bind-2.js",
"function-sent.js", "function-sent.js",
"module-blocks.js", "module-blocks.js",
"optional-chaining-assignment.js", "optional-chaining-assign.js",
"partial-application.js", "partial-application.js",
"pipeline-operator-fsharp.js", "pipeline-operator.js",
"pipeline-operator-hack.cjs", // "source-phase-imports.js",
"pipeline-operator-minimal.js",
"throw-expressions.js", "throw-expressions.js",
"typescript.js", "typescript.js",
"v8intrinsic.js", "v8intrinsic.js",
"discard-binding.js",
],
"oxc-ts": [
"async-do-expressions.js",
"destructuring-private.js",
"do-expressions.js",
"export-default-from.js",
"flow.js",
"function-bind.js",
"function-sent.js",
"module-blocks.js",
"optional-chaining-assignment.js",
"partial-application.js",
"pipeline-operator-fsharp.js",
"pipeline-operator-hack.cjs",
"pipeline-operator-minimal.js",
"throw-expressions.js",
"typescript.js",
"v8intrinsic.js",
"discard-binding.js",
], ],
yuku: [ yuku: [
"async-do-expressions.js", "async-do-expressions.js",
// "decorator-auto-accessors.js",
// "decorators.js",
// "deferred-import-evaluation.js",
"destructuring-private.js", "destructuring-private.js",
"discard-binding.js",
"do-expressions.js", "do-expressions.js",
"export-default-from.js", "export-default-from.js",
// "flow-comments.js",
"flow.js", "flow.js",
"function-bind.js", "function-bind.js",
"function-bind-2.js",
"function-sent.js", "function-sent.js",
"module-blocks.js", "module-blocks.js",
"optional-chaining-assignment.js", "optional-chaining-assign.js",
"partial-application.js", "partial-application.js",
"pipeline-operator-fsharp.js", "pipeline-operator.js",
"pipeline-operator-hack.cjs", // "source-phase-imports.js",
"pipeline-operator-minimal.js",
"throw-expressions.js", "throw-expressions.js",
"typescript.js", "typescript.js",
"v8intrinsic.js", "v8intrinsic.js",
"discard-binding.js",
], ],
"yuku-ts": [
"async-do-expressions.js",
"destructuring-private.js",
"do-expressions.js",
"export-default-from.js",
"flow.js",
"function-bind.js",
"function-sent.js",
"module-blocks.js",
"optional-chaining-assignment.js",
"partial-application.js",
"pipeline-operator-fsharp.js",
"pipeline-operator-hack.cjs",
"pipeline-operator-minimal.js",
"throw-expressions.js",
"v8intrinsic.js",
"discard-binding.js",
],
babel: ["flow.js", "typescript.js"],
__babel_estree: ["flow.js", "typescript.js"],
}, },
}); });
@@ -0,0 +1,5 @@
/*
`functionBind` ([proposal](https://github.com/zenparsing/es-function-bind))
*/
::console.log
+4 -16
View File
@@ -1,17 +1,5 @@
// https://babeljs.io/docs/babel-plugin-proposal-function-bind /*
`functionBind` ([proposal](https://github.com/zenparsing/es-function-bind))
*/
obj::func a::b
// is equivalent to:
func.bind(obj)
::obj.func
// is equivalent to:
obj.func.bind(obj)
obj::func(val)
// is equivalent to:
func.call(obj, val)
::obj.func(val)
// is equivalent to:
obj.func.call(obj, val)
@@ -1,10 +1,5 @@
// https://babeljs.io/docs/babel-plugin-proposal-function-sent /*
`functionSent` ([proposal](https://github.com/tc39/proposal-function.sent))
*/
function* generator() { function* g() { function.sent }
console.log("Sent", function.sent);
console.log("Yield", yield);
}
const iterator = generator();
iterator.next(1); // Logs "Sent 1"
iterator.next(2); // Logs "Yield 2"
@@ -1 +0,0 @@
import("./foo.json", { assert: { type: "json" } });
@@ -1 +0,0 @@
import("./foo.json", { with: { type: "json" } });
@@ -1 +0,0 @@
import json from "./foo.json" with { type: "json" };
@@ -1,18 +0,0 @@
// https://babeljs.io/docs/babel-plugin-syntax-import-meta
// Enabled by default https://github.com/babel/babel/pull/11406
// from https://github.com/tc39/proposal-import-meta
(async () => {
const response = await fetch(new URL("../hamsters.jpg", import.meta.url));
const blob = await response.blob();
const size = import.meta.scriptElement.dataset.size || 300;
const image = new Image();
image.src = URL.createObjectURL(blob);
image.width = image.height = size;
document.body.appendChild(image);
})();
+4 -5
View File
@@ -1,6 +1,5 @@
// https://babeljs.io/docs/babel-plugin-syntax-jsx /*
`jsx` ([repo](https://facebook.github.io/jsx/))
*/
var profile = <div> <a attr="b">{s}</a>
<img src="avatar.png" className="profile" />
<h3>{[user.firstName, user.lastName].join(' ')}</h3>
</div>;
@@ -1,7 +0,0 @@
// https://babeljs.io/docs/babel-plugin-proposal-logical-assignment-operators
a ||= b;
obj.a.b ||= c;
a &&= b;
obj.a.b &&= c;
@@ -1,4 +1,5 @@
let m = module { /*
export let m = 2; `moduleBlocks` ([proposal](https://github.com/tc39/proposal-js-module-blocks))
export let n = 3; */
};
let m = module { export let y = 1; };
@@ -1,2 +0,0 @@
import { "😄" as smile } from "./emojis.js";
export { smile as "😄" } from "./emojis.js";
@@ -1,3 +0,0 @@
// https://babeljs.io/docs/babel-plugin-proposal-nullish-coalescing-operator
var foo = object.foo ?? "default";
@@ -1,36 +0,0 @@
// https://babeljs.io/docs/babel-plugin-proposal-numeric-separator
let budget = 1_000_000_000_000;
// What is the value of `budget`? It's 1 trillion!
//
// Let's confirm:
console.log(budget === 10 ** 12); // true
let nibbles = 0b1010_0001_1000_0101;
// Is bit 7 on? It sure is!
// 0b1010_0001_1000_0101
// ^
//
// We can double check:
console.log(!!(nibbles & (1 << 7))); // true
// Messages are sent as 24 bit values, but should be
// treated as 3 distinct bytes:
let message = 0xa0_b0_c0;
// What's the value of the upper most byte? It's A0, or 160.
// We can confirm that:
let a = (message >> 16) & 0xff;
console.log(a.toString(16), a); // a0, 160
// What's the value of the middle byte? It's B0, or 176.
// Let's just make sure...
let b = (message >> 8) & 0xff;
console.log(b.toString(16), b); // b0, 176
// What's the value of the lower most byte? It's C0, or 192.
// Again, let's prove that:
let c = message & 0xff;
console.log(c.toString(16), b); // c0, 192
@@ -1,9 +0,0 @@
// https://babeljs.io/docs/babel-plugin-transform-object-rest-spread
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
console.log(x); // 1
console.log(y); // 2
console.log(z); // { a: 3, b: 4 }
let n = { x, y, ...z };
console.log(n); // { x: 1, y: 2, a: 3, b: 4 }
@@ -1,15 +0,0 @@
// https://babeljs.io/docs/babel-plugin-proposal-optional-catch-binding
try {
throw 0;
} catch {
doSomethingWhichDoesNotCareAboutTheValueThrown();
}
try {
throw 0;
} catch {
doSomethingWhichDoesNotCareAboutTheValueThrown();
} finally {
doSomeCleanup();
}
@@ -0,0 +1,5 @@
/*
`optionalChainingAssign` ([proposal](https://github.com/tc39/proposal-optional-chaining-assignment))
*/
x?.prop = 2
@@ -1 +0,0 @@
maybeAnObj?.prop = theValue;
@@ -1,62 +0,0 @@
// https://babeljs.io/docs/babel-plugin-proposal-optional-chaining
const obj = {
foo: {
bar: {
baz: 42,
},
},
};
const baz = obj?.foo?.bar?.baz; // 42
const safe = obj?.qux?.baz; // undefined
// Optional chaining and normal chaining can be intermixed
obj?.foo.bar?.baz; // Only access `foo` if `obj` exists, and `baz` if
// `bar` exists
// Example usage with bracket notation:
obj?.['foo']?.bar?.baz // 42
const obj2 = {
foo: {
bar: {
baz() {
return 42;
},
},
},
};
const baz2 = obj?.foo?.bar?.baz(); // 42
const safe3 = obj?.qux?.baz(); // undefined
const safe4 = obj?.foo.bar.qux?.(); // undefined
const willThrow = obj?.foo.bar.qux(); // Error: not a function
// Top function can be called directly, too.
function test() {
return 42;
}
test?.(); // 42
exists?.(); // undefined
const obj3 = {
foo: {
bar: {
baz: class {
},
},
},
};
const obj4 = {
foo: {
bar: {}
},
};
const ret = delete obj?.foo?.bar?.baz; // true
@@ -1,21 +1,5 @@
// https://babeljs.io/docs/babel-plugin-proposal-partial-application /*
`partialApplication` ([proposal](https://github.com/babel/proposals/issues/32))
*/
function add(x, y) { return x + y; } f(?, a)
const addOne = add(1, ?); // apply from the left
addOne(2); // 3
const addTen = add(?, 10); // apply from the right
addTen(2); // 12
let newScore = player.score
|> add(7, ?)
|> clamp(0, 100, ?); // shallow stack, the pipe to `clamp` is the same frame as the pipe to `add`.
f(x, ?) // partial application from left
f(?, x) // partial application from right
f(?, x, ?) // partial application for any arg
o.f(x, ?) // partial application from left
o.f(?, x) // partial application from right
o.f(?, x, ?) // partial application for any arg
super.f(?) // partial application allowed for call on |SuperProperty|
@@ -1,34 +0,0 @@
// https://babeljs.io/docs/babel-plugin-proposal-pipeline-operator
// https://github.com/valtech-nyc/proposal-fsharp-pipelines
promise
|> await
|> x => doubleSay(x, ', ')
|> capitalize
|> x => x + '!'
|> x => new User.Message(x)
|> x => stream.write(x)
|> await
|> console.log;
const result = exclaim(capitalize(doubleSay("hello")));
result //=> "Hello, hello!"
const result = "hello"
|> doubleSay
|> capitalize
|> exclaim;
result //=> "Hello, hello!"
const person = { score: 25 };
const newScore = person.score
|> double
|> n => add(7, n)
|> n => boundScore(0, 100, n);
newScore //=> 57
// As opposed to:
let newScore = boundScore(0, 100, add(7, double(person.score)));
@@ -1,8 +0,0 @@
// https://babeljs.io/docs/babel-plugin-proposal-pipeline-operator
// https://github.com/js-choi/proposal-hack-pipes
return list
|> take(prefix.length, %)
|> equals(%, prefix);
// (The % token isn't final; it might instead be @ or ? or #.)
@@ -1,12 +0,0 @@
// https://babeljs.io/docs/babel-plugin-proposal-pipeline-operator
// https://github.com/tc39/proposal-pipeline-operator/
let result = exclaim(capitalize(doubleSay("hello")));
result //=> "Hello, hello!"
let result = "hello"
|> doubleSay
|> capitalize
|> exclaim;
result //=> "Hello, hello!"
@@ -0,0 +1,5 @@
/*
`pipelineOperator` ([proposal](https://github.com/babel/proposals/issues/29))
*/
a |> b
@@ -1,55 +0,0 @@
// https://github.com/tc39/proposal-private-fields-in-in
class C {
#brand;
static isC(obj) {
try {
obj.#brand;
return true;
} catch {
return false;
}
}
}
class C2 {
#data = null; // populated later
get #getter() {
if (!this.#data) {
throw new Error('no data yet!');
}
return this.#data;
}
static isC(obj) {
try {
obj.#getter;
return true;
} catch {
return false; // oops! might have gotten here because `#getter` threw :-(
}
}
}
class C3 {
#brand;
#method() {}
get #getter() {}
static isC(obj) {
return #brand in obj && #method in obj && #getter in obj;
}
}
// Invalid https://github.com/tc39/proposal-private-fields-in-in#try-statement
// class C {
// #brand;
// static isC(obj) {
// return try obj.#brand;
// }
// }
@@ -1,19 +0,0 @@
// https://babeljs.io/docs/babel-plugin-proposal-private-methods
// Test for `classPrivateProperties` and `classPrivateMethods`
class Counter extends HTMLElement {
#xValue = 0;
#render() {}
get #x() { return this.#xValue; }
set #x(value) {
this.#xValue = value;
window.requestAnimationFrame(
this.#render.bind(this));
}
#clicked() {
this.#x++;
}
}
@@ -1 +0,0 @@
/a/v;
@@ -1 +0,0 @@
const re = /^(?i:[a-z])[a-z]$/;
@@ -1,2 +1,5 @@
import source fooSource from "foo"; /*
import.source("x"); `sourcePhaseImports` ([proposal](https://github.com/tc39/proposal-source-phase-imports))
*/
import source x from "./x"
@@ -1,5 +1,5 @@
// https://babeljs.io/docs/babel-plugin-proposal-throw-expressions /*
`throwExpressions` ([proposal](https://github.com/babel/proposals/issues/23))
*/
function test(param = throw new Error('required!')) { () => throw new Error("")
const test = param === true || throw new Error('Falsy!');
}
+4 -2
View File
@@ -1,3 +1,5 @@
// https://babeljs.io/docs/babel-preset-typescript /*
`typescript` ([repo](https://github.com/Microsoft/TypeScript))
*/
const x: number = 0; var a: string = "";
+3 -23
View File
@@ -1,25 +1,5 @@
// https://github.com/babel/babel/pull/10148 /*
`v8intrinsic`
*/
%DebugPrint(foo); %DebugPrint(foo);
// Invalid code https://github.com/JLHwung/babel/blob/c1a3cbfd65e08b7013fd6f8c62add8cb10b4b169/packages/babel-parser/test/fixtures/v8intrinsic/_errors/in-bind-expression/options.json
// ::%DebugPrint(null)
// Invalid code https://github.com/JLHwung/babel/blob/c1a3cbfd65e08b7013fd6f8c62add8cb10b4b169/packages/babel-parser/test/fixtures/v8intrinsic/_errors/in-member-expression/options.json
// a.%DebugPrint();
// Invalid code https://github.com/JLHwung/babel/blob/c1a3cbfd65e08b7013fd6f8c62add8cb10b4b169/packages/babel-parser/test/fixtures/v8intrinsic/_errors/not-in-call-expression/options.json
// const i = %DebugPrint;
// i(foo);
// https://github.com/JLHwung/babel/blob/c1a3cbfd65e08b7013fd6f8c62add8cb10b4b169/packages/babel-parser/test/fixtures/v8intrinsic/_errors/not-in-call-expression/options.json
// %DebugPrint?.(null)
new %DebugPrint(null);
function *foo() {
yield %StringParseInt("42", 10)
}
foo%bar()
@@ -0,0 +1,155 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
exports[`function-sent.js format 1`] = `
====================================options=====================================
parsers: ["babel", "flow", "typescript"]
printWidth: 80 (default) |
=====================================input======================================
function *adder(total=0) {
let increment=1;
do {
switch (request = function.sent){
case undefined: break;
case "done": return total;
default: increment = Number(request);
}
yield total += increment;
} while (true)
}
=====================================output=====================================
function* adder(total = 0) {
let increment = 1;
do {
switch ((request = function.sent)) {
case undefined:
break;
case "done":
return total;
default:
increment = Number(request);
}
yield (total += increment);
} while (true);
}
================================================================================
`;
exports[`function-sent.js format[acorn] 1`] = `
"Unexpected token (4:34)
2 | let increment=1;
3 | do {
> 4 | switch (request = function.sent){
| ^
5 | case undefined: break;
6 | case "done": return total;
7 | default: increment = Number(request);
Cause: Unexpected token (4:33)"
`;
exports[`function-sent.js format[espree] 1`] = `
"Unexpected token . (4:34)
2 | let increment=1;
3 | do {
> 4 | switch (request = function.sent){
| ^
5 | case undefined: break;
6 | case "done": return total;
7 | default: increment = Number(request);
Cause: Unexpected token ."
`;
exports[`function-sent.js format[flow] 1`] = `
"Unexpected token \`.\`, expected an identifier (4:34)
2 | let increment=1;
3 | do {
> 4 | switch (request = function.sent){
| ^
5 | case undefined: break;
6 | case "done": return total;
7 | default: increment = Number(request);
Cause: Unexpected token \`.\`, expected an identifier (4:33)"
`;
exports[`function-sent.js format[hermes] 1`] = `
"'(' expected at start of function parameter list (4:34)
2 | let increment=1;
3 | do {
> 4 | switch (request = function.sent){
| ^
5 | case undefined: break;
6 | case "done": return total;
7 | default: increment = Number(request);
Cause: '(' expected at start of function parameter list (4:33)
switch (request = function.sent){
~~~~~~~~^"
`;
exports[`function-sent.js format[meriyah] 1`] = `
"Expected '(' (4:34)
2 | let increment=1;
3 | do {
> 4 | switch (request = function.sent){
| ^
5 | case undefined: break;
6 | case "done": return total;
7 | default: increment = Number(request);
Cause: [4:33-4:34]: Expected '('"
`;
exports[`function-sent.js format[oxc] 1`] = `
"Expected \`(\` but found \`.\` (4:34)
2 | let increment=1;
3 | do {
> 4 | switch (request = function.sent){
| ^
5 | case undefined: break;
6 | case "done": return total;
7 | default: increment = Number(request);"
`;
exports[`function-sent.js format[oxc-ts] 1`] = `
"Expected \`(\` but found \`.\` (4:34)
2 | let increment=1;
3 | do {
> 4 | switch (request = function.sent){
| ^
5 | case undefined: break;
6 | case "done": return total;
7 | default: increment = Number(request);"
`;
exports[`function-sent.js format[typescript] 1`] = `
"'(' expected. (4:34)
2 | let increment=1;
3 | do {
> 4 | switch (request = function.sent){
| ^
5 | case undefined: break;
6 | case "done": return total;
7 | default: increment = Number(request);
Cause: '(' expected."
`;
exports[`function-sent.js format[yuku] 1`] = `
"Expected '(' to start parameter list, but found '.' (4:34)
2 | let increment=1;
3 | do {
> 4 | switch (request = function.sent){
| ^
5 | case undefined: break;
6 | case "done": return total;
7 | default: increment = Number(request);"
`;
exports[`function-sent.js format[yuku-ts] 1`] = `
"Expected '(' to start parameter list, but found '.' (4:34)
2 | let increment=1;
3 | do {
> 4 | switch (request = function.sent){
| ^
5 | case undefined: break;
6 | case "done": return total;
7 | default: increment = Number(request);"
`;
@@ -0,0 +1,14 @@
runFormatTest(import.meta, ["babel", "flow", "typescript"], {
errors: {
flow: true,
typescript: true,
acorn: true,
espree: true,
meriyah: true,
oxc: true,
yuku: true,
"oxc-ts": true,
"yuku-ts": true,
hermes: true,
},
});
@@ -0,0 +1,11 @@
function *adder(total=0) {
let increment=1;
do {
switch (request = function.sent){
case undefined: break;
case "done": return total;
default: increment = Number(request);
}
yield total += increment;
} while (true)
}