tools: non-Ascii linter for /lib only

Non-ASCII characters in /lib get compiled into the node binary,
and may bloat the binary size unnecessarily. A linter rule may
help prevent this.

PR-URL: https://github.com/nodejs/node/pull/18043
Fixes: https://github.com/nodejs/node/issues/11209
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Teddy Katz <teddy.katz@gmail.com>
This commit is contained in:
Sarat Addepalli 2018-01-08 23:16:27 +05:30 committed by Anna Henningsen
parent 591a8adeae
commit c45afe8198
No known key found for this signature in database
GPG Key ID: 9C63F3A6CD2AD8F9
8 changed files with 71 additions and 5 deletions

View File

@ -6,3 +6,4 @@ rules:
buffer-constructor: error buffer-constructor: error
no-let-in-for-declaration: error no-let-in-for-declaration: error
lowercase-name-for-primitive: error lowercase-name-for-primitive: error
non-ascii-character: error

View File

@ -84,7 +84,7 @@ function createWriteErrorHandler(stream) {
// If there was an error, it will be emitted on `stream` as // If there was an error, it will be emitted on `stream` as
// an `error` event. Adding a `once` listener will keep that error // an `error` event. Adding a `once` listener will keep that error
// from becoming an uncaught exception, but since the handler is // from becoming an uncaught exception, but since the handler is
// removed after the event, non-console.* writes wont be affected. // removed after the event, non-console.* writes won't be affected.
// we are only adding noop if there is no one else listening for 'error' // we are only adding noop if there is no one else listening for 'error'
if (stream.listenerCount('error') === 0) { if (stream.listenerCount('error') === 0) {
stream.on('error', noop); stream.on('error', noop);
@ -125,7 +125,7 @@ function write(ignoreErrors, stream, string, errorhandler, groupIndent) {
// even in edge cases such as low stack space. // even in edge cases such as low stack space.
if (e.message === MAX_STACK_MESSAGE && e.name === 'RangeError') if (e.message === MAX_STACK_MESSAGE && e.name === 'RangeError')
throw e; throw e;
// Sorry, theres no proper way to pass along the error here. // Sorry, there's no proper way to pass along the error here.
} finally { } finally {
stream.removeListener('error', noop); stream.removeListener('error', noop);
} }

View File

@ -1884,7 +1884,7 @@ function processRespondWithFD(self, fd, headers, offset = 0, length = -1,
return; return;
} }
// exact length of the file doesn't matter here, since the // exact length of the file doesn't matter here, since the
// stream is closing anyway just use 1 to signify that // stream is closing anyway - just use 1 to signify that
// a write does exist // a write does exist
trackWriteState(self, 1); trackWriteState(self, 1);
} }

View File

@ -3,4 +3,6 @@
// This module exists entirely for regression testing purposes. // This module exists entirely for regression testing purposes.
// See `test/parallel/test-internal-unicode.js`. // See `test/parallel/test-internal-unicode.js`.
/* eslint-disable non-ascii-character */
module.exports = '✓'; module.exports = '✓';
/* eslint-enable non-ascii-character */

View File

@ -45,7 +45,7 @@ try {
try { try {
Stream._isUint8Array = process.binding('util').isUint8Array; Stream._isUint8Array = process.binding('util').isUint8Array;
} catch (e) { } catch (e) {
// This throws for Node < 4.2.0 because theres no util binding and // This throws for Node < 4.2.0 because there's no util binding and
// returns undefined for Node < 7.4.0. // returns undefined for Node < 7.4.0.
} }
} }

View File

@ -97,6 +97,7 @@ const Timeout = timerInternals.Timeout;
// TimerWrap C++ handle, which makes the call after the duration to process the // TimerWrap C++ handle, which makes the call after the duration to process the
// list it is attached to. // list it is attached to.
// //
/* eslint-disable non-ascii-character */
// //
// ╔════ > Object Map // ╔════ > Object Map
// ║ // ║
@ -118,6 +119,7 @@ const Timeout = timerInternals.Timeout;
// ║ // ║
// ╚════ > Linked List // ╚════ > Linked List
// //
/* eslint-enable non-ascii-character */
// //
// With this, virtually constant-time insertion (append), removal, and timeout // With this, virtually constant-time insertion (append), removal, and timeout
// is possible in the JavaScript layer. Any one list of timers is able to be // is possible in the JavaScript layer. Any one list of timers is able to be

View File

@ -374,7 +374,7 @@ Zlib.prototype.flush = function flush(kind, callback) {
this._scheduledFlushFlag = maxFlush(kind, this._scheduledFlushFlag); this._scheduledFlushFlag = maxFlush(kind, this._scheduledFlushFlag);
// If a callback was passed, always register a new `drain` + flush handler, // If a callback was passed, always register a new `drain` + flush handler,
// mostly because thats simpler and flush callbacks piling up is a rare // mostly because that's simpler and flush callbacks piling up is a rare
// thing anyway. // thing anyway.
if (!alreadyHadFlushScheduled || callback) { if (!alreadyHadFlushScheduled || callback) {
const drainHandler = () => this.flush(this._scheduledFlushFlag, callback); const drainHandler = () => this.flush(this._scheduledFlushFlag, callback);

View File

@ -0,0 +1,61 @@
/**
* @fileOverview Any non-ASCII characters in lib/ will increase the size
* of the compiled node binary. This linter rule ensures that
* any such character is reported.
* @author Sarat Addepalli <sarat.addepalli@gmail.com>
*/
'use strict';
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
const nonAsciiRegexPattern = /[^\r\n\x20-\x7e]/;
const suggestions = {
'': '\'',
'': '\'',
'': '\'',
'“': '"',
'‟': '"',
'”': '"',
'«': '"',
'»': '"',
'—': '-'
};
module.exports = (context) => {
const reportIfError = (node, sourceCode) => {
const matches = sourceCode.text.match(nonAsciiRegexPattern);
if (!matches) return;
const offendingCharacter = matches[0];
const offendingCharacterPosition = matches.index;
const suggestion = suggestions[offendingCharacter];
let message = `Non-ASCII character '${offendingCharacter}' detected.`;
message = suggestion ?
`${message} Consider replacing with: ${suggestion}` :
message;
context.report({
node,
message,
loc: sourceCode.getLocFromIndex(offendingCharacterPosition),
fix: (fixer) => {
return fixer.replaceText(
node,
suggestion ? `${suggestion}` : ''
);
}
});
};
return {
Program: (node) => reportIfError(node, context.getSourceCode())
};
};