Underscore prefix visibility compatibility boundary in Gleam's JavaScript target
0 reputation · 02 Jan 2024, 18:28 UTC
0 reputation · 02 Jan 2024, 18:28 UTC
Gleam developers use the underscore prefix convention to signal private module members, on the expectation that symbols without the prefix enter the public API. The language treats this convention as a style guideline rather than an enforced keyword, so the compiler does not guarantee privacy at runtime. This creates a precise goal: assessing whether underscore‑prefixed members can be relied upon to remain truly private when the Gleam compiler targets JavaScript, where generated code may expose previously private symbols through standard runtime inspection or external library interop. The core uncertainty involves the convention's inconsistent application across tooling, custom build steps, and project configurations, which may not uniformly enforce the prefix rule.
Three questions stem from this design boundary:
31275 reputation · 03 Jan 2024, 01:43 UTC
1. Can the Gleam compiler be configured to treat an underscore‑prefixed symbol exported in JavaScript as a build error?
No. The current Gleam compiler (v0.32 and earlier) has no flag or configuration option that enforces the underscore‑prefix convention as a compile‑time error. The compiler treats all top‑level definitions the same, regardless of name, and emits them into the JavaScript module object.
2. Do common third‑party build pipelines or cross‑language dependency integrations routinely ignore the underscore convention without developer awareness?
Yes, most JavaScript bundlers (Webpack, Rollup, esbuild, etc.) will emit every exported property that the Gleam compiler places on the module object. Because the underscore prefix is only a naming convention, these tools will expose the symbol unless explicitly configured to drop it. Tree‑shaking can remove unused exports, but that depends on side‑effect analysis and the bundler’s configuration. Therefore, a developer who assumes the underscore prefix guarantees privacy may find the symbol visible to external code after a standard build.
3. Is there a formally documented strategy for projects that need to enforce stricter private visibility beyond the existing convention?
There is no official Gleam documentation that provides a stricter privacy enforcement mechanism. The recommended approaches are:
Compile a small Gleam file that contains an underscore‑prefixed function:
fn _helper() -> Int { 1 }
Run gleam build and open the generated index.js. You should see something like:
exports._helper = function _helper(){
return 1;
};
Confirm that no compiler flag exists: try gleam build --private-error and observe the error about an unknown flag.
If you use a bundler, check its configuration. For example, with Rollup:
import { defineConfig } from "rollup";
export default defineConfig({
input: "index.js",
output: { file: "bundle.js", format: "cjs" },
treeshake: { moduleSideEffects: false },
});
Run the bundle and inspect bundle.js to see whether _helper remains.
To enforce privacy, consider moving the helper into a sub‑module and importing it only where needed, or use an opaque type wrapper.
To give a more tailored recommendation, I need to know which JavaScript bundler or build pipeline you’re using (Webpack, Rollup, esbuild, etc.) and whether you’re applying any tree‑shaking or side‑effect configurations.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.