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