Lock the prototype of internal classes.
Prototypes and their properties and methods are locked down to prevent fiddling with their operation, even if the build-in object leaks. Made some built-in functions only work during bootstrapping. Review URL: http://codereview.chromium.org/7799027 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9122 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
f6c063e143
commit
ffffa716c5
31
src/array.js
31
src/array.js
@ -1314,12 +1314,13 @@ function ArrayIsArray(obj) {
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
function SetupArray() {
|
||||
// Setup non-enumerable constructor property on the Array.prototype
|
||||
function SetUpArray() {
|
||||
%CheckIsBootstrapping();
|
||||
// Set up non-enumerable constructor property on the Array.prototype
|
||||
// object.
|
||||
%SetProperty($Array.prototype, "constructor", $Array, DONT_ENUM);
|
||||
|
||||
// Setup non-enumerable functions on the Array object.
|
||||
// Set up non-enumerable functions on the Array object.
|
||||
InstallFunctions($Array, DONT_ENUM, $Array(
|
||||
"isArray", ArrayIsArray
|
||||
));
|
||||
@ -1337,7 +1338,7 @@ function SetupArray() {
|
||||
return f;
|
||||
}
|
||||
|
||||
// Setup non-enumerable functions of the Array.prototype object and
|
||||
// Set up non-enumerable functions of the Array.prototype object and
|
||||
// set their names.
|
||||
// Manipulate the length of some of the functions to meet
|
||||
// expectations set by ECMA-262 or Mozilla.
|
||||
@ -1368,19 +1369,13 @@ function SetupArray() {
|
||||
%FinishArrayPrototypeSetup($Array.prototype);
|
||||
|
||||
// The internal Array prototype doesn't need to be fancy, since it's never
|
||||
// exposed to user code, so no hidden prototypes or DONT_ENUM attributes
|
||||
// are necessary.
|
||||
// The null __proto__ ensures that we never inherit any user created
|
||||
// getters or setters from, e.g., Object.prototype.
|
||||
InternalArray.prototype.__proto__ = null;
|
||||
// Adding only the functions that are actually used, and a toString.
|
||||
InternalArray.prototype.join = getFunction("join", ArrayJoin);
|
||||
InternalArray.prototype.pop = getFunction("pop", ArrayPop);
|
||||
InternalArray.prototype.push = getFunction("push", ArrayPush);
|
||||
InternalArray.prototype.toString = function() {
|
||||
return "Internal Array, length " + this.length;
|
||||
};
|
||||
// exposed to user code.
|
||||
// Adding only the functions that are actually used.
|
||||
SetUpLockedPrototype(InternalArray, $Array(), $Array(
|
||||
"join", getFunction("join", ArrayJoin),
|
||||
"pop", getFunction("pop", ArrayPop),
|
||||
"push", getFunction("push", ArrayPush)
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
SetupArray();
|
||||
SetUpArray();
|
||||
|
11
src/date.js
11
src/date.js
@ -1048,18 +1048,19 @@ function ResetDateCache() {
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
function SetupDate() {
|
||||
// Setup non-enumerable properties of the Date object itself.
|
||||
function SetUpDate() {
|
||||
%CheckIsBootstrapping();
|
||||
// Set up non-enumerable properties of the Date object itself.
|
||||
InstallFunctions($Date, DONT_ENUM, $Array(
|
||||
"UTC", DateUTC,
|
||||
"parse", DateParse,
|
||||
"now", DateNow
|
||||
));
|
||||
|
||||
// Setup non-enumerable constructor property of the Date prototype object.
|
||||
// Set up non-enumerable constructor property of the Date prototype object.
|
||||
%SetProperty($Date.prototype, "constructor", $Date, DONT_ENUM);
|
||||
|
||||
// Setup non-enumerable functions of the Date prototype object and
|
||||
// Set up non-enumerable functions of the Date prototype object and
|
||||
// set their names.
|
||||
InstallFunctionsOnHiddenPrototype($Date.prototype, DONT_ENUM, $Array(
|
||||
"toString", DateToString,
|
||||
@ -1111,4 +1112,4 @@ function SetupDate() {
|
||||
));
|
||||
}
|
||||
|
||||
SetupDate();
|
||||
SetUpDate();
|
||||
|
@ -337,11 +337,12 @@ function JSONStringify(value, replacer, space) {
|
||||
return JSONSerialize('', {'': value}, replacer, new InternalArray(), "", gap);
|
||||
}
|
||||
|
||||
function SetupJSON() {
|
||||
function SetUpJSON() {
|
||||
%CheckIsBootstrapping();
|
||||
InstallFunctions($JSON, DONT_ENUM, $Array(
|
||||
"parse", JSONParse,
|
||||
"stringify", JSONStringify
|
||||
));
|
||||
}
|
||||
|
||||
SetupJSON();
|
||||
SetUpJSON()
|
||||
|
12
src/math.js
12
src/math.js
@ -195,8 +195,9 @@ function MathTan(x) {
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
function SetupMath() {
|
||||
// Setup math constants.
|
||||
function SetUpMath() {
|
||||
%CheckIsBootstrapping();
|
||||
// Set up math constants.
|
||||
// ECMA-262, section 15.8.1.1.
|
||||
%OptimizeObjectForAddingMultipleProperties($Math, 8);
|
||||
%SetProperty($Math,
|
||||
@ -236,7 +237,7 @@ function SetupMath() {
|
||||
DONT_ENUM | DONT_DELETE | READ_ONLY);
|
||||
%ToFastProperties($Math);
|
||||
|
||||
// Setup non-enumerable functions of the Math object and
|
||||
// Set up non-enumerable functions of the Math object and
|
||||
// set their names.
|
||||
InstallFunctionsOnHiddenPrototype($Math, DONT_ENUM, $Array(
|
||||
"random", MathRandom,
|
||||
@ -258,7 +259,6 @@ function SetupMath() {
|
||||
"max", MathMax,
|
||||
"min", MathMin
|
||||
));
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
SetupMath();
|
||||
SetUpMath();
|
||||
|
127
src/messages.js
127
src/messages.js
@ -116,10 +116,11 @@ function MakeGenericError(constructor, type, args) {
|
||||
|
||||
|
||||
/**
|
||||
* Setup the Script function and constructor.
|
||||
* Set up the Script function and constructor.
|
||||
*/
|
||||
%FunctionSetInstanceClassName(Script, 'Script');
|
||||
%SetProperty(Script.prototype, 'constructor', Script, DONT_ENUM);
|
||||
%SetProperty(Script.prototype, 'constructor', Script,
|
||||
DONT_ENUM | DONT_DELETE | READ_ONLY);
|
||||
%SetCode(Script, function(x) {
|
||||
// Script objects can only be created by the VM.
|
||||
throw new $Error("Not supported");
|
||||
@ -320,7 +321,7 @@ function MakeError(type, args) {
|
||||
* @return {number} 0 if input too small, -1 if input too large,
|
||||
else the line number.
|
||||
*/
|
||||
Script.prototype.lineFromPosition = function(position) {
|
||||
function ScriptLineFromPosition(position) {
|
||||
var lower = 0;
|
||||
var upper = this.lineCount() - 1;
|
||||
var line_ends = this.line_ends;
|
||||
@ -359,8 +360,8 @@ Script.prototype.lineFromPosition = function(position) {
|
||||
* @return {SourceLocation}
|
||||
* If line is negative or not in the source null is returned.
|
||||
*/
|
||||
Script.prototype.locationFromPosition = function (position,
|
||||
include_resource_offset) {
|
||||
function ScriptLocationFromPosition(position,
|
||||
include_resource_offset) {
|
||||
var line = this.lineFromPosition(position);
|
||||
if (line == -1) return null;
|
||||
|
||||
@ -368,7 +369,9 @@ Script.prototype.locationFromPosition = function (position,
|
||||
var line_ends = this.line_ends;
|
||||
var start = line == 0 ? 0 : line_ends[line - 1] + 1;
|
||||
var end = line_ends[line];
|
||||
if (end > 0 && %_CallFunction(this.source, end - 1, StringCharAt) == '\r') end--;
|
||||
if (end > 0 && %_CallFunction(this.source, end - 1, StringCharAt) == '\r') {
|
||||
end--;
|
||||
}
|
||||
var column = position - start;
|
||||
|
||||
// Adjust according to the offset within the resource.
|
||||
@ -393,11 +396,12 @@ Script.prototype.locationFromPosition = function (position,
|
||||
* @param {number} opt_line The line within the source. Default value is 0
|
||||
* @param {number} opt_column The column in within the line. Default value is 0
|
||||
* @param {number} opt_offset_position The offset from the begining of the
|
||||
* source from where the line and column calculation starts. Default value is 0
|
||||
* source from where the line and column calculation starts.
|
||||
* Default value is 0
|
||||
* @return {SourceLocation}
|
||||
* If line is negative or not in the source null is returned.
|
||||
*/
|
||||
Script.prototype.locationFromLine = function (opt_line, opt_column, opt_offset_position) {
|
||||
function ScriptLocationFromLine(opt_line, opt_column, opt_offset_position) {
|
||||
// Default is the first line in the script. Lines in the script is relative
|
||||
// to the offset within the resource.
|
||||
var line = 0;
|
||||
@ -439,7 +443,7 @@ Script.prototype.locationFromLine = function (opt_line, opt_column, opt_offset_p
|
||||
* @return {SourceSlice} The source slice or null of the parameters where
|
||||
* invalid
|
||||
*/
|
||||
Script.prototype.sourceSlice = function (opt_from_line, opt_to_line) {
|
||||
function ScriptSourceSlice(opt_from_line, opt_to_line) {
|
||||
var from_line = IS_UNDEFINED(opt_from_line) ? this.line_offset : opt_from_line;
|
||||
var to_line = IS_UNDEFINED(opt_to_line) ? this.line_offset + this.lineCount() : opt_to_line
|
||||
|
||||
@ -466,7 +470,7 @@ Script.prototype.sourceSlice = function (opt_from_line, opt_to_line) {
|
||||
}
|
||||
|
||||
|
||||
Script.prototype.sourceLine = function (opt_line) {
|
||||
function ScriptSourceLine(opt_line) {
|
||||
// Default is the first line in the script. Lines in the script are relative
|
||||
// to the offset within the resource.
|
||||
var line = 0;
|
||||
@ -492,7 +496,7 @@ Script.prototype.sourceLine = function (opt_line) {
|
||||
* @return {number}
|
||||
* Number of source lines.
|
||||
*/
|
||||
Script.prototype.lineCount = function() {
|
||||
function ScriptLineCount() {
|
||||
// Return number of source lines.
|
||||
return this.line_ends.length;
|
||||
};
|
||||
@ -508,9 +512,10 @@ Script.prototype.lineCount = function() {
|
||||
* @return {?string} script name if present, value for //@ sourceURL comment
|
||||
* otherwise.
|
||||
*/
|
||||
Script.prototype.nameOrSourceURL = function() {
|
||||
if (this.name)
|
||||
function ScriptNameOrSourceURL() {
|
||||
if (this.name) {
|
||||
return this.name;
|
||||
}
|
||||
// TODO(608): the spaces in a regexp below had to be escaped as \040
|
||||
// because this file is being processed by js2c whose handling of spaces
|
||||
// in regexps is broken. Also, ['"] are excluded from allowed URLs to
|
||||
@ -536,6 +541,20 @@ Script.prototype.nameOrSourceURL = function() {
|
||||
}
|
||||
|
||||
|
||||
SetUpLockedPrototype(Script,
|
||||
$Array("source", "name", "line_ends", "line_offset", "column_offset"),
|
||||
$Array(
|
||||
"lineFromPosition", ScriptLineFromPosition,
|
||||
"locationFromPosition", ScriptLocationFromPosition,
|
||||
"locationFromLine", ScriptLocationFromLine,
|
||||
"sourceSlice", ScriptSourceSlice,
|
||||
"sourceLine", ScriptSourceLine,
|
||||
"lineCount", ScriptLineCount,
|
||||
"nameOrSourceURL", ScriptNameOrSourceURL
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Class for source location. A source location is a position within some
|
||||
* source with the following properties:
|
||||
@ -566,8 +585,6 @@ function SourceLocation(script, position, line, column, start, end) {
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
SourceLocation.prototype.__proto__ = null;
|
||||
|
||||
const kLineLengthLimit = 78;
|
||||
|
||||
/**
|
||||
@ -578,7 +595,7 @@ const kLineLengthLimit = 78;
|
||||
* @param {number} opt_before The number of characters to prefer before the
|
||||
* position with a default value of 10 less that the limit
|
||||
*/
|
||||
SourceLocation.prototype.restrict = function (opt_limit, opt_before) {
|
||||
function SourceLocationRestrict(opt_limit, opt_before) {
|
||||
// Find the actual limit to use.
|
||||
var limit;
|
||||
var before;
|
||||
@ -625,11 +642,20 @@ SourceLocation.prototype.restrict = function (opt_limit, opt_before) {
|
||||
* @return {String}
|
||||
* Source text for this location.
|
||||
*/
|
||||
SourceLocation.prototype.sourceText = function () {
|
||||
function SourceLocationSourceText() {
|
||||
return %_CallFunction(this.script.source, this.start, this.end, StringSubstring);
|
||||
};
|
||||
|
||||
|
||||
SetUpLockedPrototype(SourceLocation,
|
||||
$Array("script", "position", "line", "column", "start", "end"),
|
||||
$Array(
|
||||
"restrict", SourceLocationRestrict,
|
||||
"sourceText", SourceLocationSourceText
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Class for a source slice. A source slice is a part of a script source with
|
||||
* the following properties:
|
||||
@ -656,20 +682,23 @@ function SourceSlice(script, from_line, to_line, from_position, to_position) {
|
||||
this.to_position = to_position;
|
||||
}
|
||||
|
||||
SourceSlice.prototype.__proto__ = null;
|
||||
|
||||
/**
|
||||
* Get the source text for a SourceSlice
|
||||
* @return {String} Source text for this slice. The last line will include
|
||||
* the line terminating characters (if any)
|
||||
*/
|
||||
SourceSlice.prototype.sourceText = function () {
|
||||
function SourceSliceSourceText() {
|
||||
return %_CallFunction(this.script.source,
|
||||
this.from_position,
|
||||
this.to_position,
|
||||
StringSubstring);
|
||||
};
|
||||
|
||||
SetUpLockedPrototype(SourceSlice,
|
||||
$Array("script", "from_line", "to_line", "from_position", "to_position"),
|
||||
$Array("sourceText", SourceSliceSourceText)
|
||||
);
|
||||
|
||||
|
||||
// Returns the offset of the given position within the containing
|
||||
// line.
|
||||
@ -724,13 +753,11 @@ function CallSite(receiver, fun, pos) {
|
||||
this.pos = pos;
|
||||
}
|
||||
|
||||
CallSite.prototype.__proto__ = null;
|
||||
|
||||
CallSite.prototype.getThis = function () {
|
||||
function CallSiteGetThis() {
|
||||
return this.receiver;
|
||||
};
|
||||
|
||||
CallSite.prototype.getTypeName = function () {
|
||||
function CallSiteGetTypeName() {
|
||||
var constructor = this.receiver.constructor;
|
||||
if (!constructor) {
|
||||
return %_CallFunction(this.receiver, ObjectToString);
|
||||
@ -742,33 +769,33 @@ CallSite.prototype.getTypeName = function () {
|
||||
return constructorName;
|
||||
};
|
||||
|
||||
CallSite.prototype.isToplevel = function () {
|
||||
function CallSiteIsToplevel() {
|
||||
if (this.receiver == null) {
|
||||
return true;
|
||||
}
|
||||
return IS_GLOBAL(this.receiver);
|
||||
};
|
||||
|
||||
CallSite.prototype.isEval = function () {
|
||||
function CallSiteIsEval() {
|
||||
var script = %FunctionGetScript(this.fun);
|
||||
return script && script.compilation_type == COMPILATION_TYPE_EVAL;
|
||||
};
|
||||
|
||||
CallSite.prototype.getEvalOrigin = function () {
|
||||
function CallSiteGetEvalOrigin() {
|
||||
var script = %FunctionGetScript(this.fun);
|
||||
return FormatEvalOrigin(script);
|
||||
};
|
||||
|
||||
CallSite.prototype.getScriptNameOrSourceURL = function () {
|
||||
function CallSiteGetScriptNameOrSourceURL() {
|
||||
var script = %FunctionGetScript(this.fun);
|
||||
return script ? script.nameOrSourceURL() : null;
|
||||
};
|
||||
|
||||
CallSite.prototype.getFunction = function () {
|
||||
function CallSiteGetFunction() {
|
||||
return this.fun;
|
||||
};
|
||||
|
||||
CallSite.prototype.getFunctionName = function () {
|
||||
function CallSiteGetFunctionName() {
|
||||
// See if the function knows its own name
|
||||
var name = this.fun.name;
|
||||
if (name) {
|
||||
@ -784,7 +811,7 @@ CallSite.prototype.getFunctionName = function () {
|
||||
return null;
|
||||
};
|
||||
|
||||
CallSite.prototype.getMethodName = function () {
|
||||
function CallSiteGetMethodName() {
|
||||
// See if we can find a unique property on the receiver that holds
|
||||
// this function.
|
||||
var ownName = this.fun.name;
|
||||
@ -814,12 +841,12 @@ CallSite.prototype.getMethodName = function () {
|
||||
return null;
|
||||
};
|
||||
|
||||
CallSite.prototype.getFileName = function () {
|
||||
function CallSiteGetFileName() {
|
||||
var script = %FunctionGetScript(this.fun);
|
||||
return script ? script.name : null;
|
||||
};
|
||||
|
||||
CallSite.prototype.getLineNumber = function () {
|
||||
function CallSiteGetLineNumber() {
|
||||
if (this.pos == -1) {
|
||||
return null;
|
||||
}
|
||||
@ -831,7 +858,7 @@ CallSite.prototype.getLineNumber = function () {
|
||||
return location ? location.line + 1 : null;
|
||||
};
|
||||
|
||||
CallSite.prototype.getColumnNumber = function () {
|
||||
function CallSiteGetColumnNumber() {
|
||||
if (this.pos == -1) {
|
||||
return null;
|
||||
}
|
||||
@ -843,16 +870,16 @@ CallSite.prototype.getColumnNumber = function () {
|
||||
return location ? location.column + 1: null;
|
||||
};
|
||||
|
||||
CallSite.prototype.isNative = function () {
|
||||
function CallSiteIsNative() {
|
||||
var script = %FunctionGetScript(this.fun);
|
||||
return script ? (script.type == TYPE_NATIVE) : false;
|
||||
};
|
||||
|
||||
CallSite.prototype.getPosition = function () {
|
||||
function CallSiteGetPosition() {
|
||||
return this.pos;
|
||||
};
|
||||
|
||||
CallSite.prototype.isConstructor = function () {
|
||||
function CallSiteIsConstructor() {
|
||||
var constructor = this.receiver ? this.receiver.constructor : null;
|
||||
if (!constructor) {
|
||||
return false;
|
||||
@ -860,6 +887,25 @@ CallSite.prototype.isConstructor = function () {
|
||||
return this.fun === constructor;
|
||||
};
|
||||
|
||||
SetUpLockedPrototype(CallSite, $Array("receiver", "fun", "pos"), $Array(
|
||||
"getThis", CallSiteGetThis,
|
||||
"getTypeName", CallSiteGetTypeName,
|
||||
"isToplevel", CallSiteIsToplevel,
|
||||
"isEval", CallSiteIsEval,
|
||||
"getEvalOrigin", CallSiteGetEvalOrigin,
|
||||
"getScriptNameOrSourceURL", CallSiteGetScriptNameOrSourceURL,
|
||||
"getFunction", CallSiteGetFunction,
|
||||
"getFunctionName", CallSiteGetFunctionName,
|
||||
"getMethodName", CallSiteGetMethodName,
|
||||
"getFileName", CallSiteGetFileName,
|
||||
"getLineNumber", CallSiteGetLineNumber,
|
||||
"getColumnNumber", CallSiteGetColumnNumber,
|
||||
"isNative", CallSiteIsNative,
|
||||
"getPosition", CallSiteGetPosition,
|
||||
"isConstructor", CallSiteIsConstructor
|
||||
));
|
||||
|
||||
|
||||
function FormatEvalOrigin(script) {
|
||||
var sourceURL = script.nameOrSourceURL();
|
||||
if (sourceURL) {
|
||||
@ -1001,6 +1047,7 @@ function FormatRawStackTrace(error, raw_stack) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function captureStackTrace(obj, cons_opt) {
|
||||
var stackTraceLimit = $Error.stackTraceLimit;
|
||||
if (!stackTraceLimit || !IS_NUMBER(stackTraceLimit)) return;
|
||||
@ -1016,7 +1063,7 @@ function captureStackTrace(obj, cons_opt) {
|
||||
};
|
||||
|
||||
|
||||
(function () {
|
||||
function SetUpError() {
|
||||
// Define special error type constructors.
|
||||
|
||||
function DefineError(f) {
|
||||
@ -1085,7 +1132,9 @@ function captureStackTrace(obj, cons_opt) {
|
||||
DefineError(function ReferenceError() { });
|
||||
DefineError(function EvalError() { });
|
||||
DefineError(function URIError() { });
|
||||
})();
|
||||
}
|
||||
|
||||
SetUpError();
|
||||
|
||||
$Error.captureStackTrace = captureStackTrace;
|
||||
|
||||
|
@ -405,7 +405,8 @@ var lastMatchInfoOverride = null;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
function SetupRegExp() {
|
||||
function SetUpRegExp() {
|
||||
%CheckIsBootstrapping();
|
||||
%FunctionSetInstanceClassName($RegExp, 'RegExp');
|
||||
%FunctionSetPrototype($RegExp, new $Object());
|
||||
%SetProperty($RegExp.prototype, 'constructor', $RegExp, DONT_ENUM);
|
||||
@ -484,5 +485,4 @@ function SetupRegExp() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SetupRegExp();
|
||||
SetUpRegExp();
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "accessors.h"
|
||||
#include "api.h"
|
||||
#include "arguments.h"
|
||||
#include "bootstrapper.h"
|
||||
#include "codegen.h"
|
||||
#include "compilation-cache.h"
|
||||
#include "compiler.h"
|
||||
@ -2153,6 +2154,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsBuiltin) {
|
||||
|
||||
|
||||
RUNTIME_FUNCTION(MaybeObject*, Runtime_SetCode) {
|
||||
RUNTIME_ASSERT(isolate->bootstrapper()->IsActive());
|
||||
HandleScope scope(isolate);
|
||||
ASSERT(args.length() == 2);
|
||||
|
||||
@ -8256,6 +8258,12 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileForOnStackReplacement) {
|
||||
}
|
||||
|
||||
|
||||
RUNTIME_FUNCTION(MaybeObject*, Runtime_CheckIsBootstrapping) {
|
||||
RUNTIME_ASSERT(isolate->bootstrapper()->IsActive());
|
||||
return isolate->heap()->undefined_value();
|
||||
}
|
||||
|
||||
|
||||
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionDelegate) {
|
||||
HandleScope scope(isolate);
|
||||
ASSERT(args.length() == 1);
|
||||
|
@ -79,6 +79,7 @@ namespace internal {
|
||||
F(PreventExtensions, 1, 1)\
|
||||
\
|
||||
/* Utilities */ \
|
||||
F(CheckIsBootstrapping, 0, 1) \
|
||||
F(GetFunctionDelegate, 1, 1) \
|
||||
F(GetConstructorDelegate, 1, 1) \
|
||||
F(NewArgumentsFast, 3, 1) \
|
||||
|
@ -911,50 +911,47 @@ function ReplaceResultBuilder(str) {
|
||||
this.special_string = str;
|
||||
}
|
||||
|
||||
ReplaceResultBuilder.prototype.__proto__ = null;
|
||||
|
||||
|
||||
ReplaceResultBuilder.prototype.add = function(str) {
|
||||
str = TO_STRING_INLINE(str);
|
||||
if (str.length > 0) this.elements.push(str);
|
||||
}
|
||||
|
||||
|
||||
ReplaceResultBuilder.prototype.addSpecialSlice = function(start, end) {
|
||||
var len = end - start;
|
||||
if (start < 0 || len <= 0) return;
|
||||
if (start < 0x80000 && len < 0x800) {
|
||||
this.elements.push((start << 11) | len);
|
||||
} else {
|
||||
// 0 < len <= String::kMaxLength and Smi::kMaxValue >= String::kMaxLength,
|
||||
// so -len is a smi.
|
||||
SetUpLockedPrototype(ReplaceResultBuilder,
|
||||
$Array("elements", "special_string"), $Array(
|
||||
"add", function(str) {
|
||||
str = TO_STRING_INLINE(str);
|
||||
if (str.length > 0) this.elements.push(str);
|
||||
},
|
||||
"addSpecialSlice", function(start, end) {
|
||||
var len = end - start;
|
||||
if (start < 0 || len <= 0) return;
|
||||
if (start < 0x80000 && len < 0x800) {
|
||||
this.elements.push((start << 11) | len);
|
||||
} else {
|
||||
// 0 < len <= String::kMaxLength and Smi::kMaxValue >= String::kMaxLength,
|
||||
// so -len is a smi.
|
||||
var elements = this.elements;
|
||||
elements.push(-len);
|
||||
elements.push(start);
|
||||
}
|
||||
},
|
||||
"generate", function() {
|
||||
var elements = this.elements;
|
||||
elements.push(-len);
|
||||
elements.push(start);
|
||||
return %StringBuilderConcat(elements, elements.length, this.special_string);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ReplaceResultBuilder.prototype.generate = function() {
|
||||
var elements = this.elements;
|
||||
return %StringBuilderConcat(elements, elements.length, this.special_string);
|
||||
}
|
||||
));
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
function SetupString() {
|
||||
// Setup the constructor property on the String prototype object.
|
||||
function SetUpString() {
|
||||
%CheckIsBootstrapping();
|
||||
// Set up the constructor property on the String prototype object.
|
||||
%SetProperty($String.prototype, "constructor", $String, DONT_ENUM);
|
||||
|
||||
|
||||
// Setup the non-enumerable functions on the String object.
|
||||
// Set up the non-enumerable functions on the String object.
|
||||
InstallFunctions($String, DONT_ENUM, $Array(
|
||||
"fromCharCode", StringFromCharCode
|
||||
));
|
||||
|
||||
|
||||
// Setup the non-enumerable functions on the String prototype object.
|
||||
// Set up the non-enumerable functions on the String prototype object.
|
||||
InstallFunctionsOnHiddenPrototype($String.prototype, DONT_ENUM, $Array(
|
||||
"valueOf", StringValueOf,
|
||||
"toString", StringToString,
|
||||
@ -994,5 +991,4 @@ function SetupString() {
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
SetupString();
|
||||
SetUpString();
|
||||
|
@ -392,8 +392,9 @@ function URIUnescape(str) {
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
function SetupURI() {
|
||||
// Setup non-enumerable URI functions on the global object and set
|
||||
function SetUpUri() {
|
||||
%CheckIsBootstrapping();
|
||||
// Set up non-enumerable URI functions on the global object and set
|
||||
// their names.
|
||||
InstallFunctions(global, DONT_ENUM, $Array(
|
||||
"escape", URIEscape,
|
||||
@ -405,4 +406,4 @@ function SetupURI() {
|
||||
));
|
||||
}
|
||||
|
||||
SetupURI();
|
||||
SetUpUri();
|
||||
|
253
src/v8natives.js
253
src/v8natives.js
@ -75,12 +75,48 @@ function InstallFunctions(object, attributes, functions) {
|
||||
// functions on String.prototype etc. and then restore the old function
|
||||
// with delete. See http://code.google.com/p/chromium/issues/detail?id=1717
|
||||
function InstallFunctionsOnHiddenPrototype(object, attributes, functions) {
|
||||
%CheckIsBootstrapping();
|
||||
var hidden_prototype = new $Object();
|
||||
%SetHiddenPrototype(object, hidden_prototype);
|
||||
InstallFunctions(hidden_prototype, attributes, functions);
|
||||
}
|
||||
|
||||
|
||||
// Prevents changes to the prototype of a built-infunction.
|
||||
// The "prototype" property of the function object is made non-configurable,
|
||||
// and the prototype object is made non-extensible. The latter prevents
|
||||
// changing the __proto__ property.
|
||||
function SetUpLockedPrototype(constructor, fields, methods) {
|
||||
%CheckIsBootstrapping();
|
||||
var prototype = constructor.prototype;
|
||||
// Install functions first, because this function is used to initialize
|
||||
// PropertyDescriptor itself.
|
||||
var property_count = (methods.length >> 1) + (fields ? fields.length : 0);
|
||||
if (property_count >= 4) {
|
||||
%OptimizeObjectForAddingMultipleProperties(prototype, property_count);
|
||||
}
|
||||
if (fields) {
|
||||
for (var i = 0; i < fields.length; i++) {
|
||||
%SetProperty(prototype, fields[i], void 0, DONT_ENUM | DONT_DELETE);
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < methods.length; i += 2) {
|
||||
var key = methods[i];
|
||||
var f = methods[i + 1];
|
||||
%SetProperty(prototype, key, f, DONT_ENUM | DONT_DELETE | READ_ONLY);
|
||||
%SetNativeFlag(f);
|
||||
}
|
||||
prototype.__proto__ = null;
|
||||
%PreventExtensions(prototype);
|
||||
%ToFastProperties(prototype);
|
||||
|
||||
var desc = GetOwnProperty(constructor, "prototype");
|
||||
desc.setWritable(false);
|
||||
desc.setConfigurable(false);
|
||||
DefineOwnProperty(constructor, "prototype", desc, false);
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
@ -171,8 +207,9 @@ function GlobalEval(x) {
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
function SetupGlobal() {
|
||||
// Set up global object.
|
||||
function SetUpGlobal() {
|
||||
%CheckIsBootstrapping();
|
||||
// ECMA 262 - 15.1.1.1.
|
||||
%SetProperty(global, "NaN", $NaN, DONT_ENUM | DONT_DELETE);
|
||||
|
||||
@ -182,7 +219,7 @@ function SetupGlobal() {
|
||||
// ECMA-262 - 15.1.1.3.
|
||||
%SetProperty(global, "undefined", void 0, DONT_ENUM | DONT_DELETE);
|
||||
|
||||
// Setup non-enumerable function on the global object.
|
||||
// Set up non-enumerable function on the global object.
|
||||
InstallFunctions(global, DONT_ENUM, $Array(
|
||||
"isNaN", GlobalIsNaN,
|
||||
"isFinite", GlobalIsFinite,
|
||||
@ -192,8 +229,7 @@ function SetupGlobal() {
|
||||
));
|
||||
}
|
||||
|
||||
SetupGlobal();
|
||||
|
||||
SetUpGlobal();
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Boolean (first part of definition)
|
||||
@ -490,106 +526,83 @@ function PropertyDescriptor() {
|
||||
this.hasSetter_ = false;
|
||||
}
|
||||
|
||||
PropertyDescriptor.prototype.__proto__ = null;
|
||||
|
||||
PropertyDescriptor.prototype.toString = function() {
|
||||
return "[object PropertyDescriptor]";
|
||||
};
|
||||
|
||||
PropertyDescriptor.prototype.setValue = function(value) {
|
||||
this.value_ = value;
|
||||
this.hasValue_ = true;
|
||||
}
|
||||
|
||||
|
||||
PropertyDescriptor.prototype.getValue = function() {
|
||||
return this.value_;
|
||||
}
|
||||
|
||||
|
||||
PropertyDescriptor.prototype.hasValue = function() {
|
||||
return this.hasValue_;
|
||||
}
|
||||
|
||||
|
||||
PropertyDescriptor.prototype.setEnumerable = function(enumerable) {
|
||||
this.enumerable_ = enumerable;
|
||||
this.hasEnumerable_ = true;
|
||||
}
|
||||
|
||||
|
||||
PropertyDescriptor.prototype.isEnumerable = function () {
|
||||
return this.enumerable_;
|
||||
}
|
||||
|
||||
|
||||
PropertyDescriptor.prototype.hasEnumerable = function() {
|
||||
return this.hasEnumerable_;
|
||||
}
|
||||
|
||||
|
||||
PropertyDescriptor.prototype.setWritable = function(writable) {
|
||||
this.writable_ = writable;
|
||||
this.hasWritable_ = true;
|
||||
}
|
||||
|
||||
|
||||
PropertyDescriptor.prototype.isWritable = function() {
|
||||
return this.writable_;
|
||||
}
|
||||
|
||||
|
||||
PropertyDescriptor.prototype.hasWritable = function() {
|
||||
return this.hasWritable_;
|
||||
}
|
||||
|
||||
|
||||
PropertyDescriptor.prototype.setConfigurable = function(configurable) {
|
||||
this.configurable_ = configurable;
|
||||
this.hasConfigurable_ = true;
|
||||
}
|
||||
|
||||
|
||||
PropertyDescriptor.prototype.hasConfigurable = function() {
|
||||
return this.hasConfigurable_;
|
||||
}
|
||||
|
||||
|
||||
PropertyDescriptor.prototype.isConfigurable = function() {
|
||||
return this.configurable_;
|
||||
}
|
||||
|
||||
|
||||
PropertyDescriptor.prototype.setGet = function(get) {
|
||||
this.get_ = get;
|
||||
this.hasGetter_ = true;
|
||||
}
|
||||
|
||||
|
||||
PropertyDescriptor.prototype.getGet = function() {
|
||||
return this.get_;
|
||||
}
|
||||
|
||||
|
||||
PropertyDescriptor.prototype.hasGetter = function() {
|
||||
return this.hasGetter_;
|
||||
}
|
||||
|
||||
|
||||
PropertyDescriptor.prototype.setSet = function(set) {
|
||||
this.set_ = set;
|
||||
this.hasSetter_ = true;
|
||||
}
|
||||
|
||||
|
||||
PropertyDescriptor.prototype.getSet = function() {
|
||||
return this.set_;
|
||||
}
|
||||
|
||||
|
||||
PropertyDescriptor.prototype.hasSetter = function() {
|
||||
return this.hasSetter_;
|
||||
}
|
||||
SetUpLockedPrototype(PropertyDescriptor, $Array(
|
||||
"value_",
|
||||
"hasValue_",
|
||||
"writable_",
|
||||
"hasWritable_",
|
||||
"enumerable_",
|
||||
"hasEnumerable_",
|
||||
"configurable_",
|
||||
"hasConfigurable_",
|
||||
"get_",
|
||||
"hasGetter_",
|
||||
"set_",
|
||||
"hasSetter_"
|
||||
), $Array(
|
||||
"toString", function() {
|
||||
return "[object PropertyDescriptor]";
|
||||
},
|
||||
"setValue", function(value) {
|
||||
this.value_ = value;
|
||||
this.hasValue_ = true;
|
||||
},
|
||||
"getValue", function() {
|
||||
return this.value_;
|
||||
},
|
||||
"hasValue", function() {
|
||||
return this.hasValue_;
|
||||
},
|
||||
"setEnumerable", function(enumerable) {
|
||||
this.enumerable_ = enumerable;
|
||||
this.hasEnumerable_ = true;
|
||||
},
|
||||
"isEnumerable", function () {
|
||||
return this.enumerable_;
|
||||
},
|
||||
"hasEnumerable", function() {
|
||||
return this.hasEnumerable_;
|
||||
},
|
||||
"setWritable", function(writable) {
|
||||
this.writable_ = writable;
|
||||
this.hasWritable_ = true;
|
||||
},
|
||||
"isWritable", function() {
|
||||
return this.writable_;
|
||||
},
|
||||
"hasWritable", function() {
|
||||
return this.hasWritable_;
|
||||
},
|
||||
"setConfigurable", function(configurable) {
|
||||
this.configurable_ = configurable;
|
||||
this.hasConfigurable_ = true;
|
||||
},
|
||||
"hasConfigurable", function() {
|
||||
return this.hasConfigurable_;
|
||||
},
|
||||
"isConfigurable", function() {
|
||||
return this.configurable_;
|
||||
},
|
||||
"setGet", function(get) {
|
||||
this.get_ = get;
|
||||
this.hasGetter_ = true;
|
||||
},
|
||||
"getGet", function() {
|
||||
return this.get_;
|
||||
},
|
||||
"hasGetter", function() {
|
||||
return this.hasGetter_;
|
||||
},
|
||||
"setSet", function(set) {
|
||||
this.set_ = set;
|
||||
this.hasSetter_ = true;
|
||||
},
|
||||
"getSet", function() {
|
||||
return this.set_;
|
||||
},
|
||||
"hasSetter", function() {
|
||||
return this.hasSetter_;
|
||||
}));
|
||||
|
||||
|
||||
// Converts an array returned from Runtime_GetOwnProperty to an actual
|
||||
@ -1177,10 +1190,11 @@ function ObjectIsExtensible(obj) {
|
||||
%SetExpectedNumberOfProperties($Object, 4);
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Object
|
||||
|
||||
|
||||
function SetupObject() {
|
||||
// Setup non-enumerable functions on the Object.prototype object.
|
||||
function SetUpObject() {
|
||||
%CheckIsBootstrapping();
|
||||
// Set Up non-enumerable functions on the Object.prototype object.
|
||||
InstallFunctions($Object.prototype, DONT_ENUM, $Array(
|
||||
"toString", ObjectToString,
|
||||
"toLocaleString", ObjectToLocaleString,
|
||||
@ -1210,8 +1224,7 @@ function SetupObject() {
|
||||
));
|
||||
}
|
||||
|
||||
SetupObject();
|
||||
|
||||
SetUpObject();
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Boolean
|
||||
@ -1242,14 +1255,16 @@ function BooleanValueOf() {
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
function SetupBoolean() {
|
||||
function SetUpBoolean () {
|
||||
%CheckIsBootstrapping();
|
||||
InstallFunctions($Boolean.prototype, DONT_ENUM, $Array(
|
||||
"toString", BooleanToString,
|
||||
"valueOf", BooleanValueOf
|
||||
));
|
||||
}
|
||||
|
||||
SetupBoolean();
|
||||
SetUpBoolean();
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Number
|
||||
@ -1363,9 +1378,10 @@ function NumberToPrecision(precision) {
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
function SetupNumber() {
|
||||
function SetUpNumber() {
|
||||
%CheckIsBootstrapping();
|
||||
%OptimizeObjectForAddingMultipleProperties($Number.prototype, 8);
|
||||
// Setup the constructor property on the Number prototype object.
|
||||
// Set up the constructor property on the Number prototype object.
|
||||
%SetProperty($Number.prototype, "constructor", $Number, DONT_ENUM);
|
||||
|
||||
%OptimizeObjectForAddingMultipleProperties($Number, 5);
|
||||
@ -1394,7 +1410,7 @@ function SetupNumber() {
|
||||
DONT_ENUM | DONT_DELETE | READ_ONLY);
|
||||
%ToFastProperties($Number);
|
||||
|
||||
// Setup non-enumerable functions on the Number prototype object.
|
||||
// Set up non-enumerable functions on the Number prototype object.
|
||||
InstallFunctions($Number.prototype, DONT_ENUM, $Array(
|
||||
"toString", NumberToString,
|
||||
"toLocaleString", NumberToLocaleString,
|
||||
@ -1405,7 +1421,7 @@ function SetupNumber() {
|
||||
));
|
||||
}
|
||||
|
||||
SetupNumber();
|
||||
SetUpNumber();
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -1534,11 +1550,12 @@ function NewFunction(arg1) { // length == 1
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
function SetupFunction() {
|
||||
function SetUpFunction() {
|
||||
%CheckIsBootstrapping();
|
||||
InstallFunctions($Function.prototype, DONT_ENUM, $Array(
|
||||
"bind", FunctionBind,
|
||||
"toString", FunctionToString
|
||||
));
|
||||
}
|
||||
|
||||
SetupFunction();
|
||||
SetUpFunction();
|
||||
|
@ -80,7 +80,8 @@ function WeakMapDelete(key) {
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
function SetupWeakMap() {
|
||||
(function () {
|
||||
%CheckIsBootstrapping();
|
||||
// Set up the WeakMap constructor function.
|
||||
%SetCode($WeakMap, WeakMapConstructor);
|
||||
|
||||
@ -97,7 +98,4 @@ function SetupWeakMap() {
|
||||
"has", WeakMapHas,
|
||||
"delete", WeakMapDelete
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
SetupWeakMap();
|
||||
})();
|
||||
|
83
test/mjsunit/builtins.js
Normal file
83
test/mjsunit/builtins.js
Normal file
@ -0,0 +1,83 @@
|
||||
// Copyright 2011 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Flags: --expose-natives-as=builtins
|
||||
|
||||
// Checks that all function properties of the builtin object are neither
|
||||
// writable nor configurable. Also, theose functions that are actually
|
||||
// constructors (recognized by having properties on their .prototype object),
|
||||
// have only unconfigurable properties on the prototype, and the methods
|
||||
// are also non-writable.
|
||||
|
||||
var names = Object.getOwnPropertyNames(builtins);
|
||||
|
||||
function isFunction(obj) {
|
||||
return typeof obj == "function";
|
||||
}
|
||||
|
||||
function checkConstructor(func, name) {
|
||||
// A constructor is a function with a prototype and properties on the
|
||||
// prototype object besides "constructor";
|
||||
if (name.charAt(0) == "$") return;
|
||||
if (typeof func.prototype != "object") return;
|
||||
var propNames = Object.getOwnPropertyNames(func.prototype);
|
||||
if (propNames.length == 0 ||
|
||||
(propNames.length == 1 && propNames[0] == "constructor")) {
|
||||
// Not a constructor.
|
||||
return;
|
||||
}
|
||||
var proto_desc = Object.getOwnPropertyDescriptor(func, "prototype");
|
||||
assertTrue(proto_desc.hasOwnProperty("value"), name);
|
||||
assertFalse(proto_desc.writable, name);
|
||||
assertFalse(proto_desc.configurable, name);
|
||||
var prototype = proto_desc.value;
|
||||
assertEquals(null, prototype.__proto__, name);
|
||||
assertFalse(Object.isExtensible(prototype), name);
|
||||
for (var i = 0; i < propNames.length; i++) {
|
||||
var propName = propNames[i];
|
||||
if (propName == "constructor") continue;
|
||||
var testName = name + "-" + propName;
|
||||
var propDesc = Object.getOwnPropertyDescriptor(prototype, propName);
|
||||
assertTrue(propDesc.hasOwnProperty("value"), testName);
|
||||
assertFalse(propDesc.configurable, testName);
|
||||
if (isFunction(propDesc.value)) {
|
||||
assertFalse(propDesc.writable, testName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < names.length; i++) {
|
||||
var name = names[i];
|
||||
var desc = Object.getOwnPropertyDescriptor(builtins, name);
|
||||
assertTrue(desc.hasOwnProperty("value"));
|
||||
var value = desc.value;
|
||||
if (isFunction(value)) {
|
||||
assertFalse(desc.writable, name);
|
||||
assertFalse(desc.configurable, name);
|
||||
checkConstructor(value, name);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user