[backport:1.4] JS cstring null fixes (#16979)

* [backport:1.4] JS cstring null fixes
* fix JS move string
* make it look cleaner
This commit is contained in:
hlaaftana 2021-02-11 19:04:32 +03:00 • committed by GitHub
commit 81533a0014
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 69 additions and 8 deletions

View file

@ -2011,7 +2011,9 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
gen(p, n[2], rhs) gen(p, n[2], rhs)
if skipTypes(n[1].typ, abstractVarRange).kind == tyCString: 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: else:
let (a, tmp) = maybeMakeTemp(p, n[1], lhs) let (a, tmp) = maybeMakeTemp(p, n[1], lhs)
r.res = "$1.push.apply($3, $2);" % [a, rhs.rdLoc, tmp] 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 mDestroy: discard "ignore calls to the default destructor"
of mOrd: genOrd(p, n, r) of mOrd: genOrd(p, n, r)
of mLengthStr, mLengthSeq, mLengthOpenArray, mLengthArray: 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: 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: of mInc:
if n[1].typ.skipTypes(abstractRange).kind in {tyUInt..tyUInt64}: if n[1].typ.skipTypes(abstractRange).kind in {tyUInt..tyUInt64}:
binaryUintExpr(p, n, r, "+", true) binaryUintExpr(p, n, r, "+", true)

View file

@ -2029,8 +2029,14 @@ type
when NimStackTraceMsgs: when NimStackTraceMsgs:
frameMsgLen*: int ## end position in frameMsgBuf for this frame. 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.} = 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 """ asm """
if (`x` === null) { `x` = []; } if (`x` === null) { `x` = []; }
var off = `x`.length; var off = `x`.length;
@ -2039,7 +2045,15 @@ when defined(js):
`x`[off+i] = `y`.charCodeAt(i); `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: elif hasAlloc:
{.push stackTrace: off, profiler: off.} {.push stackTrace: off, profiler: off.}

View file

@ -645,7 +645,7 @@ proc genericReset(x: JSRef, ti: PNimType): JSRef {.compilerproc.} =
asm "`result` = {m_type: `ti`};" asm "`result` = {m_type: `ti`};"
else: else:
asm "`result` = {};" asm "`result` = {};"
of tySequence, tyOpenArray: of tySequence, tyOpenArray, tyString:
asm """ asm """
`result` = []; `result` = [];
""" """

View file

@ -14,4 +14,12 @@ block:
var x = "foo".cstring var x = "foo".cstring
var y: string var y: string
add(y, x) add(y, x)
doAssert y == "foo" 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"

View file

@ -71,12 +71,35 @@ block: # `$`(SomeInteger)
testType int64 testType int64
testType BiggestInt testType BiggestInt
block: # #14350 for JS block: # #14350, #16674, #16686 for JS
var cstr: cstring var cstr: cstring
doAssert cstr == cstring(nil) doAssert cstr == cstring(nil)
doAssert cstr == nil doAssert cstr == nil
doAssert cstr.isNil doAssert cstr.isNil
doAssert cstr != cstring("") 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()= proc main()=