From 4c7f24af73300a3bd1418d21c42345e9106fae99 Mon Sep 17 00:00:00 2001 From: Petr Pucil Date: Sun, 29 Sep 2024 00:41:09 +0200 Subject: [PATCH] JavaScriptSG: fix broken generation of enum literals Related to https://github.com/kaitai-io/kaitai_struct/issues/1074 Until this commit, any generated JS test spec from a `.kst` file containing an enum literal would have a syntax error because of lines like `const ./Enum0 = require(...);`. It seems that this bug exists since 66e75b3f0c24c3be5db686565f03d216793b63f8. In that commit, I tried to fix the build error of KST translator due to the compiler API change in https://github.com/kaitai-io/kaitai_struct_compiler/commit/8007e0ecaa3b751e332732bb86c7de5c1937e7da#diff-6164bdf7b558cea6ff36b4a50508205a4569f8e98e398e77c4373679fceafffa. In JavaScriptSG, I just passed the existing `importList` to JavaScriptTranslator without thinking about the consequences (which were exactly the illegal `const ./Enum0 = require(...);` lines). This should now be fixed. --- .../specgenerators/JavaScriptSG.scala | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/translator/src/main/scala/io/kaitai/struct/testtranslator/specgenerators/JavaScriptSG.scala b/translator/src/main/scala/io/kaitai/struct/testtranslator/specgenerators/JavaScriptSG.scala index 18ebfc54a..5cab225ad 100644 --- a/translator/src/main/scala/io/kaitai/struct/testtranslator/specgenerators/JavaScriptSG.scala +++ b/translator/src/main/scala/io/kaitai/struct/testtranslator/specgenerators/JavaScriptSG.scala @@ -1,6 +1,6 @@ package io.kaitai.struct.testtranslator.specgenerators -import _root_.io.kaitai.struct.ClassTypeProvider +import _root_.io.kaitai.struct.{ClassTypeProvider, ImportList} import _root_.io.kaitai.struct.datatype.{DataType, KSError} import _root_.io.kaitai.struct.datatype.DataType.BytesType import _root_.io.kaitai.struct.exprlang.Ast @@ -10,7 +10,24 @@ import _root_.io.kaitai.struct.translators.JavaScriptTranslator class JavaScriptSG(spec: TestSpec, provider: ClassTypeProvider) extends BaseGenerator(spec) { val className = JavaScriptCompiler.type2class(spec.id) - val translator = new JavaScriptTranslator(provider, importList) + // JavaScriptTranslator accepts an ImportList so that if it translates an enum + // literal referencing an external enum (e.g. `external_spec::enum::label`), + // it can generate an import of the .ksy module in which the enum is defined. + // We don't pass our main `importList` and instead create a separate + // ImportList, because we don't want to output these imports at the top level. + // The reason is that they might refer to generated parsers that don't exist + // or contain syntax errors because of KSC bugs, and if a top-level + // `require()` fails, then the test spec "crashes" without the test framework + // having a clue what test it was). + // + // For now, we use `spec.extraImports` (i.e. the manually specified `imports` + // in the .kst spec) in runParse() instead, which we can output into the test + // body (which means that `require()` failures will be assigned correctly to + // the specific test). We cannot use `translatorImportList` there because it + // will still be empty at that point - some refactoring would be needed to use + // it instead of `spec.extraImports`. + val translatorImportList = new ImportList() + val translator = new JavaScriptTranslator(provider, translatorImportList) importList.add("assert") @@ -21,11 +38,12 @@ class JavaScriptSG(spec: TestSpec, provider: ClassTypeProvider) extends BaseGene override def runParse(): Unit = { importList.add("testHelper") - out.puts(s"testHelper('$className', 'src/${spec.data}', function(r, $className) {") + out.puts(s"testHelper('$className', 'src/${spec.data}', function(r, ${className}_) {") out.inc + // TODO: replace `spec.extraImports` with `translatorImportList` (see comment above) spec.extraImports.foreach { (entry) => val entryClass = JavaScriptCompiler.type2class(entry) - out.puts(s"var $entryClass = require('$entryClass').$entryClass;") + out.puts(s"var ${entryClass}_ = require('$entryClass');") } }