HaxeFoundation / HaxeFoundation/haxe

[JS] Use of js.Syntax.code may result in variables being redeclared during use scope

Open
#9,510 3 comments 0 reactions 0 assignees View on GitHub
Dominant language
Haxe
Stars
6.9k
Forks
715
Avg merge
2d 2h
Merged PRs (30d)
11

Description

Version: 4.2.0-rc.1+45809b90c

I felt like stitching a loop via js.Syntax.code as per [last year's recommendation](https://github.com/HaxeFoundation/haxe/issues/8069#issuecomment-478325996) was inevitably going to backfire and so it did.

Haxe:
```haxe
import haxe.DynamicAccess;

class Test {
/** https://github.com/HaxeFoundation/haxe/issues/8069#issuecomment-478325996 */
public static inline function forField(q:Dynamic, fn:String->Void):Void {
var fd:String = null;
var has:js.lib.Function = untyped js.lib.Object.prototype.hasOwnProperty;
js.Syntax.code("for ({0} in {1}) {", fd, q);
if (has.call(q, fd)) fn(fd);
js.Syntax.code("}");
}

static inline function add(comp:Comp) {
trace(comp, comp); // just forcing the variable to be preserved
}

static function trouble(kind:DynamicAccess, comp:Array) {
var results:Array<{name:String}> = [];
forField(kind, function(field:String) {
var matches = comp.filter((c) -> c.name == field);
add(matches[0]);
});
return results;
}

public static inline function main() {
trouble(
{ test: "hi", test2: "hello", test3: "oh no" },
[{name: "test"}, {name: "etc."}]
);
}
}

typedef Comp = { name:String };
```
Output of interest:
```js
Test.trouble = function(kind,comp) {
var results = [];
var q = kind;
var fd = null;
var has = Object.prototype.hasOwnProperty;
for (fd in q) {
if(has.call(q,fd)) {
var _g = [];
var _g1 = 0;
var _g2 = comp;
while(_g1 < _g2.length) {
var v = _g2[_g1];
++_g1;
if(v.name == fd) {
_g.push(v);
}
}
var matches = _g;
var comp = matches[0]; // <-- (!)
haxe_Log.trace(comp,{ fileName : "src/Test.hx", lineNumber : 14, className : "Test", methodName : "add", customParams : [comp]});
}
}
return results;
};
```
Note that the compiler shadows `comp` because, as far as it's concerned, the comp-argument will no longer be needed (but it is, since we're in a loop).

I do not have any particular suggestions as to how this should be cleanly detected - ultimately I still feel like there's need for a mechanism to inject blocks of code.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.