Commit fdc7f60f authored by lrn@chromium.org's avatar lrn@chromium.org

Make functions on the built-in object non-writable.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9096 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 9defb2f2
......@@ -774,11 +774,10 @@ void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
// Call the runtime to declare the globals.
// The context is the first argument.
__ mov(r2, Operand(pairs));
__ mov(r1, Operand(Smi::FromInt(is_eval() ? 1 : 0)));
__ mov(r0, Operand(Smi::FromInt(strict_mode_flag())));
__ Push(cp, r2, r1, r0);
__ CallRuntime(Runtime::kDeclareGlobals, 4);
__ mov(r1, Operand(pairs));
__ mov(r0, Operand(Smi::FromInt(DeclareGlobalsFlags())));
__ Push(cp, r1, r0);
__ CallRuntime(Runtime::kDeclareGlobals, 3);
// Return value is ignored.
}
......
......@@ -350,7 +350,14 @@ static Handle<JSFunction> InstallFunction(Handle<JSObject> target,
prototype,
call_code,
is_ecma_native);
SetLocalPropertyNoThrow(target, symbol, function, DONT_ENUM);
PropertyAttributes attributes;
if (target->IsJSBuiltinsObject()) {
attributes =
static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
} else {
attributes = DONT_ENUM;
}
SetLocalPropertyNoThrow(target, symbol, function, attributes);
if (is_ecma_native) {
function->shared()->set_instance_class_name(*symbol);
}
......@@ -1677,7 +1684,6 @@ bool Genesis::InstallNatives() {
global_context()->set_regexp_result_map(*initial_map);
}
#ifdef DEBUG
builtins->Verify();
#endif
......
......@@ -584,6 +584,15 @@ void FullCodeGenerator::VisitDeclarations(
}
int FullCodeGenerator::DeclareGlobalsFlags() {
int flags = 0;
if (is_eval()) flags |= kDeclareGlobalsEvalFlag;
if (is_strict_mode()) flags |= kDeclareGlobalsStrictModeFlag;
if (is_native()) flags |= kDeclareGlobalsNativeFlag;
return flags;
}
void FullCodeGenerator::SetFunctionPosition(FunctionLiteral* fun) {
CodeGenerator::RecordPositions(masm_, fun->start_position());
}
......
......@@ -358,6 +358,7 @@ class FullCodeGenerator: public AstVisitor {
void VisitDeclarations(ZoneList<Declaration*>* declarations);
void DeclareGlobals(Handle<FixedArray> pairs);
int DeclareGlobalsFlags();
// Try to perform a comparison as a fast inlined literal compare if
// the operands allow it. Returns true if the compare operations
......@@ -555,6 +556,7 @@ class FullCodeGenerator: public AstVisitor {
Handle<Script> script() { return info_->script(); }
bool is_eval() { return info_->is_eval(); }
bool is_native() { return info_->is_native(); }
bool is_strict_mode() { return function()->strict_mode(); }
StrictModeFlag strict_mode_flag() {
return is_strict_mode() ? kStrictMode : kNonStrictMode;
......
......@@ -771,9 +771,8 @@ void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
// Call the runtime to declare the globals.
__ push(esi); // The context is the first argument.
__ push(Immediate(pairs));
__ push(Immediate(Smi::FromInt(is_eval() ? 1 : 0)));
__ push(Immediate(Smi::FromInt(strict_mode_flag())));
__ CallRuntime(Runtime::kDeclareGlobals, 4);
__ push(Immediate(Smi::FromInt(DeclareGlobalsFlags())));
__ CallRuntime(Runtime::kDeclareGlobals, 3);
// Return value is ignored.
}
......
......@@ -179,3 +179,17 @@ const SETTER_INDEX = 3;
const WRITABLE_INDEX = 4;
const ENUMERABLE_INDEX = 5;
const CONFIGURABLE_INDEX = 6;
# For messages.js
# Matches Script::Type from objects.h
const TYPE_NATIVE = 0;
const TYPE_EXTENSION = 1;
const TYPE_NORMAL = 2;
# Matches Script::CompilationType from objects.h
const COMPILATION_TYPE_HOST = 0;
const COMPILATION_TYPE_EVAL = 1;
const COMPILATION_TYPE_JSON = 2;
# Matches Messages::kNoLineNumberInfo from v8.h
const kNoLineNumberInfo = 0;
......@@ -28,19 +28,6 @@
// -------------------------------------------------------------------
//
// Matches Script::Type from objects.h
var TYPE_NATIVE = 0;
var TYPE_EXTENSION = 1;
var TYPE_NORMAL = 2;
// Matches Script::CompilationType from objects.h
var COMPILATION_TYPE_HOST = 0;
var COMPILATION_TYPE_EVAL = 1;
var COMPILATION_TYPE_JSON = 2;
// Matches Messages::kNoLineNumberInfo from v8.h
var kNoLineNumberInfo = 0;
// If this object gets passed to an error constructor the error will
// get an accessor for .message that constructs a descriptive error
// message on access.
......@@ -1041,7 +1028,7 @@ function captureStackTrace(obj, cons_opt) {
// user code.
var name = f.name;
%SetProperty(global, name, f, DONT_ENUM);
builtins['$' + name] = f;
%SetProperty(builtins, '$' + name, f, DONT_ENUM | DONT_DELETE | READ_ONLY);
// Configure the error function.
if (name == 'Error') {
// The prototype of the Error object must itself be an error.
......
......@@ -781,11 +781,10 @@ void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
// Call the runtime to declare the globals.
// The context is the first argument.
__ li(a2, Operand(pairs));
__ li(a1, Operand(Smi::FromInt(is_eval() ? 1 : 0)));
__ li(a0, Operand(Smi::FromInt(strict_mode_flag())));
__ Push(cp, a2, a1, a0);
__ CallRuntime(Runtime::kDeclareGlobals, 4);
__ li(a1, Operand(pairs));
__ li(a0, Operand(Smi::FromInt(DeclareGlobalsFlags())));
__ Push(cp, a1, a0);
__ CallRuntime(Runtime::kDeclareGlobals, 3);
// Return value is ignored.
}
......
......@@ -1149,22 +1149,14 @@ static Failure* ThrowRedeclarationError(Isolate* isolate,
RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
ASSERT(args.length() == 4);
ASSERT(args.length() == 3);
HandleScope scope(isolate);
Handle<GlobalObject> global = Handle<GlobalObject>(
isolate->context()->global());
Handle<Context> context = args.at<Context>(0);
CONVERT_ARG_CHECKED(FixedArray, pairs, 1);
bool is_eval = args.smi_at(2) == 1;
StrictModeFlag strict_mode = static_cast<StrictModeFlag>(args.smi_at(3));
ASSERT(strict_mode == kStrictMode || strict_mode == kNonStrictMode);
// Compute the property attributes. According to ECMA-262, section
// 13, page 71, the property must be read-only and
// non-deletable. However, neither SpiderMonkey nor KJS creates the
// property as read-only, so we don't either.
PropertyAttributes base = is_eval ? NONE : DONT_DELETE;
CONVERT_SMI_ARG_CHECKED(flags, 2);
// Traverse the name/value pairs and set the properties.
int length = pairs->length();
......@@ -1177,7 +1169,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
// assign to it when evaluating the assignment for "const x =
// <expr>" the initial value is the hole.
bool is_const_property = value->IsTheHole();
bool is_function_declaration = false;
if (value->IsUndefined() || is_const_property) {
// Lookup the property in the global object, and don't set the
// value of the variable if the property is already there.
......@@ -1226,6 +1218,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
}
}
} else {
is_function_declaration = true;
// Copy the function and update its context. Use it as value.
Handle<SharedFunctionInfo> shared =
Handle<SharedFunctionInfo>::cast(value);
......@@ -1239,10 +1232,6 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
LookupResult lookup;
global->LocalLookup(*name, &lookup);
PropertyAttributes attributes = is_const_property
? static_cast<PropertyAttributes>(base | READ_ONLY)
: base;
// There's a local property that we need to overwrite because
// we're either declaring a function or there's an interceptor
// that claims the property is absent.
......@@ -1257,6 +1246,19 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
return ThrowRedeclarationError(isolate, type, name);
}
// Compute the property attributes. According to ECMA-262, section
// 13, page 71, the property must be read-only and
// non-deletable. However, neither SpiderMonkey nor KJS creates the
// property as read-only, so we don't either.
int attr = NONE;
if ((flags & kDeclareGlobalsEvalFlag) == 0) {
attr |= DONT_DELETE;
}
bool is_native = (flags & kDeclareGlobalsNativeFlag) != 0;
if (is_const_property || (is_native && is_function_declaration)) {
attr |= READ_ONLY;
}
// Safari does not allow the invocation of callback setters for
// function declarations. To mimic this behavior, we do not allow
// the invocation of setters for function values. This makes a
......@@ -1267,20 +1269,24 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
if (value->IsJSFunction()) {
// Do not change DONT_DELETE to false from true.
if (lookup.IsProperty() && (lookup.type() != INTERCEPTOR)) {
attributes = static_cast<PropertyAttributes>(
attributes | (lookup.GetAttributes() & DONT_DELETE));
attr |= lookup.GetAttributes() & DONT_DELETE;
}
PropertyAttributes attributes = static_cast<PropertyAttributes>(attr);
RETURN_IF_EMPTY_HANDLE(isolate,
SetLocalPropertyIgnoreAttributes(global,
name,
value,
attributes));
} else {
StrictModeFlag strict_mode =
((flags & kDeclareGlobalsStrictModeFlag) != 0) ? kStrictMode
: kNonStrictMode;
RETURN_IF_EMPTY_HANDLE(isolate,
SetProperty(global,
name,
value,
attributes,
static_cast<PropertyAttributes>(attr),
strict_mode));
}
}
......
......@@ -317,7 +317,7 @@ namespace internal {
F(StoreContextSlot, 4, 1) \
\
/* Declarations and initialization */ \
F(DeclareGlobals, 4, 1) \
F(DeclareGlobals, 3, 1) \
F(DeclareContextSlot, 4, 1) \
F(InitializeVarGlobal, -1 /* 2 or 3 */, 1) \
F(InitializeConstGlobal, 2, 1) \
......@@ -663,6 +663,16 @@ class Runtime : public AllStatic {
static void PerformGC(Object* result);
};
//---------------------------------------------------------------------------
// Constants used by interface to runtime functions.
enum kDeclareGlobalsFlags {
kDeclareGlobalsEvalFlag = 1 << 0,
kDeclareGlobalsStrictModeFlag = 1 << 1,
kDeclareGlobalsNativeFlag = 1 << 2
};
} } // namespace v8::internal
#endif // V8_RUNTIME_H_
......@@ -742,9 +742,8 @@ void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
// Call the runtime to declare the globals.
__ push(rsi); // The context is the first argument.
__ Push(pairs);
__ Push(Smi::FromInt(is_eval() ? 1 : 0));
__ Push(Smi::FromInt(strict_mode_flag()));
__ CallRuntime(Runtime::kDeclareGlobals, 4);
__ Push(Smi::FromInt(DeclareGlobalsFlags()));
__ CallRuntime(Runtime::kDeclareGlobals, 3);
// Return value is ignored.
}
......
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