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 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
- this.interfaceNames = new Set(program.statements.filter((s) => s.kind === "InterfaceDecl").map((s) => s.name));
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kopscript",
3
- "version": "0.19.0",
3
+ "version": "0.19.1",
4
4
  "description": "KopScript: a small OOP, strongly-typed language that transpiles to JavaScript, with generics and nullable types",
5
5
  "type": "module",
6
6
  "license": "MIT",