Skip to content

[fork-ffi] arrays: spliceImpl — JS xs.splice(i, howMany, ...bs) removes howMany elements at index… #75

@Unisay

Description

@Unisay

Package: purescript-lua-arrays
File: src/Data/Array/ST.lua
Function: spliceImpl
Class: semantics Severity: high

JS xs.splice(i, howMany, ...bs) removes howMany elements at index i, inserts bs in their place (in-place mutation of xs, with the array shrinking/growing as needed), and RETURNS the array of removed elements. The Lua version only does move(xs, i + howMany + 1, #xs, i + #bs + 1, xs): it shifts the tail but never inserts the bs values, never shrinks the array when #bs < howMany (leaving stale duplicated trailing elements), and returns the whole mutated xs instead of the removed slice. Confirmed under Lua 5.1: spliceImpl(1, 2, {99}, {10,20,30,40,50}) returned {10,20,40,50,50} (len 5) and the same as the 'removed' value, instead of mutating xs to {10,99,40,50} and returning {20,30}. With insert>remove, spliceImpl(1,1,{8,9},{1,2,3}) gave {1,2,3,3} instead of {1,8,9,3}.

Current (Lua):

spliceImpl = (function(i, howMany, bs, xs) return move(xs, i + howMany + 1, #xs, i + #bs + 1, xs) end)

Expected: Mutate xs by deleting howMany elements at 0-based index i and inserting bs there; return a new array of the removed elements. spliceImpl(1,2,{99},{10,20,30,40,50}) => xs={10,99,40,50}, returns {20,30}.

Proposed fix:

Implement full splice semantics, collecting removed elements, shifting the tail by (#bs - howMany), trimming surplus slots to nil when shrinking, then writing bs into the gap:
  spliceImpl = (function(i, howMany, bs, xs)
    local n = #xs
    local removed = {}
    for k = 1, howMany do removed[k] = xs[i + k] end
    local nb, delta = #bs, #bs - howMany
    if delta > 0 then
      for k = n, i + howMany + 1, -1 do xs[k + delta] = xs[k] end
    elseif delta < 0 then
      for k = i + howMany + 1, n do xs[k + delta] = xs[k] end
      for k = n + delta + 1, n do xs[k] = nil end
    end
    for k = 1, nb do xs[i + k] = bs[k] end
    return removed
  end)
Verified under Lua 5.1 across remove>insert, insert>remove, and no-op cases.

Found by the FFI audit; reproduced under Lua 5.1.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions