//
+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);
// 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);
}
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);
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);
+ }
+})();