Skip to content

Commit af35c13

Browse files
committed
JS modules: rethink how mark declarations which available with module systems and without module systems
1 parent ef5d38a commit af35c13

File tree

1 file changed

+49
-53
lines changed

1 file changed

+49
-53
lines changed

proposals/js/consume-js-modules.md

+49-53
Original file line numberDiff line numberDiff line change
@@ -26,28 +26,15 @@ Additionally, we should keep in mind that module import string should not be a v
2626
Propose to add:
2727

2828
```kotlin
29-
@Repeatable
3029
@Retention(AnnotationRetention.BINARY)
3130
@Target(
3231
AnnotationTarget.CLASS,
3332
AnnotationTarget.PROPERTY,
3433
AnnotationTarget.FUNCTION,
3534
AnnotationTarget.FILE)
36-
annotation class JsModule(
37-
val import: String,
38-
vararg val kind: JsModuleKind = ... // arrayOf(JsModuleKind.AMD, JsModuleKind.COMMON_JS, JsModuleKind.UMD)
39-
)
40-
41-
enum class JsModuleKind {
42-
SIMPLE,
43-
AMD,
44-
COMMON_JS, // CJS?
45-
UMD
46-
}
35+
annotation class JsModule(val import: String)
4736
```
4837

49-
It should be **repeatable** to allow to specialize settings for concrete JsModuleKind.
50-
5138
It should have **binary retention** to be available from binary data.
5239

5340
Annotation **allowed on classes, properties and functions** according to what can be exported from JS modules.
@@ -77,16 +64,51 @@ annotation class JsPackage(val path: String)
7764
```
7865
[TODO] think up a better name.
7966

80-
The new annotation can be reused in case when we want to have package with long path in Kotlin,
81-
but don't want to have a long path in generated JS, e.g. for public API.
67+
The new annotation prefered because it can be reused in two cases:
68+
1. _Major:_ for native declarations inside nested namespaces / packages.
69+
2. _Minor:_ when we want to have package with long path in Kotlin,
70+
but don't want to have a long path in generated JS, e.g. for JS public API.
8271
Of course, this problem can be fixed by adding another file "facade" with a short qualifier.
8372

84-
// it can't part of JsModule becouse will be reused for native declarations inside nested namespaces/packages
8573

86-
Parameters:
74+
**Parameter of `JsModule` annotation:**
8775
- `import` -- string which will be used to import related module.
88-
- `kind` -- shows for which kind of modules this role should be applied.
8976

77+
## How mark declarations which available with module systems and without module systems?
78+
79+
Possible solutions:
80+
1. Add additional parameter to `JsModule` annotation
81+
Pros:
82+
- minor: simpler to discover
83+
Cons:
84+
- it makes harder to reuse `JsModule` annotation for non-external declaration in the future
85+
- maybe it'll strange to see a parameter about declaration in the annotation about module
86+
87+
2. Add separate annotation
88+
Pros:
89+
- minor: simpler to evolve
90+
Cons:
91+
- more verbose
92+
- yet another annotation
93+
Note:
94+
- the annotation allowed only on native declarations
95+
- the annotation w/o `JsModule` doesn't change anything
96+
97+
Another problem is to think up a good name for that.
98+
99+
Some name candidates:
100+
- JsSimpleModule
101+
- JsNonModule
102+
- JsPlainModule
103+
- JsPlainModule
104+
- JsPlain
105+
- existsInNonModuleMode
106+
- availableInNonModuleMode
107+
- existsOutsideOfModule
108+
- availableOutsideOfModule
109+
110+
111+
**NOTE: In following code fragments temporary used `JsNonModule` annotation.**
90112

91113
## Use cases (based on TypeScript declarations)
92114

@@ -170,24 +192,9 @@ In Kotlin:
170192
package SomeModule
171193

172194
@JsModule("MyExternalModule")
173-
@JsModule("MyExternalModule", kind = JsModuleKind.SIMPLE)
174-
@native var prop: MyClass = noImpl
175-
```
176-
Second role means that when translate with SIMPLE module kind for this module
177-
compiler should generate import through variable `MyExternalModule`
178-
179-
180-
Another way:
181-
```kotlin
182-
package SomeModule
183-
184-
@JsModule("MyExternalModule")
185-
@JsModule("this", kind = JsModuleKind.SIMPLE)
195+
@JsNonModule
186196
@native var prop: MyClass = noImpl
187197
```
188-
And now when translate with SIMPLE module kind for this module
189-
compiler should generate import through variable `this` (usually it's Global Object)
190-
191198

192199
## Implementation details
193200

@@ -231,7 +238,7 @@ fun test() {
231238
}
232239
```
233240

234-
Use import value as is to declare dependencies when translate them with **any module kind except SIMPLE**.
241+
Use import value as is to declare dependencies when translate them with **module kind COMMON_JS or AMD**.
235242
<br/>E.g. for CommonJS generate following:
236243
```javascript
237244
var first_module = require("first-module");
@@ -242,41 +249,30 @@ var d = require("fourthModule");
242249
```
243250

244251
When **module kind is SIMPLE**
245-
- If import value is valid JS identifier or `this` then use it as is as name of identifier;
252+
- If import value is valid JS identifier use it as is as name of identifier;
246253
- Otherwise, try to get from `this` using import value as is (as string).
247254

248255
```javascript
249256
(function(first_module, b, thirdModule, d) {
257+
// ...
258+
println(first_module.a, b, thirdModule.c, d);
250259
// ...
251260
}(this["first-module"], this["second-module"], thirdModule, fourthModule));
252261
```
253262

263+
And for **module kind is UMD** compiler should use relevant rule for each block.
264+
254265
### Frontend
255-
- Report error when try to use native declaration which has `JsModule` annotations, but no one specifies a rule for current module kind.
256-
- Prohibit to have many annotations which explicitly provide the same module kind.
257266
- Prohibit to apply `JsModule` annotation to non-native declarations, except files.<br/>
258267
It can be relaxed later e.g. to reuse this annotation to allow translate a file to separate JS module,
259268
it can be useful to interop with some frameworks (see [KT-12093](https://youtrack.jetbrains.com/issue/KT-12093))
260269

261270
### IDE
262-
- Add inspection for the case when some declarations with the same fq-
271+
- Add inspection for the case when some declarations with the same fq-name
263272
Consider next cases:
264273
- function overloads
265274
- package and functions
266275

267276
## Open questions
268277
1. Can we introduce default value for `import` parameter of `JsModule` and use the name of declaration as import string when argument not provided?<br/>
269278
If so, how it should work when the annotation used on file?
270-
271-
2. What should be used as default value of `kind` parameter of `JsModule`?
272-
1. all kinds
273-
2. all kinds except SIMPLE
274-
275-
In TypeScript (external) modules can be used only when compiler ran with module kind (in our terms it's all except SIMPLE).
276-
So, should the second be default to generate simpler code from TS declarations?
277-
278-
3. Actually, right now we needs to know only is `kind === SIMPLE` or not, so should we simplify API?
279-
280-
4. Unfortunately, we can't use constants for `kind` parameter to make API better. Can we fix it somehow?
281-
282-
5. Will be nice to have the way to say that all declarations in this file are native. But how it fit with the idea to replace `@native` with `external`?

0 commit comments

Comments
 (0)