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) {
// If you return a function from here, it will be called when an
// 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
// that should be used when calling the object as a function.
if (object->IsHeapObject() &&
......
......@@ -4281,17 +4281,13 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
} else if (type_name->Equals(heap()->function_symbol())) {
__ JumpIfSmi(input, false_label);
__ CmpObjectType(input, JS_FUNCTION_TYPE, input);
__ j(equal, true_label);
// Regular expressions => 'function' (they are callable).
__ CmpInstanceType(input, JS_REGEXP_TYPE);
final_branch_condition = equal;
__ CmpObjectType(input, FIRST_FUNCTION_CLASS_TYPE, input);
final_branch_condition = above_equal;
} else if (type_name->Equals(heap()->object_symbol())) {
__ JumpIfSmi(input, false_label);
__ cmp(input, factory()->null_value());
__ j(equal, true_label);
// Regular expressions => 'function', not 'object'.
__ CmpObjectType(input, FIRST_JS_OBJECT_TYPE, input);
__ j(below, false_label);
__ CmpInstanceType(input, FIRST_FUNCTION_CLASS_TYPE);
......
......@@ -562,9 +562,9 @@ enum InstanceType {
JS_GLOBAL_PROXY_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
FIRST_TYPE = 0x0,
......@@ -583,7 +583,7 @@ enum InstanceType {
LAST_JS_OBJECT_TYPE = JS_REGEXP_TYPE,
// RegExp objects have [[Class]] "function" because they are callable.
// 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 -
......
......@@ -4637,7 +4637,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_Typeof) {
}
ASSERT(heap_obj->IsUndefined());
return isolate->heap()->undefined_symbol();
case JS_FUNCTION_TYPE: case JS_REGEXP_TYPE:
case JS_FUNCTION_TYPE:
return isolate->heap()->function_symbol();
default:
// For any kind of object not handled above, the spec rule for
......
......@@ -67,7 +67,7 @@ var d4 = {toJSON: Date.prototype.toJSON,
valueOf: "not callable",
toString: "not callable either",
toISOString: function() { return 42; }};
assertThrows("d4.toJSON()", TypeError); // ToPrimitive throws.
assertThrows("d4.toJSON()", TypeError); // ToPrimitive throws.
var d5 = {toJSON: Date.prototype.toJSON,
valueOf: "not callable",
......@@ -196,9 +196,6 @@ 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).
TestInvalid("{true:42}");
TestInvalid("{false:42}");
......@@ -382,7 +379,7 @@ var reJSON = /Is callable/;
reJSON.toJSON = function() { return "has toJSON"; };
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,
strFoo, str37, strTrue,
func, funcJSON, re, reJSON]));
......@@ -397,6 +394,9 @@ var callCount = 0;
var counter = { get toJSON() { getCount++;
return function() { callCount++;
return 42; }; } };
// RegExps are not callable, so they are stringified as objects.
assertEquals('{}', JSON.stringify(/regexp/));
assertEquals('42', JSON.stringify(counter));
assertEquals(1, getCount);
assertEquals(1, callCount);
......@@ -419,9 +419,9 @@ assertEquals('"42"', JSON.stringify(falseNum));
// We don't currently allow plain properties called __proto__ in JSON
// objects in JSON.parse. Instead we read them as we would JS object
// literals. If we change that, this test should change with it.
//
// Parse a non-object value as __proto__. This must not create a
// __proto__ property different from the original, and should not
//
// Parse a non-object value as __proto__. This must not create a
// __proto__ property different from the original, and should not
// change the original.
var o = JSON.parse('{"__proto__":5}');
assertEquals(Object.prototype, o.__proto__); // __proto__ isn't changed.
......
......@@ -25,8 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// 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']());
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)/;
var subject = "xyzabcde";
var expected = 'abc,b,c';
assertEquals(expected, String(regexp.exec(subject)));
assertEquals(expected, String(regexp(subject)));
assertThrows(function(){ regexp(subject); });
......@@ -29,21 +29,36 @@
// not mess up the stack.
// http://code.google.com/p/v8/issues/detail?id=603
function test0() {
var re = /b../;
var re = /b../;
assertThrows(function() {
return re('abcdefghijklm') + 'z';
}
assertEquals('bcdz', test0());
});
var re1 = /c../;
re1.call = Function.prototype.call;
var test1 = re1.call(null, 'abcdefghijklm') + 'z';
assertEquals('cdez', test1);
assertThrows(function() {
re1.call(null, 'abcdefghijklm') + 'z';
});
var re2 = /d../;
var test2 = Function.prototype.call.call(re2, null, 'abcdefghijklm') + 'z';
assertEquals('defz', test2);
assertThrows(function() {
Function.prototype.call.call(re2, null, 'abcdefghijklm') + 'z';
});
var re3 = /e../;
var test3 = Function.prototype.call.apply(re3, [null, 'abcdefghijklm']) + 'z';
assertEquals('efgz', test3);
assertThrows(function() {
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) {
return value === 42 ? new Boolean(false) : value;
}
assertEquals(JSON.stringify([42], replacer), "[false]");
assertEquals("[false]", JSON.stringify([42], replacer));
......@@ -29,10 +29,10 @@
// the context of string equality comparisons.
var r = new RegExp;
assertEquals('function', typeof r);
assertTrue(typeof r == 'function');
assertEquals('object', typeof r);
assertTrue(typeof r == 'object');
assertFalse(typeof r == 'function');
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
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.
js1_5/Regress/regress-315974: 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.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
# errors, for compatibility.
S15.10.2.11_A1_T2: FAIL
......@@ -244,12 +240,6 @@ S15.9.5.7_A1_T2: FAIL_OK
S15.9.5.8_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 ]
# 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