Skip to content

Commit

Permalink
fix: Avoid null coalescing and optional chaining (merge #1905)
Browse files Browse the repository at this point in the history
  • Loading branch information
kriskowal authored Dec 19, 2023
2 parents 3622b48 + 3355c04 commit 9a8ec30
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 3 deletions.
9 changes: 8 additions & 1 deletion packages/bundle-source/src/is-entrypoint.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,14 @@ import url from 'url';
import process from 'process';
import fs from 'fs';

// Agoric still uses Endo dependencies under an emulation of ESM we call RESM
// because it is invoked with `node -r esm`.
// RESM does not support ?? nor ?. operators, so we must avoid them expressly.
// TODO remove when https://github.com/Agoric/agoric-sdk/issues/8671
const favor = (primary, secondary) =>
primary === undefined ? secondary : primary;

// FIXME: Should maybe be exported by '@endo/something'?
export const isEntrypoint = href =>
String(href) ===
url.pathToFileURL(fs.realpathSync(process.argv[1]) ?? '/').href;
url.pathToFileURL(fs.realpathSync(favor(process.argv[1]), '/')).href;
5 changes: 5 additions & 0 deletions packages/eslint-plugin/lib/configs/recommended.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,5 +65,10 @@ module.exports = {
rules: {
'@endo/assert-fail-as-throw': 'error',
'guard-for-in': 'error',
// Agoric still uses Endo dependencies under an emulation of ESM we call RESM
// because it is invoked with `node -r esm`.
// RESM does not support ?? nor ?. operators, so we must avoid them expressly.
'@endo/no-optional-chaining': 'error',
'@endo/no-nullish-coalescing': 'error',
},
};
35 changes: 35 additions & 0 deletions packages/eslint-plugin/lib/rules/no-nullish-coalescing.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
'use strict';

// Agoric still uses Endo dependencies under an emulation of ESM we call RESM
// because it is invoked with `node -r esm`.
// RESM does not support ?? nor ?. operators, so we must avoid them expressly.
// TODO remove when https://github.com/Agoric/agoric-sdk/issues/8671

module.exports = {
meta: {
docs: {
description: 'disallow nullish coalescing.',
category: 'ES2020',
recommended: false,
url: 'https://github.com/endojs/endo/blob/master/packages/eslint-plugin/lib/rules/no-nullish-coalescing.js',
},
fixable: null,
messages: {
forbidden: 'ES2020 nullish coalescing is forbidden.',
},
schema: [],
type: 'problem',
},
create(context) {
return {
LogicalExpression(node) {
if (node.operator === '??') {
context.report({
node,
messageId: 'forbidden',
});
}
},
};
},
};
55 changes: 55 additions & 0 deletions packages/eslint-plugin/lib/rules/no-optional-chaining.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/** @author Yosuke Ota <https://github.com/ota-meshi> */
'use strict';

// Agoric still uses Endo dependencies under an emulation of ESM we call RESM
// because it is invoked with `node -r esm`.
// RESM does not support ?? nor ?. operators, so we must avoid them expressly.
// TODO remove when https://github.com/Agoric/agoric-sdk/issues/8671

module.exports = {
meta: {
docs: {
description: 'disallow optional chaining.',
category: 'ES2020',
recommended: false,
url: 'http://mysticatea.github.io/eslint-plugin-es/rules/no-optional-chaining.html',
},
fixable: null,
messages: {
forbidden: 'ES2020 optional chaining is forbidden.',
},
schema: [],
type: 'problem',
},
create(context) {
const sourceCode = context.getSourceCode();

/**
* @param {Token} token The token to check.
* @returns {boolean} whether the token is a `?.` token.
*/
function isQuestionDotToken(token) {
return (
token.value === '?.' &&
(token.type === 'Punctuator' || // espree has been parsed well.
// [email protected] doesn't parse "?." tokens well. Therefore, get the string from the source code and check it.
sourceCode.getText(token) === '?.')
);
}

return {
'CallExpression[optional=true]'(node) {
context.report({
node: sourceCode.getTokenAfter(node.callee, isQuestionDotToken),
messageId: 'forbidden',
});
},
'MemberExpression[optional=true]'(node) {
context.report({
node: sourceCode.getTokenAfter(node.object, isQuestionDotToken),
messageId: 'forbidden',
});
},
};
},
};
4 changes: 3 additions & 1 deletion packages/evasive-transform/src/generate.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,9 @@ const { default: generator } = /** @type {any} */ (babelGenerate);
export const generate =
/** @type {GenerateAstWithSourceMap & GenerateAstWithoutSourceMap} */ (
(ast, options) => {
const sourceUrl = options?.sourceUrl;
// TODO Use options?.sourceUrl when resolved:
// https://github.com/Agoric/agoric-sdk/issues/8671
const sourceUrl = options ? options.sourceUrl : undefined;
const result = generator(ast, {
sourceFileName: sourceUrl,
sourceMaps: Boolean(sourceUrl),
Expand Down
4 changes: 3 additions & 1 deletion packages/evasive-transform/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ import { generate } from './generate.js';
* @public
*/
export async function evadeCensor(source, options) {
const { sourceMap, sourceUrl, useLocationUnmap, sourceType } = options ?? {};
// TODO Use options ?? {} when resolved:
// https://github.com/Agoric/agoric-sdk/issues/8671
const { sourceMap, sourceUrl, useLocationUnmap, sourceType } = options || {};

// See "Chesterton's Fence"
await null;
Expand Down

0 comments on commit 9a8ec30

Please sign in to comment.