JS: clean up babel plugins (#8435)

This commit is contained in:
fisker Cheung authored and GitHub committed 2020-05-29 09:26:52 +08:00
1 parent fb9b10b180
commit e143e58545
33 files changed
+2216 -10

No files matched your search

+3 -9
View File
@@ -16,22 +16,16 @@ function babelOptions({ sourceType, extraPlugins = [] }) {
errorRecovery: true,
createParenthesizedExpressions: true,
plugins: [
// When adding a plugin, please add a test in `tests/js/babel-plugins`,
// To remove plugins, remove it here and run `yarn test tests/js/babel-plugins` to verify
"doExpressions",
"objectRestSpread",
"classProperties",
"exportDefaultFrom",
"exportNamespaceFrom",
"asyncGenerators",
"functionBind",
"functionSent",
"dynamicImport",
"numericSeparator",
"importMeta",
"optionalCatchBinding",
"optionalChaining",
"classPrivateProperties",
"nullishCoalescingOperator",
"bigInt",
"throwExpressions",
"logicalAssignment",
"classPrivateMethods",
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,6 @@
// https://babeljs.io/docs/en/babel-plugin-proposal-async-generator-functions
async function* agf() {
await 1;
yield 2;
}
+128
View File
@@ -0,0 +1,128 @@
// 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
@@ -0,0 +1,26 @@
// https://babeljs.io/docs/en/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"
+29
View File
@@ -0,0 +1,29 @@
// https://babeljs.io/docs/en/babel-plugin-proposal-decorators
@annotation
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;
}
}
+11
View File
@@ -0,0 +1,11 @@
// https://babeljs.io/docs/en/babel-plugin-proposal-do-expressions
let a = do {
if(x > 10) {
'big';
} else {
'small';
}
};
// is equivalent to:
let a = x > 10 ? 'big' : 'small';
+8
View File
@@ -0,0 +1,8 @@
// https://babeljs.io/docs/en/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));
@@ -0,0 +1,4 @@
// https://babeljs.io/docs/en/babel-plugin-proposal-export-default-from
export v from 'mod';
@@ -0,0 +1,3 @@
// https://babeljs.io/docs/en/babel-plugin-proposal-export-namespace-from
export * as ns from 'mod';
+3
View File
@@ -0,0 +1,3 @@
// https://babeljs.io/docs/en/babel-preset-flow
function foo(one: any, two: number, three?): string {}
+17
View File
@@ -0,0 +1,17 @@
// https://babeljs.io/docs/en/babel-plugin-proposal-function-bind
obj::func
// 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)
+10
View File
@@ -0,0 +1,10 @@
// https://babeljs.io/docs/en/babel-plugin-proposal-function-sent
function* generator() {
console.log("Sent", function.sent);
console.log("Yield", yield);
}
const iterator = generator();
iterator.next(1); // Logs "Sent 1"
iterator.next(2); // Logs "Yield 2"
+18
View File
@@ -0,0 +1,18 @@
// https://babeljs.io/docs/en/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
View File
@@ -0,0 +1,4 @@
// Only testing babel parsing
// Do not add extra parsers here
run_spec(__dirname, ["babel", "babel-ts", "babel-flow"]);
+6
View File
@@ -0,0 +1,6 @@
// https://babeljs.io/docs/en/babel-plugin-syntax-jsx
var profile = <div>
<img src="avatar.png" className="profile" />
<h3>{[user.firstName, user.lastName].join(' ')}</h3>
</div>;
@@ -0,0 +1,7 @@
// https://babeljs.io/docs/en/babel-plugin-proposal-logical-assignment-operators
a ||= b;
obj.a.b ||= c;
a &&= b;
obj.a.b &&= c;
@@ -0,0 +1,3 @@
// https://babeljs.io/docs/en/babel-plugin-proposal-nullish-coalescing-operator
var foo = object.foo ?? "default";
@@ -0,0 +1,36 @@
// https://babeljs.io/docs/en/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
@@ -0,0 +1,9 @@
// https://babeljs.io/docs/en/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 }
@@ -0,0 +1,15 @@
// https://babeljs.io/docs/en/babel-plugin-proposal-optional-catch-binding
try {
throw 0;
} catch {
doSomethingWhichDoesNotCareAboutTheValueThrown();
}
try {
throw 0;
} catch {
doSomethingWhichDoesNotCareAboutTheValueThrown();
} finally {
doSomeCleanup();
}
@@ -0,0 +1,76 @@
// https://babeljs.io/docs/en/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 obj = {
foo: {
bar: {
baz() {
return 42;
},
},
},
};
const baz = obj?.foo?.bar?.baz(); // 42
const safe = obj?.qux?.baz(); // undefined
const safe2 = 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 obj = {
foo: {
bar: {
baz: class {
},
},
},
};
const baz = new obj?.foo?.bar?.baz(); // baz instance
const safe = new obj?.qux?.baz(); // undefined
const safe2 = new obj?.foo.bar.qux?.(); // undefined
const willThrow = new obj?.foo.bar.qux(); // Error: not a constructor
// Top classes can be called directly, too.
class Test {
}
new Test?.(); // test instance
new exists?.(); // undefined
const obj = {
foo: {
bar: {}
},
};
const ret = delete obj?.foo?.bar?.baz; // true
@@ -0,0 +1,21 @@
// https://babeljs.io/docs/en/babel-plugin-proposal-partial-application
function add(x, y) { return x + y; }
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|
@@ -0,0 +1,34 @@
// https://babeljs.io/docs/en/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)));
@@ -0,0 +1,12 @@
// https://babeljs.io/docs/en/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,13 @@
// https://babeljs.io/docs/en/babel-plugin-proposal-pipeline-operator
// https://github.com/js-choi/proposal-smart-pipelines
value
|> await #
|> doubleSay(#, ', ')
|> capitalize // This is a function call.
|> # + '!'
|> new User.Message(#)
|> await #
|> console.log; // This is a method call.
// (The # token isn't final; it might instead be @ or ? or %.)
@@ -0,0 +1,55 @@
// https://github.com/tc39/proposal-private-fields-in-in
class C {
#brand;
static isC(obj) {
try {
obj.#brand;
return true;
} catch {
return false;
}
}
}
class C {
#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 C {
#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;
// }
// }
+18
View File
@@ -0,0 +1,18 @@
// https://babeljs.io/docs/en/babel-plugin-proposal-private-methods
// Test for `classPrivateProperties` and `classPrivateMethods`
class Counter extends HTMLElement {
#xValue = 0;
get #x() { return this.#xValue; }
set #x(value) {
this.#xValue = value;
window.requestAnimationFrame(
this.#render.bind(this));
}
#clicked() {
this.#x++;
}
}
@@ -0,0 +1,5 @@
// https://babeljs.io/docs/en/babel-plugin-proposal-throw-expressions
function test(param = throw new Error('required!')) {
const test = param === true || throw new Error('Falsy!');
}
+3
View File
@@ -0,0 +1,3 @@
// https://babeljs.io/docs/en/babel-preset-typescript
const x: number = 0;
+25
View File
@@ -0,0 +1,25 @@
// https://github.com/babel/babel/pull/10148
%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()
@@ -22,6 +22,52 @@ exports[`partial-template-strings.js error test 1`] = `
9 | Diagnostics.name_not_found(\\"foo\\"); // \\"'foo' not found.\\""
`;
exports[`snippet: #0 error test 1`] = `
"Binding should be performed on object property. (1:3)
> 1 | ::%DebugPrint(null)
| ^"
`;
exports[`snippet: #1 error test 1`] = `
"Unexpected token (1:3)
> 1 | a.%DebugPrint();
| ^"
`;
exports[`snippet: #2 error test 1`] = `
"Unexpected token (1:11)
> 1 | const i = %DebugPrint;
| ^"
`;
exports[`snippet: #3 error test 1`] = `
"Unexpected token (1:7)
> 1 | f(x + ?)
| ^"
`;
exports[`snippet: #4 error test 1`] = `
"Unexpected token (1:5)
> 1 | x + ?
| ^"
`;
exports[`snippet: #5 error test 1`] = `
"Unexpected token (1:1)
> 1 | ?.f()
| ^"
`;
exports[`snippet: #6 error test 1`] = `
"Unexpected token (5:12)
3 |
4 | static isC(obj) {
> 5 | return try obj.#brand;
| ^
6 | }
7 | }"
`;
exports[`static-import-source-should-not-has-extra-token.js error test 1`] = `
"Unexpected token (4:16)
2 | // be parenthesized, that accidentally break #8016
+33 -1
View File
@@ -1 +1,33 @@
run_spec(__dirname, ["babel"]);
const { outdent } = require("outdent");
run_spec(
{
dirname: __dirname,
snippets: [
// v8intrinsic
"::%DebugPrint(null)",
"a.%DebugPrint();",
"const i = %DebugPrint;",
// partialApplication
// https://babeljs.io/docs/en/babel-plugin-proposal-partial-application#invalid-usage
"f(x + ?)", // `?` not in top-level Arguments of call
"x + ?", // `?` not in top-level Arguments of call
"?.f()", // `?` not in top-level Arguments of call
// "new f(?)", // `?` not supported in `new`
// "super(?)", // `?` not supported in |SuperCall|
// https://github.com/tc39/proposal-private-fields-in-in#try-statement
outdent`
class C {
#brand;
static isC(obj) {
return try obj.#brand;
}
}
`,
],
},
["babel"]
);