2023-07-08 23:07:54 +09:00
|
|
|
import fs from "fs";
|
|
|
|
import path from "path";
|
|
|
|
import vm from "vm";
|
2012-08-02 06:27:42 +09:00
|
|
|
|
2022-05-11 21:21:16 +09:00
|
|
|
const AllWhitespaceRegexp = /^\s+$/g;
|
|
|
|
|
2012-08-02 06:27:42 +09:00
|
|
|
/**
|
Fix preprocessor: nesting, error & tests
Features / bug fixes in the preprocessor:
- Add word boundary after regex for preprocessor token matching.
Previously, when you mistakenly used "#ifdef" instead of "#if", the
line would be parsed as a preprocessor directive (because "#ifdef"
starts with "#if"), but without condition (because "def" does not
start with a space). Consequently, the condition would always be false
and anything between "#ifdef" and "#endif" would not be included.
- Add validation and error reporting everywhere, to aid debugging.
- Support nested comments (by accounting for the whole stack of
conditions, instead of only the current one).
- Add #elif preprocessor command. Could be used as follows:
//#if !FEATURE_ENABLED
//#error FEATURE_ENABLED must be set
//#endif
- Add #error preprocessor command.
- Add end-of-line word boundary after "-->" in the comment trimmer.
Otherwise the pattern would also match "-->" in the middle of a line,
and incorrectly convert something like "while(i-->0)" to "while(i0)".
Code health:
- Add unit tests for the preprocessor (run external/builder/test.js).
- Fix broken link to MDN (resolved to DXR).
- Refactor to use STATE_* names instead of magic numbers (the original
meaning of the numbers is preserved, with one exception).
- State 3 has been split in two states, to distinguish between being in
an #if and #else. This is needed to ensure that #else cannot be
started without an #if.
2015-07-09 18:03:34 +09:00
|
|
|
* A simple preprocessor that is based on the Firefox preprocessor
|
|
|
|
* (https://dxr.mozilla.org/mozilla-central/source/build/docs/preprocessor.rst).
|
|
|
|
* The main difference is that this supports a subset of the commands and it
|
|
|
|
* supports preprocessor commands in HTML-style comments.
|
|
|
|
*
|
|
|
|
* Currently supported commands:
|
2012-08-02 06:27:42 +09:00
|
|
|
* - if
|
Fix preprocessor: nesting, error & tests
Features / bug fixes in the preprocessor:
- Add word boundary after regex for preprocessor token matching.
Previously, when you mistakenly used "#ifdef" instead of "#if", the
line would be parsed as a preprocessor directive (because "#ifdef"
starts with "#if"), but without condition (because "def" does not
start with a space). Consequently, the condition would always be false
and anything between "#ifdef" and "#endif" would not be included.
- Add validation and error reporting everywhere, to aid debugging.
- Support nested comments (by accounting for the whole stack of
conditions, instead of only the current one).
- Add #elif preprocessor command. Could be used as follows:
//#if !FEATURE_ENABLED
//#error FEATURE_ENABLED must be set
//#endif
- Add #error preprocessor command.
- Add end-of-line word boundary after "-->" in the comment trimmer.
Otherwise the pattern would also match "-->" in the middle of a line,
and incorrectly convert something like "while(i-->0)" to "while(i0)".
Code health:
- Add unit tests for the preprocessor (run external/builder/test.js).
- Fix broken link to MDN (resolved to DXR).
- Refactor to use STATE_* names instead of magic numbers (the original
meaning of the numbers is preserved, with one exception).
- State 3 has been split in two states, to distinguish between being in
an #if and #else. This is needed to ensure that #else cannot be
started without an #if.
2015-07-09 18:03:34 +09:00
|
|
|
* - elif
|
2012-08-02 06:27:42 +09:00
|
|
|
* - else
|
|
|
|
* - endif
|
|
|
|
* - include
|
|
|
|
* - expand
|
Fix preprocessor: nesting, error & tests
Features / bug fixes in the preprocessor:
- Add word boundary after regex for preprocessor token matching.
Previously, when you mistakenly used "#ifdef" instead of "#if", the
line would be parsed as a preprocessor directive (because "#ifdef"
starts with "#if"), but without condition (because "def" does not
start with a space). Consequently, the condition would always be false
and anything between "#ifdef" and "#endif" would not be included.
- Add validation and error reporting everywhere, to aid debugging.
- Support nested comments (by accounting for the whole stack of
conditions, instead of only the current one).
- Add #elif preprocessor command. Could be used as follows:
//#if !FEATURE_ENABLED
//#error FEATURE_ENABLED must be set
//#endif
- Add #error preprocessor command.
- Add end-of-line word boundary after "-->" in the comment trimmer.
Otherwise the pattern would also match "-->" in the middle of a line,
and incorrectly convert something like "while(i-->0)" to "while(i0)".
Code health:
- Add unit tests for the preprocessor (run external/builder/test.js).
- Fix broken link to MDN (resolved to DXR).
- Refactor to use STATE_* names instead of magic numbers (the original
meaning of the numbers is preserved, with one exception).
- State 3 has been split in two states, to distinguish between being in
an #if and #else. This is needed to ensure that #else cannot be
started without an #if.
2015-07-09 18:03:34 +09:00
|
|
|
* - error
|
|
|
|
*
|
|
|
|
* Every #if must be closed with an #endif. Nested conditions are supported.
|
|
|
|
*
|
|
|
|
* Within an #if or #else block, one level of comment tokens is stripped. This
|
|
|
|
* allows us to write code that can run even without preprocessing. For example:
|
|
|
|
*
|
|
|
|
* //#if SOME_RARE_CONDITION
|
|
|
|
* // // Decrement by one
|
|
|
|
* // --i;
|
|
|
|
* //#else
|
|
|
|
* // // Increment by one.
|
|
|
|
* ++i;
|
|
|
|
* //#endif
|
2012-08-02 06:27:42 +09:00
|
|
|
*/
|
|
|
|
function preprocess(inFilename, outFilename, defines) {
|
2021-03-14 01:40:44 +09:00
|
|
|
let lineNumber = 0;
|
|
|
|
function loc() {
|
|
|
|
return fs.realpathSync(inFilename) + ":" + lineNumber;
|
|
|
|
}
|
|
|
|
|
Use the regular `preprocess`-function for the CSS files as well
An old shortcoming of the `preprocessCSS`-function is its complete lack of support for our "normal" defines, which makes it very difficult to have build-specific CSS rules. Recently we've started using specially crafted comments to remove CSS rules from the MOZCENTRAL build, but (ab)using the `preprocessCSS`-function in this way really doesn't feel great.
However, it turns out to be surprisingly simple to instead use the "regular" `preprocess`-function for the CSS files as well. The only special-handling that's still necessary is the helper-function for dealing with CSS-imports, but apart from that everything seems to just work.
One reason, as far as I can tell, for having a separate `preprocessCSS`-function was likely that we originally used *lots* of vendor-prefixed CSS rules in our CSS files. With improvements over the years, especially thanks to Autoprefixer and PostCSS, we've been able to remove *almost* all non-standard CSS rules and the need for special-casing the CSS parsing has mostly vanished.
*Please note:* As part of testing this patch I've diffed the output of `gulp generic`, `gulp mozcentral`, and `gulp chromium` against the `master`-branch to check that there was no obvious breakage.
2022-05-08 05:00:54 +09:00
|
|
|
function expandCssImports(content, baseUrl) {
|
2023-03-23 20:34:08 +09:00
|
|
|
return content.replaceAll(
|
Use the regular `preprocess`-function for the CSS files as well
An old shortcoming of the `preprocessCSS`-function is its complete lack of support for our "normal" defines, which makes it very difficult to have build-specific CSS rules. Recently we've started using specially crafted comments to remove CSS rules from the MOZCENTRAL build, but (ab)using the `preprocessCSS`-function in this way really doesn't feel great.
However, it turns out to be surprisingly simple to instead use the "regular" `preprocess`-function for the CSS files as well. The only special-handling that's still necessary is the helper-function for dealing with CSS-imports, but apart from that everything seems to just work.
One reason, as far as I can tell, for having a separate `preprocessCSS`-function was likely that we originally used *lots* of vendor-prefixed CSS rules in our CSS files. With improvements over the years, especially thanks to Autoprefixer and PostCSS, we've been able to remove *almost* all non-standard CSS rules and the need for special-casing the CSS parsing has mostly vanished.
*Please note:* As part of testing this patch I've diffed the output of `gulp generic`, `gulp mozcentral`, and `gulp chromium` against the `master`-branch to check that there was no obvious breakage.
2022-05-08 05:00:54 +09:00
|
|
|
/^\s*@import\s+url\(([^)]+)\);\s*$/gm,
|
|
|
|
function (all, url) {
|
2023-09-21 22:18:12 +09:00
|
|
|
if (defines.GECKOVIEW) {
|
|
|
|
switch (url) {
|
|
|
|
case "annotation_editor_layer_builder.css":
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
}
|
Use the regular `preprocess`-function for the CSS files as well
An old shortcoming of the `preprocessCSS`-function is its complete lack of support for our "normal" defines, which makes it very difficult to have build-specific CSS rules. Recently we've started using specially crafted comments to remove CSS rules from the MOZCENTRAL build, but (ab)using the `preprocessCSS`-function in this way really doesn't feel great.
However, it turns out to be surprisingly simple to instead use the "regular" `preprocess`-function for the CSS files as well. The only special-handling that's still necessary is the helper-function for dealing with CSS-imports, but apart from that everything seems to just work.
One reason, as far as I can tell, for having a separate `preprocessCSS`-function was likely that we originally used *lots* of vendor-prefixed CSS rules in our CSS files. With improvements over the years, especially thanks to Autoprefixer and PostCSS, we've been able to remove *almost* all non-standard CSS rules and the need for special-casing the CSS parsing has mostly vanished.
*Please note:* As part of testing this patch I've diffed the output of `gulp generic`, `gulp mozcentral`, and `gulp chromium` against the `master`-branch to check that there was no obvious breakage.
2022-05-08 05:00:54 +09:00
|
|
|
const file = path.join(path.dirname(baseUrl), url);
|
|
|
|
const imported = fs.readFileSync(file, "utf8").toString();
|
|
|
|
return expandCssImports(imported, file);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2012-08-02 06:27:42 +09:00
|
|
|
// TODO make this really read line by line.
|
Use the regular `preprocess`-function for the CSS files as well
An old shortcoming of the `preprocessCSS`-function is its complete lack of support for our "normal" defines, which makes it very difficult to have build-specific CSS rules. Recently we've started using specially crafted comments to remove CSS rules from the MOZCENTRAL build, but (ab)using the `preprocessCSS`-function in this way really doesn't feel great.
However, it turns out to be surprisingly simple to instead use the "regular" `preprocess`-function for the CSS files as well. The only special-handling that's still necessary is the helper-function for dealing with CSS-imports, but apart from that everything seems to just work.
One reason, as far as I can tell, for having a separate `preprocessCSS`-function was likely that we originally used *lots* of vendor-prefixed CSS rules in our CSS files. With improvements over the years, especially thanks to Autoprefixer and PostCSS, we've been able to remove *almost* all non-standard CSS rules and the need for special-casing the CSS parsing has mostly vanished.
*Please note:* As part of testing this patch I've diffed the output of `gulp generic`, `gulp mozcentral`, and `gulp chromium` against the `master`-branch to check that there was no obvious breakage.
2022-05-08 05:00:54 +09:00
|
|
|
let content = fs.readFileSync(inFilename, "utf8").toString();
|
|
|
|
// Handle CSS-imports first, when necessary.
|
|
|
|
if (/\.css$/i.test(inFilename)) {
|
|
|
|
content = expandCssImports(content, inFilename);
|
|
|
|
}
|
|
|
|
const lines = content.split("\n"),
|
|
|
|
totalLines = lines.length;
|
2022-05-11 19:32:41 +09:00
|
|
|
const out = [];
|
2021-03-14 01:37:27 +09:00
|
|
|
let i = 0;
|
2012-08-02 06:27:42 +09:00
|
|
|
function readLine() {
|
|
|
|
if (i < totalLines) {
|
|
|
|
return lines[i++];
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
2021-03-14 01:37:27 +09:00
|
|
|
const writeLine =
|
2014-03-10 23:53:41 +09:00
|
|
|
typeof outFilename === "function"
|
|
|
|
? outFilename
|
2020-04-14 19:28:14 +09:00
|
|
|
: function (line) {
|
2022-05-11 21:21:16 +09:00
|
|
|
if (!line || AllWhitespaceRegexp.test(line)) {
|
2023-04-26 00:19:59 +09:00
|
|
|
const prevLine = out.at(-1);
|
2022-05-11 21:21:16 +09:00
|
|
|
if (!prevLine || AllWhitespaceRegexp.test(prevLine)) {
|
|
|
|
return; // Avoid adding consecutive blank lines.
|
|
|
|
}
|
|
|
|
}
|
2022-05-11 19:32:41 +09:00
|
|
|
out.push(line);
|
2014-03-10 23:53:41 +09:00
|
|
|
};
|
Fix preprocessor: nesting, error & tests
Features / bug fixes in the preprocessor:
- Add word boundary after regex for preprocessor token matching.
Previously, when you mistakenly used "#ifdef" instead of "#if", the
line would be parsed as a preprocessor directive (because "#ifdef"
starts with "#if"), but without condition (because "def" does not
start with a space). Consequently, the condition would always be false
and anything between "#ifdef" and "#endif" would not be included.
- Add validation and error reporting everywhere, to aid debugging.
- Support nested comments (by accounting for the whole stack of
conditions, instead of only the current one).
- Add #elif preprocessor command. Could be used as follows:
//#if !FEATURE_ENABLED
//#error FEATURE_ENABLED must be set
//#endif
- Add #error preprocessor command.
- Add end-of-line word boundary after "-->" in the comment trimmer.
Otherwise the pattern would also match "-->" in the middle of a line,
and incorrectly convert something like "while(i-->0)" to "while(i0)".
Code health:
- Add unit tests for the preprocessor (run external/builder/test.js).
- Fix broken link to MDN (resolved to DXR).
- Refactor to use STATE_* names instead of magic numbers (the original
meaning of the numbers is preserved, with one exception).
- State 3 has been split in two states, to distinguish between being in
an #if and #else. This is needed to ensure that #else cannot be
started without an #if.
2015-07-09 18:03:34 +09:00
|
|
|
function evaluateCondition(code) {
|
|
|
|
if (!code || !code.trim()) {
|
|
|
|
throw new Error("No JavaScript expression given at " + loc());
|
|
|
|
}
|
|
|
|
try {
|
Fix the remaining cases of inconsistent spacing and trailing commas in objects, and enable the `comma-dangle` and `object-curly-spacing` ESLint rules
http://eslint.org/docs/rules/comma-dangle
http://eslint.org/docs/rules/object-curly-spacing
*Please note:* This patch was created automatically, using the ESLint `--fix` command line option. In a couple of places this caused lines to become too long, and I've fixed those manually; please refer to the interdiff below for the only hand-edits in this patch.
```diff
diff --git a/gulpfile.js b/gulpfile.js
index d18b9c58..7d47fd8d 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -1247,7 +1247,8 @@ gulp.task('gh-pages-git', ['gh-pages-prepare', 'wintersmith'], function () {
var reason = process.env['PDFJS_UPDATE_REASON'];
safeSpawnSync('git', ['init'], { cwd: GH_PAGES_DIR, });
- safeSpawnSync('git', ['remote', 'add', 'origin', REPO], { cwd: GH_PAGES_DIR, });
+ safeSpawnSync('git', ['remote', 'add', 'origin', REPO],
+ { cwd: GH_PAGES_DIR, });
safeSpawnSync('git', ['add', '-A'], { cwd: GH_PAGES_DIR, });
safeSpawnSync('git', [
'commit', '-am', 'gh-pages site created via gulpfile.js script',
```
2017-06-03 00:13:35 +09:00
|
|
|
return vm.runInNewContext(code, defines, { displayErrors: false });
|
Fix preprocessor: nesting, error & tests
Features / bug fixes in the preprocessor:
- Add word boundary after regex for preprocessor token matching.
Previously, when you mistakenly used "#ifdef" instead of "#if", the
line would be parsed as a preprocessor directive (because "#ifdef"
starts with "#if"), but without condition (because "def" does not
start with a space). Consequently, the condition would always be false
and anything between "#ifdef" and "#endif" would not be included.
- Add validation and error reporting everywhere, to aid debugging.
- Support nested comments (by accounting for the whole stack of
conditions, instead of only the current one).
- Add #elif preprocessor command. Could be used as follows:
//#if !FEATURE_ENABLED
//#error FEATURE_ENABLED must be set
//#endif
- Add #error preprocessor command.
- Add end-of-line word boundary after "-->" in the comment trimmer.
Otherwise the pattern would also match "-->" in the middle of a line,
and incorrectly convert something like "while(i-->0)" to "while(i0)".
Code health:
- Add unit tests for the preprocessor (run external/builder/test.js).
- Fix broken link to MDN (resolved to DXR).
- Refactor to use STATE_* names instead of magic numbers (the original
meaning of the numbers is preserved, with one exception).
- State 3 has been split in two states, to distinguish between being in
an #if and #else. This is needed to ensure that #else cannot be
started without an #if.
2015-07-09 18:03:34 +09:00
|
|
|
} catch (e) {
|
|
|
|
throw new Error(
|
|
|
|
'Could not evaluate "' +
|
|
|
|
code +
|
|
|
|
'" at ' +
|
|
|
|
loc() +
|
|
|
|
"\n" +
|
|
|
|
e.name +
|
|
|
|
": " +
|
|
|
|
e.message
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2012-08-02 06:27:42 +09:00
|
|
|
function include(file) {
|
2021-03-14 01:37:27 +09:00
|
|
|
const realPath = fs.realpathSync(inFilename);
|
|
|
|
const dir = path.dirname(realPath);
|
Fix preprocessor: nesting, error & tests
Features / bug fixes in the preprocessor:
- Add word boundary after regex for preprocessor token matching.
Previously, when you mistakenly used "#ifdef" instead of "#if", the
line would be parsed as a preprocessor directive (because "#ifdef"
starts with "#if"), but without condition (because "def" does not
start with a space). Consequently, the condition would always be false
and anything between "#ifdef" and "#endif" would not be included.
- Add validation and error reporting everywhere, to aid debugging.
- Support nested comments (by accounting for the whole stack of
conditions, instead of only the current one).
- Add #elif preprocessor command. Could be used as follows:
//#if !FEATURE_ENABLED
//#error FEATURE_ENABLED must be set
//#endif
- Add #error preprocessor command.
- Add end-of-line word boundary after "-->" in the comment trimmer.
Otherwise the pattern would also match "-->" in the middle of a line,
and incorrectly convert something like "while(i-->0)" to "while(i0)".
Code health:
- Add unit tests for the preprocessor (run external/builder/test.js).
- Fix broken link to MDN (resolved to DXR).
- Refactor to use STATE_* names instead of magic numbers (the original
meaning of the numbers is preserved, with one exception).
- State 3 has been split in two states, to distinguish between being in
an #if and #else. This is needed to ensure that #else cannot be
started without an #if.
2015-07-09 18:03:34 +09:00
|
|
|
try {
|
2021-03-14 01:37:27 +09:00
|
|
|
let fullpath;
|
2016-04-09 02:34:27 +09:00
|
|
|
if (file.indexOf("$ROOT/") === 0) {
|
|
|
|
fullpath = path.join(
|
|
|
|
__dirname,
|
|
|
|
"../..",
|
|
|
|
file.substring("$ROOT/".length)
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
fullpath = path.join(dir, file);
|
|
|
|
}
|
|
|
|
preprocess(fullpath, writeLine, defines);
|
Fix preprocessor: nesting, error & tests
Features / bug fixes in the preprocessor:
- Add word boundary after regex for preprocessor token matching.
Previously, when you mistakenly used "#ifdef" instead of "#if", the
line would be parsed as a preprocessor directive (because "#ifdef"
starts with "#if"), but without condition (because "def" does not
start with a space). Consequently, the condition would always be false
and anything between "#ifdef" and "#endif" would not be included.
- Add validation and error reporting everywhere, to aid debugging.
- Support nested comments (by accounting for the whole stack of
conditions, instead of only the current one).
- Add #elif preprocessor command. Could be used as follows:
//#if !FEATURE_ENABLED
//#error FEATURE_ENABLED must be set
//#endif
- Add #error preprocessor command.
- Add end-of-line word boundary after "-->" in the comment trimmer.
Otherwise the pattern would also match "-->" in the middle of a line,
and incorrectly convert something like "while(i-->0)" to "while(i0)".
Code health:
- Add unit tests for the preprocessor (run external/builder/test.js).
- Fix broken link to MDN (resolved to DXR).
- Refactor to use STATE_* names instead of magic numbers (the original
meaning of the numbers is preserved, with one exception).
- State 3 has been split in two states, to distinguish between being in
an #if and #else. This is needed to ensure that #else cannot be
started without an #if.
2015-07-09 18:03:34 +09:00
|
|
|
} catch (e) {
|
|
|
|
if (e.code === "ENOENT") {
|
|
|
|
throw new Error('Failed to include "' + file + '" at ' + loc());
|
|
|
|
}
|
|
|
|
throw e; // Some other error
|
|
|
|
}
|
2012-08-02 06:27:42 +09:00
|
|
|
}
|
|
|
|
function expand(line) {
|
2023-03-23 20:34:08 +09:00
|
|
|
line = line.replaceAll(/__[\w]+__/g, function (variable) {
|
2012-08-02 06:27:42 +09:00
|
|
|
variable = variable.substring(2, variable.length - 2);
|
|
|
|
if (variable in defines) {
|
|
|
|
return defines[variable];
|
|
|
|
}
|
|
|
|
return "";
|
|
|
|
});
|
|
|
|
writeLine(line);
|
|
|
|
}
|
|
|
|
|
Fix preprocessor: nesting, error & tests
Features / bug fixes in the preprocessor:
- Add word boundary after regex for preprocessor token matching.
Previously, when you mistakenly used "#ifdef" instead of "#if", the
line would be parsed as a preprocessor directive (because "#ifdef"
starts with "#if"), but without condition (because "def" does not
start with a space). Consequently, the condition would always be false
and anything between "#ifdef" and "#endif" would not be included.
- Add validation and error reporting everywhere, to aid debugging.
- Support nested comments (by accounting for the whole stack of
conditions, instead of only the current one).
- Add #elif preprocessor command. Could be used as follows:
//#if !FEATURE_ENABLED
//#error FEATURE_ENABLED must be set
//#endif
- Add #error preprocessor command.
- Add end-of-line word boundary after "-->" in the comment trimmer.
Otherwise the pattern would also match "-->" in the middle of a line,
and incorrectly convert something like "while(i-->0)" to "while(i0)".
Code health:
- Add unit tests for the preprocessor (run external/builder/test.js).
- Fix broken link to MDN (resolved to DXR).
- Refactor to use STATE_* names instead of magic numbers (the original
meaning of the numbers is preserved, with one exception).
- State 3 has been split in two states, to distinguish between being in
an #if and #else. This is needed to ensure that #else cannot be
started without an #if.
2015-07-09 18:03:34 +09:00
|
|
|
// not inside if or else (process lines)
|
2021-03-14 01:37:27 +09:00
|
|
|
const STATE_NONE = 0;
|
Fix preprocessor: nesting, error & tests
Features / bug fixes in the preprocessor:
- Add word boundary after regex for preprocessor token matching.
Previously, when you mistakenly used "#ifdef" instead of "#if", the
line would be parsed as a preprocessor directive (because "#ifdef"
starts with "#if"), but without condition (because "def" does not
start with a space). Consequently, the condition would always be false
and anything between "#ifdef" and "#endif" would not be included.
- Add validation and error reporting everywhere, to aid debugging.
- Support nested comments (by accounting for the whole stack of
conditions, instead of only the current one).
- Add #elif preprocessor command. Could be used as follows:
//#if !FEATURE_ENABLED
//#error FEATURE_ENABLED must be set
//#endif
- Add #error preprocessor command.
- Add end-of-line word boundary after "-->" in the comment trimmer.
Otherwise the pattern would also match "-->" in the middle of a line,
and incorrectly convert something like "while(i-->0)" to "while(i0)".
Code health:
- Add unit tests for the preprocessor (run external/builder/test.js).
- Fix broken link to MDN (resolved to DXR).
- Refactor to use STATE_* names instead of magic numbers (the original
meaning of the numbers is preserved, with one exception).
- State 3 has been split in two states, to distinguish between being in
an #if and #else. This is needed to ensure that #else cannot be
started without an #if.
2015-07-09 18:03:34 +09:00
|
|
|
// inside if, condition false (ignore until #else or #endif)
|
2021-03-14 01:37:27 +09:00
|
|
|
const STATE_IF_FALSE = 1;
|
Fix preprocessor: nesting, error & tests
Features / bug fixes in the preprocessor:
- Add word boundary after regex for preprocessor token matching.
Previously, when you mistakenly used "#ifdef" instead of "#if", the
line would be parsed as a preprocessor directive (because "#ifdef"
starts with "#if"), but without condition (because "def" does not
start with a space). Consequently, the condition would always be false
and anything between "#ifdef" and "#endif" would not be included.
- Add validation and error reporting everywhere, to aid debugging.
- Support nested comments (by accounting for the whole stack of
conditions, instead of only the current one).
- Add #elif preprocessor command. Could be used as follows:
//#if !FEATURE_ENABLED
//#error FEATURE_ENABLED must be set
//#endif
- Add #error preprocessor command.
- Add end-of-line word boundary after "-->" in the comment trimmer.
Otherwise the pattern would also match "-->" in the middle of a line,
and incorrectly convert something like "while(i-->0)" to "while(i0)".
Code health:
- Add unit tests for the preprocessor (run external/builder/test.js).
- Fix broken link to MDN (resolved to DXR).
- Refactor to use STATE_* names instead of magic numbers (the original
meaning of the numbers is preserved, with one exception).
- State 3 has been split in two states, to distinguish between being in
an #if and #else. This is needed to ensure that #else cannot be
started without an #if.
2015-07-09 18:03:34 +09:00
|
|
|
// inside else, #if was false, so #else is true (process lines until #endif)
|
2021-03-14 01:37:27 +09:00
|
|
|
const STATE_ELSE_TRUE = 2;
|
Fix preprocessor: nesting, error & tests
Features / bug fixes in the preprocessor:
- Add word boundary after regex for preprocessor token matching.
Previously, when you mistakenly used "#ifdef" instead of "#if", the
line would be parsed as a preprocessor directive (because "#ifdef"
starts with "#if"), but without condition (because "def" does not
start with a space). Consequently, the condition would always be false
and anything between "#ifdef" and "#endif" would not be included.
- Add validation and error reporting everywhere, to aid debugging.
- Support nested comments (by accounting for the whole stack of
conditions, instead of only the current one).
- Add #elif preprocessor command. Could be used as follows:
//#if !FEATURE_ENABLED
//#error FEATURE_ENABLED must be set
//#endif
- Add #error preprocessor command.
- Add end-of-line word boundary after "-->" in the comment trimmer.
Otherwise the pattern would also match "-->" in the middle of a line,
and incorrectly convert something like "while(i-->0)" to "while(i0)".
Code health:
- Add unit tests for the preprocessor (run external/builder/test.js).
- Fix broken link to MDN (resolved to DXR).
- Refactor to use STATE_* names instead of magic numbers (the original
meaning of the numbers is preserved, with one exception).
- State 3 has been split in two states, to distinguish between being in
an #if and #else. This is needed to ensure that #else cannot be
started without an #if.
2015-07-09 18:03:34 +09:00
|
|
|
// inside if, condition true (process lines until #else or #endif)
|
2021-03-14 01:37:27 +09:00
|
|
|
const STATE_IF_TRUE = 3;
|
2016-05-10 08:18:43 +09:00
|
|
|
// inside else or elif, #if/#elif was true, so following #else or #elif is
|
|
|
|
// false (ignore lines until #endif)
|
2021-03-14 01:37:27 +09:00
|
|
|
const STATE_ELSE_FALSE = 4;
|
Fix preprocessor: nesting, error & tests
Features / bug fixes in the preprocessor:
- Add word boundary after regex for preprocessor token matching.
Previously, when you mistakenly used "#ifdef" instead of "#if", the
line would be parsed as a preprocessor directive (because "#ifdef"
starts with "#if"), but without condition (because "def" does not
start with a space). Consequently, the condition would always be false
and anything between "#ifdef" and "#endif" would not be included.
- Add validation and error reporting everywhere, to aid debugging.
- Support nested comments (by accounting for the whole stack of
conditions, instead of only the current one).
- Add #elif preprocessor command. Could be used as follows:
//#if !FEATURE_ENABLED
//#error FEATURE_ENABLED must be set
//#endif
- Add #error preprocessor command.
- Add end-of-line word boundary after "-->" in the comment trimmer.
Otherwise the pattern would also match "-->" in the middle of a line,
and incorrectly convert something like "while(i-->0)" to "while(i0)".
Code health:
- Add unit tests for the preprocessor (run external/builder/test.js).
- Fix broken link to MDN (resolved to DXR).
- Refactor to use STATE_* names instead of magic numbers (the original
meaning of the numbers is preserved, with one exception).
- State 3 has been split in two states, to distinguish between being in
an #if and #else. This is needed to ensure that #else cannot be
started without an #if.
2015-07-09 18:03:34 +09:00
|
|
|
|
2021-03-14 01:37:27 +09:00
|
|
|
let line;
|
|
|
|
let state = STATE_NONE;
|
|
|
|
const stack = [];
|
2021-05-16 17:58:34 +09:00
|
|
|
const control =
|
Use the regular `preprocess`-function for the CSS files as well
An old shortcoming of the `preprocessCSS`-function is its complete lack of support for our "normal" defines, which makes it very difficult to have build-specific CSS rules. Recently we've started using specially crafted comments to remove CSS rules from the MOZCENTRAL build, but (ab)using the `preprocessCSS`-function in this way really doesn't feel great.
However, it turns out to be surprisingly simple to instead use the "regular" `preprocess`-function for the CSS files as well. The only special-handling that's still necessary is the helper-function for dealing with CSS-imports, but apart from that everything seems to just work.
One reason, as far as I can tell, for having a separate `preprocessCSS`-function was likely that we originally used *lots* of vendor-prefixed CSS rules in our CSS files. With improvements over the years, especially thanks to Autoprefixer and PostCSS, we've been able to remove *almost* all non-standard CSS rules and the need for special-casing the CSS parsing has mostly vanished.
*Please note:* As part of testing this patch I've diffed the output of `gulp generic`, `gulp mozcentral`, and `gulp chromium` against the `master`-branch to check that there was no obvious breakage.
2022-05-08 05:00:54 +09:00
|
|
|
/^(?:\/\/|\s*\/\*|<!--)\s*#(if|elif|else|endif|expand|include|error)\b(?:\s+(.*?)(?:\*\/|-->)?$)?/;
|
2021-03-14 01:40:44 +09:00
|
|
|
|
Fix preprocessor: nesting, error & tests
Features / bug fixes in the preprocessor:
- Add word boundary after regex for preprocessor token matching.
Previously, when you mistakenly used "#ifdef" instead of "#if", the
line would be parsed as a preprocessor directive (because "#ifdef"
starts with "#if"), but without condition (because "def" does not
start with a space). Consequently, the condition would always be false
and anything between "#ifdef" and "#endif" would not be included.
- Add validation and error reporting everywhere, to aid debugging.
- Support nested comments (by accounting for the whole stack of
conditions, instead of only the current one).
- Add #elif preprocessor command. Could be used as follows:
//#if !FEATURE_ENABLED
//#error FEATURE_ENABLED must be set
//#endif
- Add #error preprocessor command.
- Add end-of-line word boundary after "-->" in the comment trimmer.
Otherwise the pattern would also match "-->" in the middle of a line,
and incorrectly convert something like "while(i-->0)" to "while(i0)".
Code health:
- Add unit tests for the preprocessor (run external/builder/test.js).
- Fix broken link to MDN (resolved to DXR).
- Refactor to use STATE_* names instead of magic numbers (the original
meaning of the numbers is preserved, with one exception).
- State 3 has been split in two states, to distinguish between being in
an #if and #else. This is needed to ensure that #else cannot be
started without an #if.
2015-07-09 18:03:34 +09:00
|
|
|
while ((line = readLine()) !== null) {
|
2012-08-02 06:27:42 +09:00
|
|
|
++lineNumber;
|
2021-03-14 01:37:27 +09:00
|
|
|
const m = control.exec(line);
|
2012-08-02 06:27:42 +09:00
|
|
|
if (m) {
|
|
|
|
switch (m[1]) {
|
|
|
|
case "if":
|
|
|
|
stack.push(state);
|
Fix preprocessor: nesting, error & tests
Features / bug fixes in the preprocessor:
- Add word boundary after regex for preprocessor token matching.
Previously, when you mistakenly used "#ifdef" instead of "#if", the
line would be parsed as a preprocessor directive (because "#ifdef"
starts with "#if"), but without condition (because "def" does not
start with a space). Consequently, the condition would always be false
and anything between "#ifdef" and "#endif" would not be included.
- Add validation and error reporting everywhere, to aid debugging.
- Support nested comments (by accounting for the whole stack of
conditions, instead of only the current one).
- Add #elif preprocessor command. Could be used as follows:
//#if !FEATURE_ENABLED
//#error FEATURE_ENABLED must be set
//#endif
- Add #error preprocessor command.
- Add end-of-line word boundary after "-->" in the comment trimmer.
Otherwise the pattern would also match "-->" in the middle of a line,
and incorrectly convert something like "while(i-->0)" to "while(i0)".
Code health:
- Add unit tests for the preprocessor (run external/builder/test.js).
- Fix broken link to MDN (resolved to DXR).
- Refactor to use STATE_* names instead of magic numbers (the original
meaning of the numbers is preserved, with one exception).
- State 3 has been split in two states, to distinguish between being in
an #if and #else. This is needed to ensure that #else cannot be
started without an #if.
2015-07-09 18:03:34 +09:00
|
|
|
state = evaluateCondition(m[2]) ? STATE_IF_TRUE : STATE_IF_FALSE;
|
|
|
|
break;
|
|
|
|
case "elif":
|
2016-05-10 08:18:43 +09:00
|
|
|
if (state === STATE_IF_TRUE || state === STATE_ELSE_FALSE) {
|
Fix preprocessor: nesting, error & tests
Features / bug fixes in the preprocessor:
- Add word boundary after regex for preprocessor token matching.
Previously, when you mistakenly used "#ifdef" instead of "#if", the
line would be parsed as a preprocessor directive (because "#ifdef"
starts with "#if"), but without condition (because "def" does not
start with a space). Consequently, the condition would always be false
and anything between "#ifdef" and "#endif" would not be included.
- Add validation and error reporting everywhere, to aid debugging.
- Support nested comments (by accounting for the whole stack of
conditions, instead of only the current one).
- Add #elif preprocessor command. Could be used as follows:
//#if !FEATURE_ENABLED
//#error FEATURE_ENABLED must be set
//#endif
- Add #error preprocessor command.
- Add end-of-line word boundary after "-->" in the comment trimmer.
Otherwise the pattern would also match "-->" in the middle of a line,
and incorrectly convert something like "while(i-->0)" to "while(i0)".
Code health:
- Add unit tests for the preprocessor (run external/builder/test.js).
- Fix broken link to MDN (resolved to DXR).
- Refactor to use STATE_* names instead of magic numbers (the original
meaning of the numbers is preserved, with one exception).
- State 3 has been split in two states, to distinguish between being in
an #if and #else. This is needed to ensure that #else cannot be
started without an #if.
2015-07-09 18:03:34 +09:00
|
|
|
state = STATE_ELSE_FALSE;
|
|
|
|
} else if (state === STATE_IF_FALSE) {
|
|
|
|
state = evaluateCondition(m[2]) ? STATE_IF_TRUE : STATE_IF_FALSE;
|
2016-05-10 08:18:43 +09:00
|
|
|
} else if (state === STATE_ELSE_TRUE) {
|
Fix preprocessor: nesting, error & tests
Features / bug fixes in the preprocessor:
- Add word boundary after regex for preprocessor token matching.
Previously, when you mistakenly used "#ifdef" instead of "#if", the
line would be parsed as a preprocessor directive (because "#ifdef"
starts with "#if"), but without condition (because "def" does not
start with a space). Consequently, the condition would always be false
and anything between "#ifdef" and "#endif" would not be included.
- Add validation and error reporting everywhere, to aid debugging.
- Support nested comments (by accounting for the whole stack of
conditions, instead of only the current one).
- Add #elif preprocessor command. Could be used as follows:
//#if !FEATURE_ENABLED
//#error FEATURE_ENABLED must be set
//#endif
- Add #error preprocessor command.
- Add end-of-line word boundary after "-->" in the comment trimmer.
Otherwise the pattern would also match "-->" in the middle of a line,
and incorrectly convert something like "while(i-->0)" to "while(i0)".
Code health:
- Add unit tests for the preprocessor (run external/builder/test.js).
- Fix broken link to MDN (resolved to DXR).
- Refactor to use STATE_* names instead of magic numbers (the original
meaning of the numbers is preserved, with one exception).
- State 3 has been split in two states, to distinguish between being in
an #if and #else. This is needed to ensure that #else cannot be
started without an #if.
2015-07-09 18:03:34 +09:00
|
|
|
throw new Error("Found #elif after #else at " + loc());
|
|
|
|
} else {
|
|
|
|
throw new Error("Found #elif without matching #if at " + loc());
|
2012-08-02 06:27:42 +09:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case "else":
|
2016-05-10 08:18:43 +09:00
|
|
|
if (state === STATE_IF_TRUE || state === STATE_ELSE_FALSE) {
|
Fix preprocessor: nesting, error & tests
Features / bug fixes in the preprocessor:
- Add word boundary after regex for preprocessor token matching.
Previously, when you mistakenly used "#ifdef" instead of "#if", the
line would be parsed as a preprocessor directive (because "#ifdef"
starts with "#if"), but without condition (because "def" does not
start with a space). Consequently, the condition would always be false
and anything between "#ifdef" and "#endif" would not be included.
- Add validation and error reporting everywhere, to aid debugging.
- Support nested comments (by accounting for the whole stack of
conditions, instead of only the current one).
- Add #elif preprocessor command. Could be used as follows:
//#if !FEATURE_ENABLED
//#error FEATURE_ENABLED must be set
//#endif
- Add #error preprocessor command.
- Add end-of-line word boundary after "-->" in the comment trimmer.
Otherwise the pattern would also match "-->" in the middle of a line,
and incorrectly convert something like "while(i-->0)" to "while(i0)".
Code health:
- Add unit tests for the preprocessor (run external/builder/test.js).
- Fix broken link to MDN (resolved to DXR).
- Refactor to use STATE_* names instead of magic numbers (the original
meaning of the numbers is preserved, with one exception).
- State 3 has been split in two states, to distinguish between being in
an #if and #else. This is needed to ensure that #else cannot be
started without an #if.
2015-07-09 18:03:34 +09:00
|
|
|
state = STATE_ELSE_FALSE;
|
|
|
|
} else if (state === STATE_IF_FALSE) {
|
|
|
|
state = STATE_ELSE_TRUE;
|
|
|
|
} else {
|
|
|
|
throw new Error("Found #else without matching #if at " + loc());
|
|
|
|
}
|
2012-08-02 06:27:42 +09:00
|
|
|
break;
|
|
|
|
case "endif":
|
Fix preprocessor: nesting, error & tests
Features / bug fixes in the preprocessor:
- Add word boundary after regex for preprocessor token matching.
Previously, when you mistakenly used "#ifdef" instead of "#if", the
line would be parsed as a preprocessor directive (because "#ifdef"
starts with "#if"), but without condition (because "def" does not
start with a space). Consequently, the condition would always be false
and anything between "#ifdef" and "#endif" would not be included.
- Add validation and error reporting everywhere, to aid debugging.
- Support nested comments (by accounting for the whole stack of
conditions, instead of only the current one).
- Add #elif preprocessor command. Could be used as follows:
//#if !FEATURE_ENABLED
//#error FEATURE_ENABLED must be set
//#endif
- Add #error preprocessor command.
- Add end-of-line word boundary after "-->" in the comment trimmer.
Otherwise the pattern would also match "-->" in the middle of a line,
and incorrectly convert something like "while(i-->0)" to "while(i0)".
Code health:
- Add unit tests for the preprocessor (run external/builder/test.js).
- Fix broken link to MDN (resolved to DXR).
- Refactor to use STATE_* names instead of magic numbers (the original
meaning of the numbers is preserved, with one exception).
- State 3 has been split in two states, to distinguish between being in
an #if and #else. This is needed to ensure that #else cannot be
started without an #if.
2015-07-09 18:03:34 +09:00
|
|
|
if (state === STATE_NONE) {
|
|
|
|
throw new Error("Found #endif without #if at " + loc());
|
|
|
|
}
|
2012-08-02 06:27:42 +09:00
|
|
|
state = stack.pop();
|
|
|
|
break;
|
|
|
|
case "expand":
|
Fix preprocessor: nesting, error & tests
Features / bug fixes in the preprocessor:
- Add word boundary after regex for preprocessor token matching.
Previously, when you mistakenly used "#ifdef" instead of "#if", the
line would be parsed as a preprocessor directive (because "#ifdef"
starts with "#if"), but without condition (because "def" does not
start with a space). Consequently, the condition would always be false
and anything between "#ifdef" and "#endif" would not be included.
- Add validation and error reporting everywhere, to aid debugging.
- Support nested comments (by accounting for the whole stack of
conditions, instead of only the current one).
- Add #elif preprocessor command. Could be used as follows:
//#if !FEATURE_ENABLED
//#error FEATURE_ENABLED must be set
//#endif
- Add #error preprocessor command.
- Add end-of-line word boundary after "-->" in the comment trimmer.
Otherwise the pattern would also match "-->" in the middle of a line,
and incorrectly convert something like "while(i-->0)" to "while(i0)".
Code health:
- Add unit tests for the preprocessor (run external/builder/test.js).
- Fix broken link to MDN (resolved to DXR).
- Refactor to use STATE_* names instead of magic numbers (the original
meaning of the numbers is preserved, with one exception).
- State 3 has been split in two states, to distinguish between being in
an #if and #else. This is needed to ensure that #else cannot be
started without an #if.
2015-07-09 18:03:34 +09:00
|
|
|
if (state !== STATE_IF_FALSE && state !== STATE_ELSE_FALSE) {
|
2012-08-02 06:27:42 +09:00
|
|
|
expand(m[2]);
|
2014-03-10 23:53:41 +09:00
|
|
|
}
|
2012-08-02 06:27:42 +09:00
|
|
|
break;
|
|
|
|
case "include":
|
Fix preprocessor: nesting, error & tests
Features / bug fixes in the preprocessor:
- Add word boundary after regex for preprocessor token matching.
Previously, when you mistakenly used "#ifdef" instead of "#if", the
line would be parsed as a preprocessor directive (because "#ifdef"
starts with "#if"), but without condition (because "def" does not
start with a space). Consequently, the condition would always be false
and anything between "#ifdef" and "#endif" would not be included.
- Add validation and error reporting everywhere, to aid debugging.
- Support nested comments (by accounting for the whole stack of
conditions, instead of only the current one).
- Add #elif preprocessor command. Could be used as follows:
//#if !FEATURE_ENABLED
//#error FEATURE_ENABLED must be set
//#endif
- Add #error preprocessor command.
- Add end-of-line word boundary after "-->" in the comment trimmer.
Otherwise the pattern would also match "-->" in the middle of a line,
and incorrectly convert something like "while(i-->0)" to "while(i0)".
Code health:
- Add unit tests for the preprocessor (run external/builder/test.js).
- Fix broken link to MDN (resolved to DXR).
- Refactor to use STATE_* names instead of magic numbers (the original
meaning of the numbers is preserved, with one exception).
- State 3 has been split in two states, to distinguish between being in
an #if and #else. This is needed to ensure that #else cannot be
started without an #if.
2015-07-09 18:03:34 +09:00
|
|
|
if (state !== STATE_IF_FALSE && state !== STATE_ELSE_FALSE) {
|
2012-08-02 06:27:42 +09:00
|
|
|
include(m[2]);
|
2014-03-10 23:53:41 +09:00
|
|
|
}
|
2012-08-02 06:27:42 +09:00
|
|
|
break;
|
Fix preprocessor: nesting, error & tests
Features / bug fixes in the preprocessor:
- Add word boundary after regex for preprocessor token matching.
Previously, when you mistakenly used "#ifdef" instead of "#if", the
line would be parsed as a preprocessor directive (because "#ifdef"
starts with "#if"), but without condition (because "def" does not
start with a space). Consequently, the condition would always be false
and anything between "#ifdef" and "#endif" would not be included.
- Add validation and error reporting everywhere, to aid debugging.
- Support nested comments (by accounting for the whole stack of
conditions, instead of only the current one).
- Add #elif preprocessor command. Could be used as follows:
//#if !FEATURE_ENABLED
//#error FEATURE_ENABLED must be set
//#endif
- Add #error preprocessor command.
- Add end-of-line word boundary after "-->" in the comment trimmer.
Otherwise the pattern would also match "-->" in the middle of a line,
and incorrectly convert something like "while(i-->0)" to "while(i0)".
Code health:
- Add unit tests for the preprocessor (run external/builder/test.js).
- Fix broken link to MDN (resolved to DXR).
- Refactor to use STATE_* names instead of magic numbers (the original
meaning of the numbers is preserved, with one exception).
- State 3 has been split in two states, to distinguish between being in
an #if and #else. This is needed to ensure that #else cannot be
started without an #if.
2015-07-09 18:03:34 +09:00
|
|
|
case "error":
|
|
|
|
if (state !== STATE_IF_FALSE && state !== STATE_ELSE_FALSE) {
|
|
|
|
throw new Error("Found #error " + m[2] + " at " + loc());
|
|
|
|
}
|
|
|
|
break;
|
2012-08-02 06:27:42 +09:00
|
|
|
}
|
2023-07-20 17:57:30 +09:00
|
|
|
} else if (state === STATE_NONE) {
|
|
|
|
writeLine(line);
|
|
|
|
} else if (
|
|
|
|
(state === STATE_IF_TRUE || state === STATE_ELSE_TRUE) &&
|
|
|
|
!stack.includes(STATE_IF_FALSE) &&
|
|
|
|
!stack.includes(STATE_ELSE_FALSE)
|
|
|
|
) {
|
|
|
|
writeLine(
|
|
|
|
line
|
|
|
|
.replaceAll(/^\/\/|^<!--/g, " ")
|
|
|
|
.replaceAll(/(^\s*)\/\*/g, "$1 ")
|
|
|
|
.replaceAll(/\*\/$|-->$/g, "")
|
|
|
|
);
|
2012-08-02 06:27:42 +09:00
|
|
|
}
|
|
|
|
}
|
Fix preprocessor: nesting, error & tests
Features / bug fixes in the preprocessor:
- Add word boundary after regex for preprocessor token matching.
Previously, when you mistakenly used "#ifdef" instead of "#if", the
line would be parsed as a preprocessor directive (because "#ifdef"
starts with "#if"), but without condition (because "def" does not
start with a space). Consequently, the condition would always be false
and anything between "#ifdef" and "#endif" would not be included.
- Add validation and error reporting everywhere, to aid debugging.
- Support nested comments (by accounting for the whole stack of
conditions, instead of only the current one).
- Add #elif preprocessor command. Could be used as follows:
//#if !FEATURE_ENABLED
//#error FEATURE_ENABLED must be set
//#endif
- Add #error preprocessor command.
- Add end-of-line word boundary after "-->" in the comment trimmer.
Otherwise the pattern would also match "-->" in the middle of a line,
and incorrectly convert something like "while(i-->0)" to "while(i0)".
Code health:
- Add unit tests for the preprocessor (run external/builder/test.js).
- Fix broken link to MDN (resolved to DXR).
- Refactor to use STATE_* names instead of magic numbers (the original
meaning of the numbers is preserved, with one exception).
- State 3 has been split in two states, to distinguish between being in
an #if and #else. This is needed to ensure that #else cannot be
started without an #if.
2015-07-09 18:03:34 +09:00
|
|
|
if (state !== STATE_NONE || stack.length !== 0) {
|
|
|
|
throw new Error(
|
|
|
|
"Missing #endif in preprocessor for " + fs.realpathSync(inFilename)
|
|
|
|
);
|
2014-03-10 23:53:41 +09:00
|
|
|
}
|
|
|
|
if (typeof outFilename !== "function") {
|
2022-05-11 19:32:41 +09:00
|
|
|
fs.writeFileSync(outFilename, out.join("\n"));
|
2014-03-10 23:53:41 +09:00
|
|
|
}
|
2012-08-02 06:27:42 +09:00
|
|
|
}
|
|
|
|
|
2023-10-18 20:32:50 +09:00
|
|
|
export { preprocess };
|