Commit 02c4e8bf authored by lrn@chromium.org's avatar lrn@chromium.org

Make RegExp objects not callable.

Review URL: http://codereview.chromium.org/6930006

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8068 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 01395613
...@@ -210,23 +210,6 @@ Handle<Object> Execution::GetFunctionDelegate(Handle<Object> object) { ...@@ -210,23 +210,6 @@ Handle<Object> Execution::GetFunctionDelegate(Handle<Object> object) {
// If you return a function from here, it will be called when an // If you return a function from here, it will be called when an
// attempt is made to call the given object as a function. // attempt is made to call the given object as a function.
// Regular expressions can be called as functions in both Firefox
// and Safari so we allow it too.
if (object->IsJSRegExp()) {
Handle<String> exec = factory->exec_symbol();
// TODO(lrn): Bug 617. We should use the default function here, not the
// one on the RegExp object.
Object* exec_function;
{ MaybeObject* maybe_exec_function = object->GetProperty(*exec);
// This can lose an exception, but the alternative is to put a failure
// object in a handle, which is not GC safe.
if (!maybe_exec_function->ToObject(&exec_function)) {
return factory->undefined_value();
}
}
return Handle<Object>(exec_function);
}
// Objects created through the API can have an instance-call handler // Objects created through the API can have an instance-call handler
// that should be used when calling the object as a function. // that should be used when calling the object as a function.
if (object->IsHeapObject() && if (object->IsHeapObject() &&
......
...@@ -4281,17 +4281,13 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label, ...@@ -4281,17 +4281,13 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
} else if (type_name->Equals(heap()->function_symbol())) { } else if (type_name->Equals(heap()->function_symbol())) {
__ JumpIfSmi(input, false_label); __ JumpIfSmi(input, false_label);
__ CmpObjectType(input, JS_FUNCTION_TYPE, input); __ CmpObjectType(input, FIRST_FUNCTION_CLASS_TYPE, input);
__ j(equal, true_label); final_branch_condition = above_equal;
// Regular expressions => 'function' (they are callable).
__ CmpInstanceType(input, JS_REGEXP_TYPE);
final_branch_condition = equal;
} else if (type_name->Equals(heap()->object_symbol())) { } else if (type_name->Equals(heap()->object_symbol())) {
__ JumpIfSmi(input, false_label); __ JumpIfSmi(input, false_label);
__ cmp(input, factory()->null_value()); __ cmp(input, factory()->null_value());
__ j(equal, true_label); __ j(equal, true_label);
// Regular expressions => 'function', not 'object'.
__ CmpObjectType(input, FIRST_JS_OBJECT_TYPE, input); __ CmpObjectType(input, FIRST_JS_OBJECT_TYPE, input);
__ j(below, false_label); __ j(below, false_label);
__ CmpInstanceType(input, FIRST_FUNCTION_CLASS_TYPE); __ CmpInstanceType(input, FIRST_FUNCTION_CLASS_TYPE);
......
...@@ -562,9 +562,9 @@ enum InstanceType { ...@@ -562,9 +562,9 @@ enum InstanceType {
JS_GLOBAL_PROXY_TYPE, JS_GLOBAL_PROXY_TYPE,
JS_ARRAY_TYPE, JS_ARRAY_TYPE,
JS_REGEXP_TYPE, // LAST_JS_OBJECT_TYPE, FIRST_FUNCTION_CLASS_TYPE JS_REGEXP_TYPE, // LAST_JS_OBJECT_TYPE
JS_FUNCTION_TYPE, JS_FUNCTION_TYPE, // FIRST_FUNCTION_CLASS_TYPE
// Pseudo-types // Pseudo-types
FIRST_TYPE = 0x0, FIRST_TYPE = 0x0,
...@@ -583,7 +583,7 @@ enum InstanceType { ...@@ -583,7 +583,7 @@ enum InstanceType {
LAST_JS_OBJECT_TYPE = JS_REGEXP_TYPE, LAST_JS_OBJECT_TYPE = JS_REGEXP_TYPE,
// RegExp objects have [[Class]] "function" because they are callable. // RegExp objects have [[Class]] "function" because they are callable.
// All types from this type and above are objects with [[Class]] "function". // All types from this type and above are objects with [[Class]] "function".
FIRST_FUNCTION_CLASS_TYPE = JS_REGEXP_TYPE FIRST_FUNCTION_CLASS_TYPE = JS_FUNCTION_TYPE
}; };
static const int kExternalArrayTypeCount = LAST_EXTERNAL_ARRAY_TYPE - static const int kExternalArrayTypeCount = LAST_EXTERNAL_ARRAY_TYPE -
......
...@@ -4637,7 +4637,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_Typeof) { ...@@ -4637,7 +4637,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_Typeof) {
} }
ASSERT(heap_obj->IsUndefined()); ASSERT(heap_obj->IsUndefined());
return isolate->heap()->undefined_symbol(); return isolate->heap()->undefined_symbol();
case JS_FUNCTION_TYPE: case JS_REGEXP_TYPE: case JS_FUNCTION_TYPE:
return isolate->heap()->function_symbol(); return isolate->heap()->function_symbol();
default: default:
// For any kind of object not handled above, the spec rule for // For any kind of object not handled above, the spec rule for
......
...@@ -67,7 +67,7 @@ var d4 = {toJSON: Date.prototype.toJSON, ...@@ -67,7 +67,7 @@ var d4 = {toJSON: Date.prototype.toJSON,
valueOf: "not callable", valueOf: "not callable",
toString: "not callable either", toString: "not callable either",
toISOString: function() { return 42; }}; toISOString: function() { return 42; }};
assertThrows("d4.toJSON()", TypeError); // ToPrimitive throws. assertThrows("d4.toJSON()", TypeError); // ToPrimitive throws.
var d5 = {toJSON: Date.prototype.toJSON, var d5 = {toJSON: Date.prototype.toJSON,
valueOf: "not callable", valueOf: "not callable",
...@@ -196,9 +196,6 @@ TestInvalid('"Unterminated string'); ...@@ -196,9 +196,6 @@ TestInvalid('"Unterminated string');
TestInvalid('"Unterminated string\\"'); TestInvalid('"Unterminated string\\"');
TestInvalid('"Unterminated string\\\\\\"'); TestInvalid('"Unterminated string\\\\\\"');
// JavaScript RegExp literals not valid in JSON.
TestInvalid('/true/');
// Test bad JSON that would be good JavaScript (ES5). // Test bad JSON that would be good JavaScript (ES5).
TestInvalid("{true:42}"); TestInvalid("{true:42}");
TestInvalid("{false:42}"); TestInvalid("{false:42}");
...@@ -382,7 +379,7 @@ var reJSON = /Is callable/; ...@@ -382,7 +379,7 @@ var reJSON = /Is callable/;
reJSON.toJSON = function() { return "has toJSON"; }; reJSON.toJSON = function() { return "has toJSON"; };
assertEquals( assertEquals(
'[37,null,1,"foo","37","true",null,"has toJSON",null,"has toJSON"]', '[37,null,1,"foo","37","true",null,"has toJSON",{},"has toJSON"]',
JSON.stringify([num37, numFoo, numTrue, JSON.stringify([num37, numFoo, numTrue,
strFoo, str37, strTrue, strFoo, str37, strTrue,
func, funcJSON, re, reJSON])); func, funcJSON, re, reJSON]));
...@@ -397,6 +394,9 @@ var callCount = 0; ...@@ -397,6 +394,9 @@ var callCount = 0;
var counter = { get toJSON() { getCount++; var counter = { get toJSON() { getCount++;
return function() { callCount++; return function() { callCount++;
return 42; }; } }; return 42; }; } };
// RegExps are not callable, so they are stringified as objects.
assertEquals('{}', JSON.stringify(/regexp/));
assertEquals('42', JSON.stringify(counter)); assertEquals('42', JSON.stringify(counter));
assertEquals(1, getCount); assertEquals(1, getCount);
assertEquals(1, callCount); assertEquals(1, callCount);
...@@ -419,9 +419,9 @@ assertEquals('"42"', JSON.stringify(falseNum)); ...@@ -419,9 +419,9 @@ assertEquals('"42"', JSON.stringify(falseNum));
// We don't currently allow plain properties called __proto__ in JSON // We don't currently allow plain properties called __proto__ in JSON
// objects in JSON.parse. Instead we read them as we would JS object // objects in JSON.parse. Instead we read them as we would JS object
// literals. If we change that, this test should change with it. // literals. If we change that, this test should change with it.
// //
// Parse a non-object value as __proto__. This must not create a // Parse a non-object value as __proto__. This must not create a
// __proto__ property different from the original, and should not // __proto__ property different from the original, and should not
// change the original. // change the original.
var o = JSON.parse('{"__proto__":5}'); var o = JSON.parse('{"__proto__":5}');
assertEquals(Object.prototype, o.__proto__); // __proto__ isn't changed. assertEquals(Object.prototype, o.__proto__); // __proto__ isn't changed.
......
...@@ -25,8 +25,7 @@ ...@@ -25,8 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --call_regexp var callbacks = [ function() {return 'foo'}, "nonobject", /abc/ ];
var callbacks = [ function() { return 'foo'; }, "nonobject", /abc/ ];
assertEquals('foo', callbacks['0']()); assertEquals('foo', callbacks['0']());
assertThrows("callbacks['1']()"); assertThrows("callbacks['1']()");
assertEquals(['abc'], callbacks['2']("abcdefg")); assertThrows("callbacks['2']('abcdefg')");
// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// When 'eval' is overridden with a non-function object we should
// check whether the object is callable.
function test() {
eval = /foo/;
assertEquals(["foo"], eval("foobar"));
}
test();
...@@ -33,4 +33,4 @@ var regexp = /a(b)(c)/; ...@@ -33,4 +33,4 @@ var regexp = /a(b)(c)/;
var subject = "xyzabcde"; var subject = "xyzabcde";
var expected = 'abc,b,c'; var expected = 'abc,b,c';
assertEquals(expected, String(regexp.exec(subject))); assertEquals(expected, String(regexp.exec(subject)));
assertEquals(expected, String(regexp(subject))); assertThrows(function(){ regexp(subject); });
...@@ -29,21 +29,36 @@ ...@@ -29,21 +29,36 @@
// not mess up the stack. // not mess up the stack.
// http://code.google.com/p/v8/issues/detail?id=603 // http://code.google.com/p/v8/issues/detail?id=603
function test0() { var re = /b../;
var re = /b../; assertThrows(function() {
return re('abcdefghijklm') + 'z'; return re('abcdefghijklm') + 'z';
} });
assertEquals('bcdz', test0());
var re1 = /c../; var re1 = /c../;
re1.call = Function.prototype.call; re1.call = Function.prototype.call;
var test1 = re1.call(null, 'abcdefghijklm') + 'z'; assertThrows(function() {
assertEquals('cdez', test1); re1.call(null, 'abcdefghijklm') + 'z';
});
var re2 = /d../; var re2 = /d../;
var test2 = Function.prototype.call.call(re2, null, 'abcdefghijklm') + 'z'; assertThrows(function() {
assertEquals('defz', test2); Function.prototype.call.call(re2, null, 'abcdefghijklm') + 'z';
});
var re3 = /e../; var re3 = /e../;
var test3 = Function.prototype.call.apply(re3, [null, 'abcdefghijklm']) + 'z'; assertThrows(function() {
assertEquals('efgz', test3); Function.prototype.call.apply(
re3, [null, 'abcdefghijklm']) + 'z';
});
var re4 = /f../;
assertThrows(function() {
Function.prototype.apply.call(
re4, null, ['abcdefghijklm']) + 'z';
});
var re5 = /g../;
assertThrows(function() {
Function.prototype.apply.apply(
re4, [null, ['abcdefghijklm']]) + 'z';
});
...@@ -33,4 +33,4 @@ function replacer(key, value) { ...@@ -33,4 +33,4 @@ function replacer(key, value) {
return value === 42 ? new Boolean(false) : value; return value === 42 ? new Boolean(false) : value;
} }
assertEquals(JSON.stringify([42], replacer), "[false]"); assertEquals("[false]", JSON.stringify([42], replacer));
...@@ -29,10 +29,10 @@ ...@@ -29,10 +29,10 @@
// the context of string equality comparisons. // the context of string equality comparisons.
var r = new RegExp; var r = new RegExp;
assertEquals('function', typeof r); assertEquals('object', typeof r);
assertTrue(typeof r == 'function'); assertTrue(typeof r == 'object');
assertFalse(typeof r == 'function');
function test(x, y) { return x == y; } function test(x, y) { return x == y; }
assertFalse(test('object', typeof r)); assertTrue(test('object', typeof r));
assertFalse(typeof r == 'object');
...@@ -432,6 +432,14 @@ js1_2/regexp/RegExp_lastIndex: FAIL_OK ...@@ -432,6 +432,14 @@ js1_2/regexp/RegExp_lastIndex: FAIL_OK
js1_2/regexp/string_split: FAIL_OK js1_2/regexp/string_split: FAIL_OK
# RegExps are not callable.
js1_2/regexp/simple_form: FAIL_OK
js1_2/regexp/regress-6359: FAIL_OK
js1_2/regexp/regress-9141: FAIL_OK
js1_5/Regress/regress-224956: FAIL_OK
js1_5/Regress/regress-325925: FAIL_OK
ecma_2/RegExp/regress-001: FAIL_OK
# We do not check for bad surrogate pairs when quoting strings. # We do not check for bad surrogate pairs when quoting strings.
js1_5/Regress/regress-315974: FAIL_OK js1_5/Regress/regress-315974: FAIL_OK
......
...@@ -50,10 +50,6 @@ S15.8.2.13_A23: PASS || FAIL_OK ...@@ -50,10 +50,6 @@ S15.8.2.13_A23: PASS || FAIL_OK
S15.10.6.2_A1_T16: FAIL_OK S15.10.6.2_A1_T16: FAIL_OK
S15.10.6.3_A1_T16: FAIL_OK S15.10.6.3_A1_T16: FAIL_OK
# We allow regexps to be called as functions for compatibility reasons.
S15.10.7_A1_T1: FAIL_OK
S15.10.7_A1_T2: FAIL_OK
# We are silent in some regexp cases where the spec wants us to give # We are silent in some regexp cases where the spec wants us to give
# errors, for compatibility. # errors, for compatibility.
S15.10.2.11_A1_T2: FAIL S15.10.2.11_A1_T2: FAIL
...@@ -244,12 +240,6 @@ S15.9.5.7_A1_T2: FAIL_OK ...@@ -244,12 +240,6 @@ S15.9.5.7_A1_T2: FAIL_OK
S15.9.5.8_A1_T2: FAIL_OK S15.9.5.8_A1_T2: FAIL_OK
S15.9.5.9_A1_T2: FAIL_OK S15.9.5.9_A1_T2: FAIL_OK
# Regexps have type "function", not "object".
S11.4.3_A3.6: FAIL_OK
S15.10.7_A3_T2: FAIL_OK
S15.10.7_A3_T1: FAIL_OK
[ $arch == arm ] [ $arch == arm ]
# BUG(3251225): Tests that timeout with --nocrankshaft. # BUG(3251225): Tests that timeout with --nocrankshaft.
......
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