mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-28 17:04:41 +00:00
While `a.push.apply(a, b)` is better for performance than the previous `a = a.concat(b)` due to the fact that it doesn't create a new array, there is a pretty big problem with it: depending on the JS engine, if the second array is too long, it can [cause a crash](https://tanaikech.github.io/2020/04/20/limitation-of-array.prototype.push.apply-under-v8-for-google-apps-script/) due to the function `push` taking too many arguments. This has unfortunately been what the codegen produces since 1.4.0 (commit707367e1ca). So string addition is now moved to a compilerproc that just uses a `for` loop. From what I can tell this is the most compatible and the fastest. Only potential problem compared to `concat` etc is with aliasing, i.e. adding an array to itself, but I'm guessing it's enough that the length from before the iteration is used, since it can only grow. The test checks for aliased nim strings but I don't know if there's an extra protection for them. (cherry picked from commit839cbeb371)
34 lines
591 B
Nim
34 lines
591 B
Nim
discard """
|
|
targets: "c cpp js"
|
|
output: '''
|
|
DabcD
|
|
(8192, 8, 1024)
|
|
'''
|
|
"""
|
|
|
|
import std/assertions
|
|
|
|
block:
|
|
const
|
|
x = "abc"
|
|
|
|
var v = "D" & x & "D"
|
|
|
|
doAssert v == "DabcD"
|
|
echo v
|
|
|
|
block: # test large additions
|
|
var a = "abcdefgh"
|
|
let initialLen = a.len
|
|
let times = 10
|
|
for i in 1..times:
|
|
let start = a.len
|
|
a.add(a)
|
|
doAssert a.len == 2 * start
|
|
let multiplier = 1 shl times
|
|
doAssert a.len == initialLen * multiplier
|
|
echo (a.len, initialLen, multiplier)
|
|
for i in 1 ..< multiplier:
|
|
for j in 0 ..< initialLen:
|
|
doAssert a[j] == a[i * initialLen + j]
|