Add opt-in strict mode and typed browser console wrapper#31
Add opt-in strict mode and typed browser console wrapper#31sbsoftware merged 10 commits intoreleases/v1.8.0from
Conversation
sbsoftware
left a comment
There was a problem hiding this comment.
I didn't imagine the typed browser API calls to be referenced via constants in Crystal, but via method calls looking as similar as possible. In strict mode, all method calls without an explicit receiver should be "redirected" to a default browser context object that, for now, only has a #console method, which returns a JS::Browser::Console instance. The #log, #info, etc. methods should return some kind of "method call wrapper" object with a #to_js_ref method that returns the correct call chain in valid JS as a Crystal string that is appended to the emitted JS output. This also has to work transitively for chained method calls.
In the specs, there should be no direct reference to JS::Browser::Console, but only literal console.x calls.
|
Implemented in commit Addressed points from your feedback:
Validation:
|
sbsoftware
left a comment
There was a problem hiding this comment.
Let's go further and get rid of the method_missing macro. Here is an example: Calling console in a def_to_js block should be redirect to the default context, which returns a JS::Browser::Console instance. Calling #log on that returns a Crystal JS context object corresponding to what the actual JS console.log method would return (I don't know what that is; we can assume nil/undefined for now), so that theoretically one could chain more correctly typed method calls behind it. Every JS context object needs to be initialized with the preceding call chain (can be the final JS string) as well as the current method name and its arguments concatenated to it. If no more calls are chained, the evaluation macro should call #to_js_ref, which returns the full call chain in valid JS code as a Crystal String that is appended to the output IO. The other case is that another method is called on the JS context object, which in turn returns a new one with the extended call chain.
This is deviating a bit from the pure-macro implementation we had so far, but it results in a cool API that is easy to extend.
|
Implemented in commit I removed the
This keeps the chain object-based model (context object carries/extends the chain and serializes via Spec updates:
|
|
That is not entirely what I meant. In fact, I don't think there should be a generic |
|
Implemented in Changes made:
I also updated browser specs accordingly:
Validation:
|
sbsoftware
left a comment
There was a problem hiding this comment.
Let's swap the module names: Make JS::Context the parent one, providing .default, and JS::Context::Browser the nested one that is returned by JS::Context.default.
|
Implemented the namespace swap:
Validation: Committed in:
|
sbsoftware
left a comment
There was a problem hiding this comment.
Please ensure the file names are swapped as well and the README reflects the latest state.
|
Done. I aligned file paths/names with the swapped context model and updated docs to match current behavior:
Validation: Committed in:
|
README.md
Outdated
| In strict mode: | ||
|
|
||
| - Referencing/calling undeclared JS identifiers raises a compile-time error. | ||
| - `js_alias` is the explicit extern declaration escape hatch. |
There was a problem hiding this comment.
Let's remove that explicit hint here (and from the strict mode examples). It is not encouraged to use it that way.
There was a problem hiding this comment.
Done. I removed the explicit js_alias hint from the strict-mode bullet list and updated the strict-mode example to no longer use js_alias (it now only shows console.log(...)).
Validation: crystal spec passes (44 examples, 0 failures).
Committed in 3f885cc with message:
JS-45 Remove js_alias strict-mode guidance from README
Summary
This PR introduces an opt-in strict transpilation mode for generated JS units and adds the first typed browser API wrapper surface (
console).What changed
JS::Code.def_to_jsJS::File.def_to_jsJS::Module.def_to_js_literal_js(...)js_aliasremains the explicit extern declaration escape hatchJS::Browser::Consolelog,info,warn,errorconsoleviato_js_refsrc/js.cr).Specs
Added/updated specs for:
JS::Code,JS::File, andJS::Module_literal_js(...)Validation
crystal tool format src speccrystal tool format --check src speccrystal spec