Skip to content

Commit

Permalink
Add directories when they don't exist, rather than throwing an error. F…
Browse files Browse the repository at this point in the history
…ixes #440.
  • Loading branch information
hildjj committed Feb 11, 2024
1 parent 804c393 commit 3aeb0da
Show file tree
Hide file tree
Showing 9 changed files with 233 additions and 3,837 deletions.
46 changes: 24 additions & 22 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ Released: TBD

### Major Changes

- [#420](https://github.com/peggyjs/peggy/pull/420) BREAKING: Node v16+ is now
required for running the CLI or using Peggy as a library. Generated code
still targets older runtimes.
- [#379](https://github.com/peggyjs/peggy/issues/379) Fix infinite recursion
issue by moving reportInfiniteRecursion to the new prepare pass, and having
it fail after finding the first issue. This will require plugin authors
to ensure that reportInfiniteRecursion is in the new pass correctly.
- [#417](https://github.com/peggyjs/peggy/pull/417) BREAKING: change to AST to
allow topLevelInitializer and initializer to be arrays, in support of
multi-file inputs. This will require plugin updates. The CLI and API now
Expand All @@ -21,42 +22,43 @@ Released: TBD
names of the form `npm:<package-name>/<filename>` to load library rules from
an NPM package that is installed relative to the previous non-npm file name,
or to the current working directory if this is the first file name.
- [#420](https://github.com/peggyjs/peggy/pull/420) BREAKING: Node v16+ is now
required for running the CLI or using Peggy as a library. Generated code
still targets older runtimes.
- [#456](https://github.com/peggyjs/peggy/pull/456) BREAKING: Allow imports
from external compiled grammars inside a source grammar, using `import
{rule} from "external.js"`. Note that this syntax will generate either
`import` or `require` in the JavaScript output, depending on the value of
the `format` parameter. This will need explicit support from
plugins, with a few new AST node types and a few visitor changes.
- [#379](https://github.com/peggyjs/peggy/issues/379) Fix infinite recursion
issue by moving reportInfiniteRecursion to the new prepare pass, and having
it fail after finding the first issue. This will require plugin authors
to ensure that reportInfiniteRecursion is in the new pass correctly.
- [#463](https://github.com/peggyjs/peggy/issues/463) Drop support for
Internet Explorer. Move to eslint flat configs in order to lint minimized
browser code for compatibility with
`defaults, maintained node versions, not op_mini all`.

### Minor Changes

- [#453](https://github.com/peggyjs/peggy/pull/453) Make generate-bytecode.js ts-clean
- [#452](https://github.com/peggyjs/peggy/pull/452) Fixes to prepare generate-bytecode.js for ts-check
- [#404](https://github.com/peggyjs/peggy/issues/404) Add support for -w/--watch
to the command line interface.
- [#415](https://github.com/peggyjs/peggy/issues/415) Added `browser` key to package.json, pointing to Webpack output.
- [#420](https://github.com/peggyjs/peggy/pull/420) Updated dependencies to
avoid audit warnings.
- [#425](https://github.com/peggyjs/peggy/pull/425) Add a pass to simplify single-character choices
- [#427](https://github.com/peggyjs/peggy/pull/427) Avoid double extraction of
substrings in various MATCH_ bytecodes
- [#430](https://github.com/peggyjs/peggy/pull/430) Make generate-js.js ts clean
- [#432](https://github.com/peggyjs/peggy/pull/432) Add peggy.code-workspace
- [#451](https://github.com/peggyjs/peggy/pull/451) Make stack.js ts clean
- [#439](https://github.com/peggyjs/peggy/pull/439) Make peg$computePosDetails a little faster
- [#437](https://github.com/peggyjs/peggy/pull/437) Better type checking for visitor
- [#435](https://github.com/peggyjs/peggy/pull/435) Setup tsconfig to detect use of library functions from es6 or later
- [#438](https://github.com/peggyjs/peggy/pull/438) Make test build deterministic
- [#436](https://github.com/peggyjs/peggy/pull/436) Get rid of tsd
- [#430](https://github.com/peggyjs/peggy/pull/430) Make generate-js.js ts clean
- [#437](https://github.com/peggyjs/peggy/pull/437) Better type checking for visitor
- [#438](https://github.com/peggyjs/peggy/pull/438) Make test build deterministic
- [#439](https://github.com/peggyjs/peggy/pull/439) Make peg$computePosDetails a little faster
- [#440](https://github.com/peggyjs/peggy/issues/440) Create directories for
output and source-map if they do not exist, rather than erroring.
- [#446](https://github.com/peggyjs/peggy/pull/446) Add a right-associative `ExponentiationExpression` rule (operator `**`) to `javascript.pegjs` example grammar.
- [#427](https://github.com/peggyjs/peggy/pull/427) Avoid double extraction of
substrings in various MATCH_ bytecodes
- [#425](https://github.com/peggyjs/peggy/pull/425) Add a pass to simplify single-character choices
- [#420](https://github.com/peggyjs/peggy/pull/420) Updated dependencies to
avoid audit warnings.
- [#404](https://github.com/peggyjs/peggy/issues/404) Add support for -w/--watch
to the command line interface.
- [#415](https://github.com/peggyjs/peggy/issues/415) Added `browser` key to package.json, pointing to Webpack output.
- [#451](https://github.com/peggyjs/peggy/pull/451) Make stack.js ts clean
- [#452](https://github.com/peggyjs/peggy/pull/452) Fixes to prepare generate-bytecode.js for ts-check
- [#453](https://github.com/peggyjs/peggy/pull/453) Make generate-bytecode.js ts-clean

### Bug Fixes

Expand Down
128 changes: 67 additions & 61 deletions bin/peggy-cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,21 @@ function readFile(name) {
return f;
}

async function ensureDirectoryExists(filename) {
const dir = path.dirname(filename);
try {
const stats = await fs.promises.stat(dir);
if (!stats.isDirectory()) {
throw new Error(`"${dir}" exists and is not a directory`);
}
} catch (er) {
if (er.code !== "ENOENT") {
throw er;
}
await fs.promises.mkdir(dir, { recursive: true });
}
}

/**
* @typedef {object} Stdio
* @property {stream.Readable} [in] StdIn.
Expand Down Expand Up @@ -472,11 +487,12 @@ class PeggyCLI extends Command {
const hasTest = !this.testFile && (typeof this.testText !== "string");
return Promise.resolve(hasTest ? this.std.out : null);
}
return new Promise((resolve, reject) => {
const outputStream = fs.createWriteStream(this.outputFile);
outputStream.on("error", reject);
outputStream.on("open", () => resolve(outputStream));
});
return ensureDirectoryExists(this.outputFile)
.then(() => new Promise((resolve, reject) => {
const outputStream = fs.createWriteStream(this.outputFile);
outputStream.on("error", reject);
outputStream.on("open", () => resolve(outputStream));
}));
}

/**
Expand All @@ -486,64 +502,54 @@ class PeggyCLI extends Command {
* to serialize.
* @returns {Promise<string>} The plain text output.
*/
writeSourceMap(source) {
return new Promise((resolve, reject) => {
if (!this.progOptions.sourceMap) {
resolve(source);
return;
}
async writeSourceMap(source) {
if (!this.progOptions.sourceMap) {
return source;
}

let hidden = false;
if (this.progOptions.sourceMap.startsWith("hidden:")) {
hidden = true;
this.progOptions.sourceMap = this.progOptions.sourceMap.slice(7);
}
const inline = this.progOptions.sourceMap === "inline";
const mapDir = inline
? path.dirname(this.outputJS)
: path.dirname(this.progOptions.sourceMap);

const file = path.relative(mapDir, this.outputJS);
const sourceMap = source.toStringWithSourceMap({ file });

// According to specifications, paths in the "sources" array should be
// relative to the map file. Compiler cannot generate right paths, because
// it is unaware of the source map location
const json = sourceMap.map.toJSON();
json.sources = json.sources.map(
src => ((src === null) ? null : path.relative(mapDir, src))
);

if (inline) {
// Note: hidden + inline makes no sense.
const buf = Buffer.from(JSON.stringify(json));
// Use \x23 instead of # so that Jest won't treat this as a real
// source map URL for *this* file.
resolve(sourceMap.code + `\
let hidden = false;
if (this.progOptions.sourceMap.startsWith("hidden:")) {
hidden = true;
this.progOptions.sourceMap = this.progOptions.sourceMap.slice(7);
}
const inline = this.progOptions.sourceMap === "inline";
const mapDir = inline
? path.dirname(this.outputJS)
: path.dirname(this.progOptions.sourceMap);

const file = path.relative(mapDir, this.outputJS);
const sourceMap = source.toStringWithSourceMap({ file });

// According to specifications, paths in the "sources" array should be
// relative to the map file. Compiler cannot generate right paths, because
// it is unaware of the source map location
const json = sourceMap.map.toJSON();
json.sources = json.sources.map(
src => ((src === null) ? null : path.relative(mapDir, src))
);

if (inline) {
// Note: hidden + inline makes no sense.
const buf = Buffer.from(JSON.stringify(json));
// Use \x23 instead of # so that Jest won't treat this as a real
// source map URL for *this* file.
return sourceMap.code + `\
//\x23 sourceMappingURL=data:application/json;charset=utf-8;base64,${buf.toString("base64")}
`);
} else {
fs.writeFile(
this.progOptions.sourceMap,
JSON.stringify(json),
"utf8",
err => {
if (err) {
reject(err);
} else {
if (hidden) {
resolve(sourceMap.code);
} else {
// Opposite direction from mapDir
resolve(sourceMap.code + `\
`;
}
await ensureDirectoryExists(this.progOptions.sourceMap);
await fs.promises.writeFile(
this.progOptions.sourceMap,
JSON.stringify(json),
"utf8"
);
if (hidden) {
return sourceMap.code;
}
// Opposite direction from mapDir
return sourceMap.code + `\
//# sourceMappingURL=${path.relative(path.dirname(this.outputJS), this.progOptions.sourceMap)}
`);
}
}
}
);
}
});
`;
}

writeOutput(outputStream, source) {
Expand Down Expand Up @@ -645,7 +651,7 @@ class PeggyCLI extends Command {
this.verbose("CLI", errorText = "parsing grammar");
const source = peggy.generate(sources, this.argv); // All of the real work.

this.verbose("CLI", errorText = "open output stream");
this.verbose("CLI", errorText = "opening output stream");
const outputStream = await this.openOutputStream();

// If option `--ast` is specified, `generate()` returns an AST object
Expand Down
2 changes: 1 addition & 1 deletion docs/js/test-bundle.min.js

Large diffs are not rendered by default.

Loading

0 comments on commit 3aeb0da

Please sign in to comment.