Make sure builtin functions don't rely on __proto__.
This makes sure that none of the builtin functions rely on the __proto__ accessor which can now be monkey-patched by applications. Instead use a separate %SetPrototype() intrinsic or object literals to do the job. R=rossberg@chromium.org Review URL: https://codereview.chromium.org/12385082 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13815 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
1630954005
commit
0ca02ee48d
@ -90,7 +90,7 @@ function InstantiateFunction(data, name) {
|
||||
// internal ToBoolean doesn't handle that!
|
||||
if (!(typeof parent === 'undefined')) {
|
||||
var parent_fun = Instantiate(parent);
|
||||
fun.prototype.__proto__ = parent_fun.prototype;
|
||||
%SetPrototype(fun.prototype, parent_fun.prototype);
|
||||
}
|
||||
ConfigureTemplateInstance(fun, data);
|
||||
} catch (e) {
|
||||
|
@ -1646,8 +1646,6 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
// Fall through.
|
||||
case ObjectLiteral::Property::PROTOTYPE:
|
||||
// Duplicate receiver on stack.
|
||||
__ ldr(r0, MemOperand(sp));
|
||||
__ push(r0);
|
||||
@ -1661,6 +1659,18 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
__ Drop(3);
|
||||
}
|
||||
break;
|
||||
case ObjectLiteral::Property::PROTOTYPE:
|
||||
// Duplicate receiver on stack.
|
||||
__ ldr(r0, MemOperand(sp));
|
||||
__ push(r0);
|
||||
VisitForStackValue(value);
|
||||
if (property->emit_store()) {
|
||||
__ CallRuntime(Runtime::kSetPrototype, 2);
|
||||
} else {
|
||||
__ Drop(2);
|
||||
}
|
||||
break;
|
||||
|
||||
case ObjectLiteral::Property::GETTER:
|
||||
accessor_table.lookup(key)->second->getter = value;
|
||||
break;
|
||||
|
@ -885,7 +885,7 @@ function ArraySort(comparefn) {
|
||||
// of a prototype property.
|
||||
var CopyFromPrototype = function CopyFromPrototype(obj, length) {
|
||||
var max = 0;
|
||||
for (var proto = obj.__proto__; proto; proto = proto.__proto__) {
|
||||
for (var proto = %GetPrototype(obj); proto; proto = %GetPrototype(proto)) {
|
||||
var indices = %GetArrayKeys(proto, length);
|
||||
if (indices.length > 0) {
|
||||
if (indices[0] == -1) {
|
||||
@ -916,7 +916,7 @@ function ArraySort(comparefn) {
|
||||
// where a prototype of obj has an element. I.e., shadow all prototype
|
||||
// elements in that range.
|
||||
var ShadowPrototypeElements = function(obj, from, to) {
|
||||
for (var proto = obj.__proto__; proto; proto = proto.__proto__) {
|
||||
for (var proto = %GetPrototype(obj); proto; proto = %GetPrototype(proto)) {
|
||||
var indices = %GetArrayKeys(proto, to);
|
||||
if (indices.length > 0) {
|
||||
if (indices[0] == -1) {
|
||||
@ -986,7 +986,7 @@ function ArraySort(comparefn) {
|
||||
}
|
||||
for (i = length - num_holes; i < length; i++) {
|
||||
// For compatability with Webkit, do not expose elements in the prototype.
|
||||
if (i in obj.__proto__) {
|
||||
if (i in %GetPrototype(obj)) {
|
||||
obj[i] = void 0;
|
||||
} else {
|
||||
delete obj[i];
|
||||
|
@ -71,7 +71,7 @@ function GetCompletions(global, last, full) {
|
||||
result.push(name);
|
||||
}
|
||||
}
|
||||
current = ToInspectableObject(current.__proto__);
|
||||
current = ToInspectableObject(Object.getPrototypeOf(current));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -1601,8 +1601,6 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
// Fall through.
|
||||
case ObjectLiteral::Property::PROTOTYPE:
|
||||
__ push(Operand(esp, 0)); // Duplicate receiver.
|
||||
VisitForStackValue(key);
|
||||
VisitForStackValue(value);
|
||||
@ -1613,6 +1611,15 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
__ Drop(3);
|
||||
}
|
||||
break;
|
||||
case ObjectLiteral::Property::PROTOTYPE:
|
||||
__ push(Operand(esp, 0)); // Duplicate receiver.
|
||||
VisitForStackValue(value);
|
||||
if (property->emit_store()) {
|
||||
__ CallRuntime(Runtime::kSetPrototype, 2);
|
||||
} else {
|
||||
__ Drop(2);
|
||||
}
|
||||
break;
|
||||
case ObjectLiteral::Property::GETTER:
|
||||
accessor_table.lookup(key)->second->getter = value;
|
||||
break;
|
||||
|
@ -37,7 +37,7 @@ var $abs = MathAbs;
|
||||
function MathConstructor() {}
|
||||
%FunctionSetInstanceClassName(MathConstructor, 'Math');
|
||||
var $Math = new MathConstructor();
|
||||
$Math.__proto__ = $Object.prototype;
|
||||
%SetPrototype($Math, $Object.prototype);
|
||||
%SetProperty(global, "Math", $Math, DONT_ENUM);
|
||||
|
||||
// ECMA 262 - 15.8.2.1
|
||||
|
@ -1208,7 +1208,7 @@ var cyclic_error_marker = new $Object();
|
||||
function GetPropertyWithoutInvokingMonkeyGetters(error, name) {
|
||||
// Climb the prototype chain until we find the holder.
|
||||
while (error && !%HasLocalProperty(error, name)) {
|
||||
error = error.__proto__;
|
||||
error = %GetPrototype(error);
|
||||
}
|
||||
if (error === null) return void 0;
|
||||
if (!IS_OBJECT(error)) return error[name];
|
||||
|
@ -1654,8 +1654,6 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
// Fall through.
|
||||
case ObjectLiteral::Property::PROTOTYPE:
|
||||
// Duplicate receiver on stack.
|
||||
__ lw(a0, MemOperand(sp));
|
||||
__ push(a0);
|
||||
@ -1669,6 +1667,17 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
__ Drop(3);
|
||||
}
|
||||
break;
|
||||
case ObjectLiteral::Property::PROTOTYPE:
|
||||
// Duplicate receiver on stack.
|
||||
__ lw(a0, MemOperand(sp));
|
||||
__ push(a0);
|
||||
VisitForStackValue(value);
|
||||
if (property->emit_store()) {
|
||||
__ CallRuntime(Runtime::kSetPrototype, 2);
|
||||
} else {
|
||||
__ Drop(2);
|
||||
}
|
||||
break;
|
||||
case ObjectLiteral::Property::GETTER:
|
||||
accessor_table.lookup(key)->second->getter = value;
|
||||
break;
|
||||
|
@ -4872,7 +4872,7 @@ class Map: public HeapObject {
|
||||
inline bool function_with_prototype();
|
||||
|
||||
// Tells whether the instance with this map should be ignored by the
|
||||
// __proto__ accessor.
|
||||
// Object.getPrototypeOf() function and the __proto__ accessor.
|
||||
inline void set_is_hidden_prototype() {
|
||||
set_bit_field(bit_field() | (1 << kIsHiddenPrototype));
|
||||
}
|
||||
|
@ -77,8 +77,7 @@ function DerivedConstructTrap(callTrap) {
|
||||
return function() {
|
||||
var proto = this.prototype
|
||||
if (!IS_SPEC_OBJECT(proto)) proto = $Object.prototype
|
||||
var obj = new $Object()
|
||||
obj.__proto__ = proto
|
||||
var obj = { __proto__: proto };
|
||||
var result = %Apply(callTrap, obj, arguments, 0, %_ArgumentsLength());
|
||||
return IS_SPEC_OBJECT(result) ? result : obj
|
||||
}
|
||||
|
@ -975,6 +975,15 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPrototype) {
|
||||
}
|
||||
|
||||
|
||||
RUNTIME_FUNCTION(MaybeObject*, Runtime_SetPrototype) {
|
||||
NoHandleAllocation ha(isolate);
|
||||
ASSERT(args.length() == 2);
|
||||
CONVERT_ARG_CHECKED(JSReceiver, input_obj, 0);
|
||||
CONVERT_ARG_CHECKED(Object, prototype, 1);
|
||||
return input_obj->SetPrototype(prototype, true);
|
||||
}
|
||||
|
||||
|
||||
RUNTIME_FUNCTION(MaybeObject*, Runtime_IsInPrototypeChain) {
|
||||
NoHandleAllocation ha(isolate);
|
||||
ASSERT(args.length() == 2);
|
||||
|
@ -67,6 +67,7 @@ namespace internal {
|
||||
F(GetDefaultReceiver, 1, 1) \
|
||||
\
|
||||
F(GetPrototype, 1, 1) \
|
||||
F(SetPrototype, 2, 1) \
|
||||
F(IsInPrototypeChain, 2, 1) \
|
||||
\
|
||||
F(GetOwnProperty, 2, 1) \
|
||||
|
@ -94,7 +94,7 @@ function SetUpLockedPrototype(constructor, fields, methods) {
|
||||
%SetProperty(prototype, key, f, DONT_ENUM | DONT_DELETE | READ_ONLY);
|
||||
%SetNativeFlag(f);
|
||||
}
|
||||
prototype.__proto__ = null;
|
||||
%SetPrototype(prototype, null);
|
||||
%ToFastProperties(prototype);
|
||||
}
|
||||
|
||||
@ -1074,8 +1074,7 @@ function ObjectCreate(proto, properties) {
|
||||
if (!IS_SPEC_OBJECT(proto) && proto !== null) {
|
||||
throw MakeTypeError("proto_object_or_null", [proto]);
|
||||
}
|
||||
var obj = new $Object();
|
||||
obj.__proto__ = proto;
|
||||
var obj = { __proto__: proto };
|
||||
if (!IS_UNDEFINED(properties)) ObjectDefineProperties(obj, properties);
|
||||
return obj;
|
||||
}
|
||||
|
@ -1626,8 +1626,6 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
// Fall through.
|
||||
case ObjectLiteral::Property::PROTOTYPE:
|
||||
__ push(Operand(rsp, 0)); // Duplicate receiver.
|
||||
VisitForStackValue(key);
|
||||
VisitForStackValue(value);
|
||||
@ -1638,6 +1636,15 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
__ Drop(3);
|
||||
}
|
||||
break;
|
||||
case ObjectLiteral::Property::PROTOTYPE:
|
||||
__ push(Operand(rsp, 0)); // Duplicate receiver.
|
||||
VisitForStackValue(value);
|
||||
if (property->emit_store()) {
|
||||
__ CallRuntime(Runtime::kSetPrototype, 2);
|
||||
} else {
|
||||
__ Drop(2);
|
||||
}
|
||||
break;
|
||||
case ObjectLiteral::Property::GETTER:
|
||||
accessor_table.lookup(key)->second->getter = value;
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user