Skip to content

Commit

Permalink
Allow putting helpers in individual files (#13190)
Browse files Browse the repository at this point in the history
* Allow putting helpers in individual files

* Lint

* Also move `objectSpread2` (to show an helper with deps)

* Update fixture and package.json

* fixture
  • Loading branch information
nicolo-ribaudo committed Apr 22, 2021
1 parent 66181db commit f63d73c
Show file tree
Hide file tree
Showing 15 changed files with 304 additions and 172 deletions.
7 changes: 7 additions & 0 deletions .eslintrc.cjs
Expand Up @@ -111,6 +111,13 @@ module.exports = {
],
},
},
{
files: ["packages/babel-helpers/src/helpers/**.js"],
rules: {
"no-var": "off",
"comma-dangle": "off",
},
},
{
files: ["packages/babel-traverse/scripts/**/*.js"],
rules: {
Expand Down
6 changes: 6 additions & 0 deletions .prettierrc
Expand Up @@ -12,9 +12,15 @@
"files": [
"**/{codemods,eslint,packages}/*/{src,test}/**/*.{js,ts}"
],
"excludeFiles": ["**/packages/babel-helpers/src/helpers/**/*.js"],
"options": {
"trailingComma": "all"
}
}, {
"files": "**/packages/babel-helpers/src/helpers/**/*.js",
"options": {
"trailingComma": "es5"
}
}, {
"files": [
"**/{codemods,eslint,packages}/*/test/fixtures/**/*.{js,ts}"
Expand Down
23 changes: 21 additions & 2 deletions Gulpfile.mjs
Expand Up @@ -108,7 +108,7 @@ function generateHelpers(generator, dest, filename, message) {

file.path = filename;
file.contents = Buffer.from(
formatCode(generateCode(filename), dest + file.path)
formatCode(await generateCode(filename), dest + file.path)
);
fancyLog(`${chalk.green("✔")} Generated ${message}`);
callback(null, file);
Expand Down Expand Up @@ -148,6 +148,15 @@ async function generateTraverseHelpers(helperKind) {
);
}

async function generateRuntimeHelpers() {
return generateHelpers(
`./packages/babel-helpers/scripts/generate-helpers.js`,
`./packages/babel-helpers/src/`,
"helpers-generated.js",
"@babel/helpers"
);
}

function generateStandalone() {
const dest = "./packages/babel-standalone/src/generated/";
return gulp
Expand Down Expand Up @@ -487,6 +496,12 @@ gulp.task("generate-type-helpers", () => {
]);
});

gulp.task("generate-runtime-helpers", () => {
fancyLog("Generating @babel/helpers runtime helpers");

return generateRuntimeHelpers();
});

gulp.task("generate-standalone", () => generateStandalone());

gulp.task("build-rollup", () => buildRollup(libBundles));
Expand All @@ -508,7 +523,7 @@ gulp.task("build-babel", () => buildBabel(/* exclude */ libBundles));
gulp.task(
"build",
gulp.series(
gulp.parallel("build-rollup", "build-babel"),
gulp.parallel("build-rollup", "build-babel", "generate-runtime-helpers"),
gulp.parallel(
"generate-standalone",
gulp.series(
Expand Down Expand Up @@ -548,5 +563,9 @@ gulp.task(
gulp.task("generate-standalone")
);
gulp.watch(buildTypingsWatchGlob, gulp.task("generate-type-helpers"));
gulp.watch(
"./packages/babel-helpers/src/helpers/*.js",
gulp.task("generate-runtime-helpers")
);
})
);
60 changes: 60 additions & 0 deletions packages/babel-helpers/scripts/generate-helpers.js
@@ -0,0 +1,60 @@
import fs from "fs";
import { join } from "path";
import { URL } from "url";

const HELPERS_FOLDER = new URL("../src/helpers", import.meta.url);
const IGNORED_FILES = new Set(["package.json"]);

export default async function generateAsserts() {
let output = `/*
* This file is auto-generated! Do not modify it directly.
* To re-generate run 'make build'
*/
import template from "@babel/template";
`;

for (const file of (await fs.promises.readdir(HELPERS_FOLDER)).sort()) {
if (IGNORED_FILES.has(file)) continue;

const [helperName] = file.split(".");
const isValidId = isValidBindingIdentifier(helperName);
const varName = isValidId ? helperName : `_${helperName}`;

const fileContents = await fs.promises.readFile(
join(HELPERS_FOLDER.pathname, file),
"utf8"
);
const { minVersion } = fileContents.match(
/^\s*\/\*\s*@minVersion\s+(?<minVersion>\S+)\s*\*\/\s*$/m
).groups;

// TODO: We can minify the helpers in production
const source = fileContents
// Remove comments
.replace(/\/\*[^]*?\*\/|\/\/.*/g, "")
// Remove multiple newlines
.replace(/\n{2,}/g, "\n");

const intro = isValidId
? "export "
: `export { ${varName} as ${helperName} }\n`;

output += `\n${intro}const ${varName} = {
minVersion: ${JSON.stringify(minVersion)},
ast: () => template.program.ast(${JSON.stringify(source)})
};\n`;
}

return output;
}

function isValidBindingIdentifier(name) {
try {
Function(`var ${name}`);
return true;
} catch {
return false;
}
}
1 change: 1 addition & 0 deletions packages/babel-helpers/scripts/package.json
@@ -0,0 +1 @@
{ "type": "module" }
31 changes: 31 additions & 0 deletions packages/babel-helpers/src/helpers-generated.js
@@ -0,0 +1,31 @@
/*
* This file is auto-generated! Do not modify it directly.
* To re-generate run 'make build'
*/

import template from "@babel/template";

export const jsx = {
minVersion: "7.0.0-beta.0",
ast: () =>
template.program.ast(
'\nvar REACT_ELEMENT_TYPE;\nexport default function _createRawReactElement(type, props, key, children) {\n if (!REACT_ELEMENT_TYPE) {\n REACT_ELEMENT_TYPE =\n (typeof Symbol === "function" &&\n \n Symbol["for"] &&\n Symbol["for"]("react.element")) ||\n 0xeac7;\n }\n var defaultProps = type && type.defaultProps;\n var childrenLength = arguments.length - 3;\n if (!props && childrenLength !== 0) {\n \n \n props = { children: void 0 };\n }\n if (childrenLength === 1) {\n props.children = children;\n } else if (childrenLength > 1) {\n var childArray = new Array(childrenLength);\n for (var i = 0; i < childrenLength; i++) {\n childArray[i] = arguments[i + 3];\n }\n props.children = childArray;\n }\n if (props && defaultProps) {\n for (var propName in defaultProps) {\n if (props[propName] === void 0) {\n props[propName] = defaultProps[propName];\n }\n }\n } else if (!props) {\n props = defaultProps || {};\n }\n return {\n $$typeof: REACT_ELEMENT_TYPE,\n type: type,\n key: key === undefined ? null : "" + key,\n ref: null,\n props: props,\n _owner: null,\n };\n}\n',
),
};

export const objectSpread2 = {
minVersion: "7.5.0",
ast: () =>
template.program.ast(
'\nimport defineProperty from "defineProperty";\nfunction ownKeys(object, enumerableOnly) {\n var keys = Object.keys(object);\n if (Object.getOwnPropertySymbols) {\n var symbols = Object.getOwnPropertySymbols(object);\n if (enumerableOnly) {\n symbols = symbols.filter(function (sym) {\n return Object.getOwnPropertyDescriptor(object, sym).enumerable;\n });\n }\n keys.push.apply(keys, symbols);\n }\n return keys;\n}\nexport default function _objectSpread2(target) {\n for (var i = 1; i < arguments.length; i++) {\n var source = arguments[i] != null ? arguments[i] : {};\n if (i % 2) {\n ownKeys(Object(source), true).forEach(function (key) {\n defineProperty(target, key, source[key]);\n });\n } else if (Object.getOwnPropertyDescriptors) {\n Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));\n } else {\n ownKeys(Object(source)).forEach(function (key) {\n Object.defineProperty(\n target,\n key,\n Object.getOwnPropertyDescriptor(source, key)\n );\n });\n }\n }\n return target;\n}\n',
),
};

export { _typeof as typeof };
const _typeof = {
minVersion: "7.0.0-beta.0",
ast: () =>
template.program.ast(
'\nexport default function _typeof(obj) {\n "@babel/helpers - typeof";\n if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {\n _typeof = function (obj) {\n return typeof obj;\n };\n } else {\n _typeof = function (obj) {\n return obj &&\n typeof Symbol === "function" &&\n obj.constructor === Symbol &&\n obj !== Symbol.prototype\n ? "symbol"\n : typeof obj;\n };\n }\n return _typeof(obj);\n}\n',
),
};
117 changes: 3 additions & 114 deletions packages/babel-helpers/src/helpers.js
Expand Up @@ -2,85 +2,16 @@

import template from "@babel/template";

const helpers = Object.create(null);
import * as generated from "./helpers-generated";

const helpers = { __proto__: null, ...generated };
export default helpers;

const helper = (minVersion: string) => tpl => ({
minVersion,
ast: () => template.program.ast(tpl),
});

helpers.typeof = helper("7.0.0-beta.0")`
export default function _typeof(obj) {
"@babel/helpers - typeof";
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
_typeof = function (obj) { return typeof obj; };
} else {
_typeof = function (obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype
? "symbol"
: typeof obj;
};
}
return _typeof(obj);
}
`;

// "for" is a reserved keyword in ES3 so escaping it here for backward compatibility
helpers.jsx = helper("7.0.0-beta.0")`
var REACT_ELEMENT_TYPE;
export default function _createRawReactElement(type, props, key, children) {
if (!REACT_ELEMENT_TYPE) {
REACT_ELEMENT_TYPE = (
typeof Symbol === "function" && Symbol["for"] && Symbol["for"]("react.element")
) || 0xeac7;
}
var defaultProps = type && type.defaultProps;
var childrenLength = arguments.length - 3;
if (!props && childrenLength !== 0) {
// If we're going to assign props.children, we create a new object now
// to avoid mutating defaultProps.
props = {
children: void 0,
};
}
if (childrenLength === 1) {
props.children = children;
} else if (childrenLength > 1) {
var childArray = new Array(childrenLength);
for (var i = 0; i < childrenLength; i++) {
childArray[i] = arguments[i + 3];
}
props.children = childArray;
}
if (props && defaultProps) {
for (var propName in defaultProps) {
if (props[propName] === void 0) {
props[propName] = defaultProps[propName];
}
}
} else if (!props) {
props = defaultProps || {};
}
return {
$$typeof: REACT_ELEMENT_TYPE,
type: type,
key: key === undefined ? null : '' + key,
ref: null,
props: props,
_owner: null,
};
}
`;

helpers.asyncIterator = helper("7.0.0-beta.0")`
export default function _asyncIterator(iterable) {
var method;
Expand Down Expand Up @@ -406,48 +337,6 @@ helpers.objectSpread = helper("7.0.0-beta.0")`
}
`;

helpers.objectSpread2 = helper("7.5.0")`
import defineProperty from "defineProperty";
// This function is different to "Reflect.ownKeys". The enumerableOnly
// filters on symbol properties only. Returned string properties are always
// enumerable. It is good to use in objectSpread.
function ownKeys(object, enumerableOnly) {
var keys = Object.keys(object);
if (Object.getOwnPropertySymbols) {
var symbols = Object.getOwnPropertySymbols(object);
if (enumerableOnly) symbols = symbols.filter(function (sym) {
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
});
keys.push.apply(keys, symbols);
}
return keys;
}
export default function _objectSpread2(target) {
for (var i = 1; i < arguments.length; i++) {
var source = (arguments[i] != null) ? arguments[i] : {};
if (i % 2) {
ownKeys(Object(source), true).forEach(function (key) {
defineProperty(target, key, source[key]);
});
} else if (Object.getOwnPropertyDescriptors) {
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
} else {
ownKeys(Object(source)).forEach(function (key) {
Object.defineProperty(
target,
key,
Object.getOwnPropertyDescriptor(source, key)
);
});
}
}
return target;
}
`;

helpers.inherits = helper("7.0.0-beta.0")`
import setPrototypeOf from "setPrototypeOf";
Expand Down
52 changes: 52 additions & 0 deletions packages/babel-helpers/src/helpers/jsx.js
@@ -0,0 +1,52 @@
/* @minVersion 7.0.0-beta.0 */

var REACT_ELEMENT_TYPE;

export default function _createRawReactElement(type, props, key, children) {
if (!REACT_ELEMENT_TYPE) {
REACT_ELEMENT_TYPE =
(typeof Symbol === "function" &&
// "for" is a reserved keyword in ES3 so escaping it here for backward compatibility
Symbol["for"] &&
Symbol["for"]("react.element")) ||
0xeac7;
}

var defaultProps = type && type.defaultProps;
var childrenLength = arguments.length - 3;

if (!props && childrenLength !== 0) {
// If we're going to assign props.children, we create a new object now
// to avoid mutating defaultProps.
props = { children: void 0 };
}

if (childrenLength === 1) {
props.children = children;
} else if (childrenLength > 1) {
var childArray = new Array(childrenLength);
for (var i = 0; i < childrenLength; i++) {
childArray[i] = arguments[i + 3];
}
props.children = childArray;
}

if (props && defaultProps) {
for (var propName in defaultProps) {
if (props[propName] === void 0) {
props[propName] = defaultProps[propName];
}
}
} else if (!props) {
props = defaultProps || {};
}

return {
$$typeof: REACT_ELEMENT_TYPE,
type: type,
key: key === undefined ? null : "" + key,
ref: null,
props: props,
_owner: null,
};
}

0 comments on commit f63d73c

Please sign in to comment.