Repro:
const x = Object.assign({3: 'd'}, "abc");
return [x[0], x[1], x[2], x[3]];
Expected: ["a", "b", "c", "d"]
Actual: [nil, nil, nil, "d"]
Per ECMA-262 sec-object.assign, each source is passed through ToObject; for a primitive string, that yields a String wrapper whose own enumerable keys are the indexed characters "0" -> "a", "1" -> "b", etc. Our lualib helper __TS__ObjectAssign (extern/tstl/src/lualib/ObjectAssign.ts) guards with if (type(source) === "table") and silently skips everything else. Fork commit c3b3a8b added that guard to prevent a crash on false/nil (the { ...(cond && obj) } pattern) but did not add the string-wrapper path.
Fix: in __TS__ObjectAssign, handle type(source) === "string" by iterating its bytes/characters and writing each under its integer index.
Repro:
Expected:
["a", "b", "c", "d"]Actual:
[nil, nil, nil, "d"]Per ECMA-262 sec-object.assign, each source is passed through
ToObject; for a primitive string, that yields a String wrapper whose own enumerable keys are the indexed characters"0"->"a","1"->"b", etc. Our lualib helper__TS__ObjectAssign(extern/tstl/src/lualib/ObjectAssign.ts) guards withif (type(source) === "table")and silently skips everything else. Fork commit c3b3a8b added that guard to prevent a crash onfalse/nil(the{ ...(cond && obj) }pattern) but did not add the string-wrapper path.Fix: in
__TS__ObjectAssign, handletype(source) === "string"by iterating its bytes/characters and writing each under its integer index.