Implement importInterop: "node" option for module transforms (#12838)
This commit is contained in:
parent
22b0eb038f
commit
be03be1bc3
@ -6,9 +6,10 @@ import { isModule } from "@babel/helper-module-imports";
|
||||
|
||||
import rewriteThis from "./rewrite-this";
|
||||
import rewriteLiveReferences from "./rewrite-live-references";
|
||||
import normalizeAndLoadModuleMetadata, {
|
||||
import normalizeModuleAndLoadMetadata, {
|
||||
hasExports,
|
||||
isSideEffectImport,
|
||||
validateImportInteropOption,
|
||||
} from "./normalize-and-load-metadata";
|
||||
import type {
|
||||
InteropType,
|
||||
@ -38,6 +39,7 @@ export function rewriteModuleStatementsAndPrepareHeader(
|
||||
allowTopLevelThis,
|
||||
strictMode,
|
||||
noInterop,
|
||||
importInterop = noInterop ? "none" : "babel",
|
||||
lazy,
|
||||
esNamespaceOnly,
|
||||
|
||||
@ -49,6 +51,7 @@ export function rewriteModuleStatementsAndPrepareHeader(
|
||||
allowTopLevelThis?;
|
||||
strictMode;
|
||||
loose?;
|
||||
importInterop?: "none" | "babel" | "node";
|
||||
noInterop?;
|
||||
lazy?;
|
||||
esNamespaceOnly?;
|
||||
@ -56,11 +59,12 @@ export function rewriteModuleStatementsAndPrepareHeader(
|
||||
enumerableModuleMeta?;
|
||||
},
|
||||
) {
|
||||
validateImportInteropOption(importInterop);
|
||||
assert(isModule(path), "Cannot process module statements in a script");
|
||||
path.node.sourceType = "script";
|
||||
|
||||
const meta = normalizeAndLoadModuleMetadata(path, exportName, {
|
||||
noInterop,
|
||||
const meta = normalizeModuleAndLoadMetadata(path, exportName, {
|
||||
importInterop,
|
||||
initializeReexports: constantReexports,
|
||||
lazy,
|
||||
esNamespaceOnly,
|
||||
@ -128,6 +132,15 @@ export function wrapInterop(
|
||||
return null;
|
||||
}
|
||||
|
||||
if (type === "node-namespace") {
|
||||
return t.callExpression(
|
||||
programPath.hub.addHelper("interopRequireWildcard"),
|
||||
[expr, t.booleanLiteral(true)],
|
||||
);
|
||||
} else if (type === "node-default") {
|
||||
return null;
|
||||
}
|
||||
|
||||
let helper;
|
||||
if (type === "default") {
|
||||
helper = "interopRequireDefault";
|
||||
@ -227,16 +240,18 @@ const buildReexportsFromMeta = (
|
||||
|
||||
const { stringSpecifiers } = meta;
|
||||
return Array.from(metadata.reexports, ([exportName, importName]) => {
|
||||
let NAMESPACE_IMPORT;
|
||||
if (stringSpecifiers.has(importName)) {
|
||||
let NAMESPACE_IMPORT: t.Expression = t.cloneNode(namespace);
|
||||
if (importName === "default" && metadata.interop === "node-default") {
|
||||
// Nothing, it's ok as-is
|
||||
} else if (stringSpecifiers.has(importName)) {
|
||||
NAMESPACE_IMPORT = t.memberExpression(
|
||||
t.cloneNode(namespace),
|
||||
NAMESPACE_IMPORT,
|
||||
t.stringLiteral(importName),
|
||||
true,
|
||||
);
|
||||
} else {
|
||||
NAMESPACE_IMPORT = NAMESPACE_IMPORT = t.memberExpression(
|
||||
t.cloneNode(namespace),
|
||||
NAMESPACE_IMPORT = t.memberExpression(
|
||||
NAMESPACE_IMPORT,
|
||||
t.identifier(importName),
|
||||
);
|
||||
}
|
||||
@ -245,7 +260,7 @@ const buildReexportsFromMeta = (
|
||||
EXPORT_NAME: exportName,
|
||||
NAMESPACE_IMPORT,
|
||||
};
|
||||
if (constantReexports) {
|
||||
if (constantReexports || t.isIdentifier(NAMESPACE_IMPORT)) {
|
||||
if (stringSpecifiers.has(exportName)) {
|
||||
return ReexportTemplate.constantComputed(astNodes);
|
||||
} else {
|
||||
|
||||
@ -21,7 +21,12 @@ export interface ModuleMetadata {
|
||||
stringSpecifiers: Set<string>;
|
||||
}
|
||||
|
||||
export type InteropType = "default" | "namespace" | "none";
|
||||
export type InteropType =
|
||||
| "default" // Babel interop for default-only imports
|
||||
| "namespace" // Babel interop for namespace or default+named imports
|
||||
| "node-default" // Node.js interop for default-only imports
|
||||
| "node-namespace" // Node.js interop for namespace or default+named imports
|
||||
| "none"; // No interop, or named-only imports
|
||||
|
||||
export interface SourceModuleMetadata {
|
||||
// A unique variable name to use for this namespace object. Centralized for simplicity.
|
||||
@ -68,19 +73,42 @@ export function isSideEffectImport(source: SourceModuleMetadata) {
|
||||
);
|
||||
}
|
||||
|
||||
export function validateImportInteropOption(
|
||||
importInterop: any,
|
||||
): importInterop is "none" | "babel" | "node" | Function {
|
||||
if (
|
||||
typeof importInterop !== "function" &&
|
||||
importInterop !== "none" &&
|
||||
importInterop !== "babel" &&
|
||||
importInterop !== "node"
|
||||
) {
|
||||
throw new Error(
|
||||
`.importInterop must be one of "none", "babel", "node", or a function returning one of those values (received ${importInterop}).`,
|
||||
);
|
||||
}
|
||||
return importInterop;
|
||||
}
|
||||
|
||||
function resolveImportInterop(importInterop, source) {
|
||||
if (typeof importInterop === "function") {
|
||||
return validateImportInteropOption(importInterop(source));
|
||||
}
|
||||
return importInterop;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all imports and exports from the file, and return all metadata
|
||||
* needed to reconstruct the module's behavior.
|
||||
*/
|
||||
export default function normalizeModuleAndLoadMetadata(
|
||||
programPath: NodePath<t.Program>,
|
||||
exportName?: string,
|
||||
exportName: string,
|
||||
{
|
||||
noInterop = false,
|
||||
importInterop,
|
||||
initializeReexports = false,
|
||||
lazy = false,
|
||||
esNamespaceOnly = false,
|
||||
} = {},
|
||||
},
|
||||
): ModuleMetadata {
|
||||
if (!exportName) {
|
||||
exportName = programPath.scope.generateUidIdentifier("exports").name;
|
||||
@ -105,18 +133,26 @@ export default function normalizeModuleAndLoadMetadata(
|
||||
metadata.name = metadata.importsNamespace.values().next().value;
|
||||
}
|
||||
|
||||
if (noInterop) metadata.interop = "none";
|
||||
else if (esNamespaceOnly) {
|
||||
const resolvedInterop = resolveImportInterop(
|
||||
importInterop,
|
||||
metadata.source,
|
||||
);
|
||||
|
||||
if (resolvedInterop === "none") {
|
||||
metadata.interop = "none";
|
||||
} else if (resolvedInterop === "node" && metadata.interop === "namespace") {
|
||||
metadata.interop = "node-namespace";
|
||||
} else if (resolvedInterop === "node" && metadata.interop === "default") {
|
||||
metadata.interop = "node-default";
|
||||
} else if (esNamespaceOnly && metadata.interop === "namespace") {
|
||||
// Both the default and namespace interops pass through __esModule
|
||||
// objects, but the namespace interop is used to enable Babel's
|
||||
// destructuring-like interop behavior for normal CommonJS.
|
||||
// Since some tooling has started to remove that behavior, we expose
|
||||
// it as the `esNamespace` option.
|
||||
if (metadata.interop === "namespace") {
|
||||
metadata.interop = "default";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
exportName,
|
||||
@ -199,6 +235,8 @@ function getModuleMetadata(
|
||||
reexportAll: null,
|
||||
|
||||
lazy: false,
|
||||
|
||||
source,
|
||||
};
|
||||
sourceData.set(source, data);
|
||||
}
|
||||
|
||||
@ -96,6 +96,10 @@ export default function rewriteLiveReferences(
|
||||
let namespace: t.Expression = t.identifier(meta.name);
|
||||
if (meta.lazy) namespace = t.callExpression(namespace, []);
|
||||
|
||||
if (importName === "default" && meta.interop === "node-default") {
|
||||
return namespace;
|
||||
}
|
||||
|
||||
const computed = metadata.stringSpecifiers.has(importName);
|
||||
|
||||
return t.memberExpression(
|
||||
|
||||
@ -500,17 +500,19 @@ helpers.interopRequireDefault = helper("7.0.0-beta.0")`
|
||||
}
|
||||
`;
|
||||
|
||||
helpers.interopRequireWildcard = helper("7.0.0-beta.0")`
|
||||
function _getRequireWildcardCache() {
|
||||
helpers.interopRequireWildcard = helper("7.14.0")`
|
||||
function _getRequireWildcardCache(nodeInterop) {
|
||||
if (typeof WeakMap !== "function") return null;
|
||||
|
||||
var cache = new WeakMap();
|
||||
_getRequireWildcardCache = function () { return cache; };
|
||||
return cache;
|
||||
var cacheBabelInterop = new WeakMap();
|
||||
var cacheNodeInterop = new WeakMap();
|
||||
return (_getRequireWildcardCache = function (nodeInterop) {
|
||||
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
|
||||
})(nodeInterop);
|
||||
}
|
||||
|
||||
export default function _interopRequireWildcard(obj) {
|
||||
if (obj && obj.__esModule) {
|
||||
export default function _interopRequireWildcard(obj, nodeInterop) {
|
||||
if (!nodeInterop && obj && obj.__esModule) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
@ -518,7 +520,7 @@ helpers.interopRequireWildcard = helper("7.0.0-beta.0")`
|
||||
return { default: obj }
|
||||
}
|
||||
|
||||
var cache = _getRequireWildcardCache();
|
||||
var cache = _getRequireWildcardCache(nodeInterop);
|
||||
if (cache && cache.has(obj)) {
|
||||
return cache.get(obj);
|
||||
}
|
||||
@ -526,7 +528,7 @@ helpers.interopRequireWildcard = helper("7.0.0-beta.0")`
|
||||
var newObj = {};
|
||||
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
|
||||
for (var key in obj) {
|
||||
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
||||
if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
|
||||
var desc = hasPropertyDescriptor
|
||||
? Object.getOwnPropertyDescriptor(obj, key)
|
||||
: null;
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "workspace:*",
|
||||
"@babel/helper-plugin-test-runner": "workspace:*"
|
||||
"@babel/helper-plugin-test-runner": "workspace:*",
|
||||
"@babel/plugin-external-helpers": "workspace:*"
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,7 +38,13 @@ function injectWrapper(path, wrapper) {
|
||||
export default declare((api, options) => {
|
||||
api.assertVersion(7);
|
||||
|
||||
const { allowTopLevelThis, strict, strictMode, noInterop } = options;
|
||||
const {
|
||||
allowTopLevelThis,
|
||||
strict,
|
||||
strictMode,
|
||||
importInterop,
|
||||
noInterop,
|
||||
} = options;
|
||||
|
||||
const constantReexports =
|
||||
api.assumption("constantReexports") ?? options.loose;
|
||||
@ -114,6 +120,7 @@ export default declare((api, options) => {
|
||||
strict,
|
||||
strictMode,
|
||||
allowTopLevelThis,
|
||||
importInterop,
|
||||
noInterop,
|
||||
},
|
||||
);
|
||||
|
||||
@ -0,0 +1 @@
|
||||
export { default } from 'dep';
|
||||
@ -0,0 +1,8 @@
|
||||
define(["exports", "dep"], function (_exports, _dep) {
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(_exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
_exports.default = _dep;
|
||||
});
|
||||
@ -0,0 +1 @@
|
||||
export { default, name } from 'dep';
|
||||
@ -0,0 +1,20 @@
|
||||
define(["exports", "dep"], function (_exports, _dep) {
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(_exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
Object.defineProperty(_exports, "default", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _dep.default;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(_exports, "name", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _dep.name;
|
||||
}
|
||||
});
|
||||
_dep = babelHelpers.interopRequireWildcard(_dep, true);
|
||||
});
|
||||
@ -0,0 +1 @@
|
||||
export { name } from 'dep';
|
||||
@ -0,0 +1,13 @@
|
||||
define(["exports", "dep"], function (_exports, _dep) {
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(_exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
Object.defineProperty(_exports, "name", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _dep.name;
|
||||
}
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,3 @@
|
||||
import foo from "foo";
|
||||
|
||||
foo();
|
||||
@ -0,0 +1,5 @@
|
||||
define(["foo"], function (_foo) {
|
||||
"use strict";
|
||||
|
||||
_foo();
|
||||
});
|
||||
@ -0,0 +1,4 @@
|
||||
import foo, { named } from "foo";
|
||||
|
||||
foo();
|
||||
named();
|
||||
@ -0,0 +1,7 @@
|
||||
define(["foo"], function (_foo) {
|
||||
"use strict";
|
||||
|
||||
_foo = babelHelpers.interopRequireWildcard(_foo, true);
|
||||
(0, _foo.default)();
|
||||
(0, _foo.named)();
|
||||
});
|
||||
@ -0,0 +1,3 @@
|
||||
import { named } from "foo";
|
||||
|
||||
named();
|
||||
@ -0,0 +1,5 @@
|
||||
define(["foo"], function (_foo) {
|
||||
"use strict";
|
||||
|
||||
(0, _foo.named)();
|
||||
});
|
||||
@ -0,0 +1,4 @@
|
||||
import * as foo from 'foo';
|
||||
|
||||
foo.bar();
|
||||
foo.baz();
|
||||
@ -0,0 +1,7 @@
|
||||
define(["foo"], function (foo) {
|
||||
"use strict";
|
||||
|
||||
foo = babelHelpers.interopRequireWildcard(foo, true);
|
||||
foo.bar();
|
||||
foo.baz();
|
||||
});
|
||||
3
packages/babel-plugin-transform-modules-amd/test/fixtures/importInterop-node/options.json
vendored
Normal file
3
packages/babel-plugin-transform-modules-amd/test/fixtures/importInterop-node/options.json
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"plugins": [["transform-modules-amd", { "importInterop": "node" }]]
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
export { default } from 'foo';
|
||||
@ -0,0 +1,13 @@
|
||||
define(["exports", "foo"], function (_exports, _foo) {
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(_exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
Object.defineProperty(_exports, "default", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _foo.default;
|
||||
}
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,3 @@
|
||||
import foo from "foo";
|
||||
|
||||
foo();
|
||||
@ -0,0 +1,5 @@
|
||||
define(["foo"], function (_foo) {
|
||||
"use strict";
|
||||
|
||||
(0, _foo.default)();
|
||||
});
|
||||
@ -0,0 +1,4 @@
|
||||
import * as foo from 'foo';
|
||||
|
||||
foo.bar();
|
||||
foo.baz();
|
||||
@ -0,0 +1,6 @@
|
||||
define(["foo"], function (foo) {
|
||||
"use strict";
|
||||
|
||||
foo.bar();
|
||||
foo.baz();
|
||||
});
|
||||
3
packages/babel-plugin-transform-modules-amd/test/fixtures/importInterop-none/options.json
vendored
Normal file
3
packages/babel-plugin-transform-modules-amd/test/fixtures/importInterop-none/options.json
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"plugins": [["transform-modules-amd", { "importInterop": "none" }]]
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
import * as babel from "@babel/core";
|
||||
import transformAmd from "../lib";
|
||||
import externalHelpers from "@babel/plugin-external-helpers";
|
||||
|
||||
it("'importInterop' accepts a function", function () {
|
||||
const code = `
|
||||
import a from "a";
|
||||
import b from "b";
|
||||
import c from "c";
|
||||
|
||||
a();
|
||||
b();
|
||||
c();
|
||||
`;
|
||||
|
||||
const importInterop = source => {
|
||||
if (source === "a") return "babel";
|
||||
else if (source === "b") return "node";
|
||||
else if (source === "c") return "none";
|
||||
};
|
||||
|
||||
const output = babel.transformSync(code, {
|
||||
configFile: false,
|
||||
ast: false,
|
||||
plugins: [
|
||||
[externalHelpers, { helperVersion: "7.100.0" }],
|
||||
[transformAmd, { importInterop }],
|
||||
],
|
||||
}).code;
|
||||
|
||||
expect(output).toMatchInlineSnapshot(`
|
||||
"define([\\"a\\", \\"b\\", \\"c\\"], function (_a, _b, _c) {
|
||||
\\"use strict\\";
|
||||
|
||||
_a = babelHelpers.interopRequireDefault(_a);
|
||||
(0, _a.default)();
|
||||
|
||||
_b();
|
||||
|
||||
(0, _c.default)();
|
||||
});"
|
||||
`);
|
||||
});
|
||||
@ -27,6 +27,7 @@
|
||||
"devDependencies": {
|
||||
"@babel/core": "workspace:*",
|
||||
"@babel/helper-plugin-test-runner": "workspace:*",
|
||||
"@babel/plugin-external-helpers": "workspace:*",
|
||||
"@babel/plugin-syntax-object-rest-spread": "^7.8.3"
|
||||
},
|
||||
"homepage": "https://babel.dev/docs/en/next/babel-plugin-transform-modules-commonjs"
|
||||
|
||||
@ -30,6 +30,7 @@ export default declare((api, options) => {
|
||||
strict,
|
||||
strictMode,
|
||||
noInterop,
|
||||
importInterop,
|
||||
lazy = false,
|
||||
// Defaulting to 'true' for now. May change before 7.x major.
|
||||
allowCommonJSExports = true,
|
||||
@ -178,6 +179,7 @@ export default declare((api, options) => {
|
||||
strictMode,
|
||||
allowTopLevelThis,
|
||||
noInterop,
|
||||
importInterop,
|
||||
lazy,
|
||||
esNamespaceOnly:
|
||||
typeof state.filename === "string" &&
|
||||
|
||||
@ -0,0 +1 @@
|
||||
module.exports = function () { return 1 };
|
||||
@ -0,0 +1,2 @@
|
||||
module.exports = function () { return 2 };
|
||||
module.exports.__esModule = true;
|
||||
@ -0,0 +1 @@
|
||||
module.exports = function () { return 3 };
|
||||
@ -0,0 +1,2 @@
|
||||
module.exports = function () { return 4 };
|
||||
module.exports.__esModule = true;
|
||||
@ -0,0 +1,2 @@
|
||||
exports.default = function () { return 5 };
|
||||
|
||||
@ -0,0 +1,2 @@
|
||||
exports.default = function () { return 6 };
|
||||
exports.__esModule = true;
|
||||
@ -0,0 +1,2 @@
|
||||
exports.named = function () { return 7 };
|
||||
|
||||
@ -0,0 +1,2 @@
|
||||
exports.named = function () { return 8 };
|
||||
exports.__esModule = true;
|
||||
36
packages/babel-plugin-transform-modules-commonjs/test/fixtures/importInterop-node/exec/exec.js
vendored
Normal file
36
packages/babel-plugin-transform-modules-commonjs/test/fixtures/importInterop-node/exec/exec.js
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
import dep1 from "./dep1.js";
|
||||
import dep2 from "./dep2.js";
|
||||
import * as dep3 from "./dep3.js";
|
||||
import * as dep4 from "./dep4.js";
|
||||
import dep5 from "./dep5.js";
|
||||
import dep6 from "./dep6.js";
|
||||
import { named as dep7 } from "./dep7.js";
|
||||
import { named as dep8 } from "./dep8.js";
|
||||
|
||||
expect(typeof dep1).toBe("function");
|
||||
expect(dep1()).toBe(1);
|
||||
|
||||
expect(typeof dep2).toBe("function");
|
||||
expect(dep2()).toBe(2);
|
||||
|
||||
expect(typeof dep3).toBe("object");
|
||||
expect(typeof dep3.default).toBe("function");
|
||||
expect(dep3.default()).toBe(3);
|
||||
|
||||
expect(typeof dep4).toBe("object");
|
||||
expect(typeof dep4.default).toBe("function");
|
||||
expect(dep4.default()).toBe(4);
|
||||
|
||||
expect(typeof dep5).toBe("object");
|
||||
expect(typeof dep5.default).toBe("function");
|
||||
expect(dep5.default()).toBe(5);
|
||||
|
||||
expect(typeof dep6).toBe("object");
|
||||
expect(typeof dep6.default).toBe("function");
|
||||
expect(dep6.default()).toBe(6);
|
||||
|
||||
expect(typeof dep7).toBe("function");
|
||||
expect(dep7()).toBe(7);
|
||||
|
||||
expect(typeof dep8).toBe("function");
|
||||
expect(dep8()).toBe(8);
|
||||
@ -0,0 +1,3 @@
|
||||
{
|
||||
"sourceType": "module"
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
export { default } from 'dep';
|
||||
@ -0,0 +1,8 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = _dep;
|
||||
|
||||
var _dep = require("dep");
|
||||
@ -0,0 +1 @@
|
||||
export { default, name } from 'dep';
|
||||
@ -0,0 +1,19 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
Object.defineProperty(exports, "default", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _dep.default;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "name", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _dep.name;
|
||||
}
|
||||
});
|
||||
|
||||
var _dep = babelHelpers.interopRequireWildcard(require("dep"), true);
|
||||
@ -0,0 +1 @@
|
||||
export { name } from 'dep';
|
||||
@ -0,0 +1,13 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
Object.defineProperty(exports, "name", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _dep.name;
|
||||
}
|
||||
});
|
||||
|
||||
var _dep = require("dep");
|
||||
@ -0,0 +1,3 @@
|
||||
import foo from "foo";
|
||||
|
||||
foo();
|
||||
@ -0,0 +1,5 @@
|
||||
"use strict";
|
||||
|
||||
var _foo = require("foo");
|
||||
|
||||
_foo();
|
||||
@ -0,0 +1,4 @@
|
||||
import foo, { named } from "foo";
|
||||
|
||||
foo();
|
||||
named();
|
||||
@ -0,0 +1,6 @@
|
||||
"use strict";
|
||||
|
||||
var _foo = babelHelpers.interopRequireWildcard(require("foo"), true);
|
||||
|
||||
(0, _foo.default)();
|
||||
(0, _foo.named)();
|
||||
@ -0,0 +1,3 @@
|
||||
import { named } from "foo";
|
||||
|
||||
named();
|
||||
@ -0,0 +1,5 @@
|
||||
"use strict";
|
||||
|
||||
var _foo = require("foo");
|
||||
|
||||
(0, _foo.named)();
|
||||
@ -0,0 +1,4 @@
|
||||
import * as foo from 'foo';
|
||||
|
||||
foo.bar();
|
||||
foo.baz();
|
||||
@ -0,0 +1,5 @@
|
||||
"use strict";
|
||||
|
||||
var foo = babelHelpers.interopRequireWildcard(require("foo"), true);
|
||||
foo.bar();
|
||||
foo.baz();
|
||||
@ -0,0 +1,3 @@
|
||||
{
|
||||
"plugins": [["transform-modules-commonjs", { "importInterop": "node" }]]
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
export { default } from 'foo';
|
||||
@ -0,0 +1,13 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
Object.defineProperty(exports, "default", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _foo.default;
|
||||
}
|
||||
});
|
||||
|
||||
var _foo = require("foo");
|
||||
@ -0,0 +1,3 @@
|
||||
import foo from "foo";
|
||||
|
||||
foo();
|
||||
@ -0,0 +1,5 @@
|
||||
"use strict";
|
||||
|
||||
var _foo = require("foo");
|
||||
|
||||
(0, _foo.default)();
|
||||
@ -0,0 +1,4 @@
|
||||
import * as foo from 'foo';
|
||||
|
||||
foo.bar();
|
||||
foo.baz();
|
||||
@ -0,0 +1,6 @@
|
||||
"use strict";
|
||||
|
||||
var foo = require("foo");
|
||||
|
||||
foo.bar();
|
||||
foo.baz();
|
||||
@ -0,0 +1,3 @@
|
||||
{
|
||||
"plugins": [["transform-modules-commonjs", { "importInterop": "none" }]]
|
||||
}
|
||||
@ -9,6 +9,6 @@ var foo = _interopRequireWildcard(require("./moduleWithGetter"));
|
||||
|
||||
exports.foo = foo;
|
||||
|
||||
function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
|
||||
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
||||
|
||||
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
||||
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
||||
|
||||
@ -0,0 +1,46 @@
|
||||
import * as babel from "@babel/core";
|
||||
import transformCommonjs from "../lib";
|
||||
import externalHelpers from "@babel/plugin-external-helpers";
|
||||
|
||||
it("'importInterop' accepts a function", function () {
|
||||
const code = `
|
||||
import a from "a";
|
||||
import b from "b";
|
||||
import c from "c";
|
||||
|
||||
a();
|
||||
b();
|
||||
c();
|
||||
`;
|
||||
|
||||
const importInterop = source => {
|
||||
if (source === "a") return "babel";
|
||||
else if (source === "b") return "node";
|
||||
else if (source === "c") return "none";
|
||||
};
|
||||
|
||||
const output = babel.transformSync(code, {
|
||||
configFile: false,
|
||||
ast: false,
|
||||
plugins: [
|
||||
[externalHelpers, { helperVersion: "7.100.0" }],
|
||||
[transformCommonjs, { importInterop }],
|
||||
],
|
||||
}).code;
|
||||
|
||||
expect(output).toMatchInlineSnapshot(`
|
||||
"\\"use strict\\";
|
||||
|
||||
var _a = babelHelpers.interopRequireDefault(require(\\"a\\"));
|
||||
|
||||
var _b = require(\\"b\\");
|
||||
|
||||
var _c = require(\\"c\\");
|
||||
|
||||
(0, _a.default)();
|
||||
|
||||
_b();
|
||||
|
||||
(0, _c.default)();"
|
||||
`);
|
||||
});
|
||||
@ -25,6 +25,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "workspace:*",
|
||||
"@babel/helper-plugin-test-runner": "workspace:*"
|
||||
"@babel/helper-plugin-test-runner": "workspace:*",
|
||||
"@babel/plugin-external-helpers": "workspace:*"
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,6 +48,7 @@ export default declare((api, options) => {
|
||||
strict,
|
||||
strictMode,
|
||||
noInterop,
|
||||
importInterop,
|
||||
} = options;
|
||||
|
||||
const constantReexports =
|
||||
@ -157,6 +158,7 @@ export default declare((api, options) => {
|
||||
strictMode,
|
||||
allowTopLevelThis,
|
||||
noInterop,
|
||||
importInterop,
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
1
packages/babel-plugin-transform-modules-umd/test/fixtures/importInterop-node/exec/dep1.js
vendored
Normal file
1
packages/babel-plugin-transform-modules-umd/test/fixtures/importInterop-node/exec/dep1.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
module.exports = function () { return 1 };
|
||||
2
packages/babel-plugin-transform-modules-umd/test/fixtures/importInterop-node/exec/dep2.js
vendored
Normal file
2
packages/babel-plugin-transform-modules-umd/test/fixtures/importInterop-node/exec/dep2.js
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
module.exports = function () { return 2 };
|
||||
module.exports.__esModule = true;
|
||||
1
packages/babel-plugin-transform-modules-umd/test/fixtures/importInterop-node/exec/dep3.js
vendored
Normal file
1
packages/babel-plugin-transform-modules-umd/test/fixtures/importInterop-node/exec/dep3.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
module.exports = function () { return 3 };
|
||||
2
packages/babel-plugin-transform-modules-umd/test/fixtures/importInterop-node/exec/dep4.js
vendored
Normal file
2
packages/babel-plugin-transform-modules-umd/test/fixtures/importInterop-node/exec/dep4.js
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
module.exports = function () { return 4 };
|
||||
module.exports.__esModule = true;
|
||||
2
packages/babel-plugin-transform-modules-umd/test/fixtures/importInterop-node/exec/dep5.js
vendored
Normal file
2
packages/babel-plugin-transform-modules-umd/test/fixtures/importInterop-node/exec/dep5.js
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
exports.default = function () { return 5 };
|
||||
|
||||
2
packages/babel-plugin-transform-modules-umd/test/fixtures/importInterop-node/exec/dep6.js
vendored
Normal file
2
packages/babel-plugin-transform-modules-umd/test/fixtures/importInterop-node/exec/dep6.js
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
exports.default = function () { return 6 };
|
||||
exports.__esModule = true;
|
||||
2
packages/babel-plugin-transform-modules-umd/test/fixtures/importInterop-node/exec/dep7.js
vendored
Normal file
2
packages/babel-plugin-transform-modules-umd/test/fixtures/importInterop-node/exec/dep7.js
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
exports.named = function () { return 7 };
|
||||
|
||||
2
packages/babel-plugin-transform-modules-umd/test/fixtures/importInterop-node/exec/dep8.js
vendored
Normal file
2
packages/babel-plugin-transform-modules-umd/test/fixtures/importInterop-node/exec/dep8.js
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
exports.named = function () { return 8 };
|
||||
exports.__esModule = true;
|
||||
36
packages/babel-plugin-transform-modules-umd/test/fixtures/importInterop-node/exec/exec.js
vendored
Normal file
36
packages/babel-plugin-transform-modules-umd/test/fixtures/importInterop-node/exec/exec.js
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
import dep1 from "./dep1.js";
|
||||
import dep2 from "./dep2.js";
|
||||
import * as dep3 from "./dep3.js";
|
||||
import * as dep4 from "./dep4.js";
|
||||
import dep5 from "./dep5.js";
|
||||
import dep6 from "./dep6.js";
|
||||
import { named as dep7 } from "./dep7.js";
|
||||
import { named as dep8 } from "./dep8.js";
|
||||
|
||||
expect(typeof dep1).toBe("function");
|
||||
expect(dep1()).toBe(1);
|
||||
|
||||
expect(typeof dep2).toBe("function");
|
||||
expect(dep2()).toBe(2);
|
||||
|
||||
expect(typeof dep3).toBe("object");
|
||||
expect(typeof dep3.default).toBe("function");
|
||||
expect(dep3.default()).toBe(3);
|
||||
|
||||
expect(typeof dep4).toBe("object");
|
||||
expect(typeof dep4.default).toBe("function");
|
||||
expect(dep4.default()).toBe(4);
|
||||
|
||||
expect(typeof dep5).toBe("object");
|
||||
expect(typeof dep5.default).toBe("function");
|
||||
expect(dep5.default()).toBe(5);
|
||||
|
||||
expect(typeof dep6).toBe("object");
|
||||
expect(typeof dep6.default).toBe("function");
|
||||
expect(dep6.default()).toBe(6);
|
||||
|
||||
expect(typeof dep7).toBe("function");
|
||||
expect(dep7()).toBe(7);
|
||||
|
||||
expect(typeof dep8).toBe("function");
|
||||
expect(dep8()).toBe(8);
|
||||
@ -0,0 +1,3 @@
|
||||
{
|
||||
"sourceType": "module"
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
export { default } from 'dep';
|
||||
@ -0,0 +1,20 @@
|
||||
(function (global, factory) {
|
||||
if (typeof define === "function" && define.amd) {
|
||||
define(["exports", "dep"], factory);
|
||||
} else if (typeof exports !== "undefined") {
|
||||
factory(exports, require("dep"));
|
||||
} else {
|
||||
var mod = {
|
||||
exports: {}
|
||||
};
|
||||
factory(mod.exports, global.dep);
|
||||
global.input = mod.exports;
|
||||
}
|
||||
})(typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : this, function (_exports, _dep) {
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(_exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
_exports.default = _dep;
|
||||
});
|
||||
@ -0,0 +1 @@
|
||||
export { default, name } from 'dep';
|
||||
@ -0,0 +1,32 @@
|
||||
(function (global, factory) {
|
||||
if (typeof define === "function" && define.amd) {
|
||||
define(["exports", "dep"], factory);
|
||||
} else if (typeof exports !== "undefined") {
|
||||
factory(exports, require("dep"));
|
||||
} else {
|
||||
var mod = {
|
||||
exports: {}
|
||||
};
|
||||
factory(mod.exports, global.dep);
|
||||
global.input = mod.exports;
|
||||
}
|
||||
})(typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : this, function (_exports, _dep) {
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(_exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
Object.defineProperty(_exports, "default", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _dep.default;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(_exports, "name", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _dep.name;
|
||||
}
|
||||
});
|
||||
_dep = babelHelpers.interopRequireWildcard(_dep, true);
|
||||
});
|
||||
@ -0,0 +1 @@
|
||||
export { name } from 'dep';
|
||||
@ -0,0 +1,25 @@
|
||||
(function (global, factory) {
|
||||
if (typeof define === "function" && define.amd) {
|
||||
define(["exports", "dep"], factory);
|
||||
} else if (typeof exports !== "undefined") {
|
||||
factory(exports, require("dep"));
|
||||
} else {
|
||||
var mod = {
|
||||
exports: {}
|
||||
};
|
||||
factory(mod.exports, global.dep);
|
||||
global.input = mod.exports;
|
||||
}
|
||||
})(typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : this, function (_exports, _dep) {
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(_exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
Object.defineProperty(_exports, "name", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _dep.name;
|
||||
}
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,3 @@
|
||||
import foo from "foo";
|
||||
|
||||
foo();
|
||||
@ -0,0 +1,17 @@
|
||||
(function (global, factory) {
|
||||
if (typeof define === "function" && define.amd) {
|
||||
define(["foo"], factory);
|
||||
} else if (typeof exports !== "undefined") {
|
||||
factory(require("foo"));
|
||||
} else {
|
||||
var mod = {
|
||||
exports: {}
|
||||
};
|
||||
factory(global.foo);
|
||||
global.input = mod.exports;
|
||||
}
|
||||
})(typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : this, function (_foo) {
|
||||
"use strict";
|
||||
|
||||
_foo();
|
||||
});
|
||||
@ -0,0 +1,4 @@
|
||||
import foo, { named } from "foo";
|
||||
|
||||
foo();
|
||||
named();
|
||||
@ -0,0 +1,19 @@
|
||||
(function (global, factory) {
|
||||
if (typeof define === "function" && define.amd) {
|
||||
define(["foo"], factory);
|
||||
} else if (typeof exports !== "undefined") {
|
||||
factory(require("foo"));
|
||||
} else {
|
||||
var mod = {
|
||||
exports: {}
|
||||
};
|
||||
factory(global.foo);
|
||||
global.input = mod.exports;
|
||||
}
|
||||
})(typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : this, function (_foo) {
|
||||
"use strict";
|
||||
|
||||
_foo = babelHelpers.interopRequireWildcard(_foo, true);
|
||||
(0, _foo.default)();
|
||||
(0, _foo.named)();
|
||||
});
|
||||
@ -0,0 +1,3 @@
|
||||
import { named } from "foo";
|
||||
|
||||
named();
|
||||
@ -0,0 +1,17 @@
|
||||
(function (global, factory) {
|
||||
if (typeof define === "function" && define.amd) {
|
||||
define(["foo"], factory);
|
||||
} else if (typeof exports !== "undefined") {
|
||||
factory(require("foo"));
|
||||
} else {
|
||||
var mod = {
|
||||
exports: {}
|
||||
};
|
||||
factory(global.foo);
|
||||
global.input = mod.exports;
|
||||
}
|
||||
})(typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : this, function (_foo) {
|
||||
"use strict";
|
||||
|
||||
(0, _foo.named)();
|
||||
});
|
||||
@ -0,0 +1,4 @@
|
||||
import * as foo from 'foo';
|
||||
|
||||
foo.bar();
|
||||
foo.baz();
|
||||
@ -0,0 +1,19 @@
|
||||
(function (global, factory) {
|
||||
if (typeof define === "function" && define.amd) {
|
||||
define(["foo"], factory);
|
||||
} else if (typeof exports !== "undefined") {
|
||||
factory(require("foo"));
|
||||
} else {
|
||||
var mod = {
|
||||
exports: {}
|
||||
};
|
||||
factory(global.foo);
|
||||
global.input = mod.exports;
|
||||
}
|
||||
})(typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : this, function (foo) {
|
||||
"use strict";
|
||||
|
||||
foo = babelHelpers.interopRequireWildcard(foo, true);
|
||||
foo.bar();
|
||||
foo.baz();
|
||||
});
|
||||
3
packages/babel-plugin-transform-modules-umd/test/fixtures/importInterop-node/options.json
vendored
Normal file
3
packages/babel-plugin-transform-modules-umd/test/fixtures/importInterop-node/options.json
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"plugins": [["transform-modules-umd", { "importInterop": "node" }]]
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
export { default } from 'foo';
|
||||
@ -0,0 +1,25 @@
|
||||
(function (global, factory) {
|
||||
if (typeof define === "function" && define.amd) {
|
||||
define(["exports", "foo"], factory);
|
||||
} else if (typeof exports !== "undefined") {
|
||||
factory(exports, require("foo"));
|
||||
} else {
|
||||
var mod = {
|
||||
exports: {}
|
||||
};
|
||||
factory(mod.exports, global.foo);
|
||||
global.input = mod.exports;
|
||||
}
|
||||
})(typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : this, function (_exports, _foo) {
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(_exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
Object.defineProperty(_exports, "default", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _foo.default;
|
||||
}
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,3 @@
|
||||
import foo from "foo";
|
||||
|
||||
foo();
|
||||
@ -0,0 +1,17 @@
|
||||
(function (global, factory) {
|
||||
if (typeof define === "function" && define.amd) {
|
||||
define(["foo"], factory);
|
||||
} else if (typeof exports !== "undefined") {
|
||||
factory(require("foo"));
|
||||
} else {
|
||||
var mod = {
|
||||
exports: {}
|
||||
};
|
||||
factory(global.foo);
|
||||
global.input = mod.exports;
|
||||
}
|
||||
})(typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : this, function (_foo) {
|
||||
"use strict";
|
||||
|
||||
(0, _foo.default)();
|
||||
});
|
||||
@ -0,0 +1,4 @@
|
||||
import * as foo from 'foo';
|
||||
|
||||
foo.bar();
|
||||
foo.baz();
|
||||
@ -0,0 +1,18 @@
|
||||
(function (global, factory) {
|
||||
if (typeof define === "function" && define.amd) {
|
||||
define(["foo"], factory);
|
||||
} else if (typeof exports !== "undefined") {
|
||||
factory(require("foo"));
|
||||
} else {
|
||||
var mod = {
|
||||
exports: {}
|
||||
};
|
||||
factory(global.foo);
|
||||
global.input = mod.exports;
|
||||
}
|
||||
})(typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : this, function (foo) {
|
||||
"use strict";
|
||||
|
||||
foo.bar();
|
||||
foo.baz();
|
||||
});
|
||||
3
packages/babel-plugin-transform-modules-umd/test/fixtures/importInterop-none/options.json
vendored
Normal file
3
packages/babel-plugin-transform-modules-umd/test/fixtures/importInterop-none/options.json
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"plugins": [["transform-modules-umd", { "importInterop": "none" }]]
|
||||
}
|
||||
@ -0,0 +1,55 @@
|
||||
import * as babel from "@babel/core";
|
||||
import transformUmd from "../lib";
|
||||
import externalHelpers from "@babel/plugin-external-helpers";
|
||||
|
||||
it("'importInterop' accepts a function", function () {
|
||||
const code = `
|
||||
import a from "a";
|
||||
import b from "b";
|
||||
import c from "c";
|
||||
|
||||
a();
|
||||
b();
|
||||
c();
|
||||
`;
|
||||
|
||||
const importInterop = source => {
|
||||
if (source === "a") return "babel";
|
||||
else if (source === "b") return "node";
|
||||
else if (source === "c") return "none";
|
||||
};
|
||||
|
||||
const output = babel.transformSync(code, {
|
||||
configFile: false,
|
||||
ast: false,
|
||||
plugins: [
|
||||
[externalHelpers, { helperVersion: "7.100.0" }],
|
||||
[transformUmd, { importInterop }],
|
||||
],
|
||||
}).code;
|
||||
|
||||
expect(output).toMatchInlineSnapshot(`
|
||||
"(function (global, factory) {
|
||||
if (typeof define === \\"function\\" && define.amd) {
|
||||
define([\\"a\\", \\"b\\", \\"c\\"], factory);
|
||||
} else if (typeof exports !== \\"undefined\\") {
|
||||
factory(require(\\"a\\"), require(\\"b\\"), require(\\"c\\"));
|
||||
} else {
|
||||
var mod = {
|
||||
exports: {}
|
||||
};
|
||||
factory(global.a, global.b, global.c);
|
||||
global.unknown = mod.exports;
|
||||
}
|
||||
})(typeof globalThis !== \\"undefined\\" ? globalThis : typeof self !== \\"undefined\\" ? self : this, function (_a, _b, _c) {
|
||||
\\"use strict\\";
|
||||
|
||||
_a = babelHelpers.interopRequireDefault(_a);
|
||||
(0, _a.default)();
|
||||
|
||||
_b();
|
||||
|
||||
(0, _c.default)();
|
||||
});"
|
||||
`);
|
||||
});
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user