Skip to content

Commit

Permalink
chore: migrate codegen
Browse files Browse the repository at this point in the history
  • Loading branch information
SukkaW committed Oct 9, 2023
1 parent 88dba99 commit 61b26e4
Show file tree
Hide file tree
Showing 9 changed files with 222 additions and 235 deletions.
330 changes: 150 additions & 180 deletions create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { PathScurry } from 'path-scurry';
import colors from 'picocolors';
import { dequal } from 'dequal';
import { fileExists, compareAndWriteFile } from '@nolyfill/internal';
import { transform } from '@swc/core';

import type { PackageJson } from 'type-fest';

/**
Expand All @@ -32,157 +34,122 @@ interface VirtualPackage {
}

const autoGeneratedPackagesList = [
['array-includes', 'Array.prototype.includes', false],
['array.prototype.findlastindex', `Array.prototype.findLastIndex || function (callback, thisArg) {
for (let i = this.length - 1; i >= 0; i--) {
if (callback.call(thisArg, this[i], i, this)) return i;
}
return -1;
}`, false],
['array.prototype.findlast', `Array.prototype.findLast || function (callback, thisArg) {
for (let i = this.length - 1; i >= 0; i--) {
const value = this[i];
if (callback.call(thisArg, value, i, this)) return value;
}
return void undefined;
}`, false],
['array.prototype.at', `Array.prototype.at || function at(n) {
n = Math.trunc(n) || 0;
if (n < 0) n += this.length;
if (n < 0 || n >= this.length) return undefined;
return this[n];
}`, false],
['string.prototype.at', `String.prototype.at || function at(n) {
n = Math.trunc(n) || 0;
if (n < 0) n += this.length;
if (n < 0 || n >= this.length) return undefined;
return String.prototype.charAt.call(this, n);
}`, false],
['array.prototype.flat', 'Array.prototype.flat', false],
['array.prototype.flatmap', 'Array.prototype.flatMap', false],
['arraybuffer.prototype.slice', 'ArrayBuffer.prototype.slice', false],
['function.prototype.name', 'Function.prototype.name', false],
['has', 'Object.prototype.hasOwnProperty', false],
['object-keys', 'Object.keys', true],
['object.assign', 'Object.assign', true],
['object.entries', 'Object.entries', true],
['object.fromentries', 'Object.fromEntries', true],
['object.hasown', 'Object.hasOwn || require(\'@nolyfill/shared\').uncurryThis(Object.prototype.hasOwnProperty)', true, { '@nolyfill/shared': 'workspace:*' }],
['object.values', 'Object.values', true],
['string.prototype.trim', 'String.prototype.trim', false],
['string.prototype.trimend', 'String.prototype.trimEnd', false],
['string.prototype.trimstart', 'String.prototype.trimStart', false],
['string.prototype.trimleft', 'String.prototype.trimLeft', false],
['string.prototype.trimright', 'String.prototype.trimRight', false],
['string.prototype.matchall', 'String.prototype.matchAll', false],
['regexp.prototype.flags', 'RegExp.prototype.flags', false],
// ['globalthis', 'globalThis', true], // globalthis package's entrypoint is a function, not the implementation
['array.prototype.tosorted', `Array.prototype.toSorted || function (compareFn) {
const o = Object(this);
const l = Number(o.length);
const a = new Array(l);
for (let i = 0; i < l; i++) {
a[i] = o[i];
}
Array.prototype.sort.call(a, compareFn);
return a;
}`, false],
['object.groupby', `Object.groupBy || function (items, callbackfn) {
const o = Object.create(null);
let k = 0;
for (const value of items) {
const key = callbackfn(value, k++);
if (key in o) {
Array.prototype.push.call(o[key], value);
} else {
o[key] = [value];
}
}
return o;
}`, true],
['array.prototype.find', 'Array.prototype.find', false],
['array.from', 'Array.from', true],
['string.prototype.padend', 'String.prototype.padEnd', false],
['string.prototype.padstart', 'String.prototype.padStart', false],
['object.getownpropertydescriptors', 'Object.getOwnPropertyDescriptors', true],
['array.prototype.reduce', 'Array.prototype.reduce', false],
['object-is', 'Object.is', true],
['reflect.ownkeys', 'Reflect.ownKeys', true],
// ['array.prototype.filter', 'Array.prototype.filter', false],
['string.prototype.replaceall', 'String.prototype.replaceAll', false],
// ['array.prototype.map', 'Array.prototype.map', false],
['reflect.getprototypeof', 'Reflect.getPrototypeOf', true],
// ['object.getprototypeof', 'Object.getPrototypeOf', true]
['es-aggregate-error', `typeof AggregateError === 'function'
? AggregateError
: (() => {
function AggregateError(errors, message) {
const error = new Error(message);
Object.setPrototypeOf(error, AggregateError.prototype);
delete error.constructor;
Object.defineProperty(error, 'errors', { value: Array.from(errors) });
return error;
}
Object.defineProperty(AggregateError, 'prototype', { writable: false });
Object.defineProperties(AggregateError.prototype, {
constructor: {
enumerable: false,
configurable: true,
writable: true,
value: AggregateError
},
message: {
enumerable: false,
configurable: true,
writable: true,
value: ''
},
name: {
enumerable: false,
configurable: true,
writable: true,
value: 'AggregateError'
}
});
Object.setPrototypeOf(AggregateError.prototype, Error.prototype);
return AggregateError;
})()`, true],
['promise.any', `Promise.any || function any(iterable) {
const AggregateError = require('@nolyfill/es-aggregate-error/polyfill')();
const $reject = Promise.reject.bind(this);
const $resolve = Promise.resolve.bind(this);
const $all = Promise.all.bind(this);
try {
return $all(
Array.from(iterable)
.map((item) => $resolve(item).then(x => $reject(x), x => x))
).then(
(errors) => {
throw new AggregateError(errors, 'Every promise rejected');
},
x => x
);
} catch (e) {
return $reject(e);
}
}`, true, { '@nolyfill/es-aggregate-error': 'workspace:*' }, '>=12.4.0', 'Promise'],
['promise.allsettled', `Promise.allSettled || function allSettled(iterable) {
const $reject = Promise.reject.bind(this);
const $resolve = Promise.resolve.bind(this);
const $all = Promise.all.bind(this);
return $all(Array.from(iterable).map((item) => {
const p = $resolve(item);
try {
return p.then(
(value) => ({ status: 'fulfilled', value }),
(reason) => ({ status: 'rejected', reason })
);
} catch (e) {
return $reject(e);
}
}));
}`, true, {}, '>=12.4.0', 'Promise']
['array-includes'],
['array.prototype.findlastindex'],
['array.prototype.findlast'],
['array.prototype.at']
// ['string.prototype.at', `String.prototype.at || function at(n) {
// n = Math.trunc(n) || 0;
// if (n < 0) n += this.length;
// if (n < 0 || n >= this.length) return undefined;
// return String.prototype.charAt.call(this, n);
// }`, false],
// ['array.prototype.flat', 'Array.prototype.flat', false],
// ['array.prototype.flatmap', 'Array.prototype.flatMap', false],
// ['arraybuffer.prototype.slice', 'ArrayBuffer.prototype.slice', false],
// ['function.prototype.name', 'Function.prototype.name', false],
// ['has', 'Object.prototype.hasOwnProperty', false],
// ['object-keys', 'Object.keys', true],
// ['object.assign', 'Object.assign', true],
// ['object.entries', 'Object.entries', true],
// ['object.fromentries', 'Object.fromEntries', true],
// ['object.hasown', 'Object.hasOwn || require(\'@nolyfill/shared\').uncurryThis(Object.prototype.hasOwnProperty)', true, { '@nolyfill/shared': 'workspace:*' }],
// ['object.values', 'Object.values', true],
// ['string.prototype.trim', 'String.prototype.trim', false],
// ['string.prototype.trimend', 'String.prototype.trimEnd', false],
// ['string.prototype.trimstart', 'String.prototype.trimStart', false],
// ['string.prototype.trimleft', 'String.prototype.trimLeft', false],
// ['string.prototype.trimright', 'String.prototype.trimRight', false],
// ['string.prototype.matchall', 'String.prototype.matchAll', false],
// ['regexp.prototype.flags', 'RegExp.prototype.flags', false],
// // ['globalthis', 'globalThis', true], // globalthis package's entrypoint is a function, not the implementation
// ['array.prototype.tosorted', `Array.prototype.toSorted || function (compareFn) {
// const o = Object(this);
// const l = Number(o.length);
// const a = new Array(l);
// for (let i = 0; i < l; i++) {
// a[i] = o[i];
// }
// Array.prototype.sort.call(a, compareFn);
// return a;
// }`, false],
// ['object.groupby', `Object.groupBy || function (items, callbackfn) {
// const o = Object.create(null);
// let k = 0;
// for (const value of items) {
// const key = callbackfn(value, k++);
// if (key in o) {
// Array.prototype.push.call(o[key], value);
// } else {
// o[key] = [value];
// }
// }
// return o;
// }`, true],
// ['array.prototype.find', 'Array.prototype.find', false],
// ['array.from', 'Array.from', true],
// ['string.prototype.padend', 'String.prototype.padEnd', false],
// ['string.prototype.padstart', 'String.prototype.padStart', false],
// ['object.getownpropertydescriptors', 'Object.getOwnPropertyDescriptors', true],
// ['array.prototype.reduce', 'Array.prototype.reduce', false],
// ['object-is', 'Object.is', true],
// ['reflect.ownkeys', 'Reflect.ownKeys', true],
// // ['array.prototype.filter', 'Array.prototype.filter', false],
// ['string.prototype.replaceall', 'String.prototype.replaceAll', false],
// // ['array.prototype.map', 'Array.prototype.map', false],
// ['reflect.getprototypeof', 'Reflect.getPrototypeOf', true],
// // ['object.getprototypeof', 'Object.getPrototypeOf', true]
// ['es-aggregate-error', `typeof AggregateError === 'function'
// ? AggregateError
// : (() => {
// function AggregateError(errors, message) {
// const error = new Error(message);
// Object.setPrototypeOf(error, AggregateError.prototype);
// delete error.constructor;
// Object.defineProperty(error, 'errors', { value: Array.from(errors) });
// return error;
// }
// Object.defineProperty(AggregateError, 'prototype', { writable: false });
// Object.defineProperties(AggregateError.prototype, {
// constructor: {
// enumerable: false,
// configurable: true,
// writable: true,
// value: AggregateError
// },
// message: {
// enumerable: false,
// configurable: true,
// writable: true,
// value: ''
// },
// name: {
// enumerable: false,
// configurable: true,
// writable: true,
// value: 'AggregateError'
// }
// });
// Object.setPrototypeOf(AggregateError.prototype, Error.prototype);
// return AggregateError;
// })()`, true],
['promise.any', { '@nolyfill/es-aggregate-error': 'workspace:*' }, '>=12.4.0'],
// ['promise.allsettled', `Promise.allSettled || function allSettled(iterable) {
// const $reject = Promise.reject.bind(this);
// const $resolve = Promise.resolve.bind(this);
// const $all = Promise.all.bind(this);
// return $all(Array.from(iterable).map((item) => {
// const p = $resolve(item);
// try {
// return p.then(
// (value) => ({ status: 'fulfilled', value }),
// (reason) => ({ status: 'rejected', reason })
// );
// } catch (e) {
// return $reject(e);
// }
// }));
// }`, true, {}, '>=12.4.0', 'Promise']
] as const;

const singleFilePackagesList = [
Expand Down Expand Up @@ -555,16 +522,16 @@ const nonNolyfillPackagesList = [
...currentPackageJson,
overrides: allPackagesList
.reduce<Record<string, string>>((acc, packageName) => {
acc[packageName] = `npm:@nolyfill/${packageName}@latest`;
return acc;
}, {}),
acc[packageName] = `npm:@nolyfill/${packageName}@latest`;
return acc;
}, {}),
pnpm: {
...currentPackageJson.pnpm,
overrides: allPackagesList
.reduce<Record<string, string>>((acc, packageName) => {
acc[packageName] = `workspace:@nolyfill/${packageName}@*`;
return acc;
}, {})
acc[packageName] = `workspace:@nolyfill/${packageName}@*`;
return acc;
}, {})
}
};

Expand All @@ -573,7 +540,7 @@ const nonNolyfillPackagesList = [
export const allPackages = ${JSON.stringify(allPackagesList, null, 2)};\n`;

await Promise.all([
...autoGeneratedPackagesList.map(pkg => createEsShimLikePackage(pkg[0], pkg[1], pkg[2], pkg[3], pkg[4], pkg[5])),
...autoGeneratedPackagesList.map(pkg => createEsShimLikePackage(pkg[0], pkg[1], pkg[2])),
...singleFilePackagesList.map(pkg => createSingleFilePackage(pkg[0], pkg[1], pkg[2])),
compareAndWriteFile(
path.join(__dirname, 'package.json'),
Expand All @@ -595,32 +562,35 @@ export const allPackages = ${JSON.stringify(allPackagesList, null, 2)};\n`;

async function createEsShimLikePackage(
packageName: string,
packageImplementation: string,
isStatic: boolean,
extraDependencies: Record<string, string> = {},
minimumNodeVersion = '>=12.4.0',
bindTo: string | null = null
minimumNodeVersion = '>=12.4.0'
) {
const entryContent = await fsPromises.readFile(
path.join(__dirname, 'packages', 'data', 'es-shim-like', 'src', `${packageName}.ts`),
{ encoding: 'utf-8' }
);
const { code } = await transform(
entryContent,
{
isModule: true,
jsc: {
parser: {
syntax: 'typescript'
}
},
module: { type: 'commonjs' }
}
);

const pkg: VirtualPackage = {
path: path.join(__dirname, 'packages/generated', packageName),
files: {
'implementation.js': `'use strict';\nmodule.exports = ${packageImplementation};\n`,
'polyfill.js': `'use strict';\nmodule.exports = () => ${packageImplementation};\n`,
'shim.js': `'use strict';\nmodule.exports = () => ${packageImplementation};\n`,
'auto.js': '\'use strict\';\n/* noop */\n',
'index.js': [
'\'use strict\';',
isStatic
? 'const { makeEsShim } = require(\'@nolyfill/shared\');'
: 'const { uncurryThis, makeEsShim } = require(\'@nolyfill/shared\');',
`const impl = ${packageImplementation};`,
isStatic
? `const bound = ${bindTo ? `impl.bind(${bindTo})` : 'impl'};`
: `const bound = ${bindTo ? `uncurryThis(impl).bind(${bindTo})` : 'uncurryThis(impl)'};`,
'makeEsShim(bound, impl);',
'module.exports = bound;',
''
].join('\n')
'entry.js': code + 'Object.assign(exports.default, exports);\nmodule.exports = exports.default;',
'implementation.js': `'use strict';\nmodule.exports = require('./entry.js').implementation;\n`,
'polyfill.js': `'use strict';\nmodule.exports = require('./entry.js').polyfill;\n`,
'shim.js': `'use strict';\nmodule.exports = require('./entry.js').shim;\n`,
'auto.js': `'use strict';\n/* noop */\n`,
'index.js': `'use strict';\nmodule.exports = require('./entry.js').index();\n`
},
packageJson: {
name: `@nolyfill/${packageName}`,
Expand Down Expand Up @@ -655,7 +625,7 @@ async function createSingleFilePackage(
) {
const currentPackageJson = await currentPackageJsonPromise;

const pkg:VirtualPackage = {
const pkg: VirtualPackage = {
path: path.join(__dirname, 'packages/generated', packageName),
files: {
'index.js': `'use strict';\n${implementation}\n`
Expand Down
12 changes: 12 additions & 0 deletions packages/data/es-shim-like/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "es-shim-like",
"version": "0.0.0",
"private": true,
"license": "MIT",
"scripts": {
"lint": "eslint ."
},
"dependencies": {
"@nolyfill/shared": "workspace:*"
}
}
3 changes: 3 additions & 0 deletions packages/data/es-shim-like/src/array-includes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { defineEsShim } from '@nolyfill/shared';

export default defineEsShim(Array.prototype.includes)
Loading

0 comments on commit 61b26e4

Please sign in to comment.