Commit 28148854 authored by jgruber's avatar jgruber Committed by Commit bot

[string] Fix null handling in MaybeCallFunctionAtSymbol

The spec requires that a null @@split / @@replace symbol is treated exactly the
same as if it were undefined, i.e. execution should move on to the default
implementation instead of throwing a TypeError.

BUG=v8:6313

Review-Url: https://codereview.chromium.org/2845153002
Cr-Commit-Position: refs/heads/master@{#44959}
parent 53d31d06
......@@ -1059,12 +1059,18 @@ void StringBuiltinsAssembler::MaybeCallFunctionAtSymbol(
GotoIf(IsNullOrUndefined(object), &out);
// Fall back to a slow lookup of {object[symbol]}.
//
// The spec uses GetMethod({object}, {symbol}), which has a few quirks:
// * null values are turned into undefined, and
// * an exception is thrown if the value is not undefined, null, or callable.
// We handle the former by jumping to {out} for null values as well, while
// the latter is already handled by the Call({maybe_func}) operation.
Node* const maybe_func = GetProperty(context, object, symbol);
GotoIf(IsUndefined(maybe_func), &out);
GotoIf(IsNull(maybe_func), &out);
// Attempt to call the function.
Node* const result = generic_call(maybe_func);
Return(result);
......
......@@ -3,7 +3,8 @@
// found in the LICENSE file.
var pattern = {
[Symbol.replace]: (string, newValue) => string + newValue
[Symbol.replace]: (string, newValue) => string + newValue,
toString: () => "c"
};
// Check object coercible fails.
assertThrows(() => String.prototype.replace.call(null, pattern, "x"),
......@@ -13,5 +14,8 @@ assertEquals("abcdex", "abcde".replace(pattern, "x"));
// Non-callable override.
pattern[Symbol.replace] = "dumdidum";
assertThrows(() => "abcde".replace(pattern, "x"), TypeError);
// Null override.
pattern[Symbol.replace] = null;
assertEquals("abXde", "abcde".replace(pattern, "X"));
assertEquals("[Symbol.replace]", RegExp.prototype[Symbol.replace].name);
......@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
var pattern = {};
var pattern = {toString: () => ""};
var limit = { value: 3 };
pattern[Symbol.split] = function(string, limit) {
return string.length * limit.value;
......@@ -15,5 +15,8 @@ assertEquals(15, "abcde".split(pattern, limit));
// Non-callable override.
pattern[Symbol.split] = "dumdidum";
assertThrows(() => "abcde".split(pattern, limit), TypeError);
// Null override.
pattern[Symbol.split] = null;
assertEquals(["a", "b", "c", "d", "e"], "abcde".split(pattern));
assertEquals("[Symbol.split]", RegExp.prototype[Symbol.split].name);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment