Implement poison pill for non-strict mode function.caller

when caller is strict mode function.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@7313 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
mmaly@chromium.org 2011-03-23 03:45:48 +00:00
parent 41c7632a41
commit 7346fbba81
3 changed files with 67 additions and 2 deletions

View File

@ -827,6 +827,19 @@ const AccessorDescriptor Accessors::FunctionArguments = {
//
static MaybeObject* CheckNonStrictCallerOrThrow(
Isolate* isolate,
JSFunction* caller) {
DisableAssertNoAllocation enable_allocation;
if (caller->shared()->strict_mode()) {
return isolate->Throw(
*isolate->factory()->NewTypeError("strict_caller",
HandleVector<Object>(NULL, 0)));
}
return caller;
}
MaybeObject* Accessors::FunctionGetCaller(Object* object, void*) {
Isolate* isolate = Isolate::Current();
HandleScope scope(isolate);
@ -847,14 +860,14 @@ MaybeObject* Accessors::FunctionGetCaller(Object* object, void*) {
// frames, e.g. frames for scripts not functions.
if (i > 0) {
ASSERT(!functions[i - 1]->shared()->is_toplevel());
return functions[i - 1];
return CheckNonStrictCallerOrThrow(isolate, functions[i - 1]);
} else {
for (it.Advance(); !it.done(); it.Advance()) {
frame = it.frame();
functions.Rewind(0);
frame->GetFunctions(&functions);
if (!functions.last()->shared()->is_toplevel()) {
return functions.last();
return CheckNonStrictCallerOrThrow(isolate, functions.last());
}
ASSERT(functions.length() == 1);
}

View File

@ -234,6 +234,7 @@ function FormatMessage(message) {
strict_arguments_caller: ["Cannot access property 'caller' of strict mode arguments"],
strict_function_caller: ["Cannot access property 'caller' of a strict mode function"],
strict_function_arguments: ["Cannot access property 'arguments' of a strict mode function"],
strict_caller: ["Illegal access to a strict mode caller function."],
};
}
var message_type = %MessageGetType(message);

View File

@ -1081,3 +1081,54 @@ function CheckPillDescriptor(func, name) {
CheckPillDescriptor(args, "caller");
CheckPillDescriptor(args, "callee");
})();
(function TestNonStrictFunctionCallerPillSimple() {
function return_my_caller() {
return return_my_caller.caller;
}
function strict() {
"use strict";
return_my_caller();
}
assertThrows(strict, TypeError);
function non_strict() {
return return_my_caller();
}
assertSame(non_strict(), non_strict);
})();
(function TestNonStrictFunctionCallerPill() {
function strict(n) {
"use strict";
non_strict(n);
}
function recurse(n, then) {
if (n > 0) {
recurse(n - 1);
} else {
return then();
}
}
function non_strict(n) {
recurse(n, function() { non_strict.caller; });
}
function test(n) {
try {
recurse(n, function() { strict(n); });
} catch(e) {
return e instanceof TypeError;
}
return false;
}
for (var i = 0; i < 10; i ++) {
assertEquals(test(i), true);
}
})();