Add tests for well-known Symbol: @@search

This commit is contained in:
Mike Pennisi 2015-08-06 14:50:09 -04:00
parent acf2d0cb11
commit 8879cde471
22 changed files with 671 additions and 0 deletions

View File

@ -0,0 +1,26 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 21.2.5.9
description: Behavior when error thrown while coercing `string` argument
info: >
[...]
3. Let S be ToString(string).
4. ReturnIfAbrupt(S).
features: [Symbol.search]
---*/
var uncoercibleObj = {
toString: function() {
throw new Test262Error();
}
};
assert.throws(Test262Error, function() {
/./[Symbol.search](uncoercibleObj);
});
assert.throws(TypeError, function() {
/./[Symbol.search](Symbol.search);
});

View File

@ -0,0 +1,20 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 21.2.5.9
description: String coercion of `string` argument
info: >
[...]
3. Let S be ToString(string).
[...]
features: [Symbol.search]
---*/
var obj = {
toString: function() {
return 'toString value';
}
};
assert.sameValue(/ring/[Symbol.search](obj), 4);

View File

@ -0,0 +1,32 @@
// Copyright (C) 2015 Mike Pennisi. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 21.2.5.9
description: Index value returned by a custom `exec` method
info: >
[...]
9. Let result be RegExpExec(rx, S).
[...]
14. Return Get(result, "index").
21.2.5.2.1 Runtime Semantics: RegExpExec ( R, S )
[...]
5. If IsCallable(exec) is true, then
a. Let result be Call(exec, R, «S»).
b. ReturnIfAbrupt(result).
c. If Type(result) is neither Object or Null, throw a TypeError
exception.
d. Return result.
features: [Symbol.search]
---*/
var fakeRe = {
exec: function() {
return { index: 86 };
}
};
assert.sameValue(RegExp.prototype[Symbol.search].call(fakeRe, 'abc'), 86);

View File

@ -0,0 +1,56 @@
// Copyright (C) 2015 Mike Pennisi. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 21.2.5.9
description: Behavior when invalid value is returned by custom `exec` method
info: >
[...]
9. Let result be RegExpExec(rx, S).
10. ReturnIfAbrupt(result).
[...]
14. Return Get(result, "index").
21.2.5.2.1 Runtime Semantics: RegExpExec ( R, S )
[...]
5. If IsCallable(exec) is true, then
a. Let result be Call(exec, R, «S»).
b. ReturnIfAbrupt(result).
c. If Type(result) is neither Object or Null, throw a TypeError
exception.
features: [Symbol, Symbol.search]
---*/
var retVal;
var fakeRe = {
exec: function() {
return retVal;
}
};
retVal = undefined;
assert.throws(TypeError, function() {
RegExp.prototype[Symbol.search].call(fakeRe, 'a');
});
retVal = 86;
assert.throws(TypeError, function() {
RegExp.prototype[Symbol.search].call(fakeRe, 'a');
});
retVal = 'string';
assert.throws(TypeError, function() {
RegExp.prototype[Symbol.search].call(fakeRe, 'a');
});
retVal = true;
assert.throws(TypeError, function() {
RegExp.prototype[Symbol.search].call(fakeRe, 'a');
});
retVal = Symbol();
assert.throws(TypeError, function() {
RegExp.prototype[Symbol.search].call(fakeRe, 'a');
});

View File

@ -0,0 +1,13 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 21.2.5.9
description: Return value when no match is found
info: >
[...]
13. If result is null, return 1.
features: [Symbol.search]
---*/
assert.sameValue(/z/[Symbol.search]('a'), -1);

View File

@ -0,0 +1,22 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 21.2.5.9
description: Behavior when error thrown while accessing `lastIndex` property
info: >
[...]
5. Let previousLastIndex be Get(rx, "lastIndex").
6. ReturnIfAbrupt(previousLastIndex).
features: [Symbol.search]
---*/
var poisonedLastIndex = {
get lastIndex() {
throw new Test262Error();
}
};
assert.throws(Test262Error, function() {
RegExp.prototype[Symbol.search].call(poisonedLastIndex);
});

View File

@ -0,0 +1,27 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 21.2.5.9
description: RegExp.prototype[Symbol.search] `length` property
info: >
ES6 section 17:
Every built-in Function object, including constructors, has a length
property whose value is an integer. Unless otherwise specified, this value
is equal to the largest number of named arguments shown in the subclause
headings for the function description, including optional parameters.
[...]
Unless otherwise specified, the length property of a built-in Function
object has the attributes { [[Writable]]: false, [[Enumerable]]: false,
[[Configurable]]: true }.
features: [Symbol.search]
includes: [propertyHelper.js]
---*/
assert.sameValue(RegExp.prototype[Symbol.search].length, 1);
verifyNotEnumerable(RegExp.prototype[Symbol.search], 'length');
verifyNotWritable(RegExp.prototype[Symbol.search], 'length');
verifyConfigurable(RegExp.prototype[Symbol.search], 'length');

View File

@ -0,0 +1,25 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 21.2.5.9
description: Behavior when error thrown while executing match
info: >
[...]
9. Let result be RegExpExec(rx, S).
10. ReturnIfAbrupt(result).
features: [Symbol.search]
---*/
var fakeRe = {
lastIndex: 86,
exec: function() {
throw new Test262Error();
}
};
assert.throws(Test262Error, function() {
RegExp.prototype[Symbol.search].call(fakeRe);
});
assert.sameValue(fakeRe.lastIndex, 0, '`lastIndex` property is not restored');

View File

@ -0,0 +1,24 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 21.2.5.9
description: RegExp.prototype[Symbol.search] `name` property
info: >
The value of the name property of this function is "[Symbol.search]".
ES6 Section 17:
[...]
Unless otherwise specified, the name property of a built-in Function
object, if it exists, has the attributes { [[Writable]]: false,
[[Enumerable]]: false, [[Configurable]]: true }.
features: [Symbol.search]
includes: [propertyHelper.js]
---*/
assert.sameValue(RegExp.prototype[Symbol.search].name, '[Symbol.search]');
verifyNotEnumerable(RegExp.prototype[Symbol.search], 'name');
verifyNotWritable(RegExp.prototype[Symbol.search], 'name');
verifyConfigurable(RegExp.prototype[Symbol.search], 'name');

View File

@ -0,0 +1,19 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 21.2.5.9
description: RegExp.prototype[Symbol.search] property descriptor
info: >
ES6 Section 17
Every other data property described in clauses 18 through 26 and in Annex
B.2 has the attributes { [[Writable]]: true, [[Enumerable]]: false,
[[Configurable]]: true } unless otherwise specified.
includes: [propertyHelper.js]
features: [Symbol.search]
---*/
verifyNotEnumerable(RegExp.prototype, Symbol.search);
verifyWritable(RegExp.prototype, Symbol.search);
verifyConfigurable(RegExp.prototype, Symbol.search);

View File

@ -0,0 +1,52 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 21.2.5.9
description: >
Behavior when error thrown while initially setting `lastIndex` property
info: >
[...]
7. Let status be Set(rx, "lastIndex", 0, true).
8. ReturnIfAbrupt(status).
features: [Symbol.search]
---*/
var callCount;
var poisonedLastIndex = {
get lastIndex() {
callCount += 1;
},
set lastIndex(_) {
throw new Test262Error();
}
};
var nonWritableLastIndex = {
get lastIndex() {
callCount += 1;
},
// This method defined to avoid false positives from unrelated TypeErrors
exec: function() {
return null;
}
};
callCount = 0;
assert.throws(Test262Error, function() {
RegExp.prototype[Symbol.search].call(poisonedLastIndex);
});
assert.sameValue(
callCount,
1,
'Property value was accessed before being set ("poisoned" lastIndex)'
);
callCount = 0;
assert.throws(TypeError, function() {
RegExp.prototype[Symbol.search].call(nonWritableLastIndex);
});
assert.sameValue(
callCount,
1,
'Property value was accessed before being set (non-writable lastIndex)'
);

View File

@ -0,0 +1,28 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 21.2.5.9
description: >
The `lastIndex` value is set to 0 immediately prior to match execution
info: >
[...]
7. Let status be Set(rx, "lastIndex", 0, true).
8. ReturnIfAbrupt(status).
9. Let result be RegExpExec(rx, S).
[...]
features: [Symbol.search]
---*/
var duringExec;
var fakeRe = {
lastIndex: 34,
exec: function() {
duringExec = fakeRe.lastIndex;
return null;
}
};
RegExp.prototype[Symbol.search].call(fakeRe);
assert.sameValue(duringExec, 0);

View File

@ -0,0 +1,49 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 21.2.5.9
description: >
Behavior when error thrown while restoring `lastIndex` property following
match execution
info: >
[...]
11. Let status be Set(rx, "lastIndex", previousLastIndex, true).
12. ReturnIfAbrupt(status).
features: [Symbol.search]
---*/
var callCount;
var poisonedLastIndex = {
get lastIndex() {},
set lastIndex(_) {
if (callCount === 1) {
throw new Test262Error();
}
},
exec: function() {
callCount += 1;
return null;
}
};
var nonWritableLastIndex = {
exec: function() {
Object.defineProperty(
nonWritableLastIndex, 'lastIndex', { writable: false }
);
callCount += 1;
return null;
}
};
callCount = 0;
assert.throws(Test262Error, function() {
RegExp.prototype[Symbol.search].call(poisonedLastIndex);
});
assert.sameValue(callCount, 1, 'Match executed ("poisoned" lastIndex)');
callCount = 0;
assert.throws(TypeError, function() {
RegExp.prototype[Symbol.search].call(nonWritableLastIndex);
});
assert.sameValue(callCount, 1, 'Match executed (non-writable lastIndex)');

View File

@ -0,0 +1,30 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 21.2.5.9
description: The `lastIndex` value is restored following match execution
info: >
[...]
11. Let status be Set(rx, "lastIndex", previousLastIndex, true).
[...]
features: [Symbol.search]
---*/
var latestValue;
var fakeRe = {
get lastIndex() {
return 86;
},
set lastIndex(_) {
latestValue = _;
},
exec: function() {
latestValue = null;
return null;
}
};
RegExp.prototype[Symbol.search].call(fakeRe);
assert.sameValue(latestValue, 86);

View File

@ -0,0 +1,27 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 21.2.5.9
description: >
Behavior when error thrown while accessing `index` property of match result
info: >
[...]
14. Return Get(result, "index").
features: [Symbol.search]
---*/
var poisonedIndex = {
get index() {
throw new Test262Error();
}
};
var fakeRe = {
exec: function() {
return poisonedIndex;
}
};
assert.throws(Test262Error, function() {
RegExp.prototype[Symbol.search].call(fakeRe);
});

View File

@ -0,0 +1,15 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 21.2.5.9
description: Return value following successful match
info: >
[...]
14. Return Get(result, "index").
features: [Symbol.search]
---*/
assert.sameValue(/a/[Symbol.search]('abc'), 0);
assert.sameValue(/b/[Symbol.search]('abc'), 1);
assert.sameValue(/c/[Symbol.search]('abc'), 2);

View File

@ -0,0 +1,39 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: The `this` value must be an object
es6id: 21.2.5.9
info: >
1. Let rx be the this value.
2. If Type(rx) is not Object, throw a TypeError exception.
features: [Symbol.search]
---*/
assert.throws(TypeError, function() {
RegExp.prototype[Symbol.search].call();
});
assert.throws(TypeError, function() {
RegExp.prototype[Symbol.search].call(undefined);
});
assert.throws(TypeError, function() {
RegExp.prototype[Symbol.search].call(null);
});
assert.throws(TypeError, function() {
RegExp.prototype[Symbol.search].call(true);
});
assert.throws(TypeError, function() {
RegExp.prototype[Symbol.search].call('string');
});
assert.throws(TypeError, function() {
RegExp.prototype[Symbol.search].call(Symbol.search);
});
assert.throws(TypeError, function() {
RegExp.prototype[Symbol.search].call(86);
});

View File

@ -0,0 +1,24 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: Behavior when error is thrown accessing @@search property
es6id: 21.1.3.15
info: >
[...]
3. If regexp is neither undefined nor null, then
a. Let searcher be GetMethod(regexp, @@search).
b. ReturnIfAbrupt(searcher).
features: [Symbol.search]
---*/
var poisonedSearch = {};
Object.defineProperty(poisonedSearch, Symbol.search, {
get: function() {
throw new Test262Error();
}
});
assert.throws(Test262Error, function() {
''.search(poisonedSearch);
});

View File

@ -0,0 +1,34 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: Invocation of @@search property of user-supplied objects
es6id: 21.1.3.15
info: >
[...]
3. If regexp is neither undefined nor null, then
a. Let searcher be GetMethod(regexp, @@search).
b. ReturnIfAbrupt(searcher).
c. If searcher is not undefined, then
i. Return Call(searcher, regexp, «O»)
features: [Symbol.search]
---*/
var regexp = {};
var returnVal = {};
var callCount = 0;
var thisVal, args;
regexp[Symbol.search] = function() {
callCount += 1;
thisVal = this;
args = arguments;
return returnVal;
};
assert.sameValue('O'.search(regexp), returnVal);
assert.sameValue(callCount, 1, 'Invokes the method exactly once');
assert.sameValue(thisVal, regexp);
assert.notSameValue(args, undefined);
assert.sameValue(args.length, 1);
assert.sameValue(args[0], 'O');

View File

@ -0,0 +1,51 @@
// Copyright (C) 2015 Mike Pennisi. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: >
Invocation of @@search property of internally-created RegExps when `this` value has an `undefined` @@search property
es6id: 21.1.3.15
info: >
[...]
3. If regexp is neither undefined nor null, then
a. Let searcher be GetMethod(regexp, @@search).
b. ReturnIfAbrupt(searcher).
c. If searcher is not undefined , then
[...]
[...]
6. Let rx be RegExpCreate(regexp, undefined) (see 21.2.3.2.3).
7. ReturnIfAbrupt(rx).
8. Return Invoke(rx, @@search, «S»).
features: [Symbol.search]
---*/
var target = new String('target');
var originalSearch = RegExp.prototype[Symbol.search];
var returnVal = {};
var result, thisVal, args;
target[Symbol.search] = undefined;
// Fail early if the method is undefined. This test's cleanup logic would
// otherwise install the value `undefined` to the `Symbol.search` property of
// the built-in prototype.
assert.notSameValue(originalSearch, undefined);
RegExp.prototype[Symbol.search] = function() {
thisVal = this;
args = arguments;
return returnVal;
};
try {
result = target.search('string source');
assert(thisVal instanceof RegExp);
assert.sameValue(thisVal.source, 'string source');
assert.sameValue(thisVal.flags, '');
assert.sameValue(args.length, 1);
assert.sameValue(args[0], 'target');
assert.sameValue(result, returnVal);
} finally {
RegExp.prototype[Symbol.search] = originalSearch;
}

View File

@ -0,0 +1,41 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: Invocation of @@search property of internally-created RegExps
es6id: 21.1.3.15
info: >
[...]
6. Let rx be RegExpCreate(regexp, undefined) (see 21.2.3.2.3).
7. ReturnIfAbrupt(rx).
8. Return Invoke(rx, @@search, «S»).
features: [Symbol.search]
---*/
var originalSearch = RegExp.prototype[Symbol.search];
var returnVal = {};
var result, thisVal, args;
// Fail early if the method is undefined. This test's cleanup logic would
// otherwise install the value `undefined` to the `Symbol.search` property of
// the built-in prototype.
assert.notSameValue(originalSearch, undefined);
RegExp.prototype[Symbol.search] = function() {
thisVal = this;
args = arguments;
return returnVal;
};
try {
result = 'target'.search('string source');
assert(thisVal instanceof RegExp);
assert.sameValue(thisVal.source, 'string source');
assert.sameValue(thisVal.flags, '');
assert.sameValue(args.length, 1);
assert.sameValue(args[0], 'target');
assert.sameValue(result, returnVal);
} finally {
RegExp.prototype[Symbol.search] = originalSearch;
}

View File

@ -0,0 +1,17 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 19.4.2.9
description: >
`Symbol.search` property descriptor
info: >
This property has the attributes { [[Writable]]: false, [[Enumerable]]:
false, [[Configurable]]: false }.
includes: [propertyHelper.js]
features: [Symbol.search]
---*/
assert.sameValue(typeof Symbol.search, 'symbol');
verifyNotEnumerable(Symbol, 'search');
verifyNotWritable(Symbol, 'search');
verifyNotConfigurable(Symbol, 'search');