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
This commit is contained in:
Daniel Ehrenberg 2018-02-05 20:40:19 +01:00 committed by Leo Balter
parent 31dfa8761a
commit d5fc8b25af
12 changed files with 159 additions and 54 deletions

View File

@ -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'
);

View File

@ -1,13 +1,12 @@
// Copyright (C) 2014 the V8 project authors. All rights reserved. // Copyright (C) 2014 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file. // 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` description: Template caching using distinct expressions within `eval`
info: | info: >
Previously-created template objects should be retrieved from the internal 1. For each element _e_ of _templateRegistry_, do
template registry when their source is identical but their expressions 1. If _e_.[[Site]] is the same Parse Node as _templateLiteral_, then
evaluate to different values and the tagged template is being evaluated in 1. Return _e_.[[Array]].
an `eval` context.
---*/ ---*/
function tag(templateObject) { function tag(templateObject) {
previousObject = templateObject; previousObject = templateObject;
@ -23,4 +22,4 @@ assert(firstObject !== null);
previousObject = null; previousObject = null;
eval('tag`head${b}tail`'); eval('tag`head${b}tail`');
assert.sameValue(previousObject, firstObject); assert.notSameValue(previousObject, firstObject);

View File

@ -1,13 +1,12 @@
// Copyright (C) 2014 the V8 project authors. All rights reserved. // Copyright (C) 2014 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file. // 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` description: Template caching using distinct expressions within `new Function`
info: | info: >
Previously-created template objects should be retrieved from the internal 1. For each element _e_ of _templateRegistry_, do
template registry when their source is identical but their expressions 1. If _e_.[[Site]] is the same Parse Node as _templateLiteral_, then
evaluate to different values and the tagged template is being evaluated in 1. Return _e_.[[Array]].
an `eval` context.
---*/ ---*/
function tag(templateObject) { function tag(templateObject) {
previousObject = templateObject; previousObject = templateObject;
@ -23,8 +22,8 @@ assert(firstObject !== null);
previousObject = null; previousObject = null;
(new Function('tag', 'a', 'b', 'return tag`head${b}tail`;'))(tag, 1, 2); (new Function('tag', 'a', 'b', 'return tag`head${b}tail`;'))(tag, 1, 2);
assert.sameValue( assert.notSameValue(
previousObject, previousObject,
firstObject, 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'
); );

View File

@ -1,12 +1,12 @@
// Copyright (C) 2014 the V8 project authors. All rights reserved. // Copyright (C) 2014 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file. // 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 description: Template caching using distinct expressions
info: | info: >
Previously-created template objects should be retrieved from the internal 1. For each element _e_ of _templateRegistry_, do
template registry when their source is identical but their expressions 1. If _e_.[[Site]] is the same Parse Node as _templateLiteral_, then
evaluate to different values. 1. Return _e_.[[Array]].
---*/ ---*/
function tag(templateObject) { function tag(templateObject) {
previousObject = templateObject; previousObject = templateObject;
@ -22,4 +22,4 @@ assert(firstObject !== null);
previousObject = null; previousObject = null;
tag`head${b}tail`; tag`head${b}tail`;
assert.sameValue(previousObject, firstObject); assert.notSameValue(previousObject, firstObject);

View File

@ -1,11 +1,12 @@
// Copyright (C) 2014 the V8 project authors. All rights reserved. // Copyright (C) 2014 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file. // This code is governed by the BSD license found in the LICENSE file.
/*--- /*---
es6id: 12.2.8 esid: sec-gettemplateobject
description: Templates are cached according to their "raw" representation description: Templates are cached according to their site
info: | info: >
The internal template registry should be queried according to the "raw" 1. For each element _e_ of _templateRegistry_, do
strings of the tagged template. 1. If _e_.[[Site]] is the same Parse Node as _templateLiteral_, then
1. Return _e_.[[Array]].
---*/ ---*/
var previousObject = null; var previousObject = null;
var firstObject = null; var firstObject = null;

View File

@ -1,11 +1,12 @@
// Copyright (C) 2014 the V8 project authors. All rights reserved. // Copyright (C) 2014 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file. // This code is governed by the BSD license found in the LICENSE file.
/*--- /*---
es6id: 12.2.8 esid: sec-gettemplateobject
description: Templates are cached according to the number of "raw" strings description: Templates are cached according to the site
info: | info: >
The internal template registry should be queried according to the number of 1. For each element _e_ of _templateRegistry_, do
"raw" strings in the tagged template. 1. If _e_.[[Site]] is the same Parse Node as _templateLiteral_, then
1. Return _e_.[[Array]].
---*/ ---*/
var previousObject = null; var previousObject = null;
var firstObject = null; var firstObject = null;

View File

@ -1,12 +1,12 @@
// Copyright (C) 2014 the V8 project authors. All rights reserved. // Copyright (C) 2014 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file. // This code is governed by the BSD license found in the LICENSE file.
/*--- /*---
es6id: 12.2.8 esid: sec-gettemplateobject
description: Template caching using identical expressions within `eval` description: Templates are cached by site, even using identical expressions within `eval`
info: | info: >
Previously-created template objects should be retrieved from the internal 1. For each element _e_ of _templateRegistry_, do
template registry when their source is identical and the tagged template is 1. If _e_.[[Site]] is the same Parse Node as _templateLiteral_, then
being evaluated in an `eval` context. 1. Return _e_.[[Array]].
---*/ ---*/
function tag(templateObject) { function tag(templateObject) {
previousObject = templateObject; previousObject = templateObject;
@ -21,4 +21,4 @@ assert(firstObject !== null);
previousObject = null; previousObject = null;
eval('tag`head${a}tail`'); eval('tag`head${a}tail`');
assert.sameValue(previousObject, firstObject); assert.notSameValue(previousObject, firstObject);

View File

@ -1,12 +1,12 @@
// Copyright (C) 2014 the V8 project authors. All rights reserved. // Copyright (C) 2014 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file. // This code is governed by the BSD license found in the LICENSE file.
/*--- /*---
es6id: 12.2.8 esid: sec-gettemplateobject
description: Template caching using identical expressions within `new Function` description: Template caching is by site, using identical expressions within `new Function`
info: | info: >
Previously-created template objects should be retrieved from the internal 1. For each element _e_ of _templateRegistry_, do
template registry when their source is identical and the tagged template is 1. If _e_.[[Site]] is the same Parse Node as _templateLiteral_, then
being evaluated in a `new Function` context. 1. Return _e_.[[Array]].
---*/ ---*/
function tag(templateObject) { function tag(templateObject) {
previousObject = templateObject; previousObject = templateObject;
@ -21,4 +21,4 @@ assert(firstObject !== null);
previousObject = null; previousObject = null;
(new Function('tag', 'a', 'b', 'return tag`head${b}tail`;'))(tag, 1, 2); (new Function('tag', 'a', 'b', 'return tag`head${b}tail`;'))(tag, 1, 2);
assert.sameValue(previousObject, firstObject); assert.notSameValue(previousObject, firstObject);

View File

@ -1,11 +1,12 @@
// Copyright (C) 2014 the V8 project authors. All rights reserved. // Copyright (C) 2014 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file. // This code is governed by the BSD license found in the LICENSE file.
/*--- /*---
es6id: 12.2.8 esid: sec-gettemplateobject
description: Template caching using identical expressions description: Templates are cached by site, even when using identical expressions
info: | info: >
Previously-created template objects should be retrieved from the internal 1. For each element _e_ of _templateRegistry_, do
template registry when their source is identical. 1. If _e_.[[Site]] is the same Parse Node as _templateLiteral_, then
1. Return _e_.[[Array]].
---*/ ---*/
function tag(templateObject) { function tag(templateObject) {
previousObject = templateObject; previousObject = templateObject;
@ -20,8 +21,8 @@ assert(firstObject !== null);
previousObject = null; previousObject = null;
tag`head${a}tail`; tag`head${a}tail`;
assert.sameValue( assert.notSameValue(
previousObject, previousObject,
firstObject, 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'
); );

View File

@ -25,8 +25,7 @@ info: |
2. Let realm be the current Realm Record. 2. Let realm be the current Realm Record.
3. Let templateRegistry be realm.[[TemplateMap]]. 3. Let templateRegistry be realm.[[TemplateMap]].
4. For each element e of templateRegistry, do 4. For each element e of templateRegistry, do
a, If e.[[Strings]] and rawStrings contain the same values in the same a. If _e_.[[Site]] is the same Parse Node as _templateLiteral_, then
order, then
i. Return e.[[Array]]. i. Return e.[[Array]].
features: [cross-realm] features: [cross-realm]
---*/ ---*/

View File

@ -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'
);

View File

@ -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'
);