Repository: swig/swig (language: cpp)

Issue:
[JS] napi generator inserts `in` typemaps twice when using `numinputs=0`
```
ENGINE=napi make ignore_parameter.cpptest
grep -C 1 "hello" ignore_parameter_wrap.cxx
```


Discussion / hints:
is this fixed by #2653?
Yes (@mmomtchev I think you need to say "Fixes #nnnn" not "Fix #nnnn" in the commit message for it to automatically get linked).

However I just noticed there's a warning from that fix:

```
Modules/javascript.cxx: In member function ‘virtual void NAPIEmitter::marshalInputArgs(Node*, ParmList*, Wrapper*, JSEmitter::MarshallingMode, bool, bool)’:
Modules/javascript.cxx:2948:5: warning: ‘tm’ may be used uninitialized [-Wmaybe-uninitialized]
 2948 |     if (tm) {
      |     ^~
Modules/javascript.cxx:2878:11: note: ‘tm’ was declared here
 2878 |   String *tm;
      |           ^~
```

Initialising `tm` to `NULL` would fix the warning, but I'm not sure that's correct - it would mean we always do `p = nextSibling(p);` after a parameter `tmap:in:numinputs` set to `0` rather than `p = Getattr(p, "tmap:in:next");` but in this case there **is** an `in` typemap - looking at other target languages it looks to me like that decision should be based on whether `tmap:in` is set or not (and it should be if `tmap:in:numinputs` is set).
This is a real problem in all generators, it has been masked in V8/JSC because the variable is initialised.
However, as the input typemap can't really be `NULL` - because the code will be invalid - there are no functional consequences.

Fix patch:
diff --git a/Source/Modules/javascript.cxx b/Source/Modules/javascript.cxx
index 02dbc16ed4d..7f7431022ae 100644
--- a/Source/Modules/javascript.cxx
+++ b/Source/Modules/javascript.cxx
@@ -1406,13 +1406,19 @@ String *JSEmitter::emitInputTypemap(Node *n, Parm *p, Wrapper *wrapper, String *
     }
   } else {
     Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(type, 0));
+    return NULL;
   }
 
   if (is_optional) {
     Printf(code, "}\n");
   }
 
-  Append(wrapper->code, code);
+  // numinputs=0 typemaps are emitted by the legacy code in
+  // emit_attach_parmmaps() in emit.cxx, check the comment there
+  // All generators work around this
+  if (!checkAttribute(p, "tmap:in:numinputs", "0")) {
+    Append(wrapper->code, code);
+  }
   return code;
 }
 
@@ -1700,10 +1706,7 @@ void JSCEmitter::marshalInputArgs(Node *n, ParmList *parms, Wrapper *wrapper, Ma
       Exit(EXIT_FAILURE);
     }
 
-    // numinputs=0 typemaps are emitted by the legacy code in
-    // emit_attach_parmmaps() in emit.cxx, check the comment there
-    if (!checkAttribute(p, "tmap:in:numinputs", "0"))
-      tm = emitInputTypemap(n, p, wrapper, arg);
+    tm = emitInputTypemap(n, p, wrapper, arg);
     Delete(arg);
 
     if (tm) {
@@ -2368,11 +2371,7 @@ void V8Emitter::marshalInputArgs(Node *n, ParmList *parms, Wrapper *wrapper, Mar
       Exit(EXIT_FAILURE);
     }
 
-    // numinputs=0 typemaps are emitted by the legacy code in
-    // emit_attach_parmmaps() in emit.cxx, check the comment there
-    // All language backends work around this
-    if (!checkAttribute(p, "tmap:in:numinputs", "0"))
-      tm = emitInputTypemap(n, p, wrapper, arg);
+    tm = emitInputTypemap(n, p, wrapper, arg);
     Delete(arg);
 
     if (tm) {
@@ -2938,11 +2937,7 @@ void NAPIEmitter::marshalInputArgs(Node *n, ParmList *parms, Wrapper *wrapper, M
       Exit(EXIT_FAILURE);
     }
 
-    if (GetInt(p, "tmap:in:numinputs") != 0) {
-      // in typemaps with numinputs=0 are a special case
-      // and are handled in emit.cxx:emit_attach_parmmaps()
-      tm = emitInputTypemap(n, p, wrapper, arg);
-    }
+    tm = emitInputTypemap(n, p, wrapper, arg);
     Delete(arg);
 
     if (tm) {


Test patch: