-
Notifications
You must be signed in to change notification settings - Fork 484
Declare exports left unbound by a toplevel throw #8692
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -63,6 +63,24 @@ let compile_group output_prefix (meta : Lam_stats.t) (x : Lam_group.t) : | |
| } | ||
| lam | ||
|
|
||
| (* When a toplevel group always throws, [Js_output.concat] drops every later | ||
| group, and a [let] whose right-hand side throws compiles to the [throw] | ||
| alone. The identifiers those groups bind are then undeclared, and an export | ||
| list naming them is a JavaScript syntax error. This appends a declaration | ||
| for each such exported identifier after the [throw]. *) | ||
| let declare_undeclared_exports (exports : Ident.t list) (block : J.block) : | ||
| J.block = | ||
| let declared = | ||
| Ext_list.fold_left block Set_ident.empty (fun acc (stmt : J.statement) -> | ||
| match stmt.statement_desc with | ||
| | Variable {ident} -> Set_ident.add acc ident | ||
| | _ -> acc) | ||
| in | ||
| block | ||
| @ Ext_list.filter_map exports (fun id -> | ||
| if Set_ident.mem declared id then None | ||
| else Some (Js_stmt_make.declare_variable ~kind:Strict id)) | ||
|
|
||
| (** Also need analyze its depenency is pure or not *) | ||
| let no_side_effects (rest : Lam_group.t list) : string option = | ||
| Ext_list.find_opt rest (fun x -> | ||
|
|
@@ -355,8 +373,14 @@ let compile (output_prefix : string) export_idents hoisted (lam : Lambda.t) = | |
| (Sys.time () *. 1000.) | ||
| in | ||
| let body = | ||
| Ext_list.map groups (fun group -> compile_group output_prefix meta group) | ||
| |> Js_output.concat |> Js_output.output_as_block | ||
| let output = | ||
| Ext_list.map groups (fun group -> compile_group output_prefix meta group) | ||
| |> Js_output.concat | ||
| in | ||
| let block = Js_output.output_as_block output in | ||
| if output.output_finished = True then | ||
| declare_undeclared_exports meta.exports block | ||
|
Comment on lines
+381
to
+382
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
This changes compiler output for affected user programs from invalid to valid JavaScript, making it a user-facing bug fix, but the commit does not add the required entry under the current Unreleased bug-fix section of AGENTS.md reference: AGENTS.md:L93-L95 Useful? React with 👍 / 👎.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added in 59571ed, under the Unreleased section with the PR link. |
||
| else block | ||
| in | ||
| let () = | ||
| if debug_ir then | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,6 +11,8 @@ throw { | |
| Error: new Error() | ||
| }; | ||
|
|
||
| let u; | ||
|
|
||
| export { | ||
| u, | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| // Generated by ReScript, PLEASE EDIT WITH CARE | ||
|
|
||
| import * as Mocha from "mocha"; | ||
| import * as Pervasives from "@rescript/runtime/lib/es6/Pervasives.mjs"; | ||
| import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.mjs"; | ||
|
|
||
| async function loadCondANone() { | ||
| let M = await import("./cond_a_none.mjs"); | ||
| return M.A.u; | ||
| } | ||
|
|
||
| async function raisesAssertFailure(load) { | ||
| try { | ||
| await load(); | ||
| return false; | ||
| } catch (raw_exn) { | ||
| let exn = Primitive_exceptions.internalToException(raw_exn); | ||
| if (exn.RE_EXN_ID === "Assert_failure") { | ||
| return true; | ||
| } | ||
| throw exn; | ||
| } | ||
| } | ||
|
|
||
| Mocha.describe("Cond_a_load_test", () => { | ||
| Mocha.test("cond_a loads as a module whose body throws Assert_failure", async () => { | ||
| let ok = await raisesAssertFailure(() => import("./cond_a.mjs").then(m => m.u)); | ||
| if (!ok) { | ||
| return Pervasives.failwith("cond_a did not throw Assert_failure on load"); | ||
| } | ||
| }); | ||
| Mocha.test("cond_a_none loads as a module whose body throws Assert_failure", async () => { | ||
| let ok = await raisesAssertFailure(loadCondANone); | ||
| if (!ok) { | ||
| return Pervasives.failwith("cond_a_none did not throw Assert_failure on load"); | ||
| } | ||
| }); | ||
| }); | ||
|
|
||
| export { | ||
| loadCondANone, | ||
| raisesAssertFailure, | ||
| } | ||
| /* Not a pure module */ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| open Mocha | ||
|
|
||
| @module("mocha") | ||
| external testAsync: (string, unit => promise<unit>) => unit = "test" | ||
|
|
||
| let loadCondANone = async () => { | ||
| module M = await Cond_a_none | ||
| M.A.u | ||
| } | ||
|
|
||
| let raisesAssertFailure = async load => | ||
| switch await load() { | ||
| | _ => false | ||
| | exception Assert_failure(_) => true | ||
| } | ||
|
|
||
| describe(__MODULE__, () => { | ||
| testAsync("cond_a loads as a module whose body throws Assert_failure", async () => { | ||
| let ok = await raisesAssertFailure(() => import(Cond_a.u)) | ||
| if !ok { | ||
| failwith("cond_a did not throw Assert_failure on load") | ||
| } | ||
| }) | ||
| testAsync("cond_a_none loads as a module whose body throws Assert_failure", async () => { | ||
| let ok = await raisesAssertFailure(loadCondANone) | ||
| if !ok { | ||
| failwith("cond_a_none did not throw Assert_failure on load") | ||
| } | ||
| }) | ||
| }) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,6 +11,8 @@ throw { | |
| Error: new Error() | ||
| }; | ||
|
|
||
| let A; | ||
|
|
||
| export { | ||
| A, | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The message for commit
c00d4f6c38e4239dcb5d2ed117c2b7b0b7e598cdhas noSigned-Off-Bytrailer, so the contribution does not meet the repository's required DCO commit standard and cannot be accepted as submitted.AGENTS.md reference: AGENTS.md:L68-L70
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Every commit on this branch carries a
Signed-off-bytrailer (git log --format='%(trailers:key=Signed-off-by)' origin/master..HEADlists one per commit), so there is nothing to add.