kopscript 0.19.0 → 0.19.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/codegen.js +21 -2
- package/dist/modules.js +12 -1
- package/package.json +1 -1
package/dist/codegen.js
CHANGED
|
@@ -98,8 +98,27 @@ export class CodeGenerator {
|
|
|
98
98
|
// `public` into scope without naming it explicitly. `sourceFileName`/
|
|
99
99
|
// `sourceText` are for the emitted source map only (both optional so every
|
|
100
100
|
// existing test call site keeps compiling unchanged).
|
|
101
|
-
generate(program, usingExports = new Map(), rawContents = new Map(), sourceFileName = "source.ks", sourceText = ""
|
|
102
|
-
|
|
101
|
+
generate(program, usingExports = new Map(), rawContents = new Map(), sourceFileName = "source.ks", sourceText = "",
|
|
102
|
+
// Interface names visible via a `using` this module doesn't declare
|
|
103
|
+
// itself — separate from `usingExports` above, which deliberately
|
|
104
|
+
// excludes interfaces (they're compile-time only and never produce a
|
|
105
|
+
// JS import). Without this, a class implementing an interface declared
|
|
106
|
+
// in a DIFFERENT file (e.g. `class Component : Flushable` where
|
|
107
|
+
// `Flushable` lives in vdom.ks) has that interface name missing from
|
|
108
|
+
// `interfaceNames` entirely, so genClass's own "only a non-interface
|
|
109
|
+
// base list entry becomes `extends`" check can't tell it apart from a
|
|
110
|
+
// real (missing) superclass — it gets emitted as `extends Flushable`,
|
|
111
|
+
// a real runtime reference to a name nothing ever imports, throwing
|
|
112
|
+
// `ReferenceError: Flushable is not defined` the moment the class is
|
|
113
|
+
// ever loaded. Found for real building Kopular's own event-batching
|
|
114
|
+
// fix — the checker already resolves a cross-module interface's base
|
|
115
|
+
// list entry correctly (it type-checks fine); only codegen's own,
|
|
116
|
+
// separate, same-file-only interfaceNames set didn't know about it.
|
|
117
|
+
importedInterfaceNames = new Set()) {
|
|
118
|
+
this.interfaceNames = new Set([
|
|
119
|
+
...program.statements.filter((s) => s.kind === "InterfaceDecl").map((s) => s.name),
|
|
120
|
+
...importedInterfaceNames,
|
|
121
|
+
]);
|
|
103
122
|
this.outputLine = 1;
|
|
104
123
|
const outFileName = sourceFileName.replace(/\.ks$/, ".js");
|
|
105
124
|
this.sourceMap = new SourceMapBuilder(outFileName, sourceFileName, sourceText);
|
package/dist/modules.js
CHANGED
|
@@ -226,6 +226,13 @@ export function compileGraph(entryAbsPath, fileOverrides) {
|
|
|
226
226
|
for (const absPath of order) {
|
|
227
227
|
const mod = modules.get(absPath);
|
|
228
228
|
const usingExports = new Map();
|
|
229
|
+
// Separate from usingExports (interfaces are excluded there — see its
|
|
230
|
+
// own comment below) — this is what tells codegen's own interfaceNames
|
|
231
|
+
// set about an interface declared in a DIFFERENT file this module
|
|
232
|
+
// `using`s, so a class implementing one doesn't get miscompiled into a
|
|
233
|
+
// real `extends <InterfaceName>` runtime reference (see
|
|
234
|
+
// CodeGenerator.generate's own comment on importedInterfaceNames).
|
|
235
|
+
const importedInterfaceNames = new Set();
|
|
229
236
|
for (const u of mod.program.usings) {
|
|
230
237
|
const depPath = resolve(dirname(absPath), u.path) + ".ks";
|
|
231
238
|
const depExports = exportsByModule.get(depPath);
|
|
@@ -234,13 +241,17 @@ export function compileGraph(entryAbsPath, fileOverrides) {
|
|
|
234
241
|
// they'd make an invalid import specifier if listed here.
|
|
235
242
|
const importableTypeNames = [...depExports.namedTypes.entries()].filter(([, kind]) => kind !== "interface").map(([name]) => name);
|
|
236
243
|
usingExports.set(u.path, [...importableTypeNames, ...depExports.functions.keys(), ...depExports.externValues.keys()]);
|
|
244
|
+
for (const [name, kind] of depExports.namedTypes) {
|
|
245
|
+
if (kind === "interface")
|
|
246
|
+
importedInterfaceNames.add(name);
|
|
247
|
+
}
|
|
237
248
|
}
|
|
238
249
|
}
|
|
239
250
|
// Just the basename, not a cwd-relative path — the .js.map file always
|
|
240
251
|
// lands right next to its .ks/.js siblings (ks build writes output in
|
|
241
252
|
// place), so "sources" has to resolve relative to *that* directory, not
|
|
242
253
|
// wherever the compiler happened to be invoked from.
|
|
243
|
-
const { code, map } = new CodeGenerator().generate(mod.program, usingExports, rawContentsByModule.get(absPath) ?? new Map(), basename(absPath), mod.source);
|
|
254
|
+
const { code, map } = new CodeGenerator().generate(mod.program, usingExports, rawContentsByModule.get(absPath) ?? new Map(), basename(absPath), mod.source, importedInterfaceNames);
|
|
244
255
|
outputs.set(absPath, code);
|
|
245
256
|
sourceMaps.set(absPath, map);
|
|
246
257
|
}
|
package/package.json
CHANGED