Co-authored-by: Huáng Jùnliàng <jlhwung@gmail.com> Co-authored-by: Nicolò Ribaudo <nicolo.ribaudo@gmail.com>
89 lines
2.8 KiB
JavaScript
89 lines
2.8 KiB
JavaScript
/*
|
|
** Copyright 2020 Bloomberg Finance L.P.
|
|
**
|
|
** Licensed under the MIT License (the "License");
|
|
** you may not use this file except in compliance with the License.
|
|
** You may obtain a copy of the License at
|
|
**
|
|
** https://opensource.org/licenses/MIT
|
|
**
|
|
** Unless required by applicable law or agreed to in writing, software
|
|
** distributed under the License is distributed on an "AS IS" BASIS,
|
|
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
** See the License for the specific language governing permissions and
|
|
** limitations under the License.
|
|
*/
|
|
|
|
import { declare } from "@babel/helper-plugin-utils";
|
|
import syntaxRecordAndTuple from "@babel/plugin-syntax-record-and-tuple";
|
|
import { types as t } from "@babel/core";
|
|
import { addNamed, isModule } from "@babel/helper-module-imports";
|
|
import { OptionValidator } from "@babel/helper-validator-option";
|
|
|
|
const v = new OptionValidator(PACKAGE_JSON.name);
|
|
|
|
export default declare((api, options) => {
|
|
api.assertVersion(7);
|
|
|
|
const polyfillModuleName = v.validateStringOption(
|
|
"polyfillModuleName",
|
|
options.polyfillModuleName,
|
|
"@bloomberg/record-tuple-polyfill",
|
|
);
|
|
const shouldImportPolyfill = v.validateBooleanOption(
|
|
"importPolyfill",
|
|
options.importPolyfill,
|
|
!!options.polyfillModuleName,
|
|
);
|
|
|
|
// program -> cacheKey -> localBindingName
|
|
const importCaches = new WeakMap();
|
|
|
|
function getOr(map, key, getDefault) {
|
|
let value = map.get(key);
|
|
if (!value) map.set(key, (value = getDefault()));
|
|
return value;
|
|
}
|
|
|
|
function getBuiltIn(name, path, programPath) {
|
|
if (!shouldImportPolyfill) return t.identifier(name);
|
|
if (!programPath) {
|
|
throw new Error("Internal error: unable to find the Program node.");
|
|
}
|
|
|
|
const cacheKey = `${name}:${isModule(programPath)}`;
|
|
|
|
const cache = getOr(importCaches, programPath.node, () => new Map());
|
|
const localBindingName = getOr(cache, cacheKey, () => {
|
|
return addNamed(programPath, name, polyfillModuleName, {
|
|
importedInterop: "uncompiled",
|
|
}).name;
|
|
});
|
|
|
|
return t.identifier(localBindingName);
|
|
}
|
|
|
|
return {
|
|
name: "proposal-record-and-tuple",
|
|
inherits: syntaxRecordAndTuple,
|
|
visitor: {
|
|
Program(path, state) {
|
|
state.programPath = path;
|
|
},
|
|
RecordExpression(path, state) {
|
|
const record = getBuiltIn("Record", path, state.programPath);
|
|
|
|
const object = t.objectExpression(path.node.properties);
|
|
const wrapped = t.callExpression(record, [object]);
|
|
path.replaceWith(wrapped);
|
|
},
|
|
TupleExpression(path, state) {
|
|
const tuple = getBuiltIn("Tuple", path, state.programPath);
|
|
|
|
const wrapped = t.callExpression(tuple, path.node.elements);
|
|
path.replaceWith(wrapped);
|
|
},
|
|
},
|
|
};
|
|
});
|