Reject bindings of a module that get the same JavaScript name
Why
Ext_ident.convert maps both delete and $$delete to $$delete, and \"a-b" like a$b, so two bindings could share an export name or a module object key: the ES export list repeated a name, which Node rejects, and CommonJS output and nested modules lost a binding. The type checker now rejects such a module, at the second binding. This replaces Lam_coercion's "is exported twice" check, which only covered equal source names and had no location.
addedDiagnostic JavaScript name clash
let delete = 1let $$delete = 2
js
let $$delete = 1;let $$delete$1 = 2;export { $$delete, $$delete$1 as $$delete,}
diagnostic
This value has the same JavaScript name $$deleteas the value at A.res:1:5-10.Rename one of them.
modifiedDiagnostic exception and module of one name
exception M(int)module M = { let x = 3}
diagnostic
Before
After
M is exported twice This module has the same JavaScript name Mas the extension constructor at A.res:1:1-16.Rename one of them.
Review
- Why not rename one of the two exports? Importers derive an export's name from the source name alone (
js_export_name), so a renamed export would not be found by them; the clash has to be resolved in the source. - Which signatures are checked? Each structure's signature and each written signature (module types and
.resifiles), since every module block is built from one of them. The exports of a compilation unit keepdefaultas written, so only nested modules rejectdefaultbeside$$default.