From d5fc8b25afe9adca74cc99b609bb268fc98943a4 Mon Sep 17 00:00:00 2001
From: Daniel Ehrenberg <littledan@chromium.org>
Date: Mon, 5 Feb 2018 20:40:19 +0100
Subject: [PATCH] Test for change to cache templates by site, not contents
 (#972)

* Test for change to cache templates by site, not contents

These tests are against a specification change based on discussion in
https://github.com/tc39/ecma262/issues/840

The tests here passed on SpiderMonkey but failed on other
implementations, which implement the current specification.

* Add a test that caching is by source location, not function identity

* Update existing tests to reference the spec properly
---
 .../cache-different-functions-same-site.js    | 38 +++++++++++++++++++
 .../cache-differing-expressions-eval.js       | 13 +++----
 ...ache-differing-expressions-new-function.js | 15 ++++----
 .../cache-differing-expressions.js            | 12 +++---
 .../cache-differing-raw-strings.js            | 11 +++---
 .../cache-differing-string-count.js           | 11 +++---
 .../cache-identical-source-eval.js            | 14 +++----
 .../cache-identical-source-new-function.js    | 14 +++----
 .../tagged-template/cache-identical-source.js | 15 ++++----
 .../tagged-template/cache-realm.js            |  3 +-
 .../cache-same-site-top-level.js              | 31 +++++++++++++++
 .../tagged-template/cache-same-site.js        | 36 ++++++++++++++++++
 12 files changed, 159 insertions(+), 54 deletions(-)
 create mode 100644 test/language/expressions/tagged-template/cache-different-functions-same-site.js
 create mode 100644 test/language/expressions/tagged-template/cache-same-site-top-level.js
 create mode 100644 test/language/expressions/tagged-template/cache-same-site.js

diff --git a/test/language/expressions/tagged-template/cache-different-functions-same-site.js b/test/language/expressions/tagged-template/cache-different-functions-same-site.js
new file mode 100644
index 0000000000..91a554b8b1
--- /dev/null
+++ b/test/language/expressions/tagged-template/cache-different-functions-same-site.js
@@ -0,0 +1,38 @@
+// Copyright (C) 2017 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-gettemplateobject
+description: Templates are cached by source location inside a function
+info: >
+    1. For each element _e_ of _templateRegistry_, do
+      1. If _e_.[[Site]] is the same Parse Node as _templateLiteral_, then
+        1. Return _e_.[[Array]].
+---*/
+function tag(templateObject) {
+  previousObject = templateObject;
+}
+
+var a = 1;
+var firstObject = null;
+var previousObject = null;
+
+function factory() {
+  return function() {
+    tag`head${a}tail`;
+  }
+}
+
+factory()();
+firstObject = previousObject;
+
+assert(firstObject !== null);
+previousObject = null;
+
+factory()();
+
+assert.sameValue(
+  previousObject,
+  firstObject,
+  'The realm\'s template cache is for source code locations in a function'
+);
+
diff --git a/test/language/expressions/tagged-template/cache-differing-expressions-eval.js b/test/language/expressions/tagged-template/cache-differing-expressions-eval.js
index 1ae1f2d992..3c89f7fcda 100644
--- a/test/language/expressions/tagged-template/cache-differing-expressions-eval.js
+++ b/test/language/expressions/tagged-template/cache-differing-expressions-eval.js
@@ -1,13 +1,12 @@
 // Copyright (C) 2014 the V8 project authors. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 /*---
-es6id: 12.2.8
+esid: sec-gettemplateobject
 description: Template caching using distinct expressions within `eval`
-info: |
-    Previously-created template objects should be retrieved from the internal
-    template registry when their source is identical but their expressions
-    evaluate to different values and the tagged template is being evaluated in
-    an `eval` context.
+info: >
+    1. For each element _e_ of _templateRegistry_, do
+      1. If _e_.[[Site]] is the same Parse Node as _templateLiteral_, then
+        1. Return _e_.[[Array]].
 ---*/
 function tag(templateObject) {
   previousObject = templateObject;
@@ -23,4 +22,4 @@ assert(firstObject !== null);
 previousObject = null;
 
 eval('tag`head${b}tail`');
-assert.sameValue(previousObject, firstObject);
+assert.notSameValue(previousObject, firstObject);
diff --git a/test/language/expressions/tagged-template/cache-differing-expressions-new-function.js b/test/language/expressions/tagged-template/cache-differing-expressions-new-function.js
index f909e9b944..35dcf4485f 100644
--- a/test/language/expressions/tagged-template/cache-differing-expressions-new-function.js
+++ b/test/language/expressions/tagged-template/cache-differing-expressions-new-function.js
@@ -1,13 +1,12 @@
 // Copyright (C) 2014 the V8 project authors. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 /*---
-es6id: 12.2.8
+esid: sec-gettemplateobject
 description: Template caching using distinct expressions within `new Function`
-info: |
-    Previously-created template objects should be retrieved from the internal
-    template registry when their source is identical but their expressions
-    evaluate to different values and the tagged template is being evaluated in
-    an `eval` context.
+info: >
+    1. For each element _e_ of _templateRegistry_, do
+      1. If _e_.[[Site]] is the same Parse Node as _templateLiteral_, then
+        1. Return _e_.[[Array]].
 ---*/
 function tag(templateObject) {
   previousObject = templateObject;
@@ -23,8 +22,8 @@ assert(firstObject !== null);
 previousObject = null;
 
 (new Function('tag', 'a', 'b', 'return tag`head${b}tail`;'))(tag, 1, 2);
-assert.sameValue(
+assert.notSameValue(
   previousObject,
   firstObject,
-  'The realm\'s template cache is referenced when tagged templates are declared within "new Function" contexts and templated values differ'
+  'The realm\'s template cache is by site, not string contents'
 );
diff --git a/test/language/expressions/tagged-template/cache-differing-expressions.js b/test/language/expressions/tagged-template/cache-differing-expressions.js
index 17689d87df..dd0b70cc40 100644
--- a/test/language/expressions/tagged-template/cache-differing-expressions.js
+++ b/test/language/expressions/tagged-template/cache-differing-expressions.js
@@ -1,12 +1,12 @@
 // Copyright (C) 2014 the V8 project authors. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 /*---
-es6id: 12.2.8
+esid: sec-gettemplateobject
 description: Template caching using distinct expressions
-info: |
-    Previously-created template objects should be retrieved from the internal
-    template registry when their source is identical but their expressions
-    evaluate to different values.
+info: >
+    1. For each element _e_ of _templateRegistry_, do
+      1. If _e_.[[Site]] is the same Parse Node as _templateLiteral_, then
+        1. Return _e_.[[Array]].
 ---*/
 function tag(templateObject) {
   previousObject = templateObject;
@@ -22,4 +22,4 @@ assert(firstObject !== null);
 previousObject = null;
 
 tag`head${b}tail`;
-assert.sameValue(previousObject, firstObject);
+assert.notSameValue(previousObject, firstObject);
diff --git a/test/language/expressions/tagged-template/cache-differing-raw-strings.js b/test/language/expressions/tagged-template/cache-differing-raw-strings.js
index 7e3cbeceff..54ee21ba48 100644
--- a/test/language/expressions/tagged-template/cache-differing-raw-strings.js
+++ b/test/language/expressions/tagged-template/cache-differing-raw-strings.js
@@ -1,11 +1,12 @@
 // Copyright (C) 2014 the V8 project authors. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 /*---
-es6id: 12.2.8
-description: Templates are cached according to their "raw" representation
-info: |
-    The internal template registry should be queried according to the "raw"
-    strings of the tagged template.
+esid: sec-gettemplateobject
+description: Templates are cached according to their site
+info: >
+    1. For each element _e_ of _templateRegistry_, do
+      1. If _e_.[[Site]] is the same Parse Node as _templateLiteral_, then
+        1. Return _e_.[[Array]].
 ---*/
 var previousObject = null;
 var firstObject = null;
diff --git a/test/language/expressions/tagged-template/cache-differing-string-count.js b/test/language/expressions/tagged-template/cache-differing-string-count.js
index 6e02a124be..bebf79b1a0 100644
--- a/test/language/expressions/tagged-template/cache-differing-string-count.js
+++ b/test/language/expressions/tagged-template/cache-differing-string-count.js
@@ -1,11 +1,12 @@
 // Copyright (C) 2014 the V8 project authors. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 /*---
-es6id: 12.2.8
-description: Templates are cached according to the number of "raw" strings
-info: |
-    The internal template registry should be queried according to the number of
-    "raw" strings in the tagged template.
+esid: sec-gettemplateobject
+description: Templates are cached according to the site
+info: >
+    1. For each element _e_ of _templateRegistry_, do
+      1. If _e_.[[Site]] is the same Parse Node as _templateLiteral_, then
+        1. Return _e_.[[Array]].
 ---*/
 var previousObject = null;
 var firstObject = null;
diff --git a/test/language/expressions/tagged-template/cache-identical-source-eval.js b/test/language/expressions/tagged-template/cache-identical-source-eval.js
index e7e3078e64..3a2a24f2c7 100644
--- a/test/language/expressions/tagged-template/cache-identical-source-eval.js
+++ b/test/language/expressions/tagged-template/cache-identical-source-eval.js
@@ -1,12 +1,12 @@
 // Copyright (C) 2014 the V8 project authors. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 /*---
-es6id: 12.2.8
-description: Template caching using identical expressions within `eval`
-info: |
-    Previously-created template objects should be retrieved from the internal
-    template registry when their source is identical and the tagged template is
-    being evaluated in an `eval` context.
+esid: sec-gettemplateobject
+description: Templates are cached by site, even using identical expressions within `eval`
+info: >
+    1. For each element _e_ of _templateRegistry_, do
+      1. If _e_.[[Site]] is the same Parse Node as _templateLiteral_, then
+        1. Return _e_.[[Array]].
 ---*/
 function tag(templateObject) {
   previousObject = templateObject;
@@ -21,4 +21,4 @@ assert(firstObject !== null);
 previousObject = null;
 
 eval('tag`head${a}tail`');
-assert.sameValue(previousObject, firstObject);
+assert.notSameValue(previousObject, firstObject);
diff --git a/test/language/expressions/tagged-template/cache-identical-source-new-function.js b/test/language/expressions/tagged-template/cache-identical-source-new-function.js
index da0393f723..01a5dd57ff 100644
--- a/test/language/expressions/tagged-template/cache-identical-source-new-function.js
+++ b/test/language/expressions/tagged-template/cache-identical-source-new-function.js
@@ -1,12 +1,12 @@
 // Copyright (C) 2014 the V8 project authors. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 /*---
-es6id: 12.2.8
-description: Template caching using identical expressions within `new Function`
-info: |
-    Previously-created template objects should be retrieved from the internal
-    template registry when their source is identical and the tagged template is
-    being evaluated in a `new Function` context.
+esid: sec-gettemplateobject
+description: Template caching is by site, using identical expressions within `new Function`
+info: >
+    1. For each element _e_ of _templateRegistry_, do
+      1. If _e_.[[Site]] is the same Parse Node as _templateLiteral_, then
+        1. Return _e_.[[Array]].
 ---*/
 function tag(templateObject) {
   previousObject = templateObject;
@@ -21,4 +21,4 @@ assert(firstObject !== null);
 previousObject = null;
 
 (new Function('tag', 'a', 'b', 'return tag`head${b}tail`;'))(tag, 1, 2);
-assert.sameValue(previousObject, firstObject);
+assert.notSameValue(previousObject, firstObject);
diff --git a/test/language/expressions/tagged-template/cache-identical-source.js b/test/language/expressions/tagged-template/cache-identical-source.js
index c6a5644a06..436aea6bde 100644
--- a/test/language/expressions/tagged-template/cache-identical-source.js
+++ b/test/language/expressions/tagged-template/cache-identical-source.js
@@ -1,11 +1,12 @@
 // Copyright (C) 2014 the V8 project authors. All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 /*---
-es6id: 12.2.8
-description: Template caching using identical expressions
-info: |
-    Previously-created template objects should be retrieved from the internal
-    template registry when their source is identical.
+esid: sec-gettemplateobject
+description: Templates are cached by site, even when using identical expressions
+info: >
+    1. For each element _e_ of _templateRegistry_, do
+      1. If _e_.[[Site]] is the same Parse Node as _templateLiteral_, then
+        1. Return _e_.[[Array]].
 ---*/
 function tag(templateObject) {
   previousObject = templateObject;
@@ -20,8 +21,8 @@ assert(firstObject !== null);
 previousObject = null;
 
 tag`head${a}tail`;
-assert.sameValue(
+assert.notSameValue(
   previousObject,
   firstObject,
-  'The realm\'s template cache is used when tagged templates are executed in the source code directly'
+  'The realm\'s template cache is by site, not string contents'
 );
diff --git a/test/language/expressions/tagged-template/cache-realm.js b/test/language/expressions/tagged-template/cache-realm.js
index 039d9ba171..2d185391c1 100644
--- a/test/language/expressions/tagged-template/cache-realm.js
+++ b/test/language/expressions/tagged-template/cache-realm.js
@@ -25,8 +25,7 @@ info: |
      2. Let realm be the current Realm Record.
      3. Let templateRegistry be realm.[[TemplateMap]].
      4. For each element e of templateRegistry, do
-        a, If e.[[Strings]] and rawStrings contain the same values in the same
-           order, then
+        a. If _e_.[[Site]] is the same Parse Node as _templateLiteral_, then
            i. Return e.[[Array]].
 features: [cross-realm]
 ---*/
diff --git a/test/language/expressions/tagged-template/cache-same-site-top-level.js b/test/language/expressions/tagged-template/cache-same-site-top-level.js
new file mode 100644
index 0000000000..6968f3f3c3
--- /dev/null
+++ b/test/language/expressions/tagged-template/cache-same-site-top-level.js
@@ -0,0 +1,31 @@
+// Copyright (C) 2017 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-gettemplateobject
+description: Templates are cached by source location inside a function
+info: >
+    1. For each element _e_ of _templateRegistry_, do
+      1. If _e_.[[Site]] is the same Parse Node as _templateLiteral_, then
+        1. Return _e_.[[Array]].
+---*/
+
+let templates = [];
+
+function tag(templateObject) {
+  templates.push(templateObject);
+}
+
+let a = 1;
+for (let i = 0; i < 2; i++) {
+  tag`head${a}tail`;
+}
+
+assert.sameValue(templates.length, 2);
+
+assert.sameValue(
+  templates[0],
+  templates[1],
+  'The realm\'s template cache is for source code locations in a top-level script'
+);
+
+
diff --git a/test/language/expressions/tagged-template/cache-same-site.js b/test/language/expressions/tagged-template/cache-same-site.js
new file mode 100644
index 0000000000..ab37d62502
--- /dev/null
+++ b/test/language/expressions/tagged-template/cache-same-site.js
@@ -0,0 +1,36 @@
+// Copyright (C) 2017 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-gettemplateobject
+description: Templates are cached by source location inside a function
+info: >
+    1. For each element _e_ of _templateRegistry_, do
+      1. If _e_.[[Site]] is the same Parse Node as _templateLiteral_, then
+        1. Return _e_.[[Array]].
+---*/
+function tag(templateObject) {
+  previousObject = templateObject;
+}
+
+var a = 1;
+var firstObject = null;
+var previousObject = null;
+
+function runTemplate() {
+  tag`head${a}tail`;
+}
+
+runTemplate();
+firstObject = previousObject;
+
+assert(firstObject !== null);
+previousObject = null;
+
+runTemplate();
+
+assert.sameValue(
+  previousObject,
+  firstObject,
+  'The realm\'s template cache is for source code locations in a function'
+);
+
-- 
GitLab