@@ -360,6 +360,51 @@ func TestDeclSelection_RemoveUnusedTypeConstraint(t *testing.T) {
360
360
sel .InitCode .IsDead (`ghost = new Bar\[\d+ /\* int \*/\]\.ptr\(7\)` )
361
361
}
362
362
363
+ func TestLengthParenthesizingIssue841 (t * testing.T ) {
364
+ // See issue https://github.com/gopherjs/gopherjs/issues/841
365
+ //
366
+ // Summary: Given `len(a+b)` where a and b are strings being concatenated
367
+ // together, the result was `a + b.length` instead of `(a+b).length`.
368
+ //
369
+ // The fix was to check if the expression in `len` is a binary
370
+ // expression or not. If it is, then the expression is parenthesized.
371
+ // This will work for concatenations any combination of variables and
372
+ // literals but won't pick up `len(Foo(a+b))` or `len(a[0:i+3])`.
373
+
374
+ src := `
375
+ package main
376
+
377
+ func main() {
378
+ a := "a"
379
+ b := "b"
380
+ ab := a + b
381
+ if len(a+b) != len(ab) {
382
+ panic("unreachable")
383
+ }
384
+ }`
385
+
386
+ srcFiles := []srctesting.Source {{Name : `main.go` , Contents : []byte (src )}}
387
+ root := srctesting .ParseSources (t , srcFiles , nil )
388
+ archives := compileProject (t , root , false )
389
+ mainPkg := archives [root .PkgPath ]
390
+
391
+ badRegex := regexp .MustCompile (`a\s*\+\s*b\.length` )
392
+ goodRegex := regexp .MustCompile (`\(a\s*\+\s*b\)\.length` )
393
+ goodFound := false
394
+ for i , decl := range mainPkg .Declarations {
395
+ if badRegex .Match (decl .DeclCode ) {
396
+ t .Errorf ("found length issue in decl #%d: %s" , i , decl .FullName )
397
+ t .Logf ("decl code:\n %s" , string (decl .DeclCode ))
398
+ }
399
+ if goodRegex .Match (decl .DeclCode ) {
400
+ goodFound = true
401
+ }
402
+ }
403
+ if ! goodFound {
404
+ t .Error ("parenthesized length not found" )
405
+ }
406
+ }
407
+
363
408
func compareOrder (t * testing.T , sourceFiles []srctesting.Source , minify bool ) {
364
409
t .Helper ()
365
410
outputNormal := compile (t , sourceFiles , minify )
0 commit comments