@@ -284,6 +284,15 @@ namespace pxt.blocks {
284
284
let output = ""
285
285
let indent = ""
286
286
let variables : Map < string > [ ] = [ { } ] ;
287
+ let currentLine = 0 ;
288
+
289
+ function append ( s : string ) {
290
+ // At runtime sometimes `s` is a number.
291
+ if ( typeof ( s ) === 'string' ) {
292
+ currentLine += ( s . match ( / \n / g) || [ ] ) . length ;
293
+ }
294
+ output += s ;
295
+ }
287
296
288
297
function flatten ( e0 : JsNode ) {
289
298
function rec ( e : JsNode , outPrio : number ) {
@@ -340,50 +349,50 @@ namespace pxt.blocks {
340
349
341
350
// never return empty string - TS compiler service thinks it's an error
342
351
if ( ! output )
343
- output += "\n"
352
+ append ( "\n" ) ;
344
353
345
354
return { output, sourceMap }
346
355
347
356
function emit ( n : JsNode ) {
348
357
if ( n . glueToBlock ) {
349
358
removeLastIndent ( )
350
359
if ( n . glueToBlock == GlueMode . WithSpace ) {
351
- output += " "
360
+ append ( " " ) ;
352
361
}
353
362
}
354
363
355
- let startLine = getCurrentLine ( ) ;
364
+ let startLine = currentLine ;
356
365
let startPos = output . length ;
357
366
358
367
switch ( n . type ) {
359
368
case NT . Infix :
360
369
U . oops ( "no infix should be left" )
361
370
break
362
371
case NT . NewLine :
363
- output += "\n" + indent
372
+ append ( "\n" + indent )
364
373
break
365
374
case NT . Block :
366
375
block ( n )
367
376
break
368
377
case NT . Prefix :
369
378
if ( n . canIndentInside )
370
- output += n . op . replace ( / \n / g, "\n" + indent + " " )
379
+ append ( n . op . replace ( / \n / g, "\n" + indent + " " ) )
371
380
else
372
- output += n . op
381
+ append ( n . op )
373
382
n . children . forEach ( emit )
374
383
break
375
384
case NT . Postfix :
376
385
n . children . forEach ( emit )
377
386
if ( n . canIndentInside )
378
- output += n . op . replace ( / \n / g, "\n" + indent + " " )
387
+ append ( n . op . replace ( / \n / g, "\n" + indent + " " ) )
379
388
else
380
- output += n . op
389
+ append ( n . op )
381
390
break
382
391
default :
383
392
break
384
393
}
385
394
386
- let endLine = getCurrentLine ( ) ;
395
+ let endLine = currentLine ;
387
396
// end position is non-inclusive
388
397
let endPos = Math . max ( output . length , 1 ) ;
389
398
@@ -406,16 +415,16 @@ namespace pxt.blocks {
406
415
}
407
416
}
408
417
409
- function getCurrentLine ( ) {
410
- return ( output . match ( / \n / g) || [ ] ) . length ;
411
- }
412
-
413
418
function write ( s : string ) {
414
- output += s . replace ( / \n / g, "\n" + indent )
419
+ append ( s . replace ( / \n / g, "\n" + indent ) )
415
420
}
416
421
417
422
function removeLastIndent ( ) {
418
- output = output . replace ( / \n * $ / , "" )
423
+ // Note: performance of this regular expression degrades with program size, and could therefore become a perf issue.
424
+ output = output . replace ( / \n * $ / , function ( ) {
425
+ currentLine -- ;
426
+ return "" ;
427
+ } ) ;
419
428
}
420
429
421
430
function block ( n : JsNode ) {
@@ -463,4 +472,4 @@ namespace pxt.blocks {
463
472
}
464
473
return false ;
465
474
}
466
- }
475
+ }
0 commit comments