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!
|
// internal ToBoolean doesn't handle that!
|
||||||
if (!(typeof parent === 'undefined')) {
|
if (!(typeof parent === 'undefined')) {
|
||||||
var parent_fun = Instantiate(parent);
|
var parent_fun = Instantiate(parent);
|
||||||
fun.prototype.__proto__ = parent_fun.prototype;
|
%SetPrototype(fun.prototype, parent_fun.prototype);
|
||||||
}
|
}
|
||||||
ConfigureTemplateInstance(fun, data);
|
ConfigureTemplateInstance(fun, data);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -1646,8 +1646,6 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Fall through.
|
|
||||||
case ObjectLiteral::Property::PROTOTYPE:
|
|
||||||
// Duplicate receiver on stack.
|
// Duplicate receiver on stack.
|
||||||
__ ldr(r0, MemOperand(sp));
|
__ ldr(r0, MemOperand(sp));
|
||||||
__ push(r0);
|
__ push(r0);
|
||||||
@ -1661,6 +1659,18 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
|||||||
__ Drop(3);
|
__ Drop(3);
|
||||||
}
|
}
|
||||||
break;
|
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:
|
case ObjectLiteral::Property::GETTER:
|
||||||
accessor_table.lookup(key)->second->getter = value;
|
accessor_table.lookup(key)->second->getter = value;
|
||||||
break;
|
break;
|
||||||
|
@ -885,7 +885,7 @@ function ArraySort(comparefn) {
|
|||||||
// of a prototype property.
|
// of a prototype property.
|
||||||
var CopyFromPrototype = function CopyFromPrototype(obj, length) {
|
var CopyFromPrototype = function CopyFromPrototype(obj, length) {
|
||||||
var max = 0;
|
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);
|
var indices = %GetArrayKeys(proto, length);
|
||||||
if (indices.length > 0) {
|
if (indices.length > 0) {
|
||||||
if (indices[0] == -1) {
|
if (indices[0] == -1) {
|
||||||
@ -916,7 +916,7 @@ function ArraySort(comparefn) {
|
|||||||
// where a prototype of obj has an element. I.e., shadow all prototype
|
// where a prototype of obj has an element. I.e., shadow all prototype
|
||||||
// elements in that range.
|
// elements in that range.
|
||||||
var ShadowPrototypeElements = function(obj, from, to) {
|
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);
|
var indices = %GetArrayKeys(proto, to);
|
||||||
if (indices.length > 0) {
|
if (indices.length > 0) {
|
||||||
if (indices[0] == -1) {
|
if (indices[0] == -1) {
|
||||||
@ -986,7 +986,7 @@ function ArraySort(comparefn) {
|
|||||||
}
|
}
|
||||||
for (i = length - num_holes; i < length; i++) {
|
for (i = length - num_holes; i < length; i++) {
|
||||||
// For compatability with Webkit, do not expose elements in the prototype.
|
// 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;
|
obj[i] = void 0;
|
||||||
} else {
|
} else {
|
||||||
delete obj[i];
|
delete obj[i];
|
||||||
|
@ -71,7 +71,7 @@ function GetCompletions(global, last, full) {
|
|||||||
result.push(name);
|
result.push(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
current = ToInspectableObject(current.__proto__);
|
current = ToInspectableObject(Object.getPrototypeOf(current));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -1601,8 +1601,6 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Fall through.
|
|
||||||
case ObjectLiteral::Property::PROTOTYPE:
|
|
||||||
__ push(Operand(esp, 0)); // Duplicate receiver.
|
__ push(Operand(esp, 0)); // Duplicate receiver.
|
||||||
VisitForStackValue(key);
|
VisitForStackValue(key);
|
||||||
VisitForStackValue(value);
|
VisitForStackValue(value);
|
||||||
@ -1613,6 +1611,15 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
|||||||
__ Drop(3);
|
__ Drop(3);
|
||||||
}
|
}
|
||||||
break;
|
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:
|
case ObjectLiteral::Property::GETTER:
|
||||||
accessor_table.lookup(key)->second->getter = value;
|
accessor_table.lookup(key)->second->getter = value;
|
||||||
break;
|
break;
|
||||||
|
@ -37,7 +37,7 @@ var $abs = MathAbs;
|
|||||||
function MathConstructor() {}
|
function MathConstructor() {}
|
||||||
%FunctionSetInstanceClassName(MathConstructor, 'Math');
|
%FunctionSetInstanceClassName(MathConstructor, 'Math');
|
||||||
var $Math = new MathConstructor();
|
var $Math = new MathConstructor();
|
||||||
$Math.__proto__ = $Object.prototype;
|
%SetPrototype($Math, $Object.prototype);
|
||||||
%SetProperty(global, "Math", $Math, DONT_ENUM);
|
%SetProperty(global, "Math", $Math, DONT_ENUM);
|
||||||
|
|
||||||
// ECMA 262 - 15.8.2.1
|
// ECMA 262 - 15.8.2.1
|
||||||
|
@ -1208,7 +1208,7 @@ var cyclic_error_marker = new $Object();
|
|||||||
function GetPropertyWithoutInvokingMonkeyGetters(error, name) {
|
function GetPropertyWithoutInvokingMonkeyGetters(error, name) {
|
||||||
// Climb the prototype chain until we find the holder.
|
// Climb the prototype chain until we find the holder.
|
||||||
while (error && !%HasLocalProperty(error, name)) {
|
while (error && !%HasLocalProperty(error, name)) {
|
||||||
error = error.__proto__;
|
error = %GetPrototype(error);
|
||||||
}
|
}
|
||||||
if (error === null) return void 0;
|
if (error === null) return void 0;
|
||||||
if (!IS_OBJECT(error)) return error[name];
|
if (!IS_OBJECT(error)) return error[name];
|
||||||
|
@ -1654,8 +1654,6 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Fall through.
|
|
||||||
case ObjectLiteral::Property::PROTOTYPE:
|
|
||||||
// Duplicate receiver on stack.
|
// Duplicate receiver on stack.
|
||||||
__ lw(a0, MemOperand(sp));
|
__ lw(a0, MemOperand(sp));
|
||||||
__ push(a0);
|
__ push(a0);
|
||||||
@ -1669,6 +1667,17 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
|||||||
__ Drop(3);
|
__ Drop(3);
|
||||||
}
|
}
|
||||||
break;
|
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:
|
case ObjectLiteral::Property::GETTER:
|
||||||
accessor_table.lookup(key)->second->getter = value;
|
accessor_table.lookup(key)->second->getter = value;
|
||||||
break;
|
break;
|
||||||
|
@ -4872,7 +4872,7 @@ class Map: public HeapObject {
|
|||||||
inline bool function_with_prototype();
|
inline bool function_with_prototype();
|
||||||
|
|
||||||
// Tells whether the instance with this map should be ignored by the
|
// 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() {
|
inline void set_is_hidden_prototype() {
|
||||||
set_bit_field(bit_field() | (1 << kIsHiddenPrototype));
|
set_bit_field(bit_field() | (1 << kIsHiddenPrototype));
|
||||||
}
|
}
|
||||||
|
@ -77,8 +77,7 @@ function DerivedConstructTrap(callTrap) {
|
|||||||
return function() {
|
return function() {
|
||||||
var proto = this.prototype
|
var proto = this.prototype
|
||||||
if (!IS_SPEC_OBJECT(proto)) proto = $Object.prototype
|
if (!IS_SPEC_OBJECT(proto)) proto = $Object.prototype
|
||||||
var obj = new $Object()
|
var obj = { __proto__: proto };
|
||||||
obj.__proto__ = proto
|
|
||||||
var result = %Apply(callTrap, obj, arguments, 0, %_ArgumentsLength());
|
var result = %Apply(callTrap, obj, arguments, 0, %_ArgumentsLength());
|
||||||
return IS_SPEC_OBJECT(result) ? result : obj
|
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) {
|
RUNTIME_FUNCTION(MaybeObject*, Runtime_IsInPrototypeChain) {
|
||||||
NoHandleAllocation ha(isolate);
|
NoHandleAllocation ha(isolate);
|
||||||
ASSERT(args.length() == 2);
|
ASSERT(args.length() == 2);
|
||||||
|
@ -67,6 +67,7 @@ namespace internal {
|
|||||||
F(GetDefaultReceiver, 1, 1) \
|
F(GetDefaultReceiver, 1, 1) \
|
||||||
\
|
\
|
||||||
F(GetPrototype, 1, 1) \
|
F(GetPrototype, 1, 1) \
|
||||||
|
F(SetPrototype, 2, 1) \
|
||||||
F(IsInPrototypeChain, 2, 1) \
|
F(IsInPrototypeChain, 2, 1) \
|
||||||
\
|
\
|
||||||
F(GetOwnProperty, 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);
|
%SetProperty(prototype, key, f, DONT_ENUM | DONT_DELETE | READ_ONLY);
|
||||||
%SetNativeFlag(f);
|
%SetNativeFlag(f);
|
||||||
}
|
}
|
||||||
prototype.__proto__ = null;
|
%SetPrototype(prototype, null);
|
||||||
%ToFastProperties(prototype);
|
%ToFastProperties(prototype);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1074,8 +1074,7 @@ function ObjectCreate(proto, properties) {
|
|||||||
if (!IS_SPEC_OBJECT(proto) && proto !== null) {
|
if (!IS_SPEC_OBJECT(proto) && proto !== null) {
|
||||||
throw MakeTypeError("proto_object_or_null", [proto]);
|
throw MakeTypeError("proto_object_or_null", [proto]);
|
||||||
}
|
}
|
||||||
var obj = new $Object();
|
var obj = { __proto__: proto };
|
||||||
obj.__proto__ = proto;
|
|
||||||
if (!IS_UNDEFINED(properties)) ObjectDefineProperties(obj, properties);
|
if (!IS_UNDEFINED(properties)) ObjectDefineProperties(obj, properties);
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
@ -1626,8 +1626,6 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Fall through.
|
|
||||||
case ObjectLiteral::Property::PROTOTYPE:
|
|
||||||
__ push(Operand(rsp, 0)); // Duplicate receiver.
|
__ push(Operand(rsp, 0)); // Duplicate receiver.
|
||||||
VisitForStackValue(key);
|
VisitForStackValue(key);
|
||||||
VisitForStackValue(value);
|
VisitForStackValue(value);
|
||||||
@ -1638,6 +1636,15 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
|||||||
__ Drop(3);
|
__ Drop(3);
|
||||||
}
|
}
|
||||||
break;
|
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:
|
case ObjectLiteral::Property::GETTER:
|
||||||
accessor_table.lookup(key)->second->getter = value;
|
accessor_table.lookup(key)->second->getter = value;
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user