summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/jsgen.nim22
-rw-r--r--lib/system.nim18
-rw-r--r--lib/system/jssys.nim2
-rw-r--r--tests/js/tnilstrs.nim10
-rw-r--r--tests/system/tdollars.nim25
5 files changed, 69 insertions, 8 deletions
diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim
index 3bf2145df..1bf204c0f 100644
--- a/compiler/jsgen.nim
+++ b/compiler/jsgen.nim
@@ -2011,7 +2011,9 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
     gen(p, n[2], rhs)
 
     if skipTypes(n[1].typ, abstractVarRange).kind == tyCString:
-      r.res = "$1 += $2;" % [lhs.rdLoc, rhs.rdLoc]
+      let (b, tmp) = maybeMakeTemp(p, n[2], rhs)
+      r.res = "if (null != $1) { if (null == $2) $2 = $3; else $2 += $3; }" %
+        [b, lhs.rdLoc, tmp]
     else:
       let (a, tmp) = maybeMakeTemp(p, n[1], lhs)
       r.res = "$1.push.apply($3, $2);" % [a, rhs.rdLoc, tmp]
@@ -2062,9 +2064,23 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
   of mDestroy: discard "ignore calls to the default destructor"
   of mOrd: genOrd(p, n, r)
   of mLengthStr, mLengthSeq, mLengthOpenArray, mLengthArray:
-    unaryExpr(p, n, r, "", "($1).length")
+    var x: TCompRes
+    gen(p, n[1], x)
+    if skipTypes(n[1].typ, abstractInst).kind == tyCString:
+      let (a, tmp) = maybeMakeTemp(p, n[1], x)
+      r.res = "(($1) == null ? 0 : ($2).length)" % [a, tmp]
+    else:
+      r.res = "($1).length" % [x.rdLoc]
+    r.kind = resExpr
   of mHigh:
-    unaryExpr(p, n, r, "", "(($1).length-1)")
+    var x: TCompRes
+    gen(p, n[1], x)
+    if skipTypes(n[1].typ, abstractInst).kind == tyCString:
+      let (a, tmp) = maybeMakeTemp(p, n[1], x)
+      r.res = "(($1) == null ? -1 : ($2).length - 1)" % [a, tmp]
+    else:
+      r.res = "($1).length - 1" % [x.rdLoc]
+    r.kind = resExpr
   of mInc:
     if n[1].typ.skipTypes(abstractRange).kind in {tyUInt..tyUInt64}:
       binaryUintExpr(p, n, r, "+", true)
diff --git a/lib/system.nim b/lib/system.nim
index 82b8a6586..09a7faca9 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -2029,8 +2029,14 @@ type
     when NimStackTraceMsgs:
       frameMsgLen*: int   ## end position in frameMsgBuf for this frame.
 
-when defined(js):
+when defined(js) or defined(nimdoc):
   proc add*(x: var string, y: cstring) {.asmNoStackFrame.} =
+    ## Appends `y` to `x` in place.
+    runnableExamples:
+      var tmp = ""
+      tmp.add(cstring("ab"))
+      tmp.add(cstring("cd"))
+      doAssert tmp == "abcd"
     asm """
       if (`x` === null) { `x` = []; }
       var off = `x`.length;
@@ -2039,7 +2045,15 @@ when defined(js):
         `x`[off+i] = `y`.charCodeAt(i);
       }
     """
-  proc add*(x: var cstring, y: cstring) {.magic: "AppendStrStr".}
+  proc add*(x: var cstring, y: cstring) {.magic: "AppendStrStr".} =
+    ## Appends `y` to `x` in place.
+    ## Only implemented for JS backend.
+    runnableExamples:
+      when defined(js):
+        var tmp: cstring = ""
+        tmp.add(cstring("ab"))
+        tmp.add(cstring("cd"))
+        doAssert tmp == cstring("abcd")
 
 elif hasAlloc:
   {.push stackTrace: off, profiler: off.}
diff --git a/lib/system/jssys.nim b/lib/system/jssys.nim
index 64c766482..ef06437e5 100644
--- a/lib/system/jssys.nim
+++ b/lib/system/jssys.nim
@@ -645,7 +645,7 @@ proc genericReset(x: JSRef, ti: PNimType): JSRef {.compilerproc.} =
       asm "`result` = {m_type: `ti`};"
     else:
       asm "`result` = {};"
-  of tySequence, tyOpenArray:
+  of tySequence, tyOpenArray, tyString:
     asm """
       `result` = [];
     """
diff --git a/tests/js/tnilstrs.nim b/tests/js/tnilstrs.nim
index c0048cb24..6c1e4e401 100644
--- a/tests/js/tnilstrs.nim
+++ b/tests/js/tnilstrs.nim
@@ -14,4 +14,12 @@ block:
   var x = "foo".cstring
   var y: string
   add(y, x)
-  doAssert y == "foo"
\ No newline at end of file
+  doAssert y == "foo"
+
+block:
+  type Foo = object
+    a: string
+  var foo = Foo(a: "foo")
+  var y = move foo.a
+  doAssert foo.a.len == 0
+  doAssert y == "foo"
diff --git a/tests/system/tdollars.nim b/tests/system/tdollars.nim
index 1b2602ad0..62f77c857 100644
--- a/tests/system/tdollars.nim
+++ b/tests/system/tdollars.nim
@@ -71,12 +71,35 @@ block: # `$`(SomeInteger)
     testType int64
     testType BiggestInt
 
-block: # #14350 for JS
+block: # #14350, #16674, #16686 for JS
   var cstr: cstring
   doAssert cstr == cstring(nil)
   doAssert cstr == nil
   doAssert cstr.isNil
   doAssert cstr != cstring("")
+  doAssert cstr.len == 0
+
+  when defined(js):
+    cstr.add(cstring("abc"))
+    doAssert cstr == cstring("abc")
+
+    var nil1, nil2: cstring = nil
+
+    nil1.add(nil2)
+    doAssert nil1 == cstring(nil)
+    doAssert nil2 == cstring(nil)
+
+    nil1.add(cstring(""))
+    doAssert nil1 == cstring("")
+    doAssert nil2 == cstring(nil)
+
+    nil1.add(nil2)
+    doAssert nil1 == cstring("")
+    doAssert nil2 == cstring(nil)
+
+    nil2.add(nil1)
+    doAssert nil1 == cstring("")
+    doAssert nil2 == cstring("")
 
 
 proc main()=