1// Copyright 2014 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5var num = 5; 6var str = "str"; 7function fn() { return "result"; } 8var obj = { 9 num: num, 10 str: str, 11 fn: function() { return "result"; } 12}; 13 14(function testBasicExpressions() { 15 assertEquals("foo 5 bar", `foo ${num} bar`); 16 assertEquals("foo str bar", `foo ${str} bar`); 17 assertEquals("foo [object Object] bar", `foo ${obj} bar`); 18 assertEquals("foo result bar", `foo ${fn()} bar`); 19 assertEquals("foo 5 bar", `foo ${obj.num} bar`); 20 assertEquals("foo str bar", `foo ${obj.str} bar`); 21 assertEquals("foo result bar", `foo ${obj.fn()} bar`); 22})(); 23 24(function testExpressionsContainingTemplates() { 25 assertEquals("foo bar 5", `foo ${`bar ${num}`}`); 26})(); 27 28(function testMultilineTemplates() { 29 assertEquals("foo\n bar\n baz", `foo 30 bar 31 baz`); 32 33 assertEquals("foo\n bar\n baz", eval("`foo\r\n bar\r baz`")); 34})(); 35 36(function testLineContinuation() { 37 assertEquals("\n", `\ 38 39`); 40})(); 41 42(function testTaggedTemplates() { 43 var calls = 0; 44 (function(s) { 45 calls++; 46 })`test`; 47 assertEquals(1, calls); 48 49 calls = 0; 50 // assert tag is invoked in right context 51 obj = { 52 fn: function() { 53 calls++; 54 assertEquals(obj, this); 55 } 56 }; 57 58 obj.fn`test`; 59 assertEquals(1, calls); 60 61 calls = 0; 62 // Simple templates only have a callSiteObj 63 (function(s) { 64 calls++; 65 assertEquals(1, arguments.length); 66 })`test`; 67 assertEquals(1, calls); 68 69 // Templates containing expressions have the values of evaluated expressions 70 calls = 0; 71 (function(site, n, s, o, f, r) { 72 calls++; 73 assertEquals(6, arguments.length); 74 assertEquals("number", typeof n); 75 assertEquals("string", typeof s); 76 assertEquals("object", typeof o); 77 assertEquals("function", typeof f); 78 assertEquals("result", r); 79 })`${num}${str}${obj}${fn}${fn()}`; 80 assertEquals(1, calls); 81 82 // The TV and TRV of NoSubstitutionTemplate :: `` is the empty code unit 83 // sequence. 84 calls = 0; 85 (function(s) { 86 calls++; 87 assertEquals(1, s.length); 88 assertEquals(1, s.raw.length); 89 assertEquals("", s[0]); 90 91 // Failure: expected <""> found <"foo barfoo barfoo foo foo foo testtest"> 92 assertEquals("", s.raw[0]); 93 })``; 94 assertEquals(1, calls); 95 96 // The TV and TRV of TemplateHead :: `${ is the empty code unit sequence. 97 calls = 0; 98 (function(s) { 99 calls++; 100 assertEquals(2, s.length); 101 assertEquals(2, s.raw.length); 102 assertEquals("", s[0]); 103 assertEquals("", s.raw[0]); 104 })`${1}`; 105 assertEquals(1, calls); 106 107 // The TV and TRV of TemplateMiddle :: }${ is the empty code unit sequence. 108 calls = 0; 109 (function(s) { 110 calls++; 111 assertEquals(3, s.length); 112 assertEquals(3, s.raw.length); 113 assertEquals("", s[1]); 114 assertEquals("", s.raw[1]); 115 })`${1}${2}`; 116 assertEquals(1, calls); 117 118 // The TV and TRV of TemplateTail :: }` is the empty code unit sequence. 119 calls = 0; 120 (function(s) { 121 calls++; 122 assertEquals(2, s.length); 123 assertEquals(2, s.raw.length); 124 assertEquals("", s[1]); 125 assertEquals("", s.raw[1]); 126 })`${1}`; 127 assertEquals(1, calls); 128 129 // The TV of NoSubstitutionTemplate :: ` TemplateCharacters ` is the TV of 130 // TemplateCharacters. 131 calls = 0; 132 (function(s) { calls++; assertEquals("foo", s[0]); })`foo`; 133 assertEquals(1, calls); 134 135 // The TV of TemplateHead :: ` TemplateCharacters ${ is the TV of 136 // TemplateCharacters. 137 calls = 0; 138 (function(s) { calls++; assertEquals("foo", s[0]); })`foo${1}`; 139 assertEquals(1, calls); 140 141 // The TV of TemplateMiddle :: } TemplateCharacters ${ is the TV of 142 // TemplateCharacters. 143 calls = 0; 144 (function(s) { calls++; assertEquals("foo", s[1]); })`${1}foo${2}`; 145 assertEquals(1, calls); 146 147 // The TV of TemplateTail :: } TemplateCharacters ` is the TV of 148 // TemplateCharacters. 149 calls = 0; 150 (function(s) { calls++; assertEquals("foo", s[1]); })`${1}foo`; 151 assertEquals(1, calls); 152 153 // The TV of TemplateCharacters :: TemplateCharacter is the TV of 154 // TemplateCharacter. 155 calls = 0; 156 (function(s) { calls++; assertEquals("f", s[0]); })`f`; 157 assertEquals(1, calls); 158 159 // The TV of TemplateCharacter :: $ is the code unit value 0x0024. 160 calls = 0; 161 (function(s) { calls++; assertEquals("$", s[0]); })`$`; 162 assertEquals(1, calls); 163 164 // The TV of TemplateCharacter :: \ EscapeSequence is the CV of 165 // EscapeSequence. 166 calls = 0; 167 (function(s) { calls++; assertEquals("안녕", s[0]); })`\uc548\uB155`; 168 (function(s) { calls++; assertEquals("\xff", s[0]); })`\xff`; 169 (function(s) { calls++; assertEquals("\n", s[0]); })`\n`; 170 assertEquals(3, calls); 171 172 // The TV of TemplateCharacter :: LineContinuation is the TV of 173 // LineContinuation. The TV of LineContinuation :: \ LineTerminatorSequence is 174 // the empty code unit sequence. 175 calls = 0; 176 (function(s) { calls++; assertEquals("", s[0]); })`\ 177`; 178 assertEquals(1, calls); 179 180 // The TRV of NoSubstitutionTemplate :: ` TemplateCharacters ` is the TRV of 181 // TemplateCharacters. 182 calls = 0; 183 (function(s) { calls++; assertEquals("test", s.raw[0]); })`test`; 184 assertEquals(1, calls); 185 186 // The TRV of TemplateHead :: ` TemplateCharacters ${ is the TRV of 187 // TemplateCharacters. 188 calls = 0; 189 (function(s) { calls++; assertEquals("test", s.raw[0]); })`test${1}`; 190 assertEquals(1, calls); 191 192 // The TRV of TemplateMiddle :: } TemplateCharacters ${ is the TRV of 193 // TemplateCharacters. 194 calls = 0; 195 (function(s) { calls++; assertEquals("test", s.raw[1]); })`${1}test${2}`; 196 assertEquals(1, calls); 197 198 // The TRV of TemplateTail :: } TemplateCharacters ` is the TRV of 199 // TemplateCharacters. 200 calls = 0; 201 (function(s) { calls++; assertEquals("test", s.raw[1]); })`${1}test`; 202 assertEquals(1, calls); 203 204 // The TRV of TemplateCharacters :: TemplateCharacter is the TRV of 205 // TemplateCharacter. 206 calls = 0; 207 (function(s) { calls++; assertEquals("f", s.raw[0]); })`f`; 208 assertEquals(1, calls); 209 210 // The TRV of TemplateCharacter :: $ is the code unit value 0x0024. 211 calls = 0; 212 (function(s) { calls++; assertEquals("\u0024", s.raw[0]); })`$`; 213 assertEquals(1, calls); 214 215 // The TRV of EscapeSequence :: 0 is the code unit value 0x0030. 216 calls = 0; 217 (function(s) { calls++; assertEquals("\u005C\u0030", s.raw[0]); })`\0`; 218 assertEquals(1, calls); 219 220 // The TRV of TemplateCharacter :: \ EscapeSequence is the sequence consisting 221 // of the code unit value 0x005C followed by the code units of TRV of 222 // EscapeSequence. 223 224 // The TRV of EscapeSequence :: HexEscapeSequence is the TRV of the 225 // HexEscapeSequence. 226 calls = 0; 227 (function(s) { calls++; assertEquals("\u005Cxff", s.raw[0]); })`\xff`; 228 assertEquals(1, calls); 229 230 // The TRV of EscapeSequence :: UnicodeEscapeSequence is the TRV of the 231 // UnicodeEscapeSequence. 232 calls = 0; 233 (function(s) { calls++; assertEquals("\u005Cuc548", s.raw[0]); })`\uc548`; 234 assertEquals(1, calls); 235 236 // The TRV of CharacterEscapeSequence :: SingleEscapeCharacter is the TRV of 237 // the SingleEscapeCharacter. 238 calls = 0; 239 (function(s) { calls++; assertEquals("\u005C\u0027", s.raw[0]); })`\'`; 240 (function(s) { calls++; assertEquals("\u005C\u0022", s.raw[0]); })`\"`; 241 (function(s) { calls++; assertEquals("\u005C\u005C", s.raw[0]); })`\\`; 242 (function(s) { calls++; assertEquals("\u005Cb", s.raw[0]); })`\b`; 243 (function(s) { calls++; assertEquals("\u005Cf", s.raw[0]); })`\f`; 244 (function(s) { calls++; assertEquals("\u005Cn", s.raw[0]); })`\n`; 245 (function(s) { calls++; assertEquals("\u005Cr", s.raw[0]); })`\r`; 246 (function(s) { calls++; assertEquals("\u005Ct", s.raw[0]); })`\t`; 247 (function(s) { calls++; assertEquals("\u005Cv", s.raw[0]); })`\v`; 248 (function(s) { calls++; assertEquals("\u005C`", s.raw[0]); })`\``; 249 assertEquals(10, calls); 250 251 // The TRV of CharacterEscapeSequence :: NonEscapeCharacter is the CV of the 252 // NonEscapeCharacter. 253 calls = 0; 254 (function(s) { calls++; assertEquals("\u005Cz", s.raw[0]); })`\z`; 255 assertEquals(1, calls); 256 257 // The TRV of LineTerminatorSequence :: <LF> is the code unit value 0x000A. 258 // The TRV of LineTerminatorSequence :: <CR> is the code unit value 0x000A. 259 // The TRV of LineTerminatorSequence :: <CR><LF> is the sequence consisting of 260 // the code unit value 0x000A. 261 calls = 0; 262 function testRawLineNormalization(cs) { 263 calls++; 264 assertEquals(cs.raw[0], "\n\n\n"); 265 assertEquals(cs.raw[1], "\n\n\n"); 266 } 267 eval("testRawLineNormalization`\r\n\n\r${1}\r\n\n\r`"); 268 assertEquals(1, calls); 269 270 // The TRV of LineContinuation :: \ LineTerminatorSequence is the sequence 271 // consisting of the code unit value 0x005C followed by the code units of TRV 272 // of LineTerminatorSequence. 273 calls = 0; 274 function testRawLineContinuation(cs) { 275 calls++; 276 assertEquals(cs.raw[0], "\u005C\n\u005C\n\u005C\n"); 277 assertEquals(cs.raw[1], "\u005C\n\u005C\n\u005C\n"); 278 } 279 eval("testRawLineContinuation`\\\r\n\\\n\\\r${1}\\\r\n\\\n\\\r`"); 280 assertEquals(1, calls); 281})(); 282 283 284(function testCallSiteObj() { 285 var calls = 0; 286 function tag(cs) { 287 calls++; 288 assertTrue(cs.hasOwnProperty("raw")); 289 assertTrue(Object.isFrozen(cs)); 290 assertTrue(Object.isFrozen(cs.raw)); 291 var raw = Object.getOwnPropertyDescriptor(cs, "raw"); 292 assertFalse(raw.writable); 293 assertFalse(raw.configurable); 294 assertFalse(raw.enumerable); 295 assertEquals(Array.prototype, Object.getPrototypeOf(cs.raw)); 296 assertTrue(Array.isArray(cs.raw)); 297 assertEquals(Array.prototype, Object.getPrototypeOf(cs)); 298 assertTrue(Array.isArray(cs)); 299 300 var cooked0 = Object.getOwnPropertyDescriptor(cs, "0"); 301 assertFalse(cooked0.writable); 302 assertFalse(cooked0.configurable); 303 assertTrue(cooked0.enumerable); 304 305 var raw0 = Object.getOwnPropertyDescriptor(cs.raw, "0"); 306 assertFalse(raw0.writable); 307 assertFalse(raw0.configurable); 308 assertTrue(raw0.enumerable); 309 310 var length = Object.getOwnPropertyDescriptor(cs, "length"); 311 assertFalse(length.writable); 312 assertFalse(length.configurable); 313 assertFalse(length.enumerable); 314 315 length = Object.getOwnPropertyDescriptor(cs.raw, "length"); 316 assertFalse(length.writable); 317 assertFalse(length.configurable); 318 assertFalse(length.enumerable); 319 } 320 tag`${1}`; 321 assertEquals(1, calls); 322})(); 323 324 325(function testUTF16ByteOrderMark() { 326 assertEquals("\uFEFFtest", `\uFEFFtest`); 327 assertEquals("\uFEFFtest", eval("`\uFEFFtest`")); 328})(); 329 330 331(function testStringRawAsTagFn() { 332 assertEquals("\\u0065\\`\\r\\r\\n\\ntestcheck", 333 String.raw`\u0065\`\r\r\n\n${"test"}check`); 334 assertEquals("\\\n\\\n\\\n", eval("String.raw`\\\r\\\r\n\\\n`")); 335 assertEquals("", String.raw``); 336})(); 337 338 339(function testCallSiteCaching() { 340 var callSites = []; 341 function tag(cs) { callSites.push(cs); } 342 var a = 1; 343 var b = 2; 344 345 tag`head${a}tail`; 346 tag`head${b}tail`; 347 348 assertEquals(2, callSites.length); 349 assertSame(callSites[0], callSites[1]); 350 351 eval("tag`head${a}tail`"); 352 assertEquals(3, callSites.length); 353 assertSame(callSites[1], callSites[2]); 354 355 eval("tag`head${b}tail`"); 356 assertEquals(4, callSites.length); 357 assertSame(callSites[2], callSites[3]); 358 359 (new Function("tag", "a", "b", "return tag`head${a}tail`;"))(tag, 1, 2); 360 assertEquals(5, callSites.length); 361 assertSame(callSites[3], callSites[4]); 362 363 (new Function("tag", "a", "b", "return tag`head${b}tail`;"))(tag, 1, 2); 364 assertEquals(6, callSites.length); 365 assertSame(callSites[4], callSites[5]); 366 367 callSites = []; 368 369 tag`foo${a}bar`; 370 tag`foo\${.}bar`; 371 assertEquals(2, callSites.length); 372 assertEquals(2, callSites[0].length); 373 assertEquals(1, callSites[1].length); 374 375 callSites = []; 376 377 eval("tag`\\\r\n\\\n\\\r`"); 378 eval("tag`\\\r\n\\\n\\\r`"); 379 assertEquals(2, callSites.length); 380 assertSame(callSites[0], callSites[1]); 381 assertEquals("", callSites[0][0]); 382 assertEquals("\\\n\\\n\\\n", callSites[0].raw[0]); 383 384 callSites = []; 385 386 tag`\uc548\ub155`; 387 tag`\uc548\ub155`; 388 assertEquals(2, callSites.length); 389 assertSame(callSites[0], callSites[1]); 390 assertEquals("안녕", callSites[0][0]); 391 assertEquals("\\uc548\\ub155", callSites[0].raw[0]); 392 393 callSites = []; 394 395 tag`\uc548\ub155`; 396 tag`안녕`; 397 assertEquals(2, callSites.length); 398 assertTrue(callSites[0] !== callSites[1]); 399 assertEquals("안녕", callSites[0][0]); 400 assertEquals("\\uc548\\ub155", callSites[0].raw[0]); 401 assertEquals("안녕", callSites[1][0]); 402 assertEquals("안녕", callSites[1].raw[0]); 403 404 // Extra-thorough UTF8 decoding test. 405 callSites = []; 406 407 tag`Iñtërnâtiônàlizætiøn\u2603\uD83D\uDCA9`; 408 tag`Iñtërnâtiônàlizætiøn☃`; 409 410 assertEquals(2, callSites.length); 411 assertTrue(callSites[0] !== callSites[1]); 412 assertEquals("Iñtërnâtiônàlizætiøn☃", callSites[0][0]); 413 assertEquals( 414 "Iñtërnâtiônàlizætiøn\\u2603\\uD83D\\uDCA9", callSites[0].raw[0]); 415 assertEquals("Iñtërnâtiônàlizætiøn☃", callSites[1][0]); 416 assertEquals("Iñtërnâtiônàlizætiøn☃", callSites[1].raw[0]); 417})(); 418 419 420(function testExtendedArrayPrototype() { 421 Object.defineProperty(Array.prototype, 0, { 422 set: function() { 423 assertUnreachable(); 424 }, 425 configurable: true 426 }); 427 function tag(){} 428 tag`a${1}b`; 429 delete Array.prototype[0]; 430})(); 431 432 433(function testRawLineNormalization() { 434 function raw0(callSiteObj) { 435 return callSiteObj.raw[0]; 436 } 437 assertEquals(eval("raw0`\r`"), "\n"); 438 assertEquals(eval("raw0`\r\n`"), "\n"); 439 assertEquals(eval("raw0`\r\r\n`"), "\n\n"); 440 assertEquals(eval("raw0`\r\n\r\n`"), "\n\n"); 441 assertEquals(eval("raw0`\r\r\r\n`"), "\n\n\n"); 442})(); 443 444 445(function testHarmonyUnicode() { 446 function raw0(callSiteObj) { 447 return callSiteObj.raw[0]; 448 } 449 assertEquals(raw0`a\u{62}c`, "a\\u{62}c"); 450 assertEquals(raw0`a\u{000062}c`, "a\\u{000062}c"); 451 assertEquals(raw0`a\u{0}c`, "a\\u{0}c"); 452 453 assertEquals(`a\u{62}c`, "abc"); 454 assertEquals(`a\u{000062}c`, "abc"); 455})(); 456 457 458(function testLiteralAfterRightBrace() { 459 // Regression test for https://code.google.com/p/v8/issues/detail?id=3734 460 function f() {} 461 `abc`; 462 463 function g() {}`def`; 464 465 { 466 // block 467 } 468 `ghi`; 469 470 { 471 // block 472 }`jkl`; 473})(); 474 475 476(function testLegacyOctal() { 477 assertEquals('\u0000', `\0`); 478 assertEquals('\u0000a', `\0a`); 479 for (var i = 0; i < 8; i++) { 480 var code = "`\\0" + i + "`"; 481 assertThrows(code, SyntaxError); 482 code = "(function(){})" + code; 483 assertThrows(code, SyntaxError); 484 } 485 486 assertEquals('\\0', String.raw`\0`); 487})(); 488 489 490(function testSyntaxErrorsNonEscapeCharacter() { 491 assertThrows("`\\x`", SyntaxError); 492 assertThrows("`\\u`", SyntaxError); 493 for (var i = 1; i < 8; i++) { 494 var code = "`\\" + i + "`"; 495 assertThrows(code, SyntaxError); 496 code = "(function(){})" + code; 497 assertThrows(code, SyntaxError); 498 } 499})(); 500 501 502(function testValidNumericEscapes() { 503 assertEquals("8", `\8`); 504 assertEquals("9", `\9`); 505 assertEquals("\u00008", `\08`); 506 assertEquals("\u00009", `\09`); 507})(); 508 509 510(function testLegacyOctalEscapesInExpressions() { 511 // Allowed in sloppy expression 512 assertEquals("\x07", `${"\07"}`); 513 514 // Disallowed in template tail 515 assertThrows("`${\"\\07\"}\\07`", SyntaxError); 516 517 // Disallowed in strict expression 518 assertThrows("`${(function() { \"use strict\"; return \"\\07\"; })()}`", 519 SyntaxError); 520})(); 521 522 523var global = this; 524(function testCallNew() { 525 "use strict"; 526 var called = false; 527 var calledWith; 528 global.log = function(x) { called = true; calledWith = x; } 529 530 assertInstanceof(new Function`log("test")`, Object); 531 assertTrue(called); 532 assertSame("test", calledWith); 533 delete global.log; 534})(); 535 536 537(function testCallNew2() { 538 "use strict"; 539 var log = []; 540 function tag(x) { 541 log.push(x); 542 if (!(this instanceof tag)) { 543 return tag; 544 } 545 this.x = x === void 0 ? null : x; 546 return this; 547 } 548 // No arguments passed to constructor 549 var instance = new tag`x``y``z`; 550 assertInstanceof(instance, tag); 551 assertSame(tag.prototype, Object.getPrototypeOf(instance)); 552 assertEquals({ x: null }, instance); 553 assertEquals([["x"], ["y"], ["z"], undefined], log); 554 555 // Arguments passed to constructor 556 log.length = 0; 557 instance = new tag`x2` `y2` `z2` (`test`); 558 assertInstanceof(instance, tag); 559 assertSame(tag.prototype, Object.getPrototypeOf(instance)); 560 assertEquals({ x: "test" }, instance); 561 assertEquals([["x2"], ["y2"], ["z2"], "test"], log); 562})(); 563 564 565(function testCallResultOfTagFn() { 566 "use strict"; 567 var i = 0; 568 var raw = []; 569 function tag(cs) { 570 var args = Array.prototype.slice.call(arguments); 571 var text = String.raw.apply(null, args); 572 if (i++ < 2) { 573 raw.push("tag;" + text); 574 return tag; 575 } 576 577 raw.push("raw;" + text); 578 return text; 579 } 580 assertEquals("test3", tag`test1``test2``test3`); 581 assertEquals([ 582 "tag;test1", 583 "tag;test2", 584 "raw;test3" 585 ], raw); 586})(); 587 588 589(function testReturnValueAsTagFn() { 590 "use strict"; 591 var i = 0; 592 function makeTag() { 593 return function tag(cs) { 594 var args = Array.prototype.slice.call(arguments, 1); 595 var rcs = []; 596 rcs.raw = cs.map(function(s) { 597 return '!' + s + '!'; 598 }); 599 args.unshift(rcs); 600 return String.raw.apply(null, args); 601 } 602 } 603 assertEquals('!hi!', makeTag()`hi`); 604 assertEquals('!test!0!test!', makeTag()`test${0}test`); 605 assertEquals('!!', makeTag()``); 606}); 607 608 609(function testToStringSubstitutions() { 610 var a = { 611 toString: function() { return "a"; }, 612 valueOf: function() { return "-a-"; } 613 }; 614 var b = { 615 toString: function() { return "b"; }, 616 valueOf: function() { return "-b-"; } 617 }; 618 assertEquals("a", `${a}`); 619 assertEquals("ab", `${a}${b}`); 620 assertEquals("-a--b-", `${a + b}`); 621 assertEquals("-a-", `${a + ""}`); 622 assertEquals("1a", `1${a}`); 623 assertEquals("1a2", `1${a}2`); 624 assertEquals("1a2b", `1${a}2${b}`); 625 assertEquals("1a2b3", `1${a}2${b}3`); 626})(); 627 628 629(function testToStringSubstitutionsOrder() { 630 var subs = []; 631 var log = []; 632 function getter(name, value) { 633 return { 634 get: function() { 635 log.push("get" + name); 636 return value; 637 }, 638 set: function(v) { 639 log.push("set" + name); 640 } 641 }; 642 } 643 Object.defineProperties(subs, { 644 0: getter(0, "a"), 645 1: getter(1, "b"), 646 2: getter(2, "c") 647 }); 648 649 assertEquals("-a-b-c-", `-${subs[0]}-${subs[1]}-${subs[2]}-`); 650 assertArrayEquals(["get0", "get1", "get2"], log); 651})(); 652 653 654(function testTaggedToStringSubstitutionsOrder() { 655 var subs = []; 656 var log = []; 657 var tagged = []; 658 function getter(name, value) { 659 return { 660 get: function() { 661 log.push("get" + name); 662 return value; 663 }, 664 set: function(v) { 665 log.push("set" + name); 666 } 667 }; 668 } 669 Object.defineProperties(subs, { 670 0: getter(0, 1), 671 1: getter(1, 2), 672 2: getter(2, 3) 673 }); 674 675 function tag(cs) { 676 var n_substitutions = arguments.length - 1; 677 var n_cooked = cs.length; 678 var e = cs[0]; 679 var i = 0; 680 assertEquals(n_cooked, n_substitutions + 1); 681 while (i < n_substitutions) { 682 var sub = arguments[i++ + 1]; 683 var tail = cs[i]; 684 tagged.push(sub); 685 e = e.concat(sub, tail); 686 } 687 return e; 688 } 689 690 assertEquals("-1-2-3-", tag`-${subs[0]}-${subs[1]}-${subs[2]}-`); 691 assertArrayEquals(["get0", "get1", "get2"], log); 692 assertArrayEquals([1, 2, 3], tagged); 693 694 tagged.length = 0; 695 log.length = 0; 696 assertEquals("-1-", tag`-${subs[0]}-`); 697 assertArrayEquals(["get0"], log); 698 assertArrayEquals([1], tagged); 699})(); 700 701 702// Since the first argument to the tag function is always an array, 703// eval calls will always just return that array. 704(function testEvalTagStrict() { 705 "use strict"; 706 var f = (x) => eval`a${x}b`; 707 var result = f(); 708 assertEquals(["a", "b"], result); 709 assertSame(result, f()); 710})(); 711 712 713(function testEvalTagSloppy() { 714 var f = (x) => eval`a${x}b`; 715 var result = f(); 716 assertEquals(["a", "b"], result); 717 assertSame(result, f()); 718})(); 719