Finish V8 update
This commit is contained in:
parent
48f5f77713
commit
a49bf8622f
1
deps/v8/SConstruct
vendored
1
deps/v8/SConstruct
vendored
@ -275,7 +275,6 @@ V8_EXTRA_FLAGS = {
|
||||
'gcc': {
|
||||
'all': {
|
||||
'WARNINGFLAGS': ['-Wall',
|
||||
'-Werror',
|
||||
'-W',
|
||||
'-Wno-unused-parameter',
|
||||
'-Wnon-virtual-dtor']
|
||||
|
1089
deps/v8/src/date-delay.js
vendored
1089
deps/v8/src/date-delay.js
vendored
File diff suppressed because it is too large
Load Diff
2130
deps/v8/src/debug-delay.js
vendored
2130
deps/v8/src/debug-delay.js
vendored
File diff suppressed because it is too large
Load Diff
268
deps/v8/src/json-delay.js
vendored
268
deps/v8/src/json-delay.js
vendored
@ -1,268 +0,0 @@
|
||||
// Copyright 2009 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.
|
||||
|
||||
var $JSON = global.JSON;
|
||||
|
||||
function ParseJSONUnfiltered(text) {
|
||||
var s = $String(text);
|
||||
var f = %CompileString(text, true);
|
||||
return f();
|
||||
}
|
||||
|
||||
function Revive(holder, name, reviver) {
|
||||
var val = holder[name];
|
||||
if (IS_OBJECT(val)) {
|
||||
if (IS_ARRAY(val)) {
|
||||
var length = val.length;
|
||||
for (var i = 0; i < length; i++) {
|
||||
var newElement = Revive(val, $String(i), reviver);
|
||||
val[i] = newElement;
|
||||
}
|
||||
} else {
|
||||
for (var p in val) {
|
||||
if (ObjectHasOwnProperty.call(val, p)) {
|
||||
var newElement = Revive(val, p, reviver);
|
||||
if (IS_UNDEFINED(newElement)) {
|
||||
delete val[p];
|
||||
} else {
|
||||
val[p] = newElement;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return reviver.call(holder, name, val);
|
||||
}
|
||||
|
||||
function JSONParse(text, reviver) {
|
||||
var unfiltered = ParseJSONUnfiltered(text);
|
||||
if (IS_FUNCTION(reviver)) {
|
||||
return Revive({'': unfiltered}, '', reviver);
|
||||
} else {
|
||||
return unfiltered;
|
||||
}
|
||||
}
|
||||
|
||||
var characterQuoteCache = {
|
||||
'\"': '\\"',
|
||||
'\\': '\\\\',
|
||||
'/': '\\/',
|
||||
'\b': '\\b',
|
||||
'\f': '\\f',
|
||||
'\n': '\\n',
|
||||
'\r': '\\r',
|
||||
'\t': '\\t',
|
||||
'\x0B': '\\u000b'
|
||||
};
|
||||
|
||||
function QuoteSingleJSONCharacter(c) {
|
||||
if (c in characterQuoteCache) {
|
||||
return characterQuoteCache[c];
|
||||
}
|
||||
var charCode = c.charCodeAt(0);
|
||||
var result;
|
||||
if (charCode < 16) result = '\\u000';
|
||||
else if (charCode < 256) result = '\\u00';
|
||||
else if (charCode < 4096) result = '\\u0';
|
||||
else result = '\\u';
|
||||
result += charCode.toString(16);
|
||||
characterQuoteCache[c] = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
function QuoteJSONString(str) {
|
||||
var quotable = /[\\\"\x00-\x1f\x80-\uffff]/g;
|
||||
return '"' + str.replace(quotable, QuoteSingleJSONCharacter) + '"';
|
||||
}
|
||||
|
||||
function StackContains(stack, val) {
|
||||
var length = stack.length;
|
||||
for (var i = 0; i < length; i++) {
|
||||
if (stack[i] === val) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function SerializeArray(value, replacer, stack, indent, gap) {
|
||||
if (StackContains(stack, value)) {
|
||||
throw MakeTypeError('circular_structure', []);
|
||||
}
|
||||
stack.push(value);
|
||||
var stepback = indent;
|
||||
indent += gap;
|
||||
var partial = [];
|
||||
var len = value.length;
|
||||
for (var i = 0; i < len; i++) {
|
||||
var strP = JSONSerialize($String(i), value, replacer, stack,
|
||||
indent, gap);
|
||||
if (IS_UNDEFINED(strP)) {
|
||||
strP = "null";
|
||||
}
|
||||
partial.push(strP);
|
||||
}
|
||||
var final;
|
||||
if (gap == "") {
|
||||
final = "[" + partial.join(",") + "]";
|
||||
} else if (partial.length > 0) {
|
||||
var separator = ",\n" + indent;
|
||||
final = "[\n" + indent + partial.join(separator) + "\n" +
|
||||
stepback + "]";
|
||||
} else {
|
||||
final = "[]";
|
||||
}
|
||||
stack.pop();
|
||||
return final;
|
||||
}
|
||||
|
||||
function SerializeObject(value, replacer, stack, indent, gap) {
|
||||
if (StackContains(stack, value)) {
|
||||
throw MakeTypeError('circular_structure', []);
|
||||
}
|
||||
stack.push(value);
|
||||
var stepback = indent;
|
||||
indent += gap;
|
||||
var partial = [];
|
||||
if (IS_ARRAY(replacer)) {
|
||||
var length = replacer.length;
|
||||
for (var i = 0; i < length; i++) {
|
||||
if (ObjectHasOwnProperty.call(replacer, i)) {
|
||||
var p = replacer[i];
|
||||
var strP = JSONSerialize(p, value, replacer, stack, indent, gap);
|
||||
if (!IS_UNDEFINED(strP)) {
|
||||
var member = QuoteJSONString(p) + ":";
|
||||
if (gap != "") member += " ";
|
||||
member += strP;
|
||||
partial.push(member);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (var p in value) {
|
||||
if (ObjectHasOwnProperty.call(value, p)) {
|
||||
var strP = JSONSerialize(p, value, replacer, stack, indent, gap);
|
||||
if (!IS_UNDEFINED(strP)) {
|
||||
var member = QuoteJSONString(p) + ":";
|
||||
if (gap != "") member += " ";
|
||||
member += strP;
|
||||
partial.push(member);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var final;
|
||||
if (gap == "") {
|
||||
final = "{" + partial.join(",") + "}";
|
||||
} else if (partial.length > 0) {
|
||||
var separator = ",\n" + indent;
|
||||
final = "{\n" + indent + partial.join(separator) + "\n" +
|
||||
stepback + "}";
|
||||
} else {
|
||||
final = "{}";
|
||||
}
|
||||
stack.pop();
|
||||
return final;
|
||||
}
|
||||
|
||||
function JSONSerialize(key, holder, replacer, stack, indent, gap) {
|
||||
var value = holder[key];
|
||||
if (IS_OBJECT(value) && value) {
|
||||
var toJSON = value.toJSON;
|
||||
if (IS_FUNCTION(toJSON)) {
|
||||
value = toJSON.call(value, key);
|
||||
}
|
||||
}
|
||||
if (IS_FUNCTION(replacer)) {
|
||||
value = replacer.call(holder, key, value);
|
||||
}
|
||||
// Unwrap value if necessary
|
||||
if (IS_OBJECT(value)) {
|
||||
if (IS_NUMBER_WRAPPER(value)) {
|
||||
value = $Number(value);
|
||||
} else if (IS_STRING_WRAPPER(value)) {
|
||||
value = $String(value);
|
||||
} else if (IS_BOOLEAN_WRAPPER(value)) {
|
||||
value = $Boolean(value);
|
||||
}
|
||||
}
|
||||
switch (typeof value) {
|
||||
case "string":
|
||||
return QuoteJSONString(value);
|
||||
case "object":
|
||||
if (!value) {
|
||||
return "null";
|
||||
} else if (IS_ARRAY(value)) {
|
||||
return SerializeArray(value, replacer, stack, indent, gap);
|
||||
} else {
|
||||
return SerializeObject(value, replacer, stack, indent, gap);
|
||||
}
|
||||
case "number":
|
||||
return $isFinite(value) ? $String(value) : "null";
|
||||
case "boolean":
|
||||
return value ? "true" : "false";
|
||||
}
|
||||
}
|
||||
|
||||
function JSONStringify(value, replacer, space) {
|
||||
var stack = [];
|
||||
var indent = "";
|
||||
if (IS_OBJECT(space)) {
|
||||
// Unwrap 'space' if it is wrapped
|
||||
if (IS_NUMBER_WRAPPER(space)) {
|
||||
space = $Number(space);
|
||||
} else if (IS_STRING_WRAPPER(space)) {
|
||||
space = $String(space);
|
||||
}
|
||||
}
|
||||
var gap;
|
||||
if (IS_NUMBER(space)) {
|
||||
space = $Math.min(space, 10);
|
||||
gap = "";
|
||||
for (var i = 0; i < space; i++) {
|
||||
gap += " ";
|
||||
}
|
||||
} else if (IS_STRING(space)) {
|
||||
if (space.length > 10) {
|
||||
gap = space.substring(0, 10);
|
||||
} else {
|
||||
gap = space;
|
||||
}
|
||||
} else {
|
||||
gap = "";
|
||||
}
|
||||
return JSONSerialize('', {'': value}, replacer, stack, indent, gap);
|
||||
}
|
||||
|
||||
function SetupJSON() {
|
||||
InstallFunctions($JSON, DONT_ENUM, $Array(
|
||||
"parse", JSONParse,
|
||||
"stringify", JSONStringify
|
||||
));
|
||||
}
|
||||
|
||||
SetupJSON();
|
431
deps/v8/src/liveedit-delay.js
vendored
431
deps/v8/src/liveedit-delay.js
vendored
@ -1,431 +0,0 @@
|
||||
// Copyright 2010 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.
|
||||
|
||||
// LiveEdit feature implementation. The script should be executed after
|
||||
// debug-delay.js.
|
||||
|
||||
|
||||
// Changes script text and recompiles all relevant functions if possible.
|
||||
// The change is always a substring (change_pos, change_pos + change_len)
|
||||
// being replaced with a completely different string new_str.
|
||||
//
|
||||
// Only one function will have its Code changed in result of this function.
|
||||
// All nested functions (should they have any instances at the moment) are left
|
||||
// unchanged and re-linked to a newly created script instance representing old
|
||||
// version of the source. (Generally speaking,
|
||||
// during the change all nested functions are erased and completely different
|
||||
// set of nested functions are introduced.) All other functions just have
|
||||
// their positions updated.
|
||||
//
|
||||
// @param {Script} script that is being changed
|
||||
// @param {Array} change_log a list that collects engineer-readable description
|
||||
// of what happened.
|
||||
Debug.LiveEditChangeScript = function(script, change_pos, change_len, new_str,
|
||||
change_log) {
|
||||
|
||||
// So far the function works as namespace.
|
||||
var liveedit = Debug.LiveEditChangeScript;
|
||||
var Assert = liveedit.Assert;
|
||||
|
||||
// Fully compiles source string as a script. Returns Array of
|
||||
// FunctionCompileInfo -- a descriptions of all functions of the script.
|
||||
// Elements of array are ordered by start positions of functions (from top
|
||||
// to bottom) in the source. Fields outer_index and next_sibling_index help
|
||||
// to navigate the nesting structure of functions.
|
||||
//
|
||||
// The script is used for compilation, because it produces code that
|
||||
// needs to be linked with some particular script (for nested functions).
|
||||
function DebugGatherCompileInfo(source) {
|
||||
// Get function info, elements are partially sorted (it is a tree
|
||||
// of nested functions serialized as parent followed by serialized children.
|
||||
var raw_compile_info = %LiveEditGatherCompileInfo(script, source);
|
||||
|
||||
// Sort function infos by start position field.
|
||||
var compile_info = new Array();
|
||||
var old_index_map = new Array();
|
||||
for (var i = 0; i < raw_compile_info.length; i++) {
|
||||
compile_info.push(new liveedit.FunctionCompileInfo(raw_compile_info[i]));
|
||||
old_index_map.push(i);
|
||||
}
|
||||
|
||||
for (var i = 0; i < compile_info.length; i++) {
|
||||
var k = i;
|
||||
for (var j = i + 1; j < compile_info.length; j++) {
|
||||
if (compile_info[k].start_position > compile_info[j].start_position) {
|
||||
k = j;
|
||||
}
|
||||
}
|
||||
if (k != i) {
|
||||
var temp_info = compile_info[k];
|
||||
var temp_index = old_index_map[k];
|
||||
compile_info[k] = compile_info[i];
|
||||
old_index_map[k] = old_index_map[i];
|
||||
compile_info[i] = temp_info;
|
||||
old_index_map[i] = temp_index;
|
||||
}
|
||||
}
|
||||
|
||||
// After sorting update outer_inder field using old_index_map. Also
|
||||
// set next_sibling_index field.
|
||||
var current_index = 0;
|
||||
|
||||
// The recursive function, that goes over all children of a particular
|
||||
// node (i.e. function info).
|
||||
function ResetIndexes(new_parent_index, old_parent_index) {
|
||||
var previous_sibling = -1;
|
||||
while (current_index < compile_info.length &&
|
||||
compile_info[current_index].outer_index == old_parent_index) {
|
||||
var saved_index = current_index;
|
||||
compile_info[saved_index].outer_index = new_parent_index;
|
||||
if (previous_sibling != -1) {
|
||||
compile_info[previous_sibling].next_sibling_index = saved_index;
|
||||
}
|
||||
previous_sibling = saved_index;
|
||||
current_index++;
|
||||
ResetIndexes(saved_index, old_index_map[saved_index]);
|
||||
}
|
||||
if (previous_sibling != -1) {
|
||||
compile_info[previous_sibling].next_sibling_index = -1;
|
||||
}
|
||||
}
|
||||
|
||||
ResetIndexes(-1, -1);
|
||||
Assert(current_index == compile_info.length);
|
||||
|
||||
return compile_info;
|
||||
}
|
||||
|
||||
// Given a positions, finds a function that fully includes the entire change.
|
||||
function FindChangedFunction(compile_info, offset, len) {
|
||||
// First condition: function should start before the change region.
|
||||
// Function #0 (whole-script function) always does, but we want
|
||||
// one, that is later in this list.
|
||||
var index = 0;
|
||||
while (index + 1 < compile_info.length &&
|
||||
compile_info[index + 1].start_position <= offset) {
|
||||
index++;
|
||||
}
|
||||
// Now we are at the last function that begins before the change
|
||||
// region. The function that covers entire change region is either
|
||||
// this function or the enclosing one.
|
||||
for (; compile_info[index].end_position < offset + len;
|
||||
index = compile_info[index].outer_index) {
|
||||
Assert(index != -1);
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
// Variable forward declarations. Preprocessor "Minifier" needs them.
|
||||
var old_compile_info;
|
||||
var shared_infos;
|
||||
// Finds SharedFunctionInfo that corresponds compile info with index
|
||||
// in old version of the script.
|
||||
function FindFunctionInfo(index) {
|
||||
var old_info = old_compile_info[index];
|
||||
for (var i = 0; i < shared_infos.length; i++) {
|
||||
var info = shared_infos[i];
|
||||
if (info.start_position == old_info.start_position &&
|
||||
info.end_position == old_info.end_position) {
|
||||
return info;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Replaces function's Code.
|
||||
function PatchCode(new_info, shared_info) {
|
||||
%LiveEditReplaceFunctionCode(new_info.raw_array, shared_info.raw_array);
|
||||
|
||||
change_log.push( {function_patched: new_info.function_name} );
|
||||
}
|
||||
|
||||
var change_len_old;
|
||||
var change_len_new;
|
||||
// Translate position in old version of script into position in new
|
||||
// version of script.
|
||||
function PosTranslator(old_pos) {
|
||||
if (old_pos <= change_pos) {
|
||||
return old_pos;
|
||||
}
|
||||
if (old_pos >= change_pos + change_len_old) {
|
||||
return old_pos + change_len_new - change_len_old;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
var position_change_array;
|
||||
var position_patch_report;
|
||||
function PatchPositions(new_info, shared_info) {
|
||||
if (!shared_info) {
|
||||
// TODO: explain what is happening.
|
||||
return;
|
||||
}
|
||||
%LiveEditPatchFunctionPositions(shared_info.raw_array,
|
||||
position_change_array);
|
||||
position_patch_report.push( { name: new_info.function_name } );
|
||||
}
|
||||
|
||||
var link_to_old_script_report;
|
||||
var old_script;
|
||||
// Makes a function associated with another instance of a script (the
|
||||
// one representing its old version). This way the function still
|
||||
// may access its own text.
|
||||
function LinkToOldScript(shared_info) {
|
||||
%LiveEditRelinkFunctionToScript(shared_info.raw_array, old_script);
|
||||
|
||||
link_to_old_script_report.push( { name: shared_info.function_name } );
|
||||
}
|
||||
|
||||
|
||||
|
||||
var old_source = script.source;
|
||||
var change_len_old = change_len;
|
||||
var change_len_new = new_str.length;
|
||||
|
||||
// Prepare new source string.
|
||||
var new_source = old_source.substring(0, change_pos) +
|
||||
new_str + old_source.substring(change_pos + change_len);
|
||||
|
||||
// Find all SharedFunctionInfo's that are compiled from this script.
|
||||
var shared_raw_list = %LiveEditFindSharedFunctionInfosForScript(script);
|
||||
|
||||
var shared_infos = new Array();
|
||||
|
||||
for (var i = 0; i < shared_raw_list.length; i++) {
|
||||
shared_infos.push(new liveedit.SharedInfoWrapper(shared_raw_list[i]));
|
||||
}
|
||||
|
||||
// Gather compile information about old version of script.
|
||||
var old_compile_info = DebugGatherCompileInfo(old_source);
|
||||
|
||||
// Gather compile information about new version of script.
|
||||
var new_compile_info;
|
||||
try {
|
||||
new_compile_info = DebugGatherCompileInfo(new_source);
|
||||
} catch (e) {
|
||||
throw new liveedit.Failure("Failed to compile new version of script: " + e);
|
||||
}
|
||||
|
||||
// An index of a single function, that is going to have its code replaced.
|
||||
var function_being_patched =
|
||||
FindChangedFunction(old_compile_info, change_pos, change_len_old);
|
||||
|
||||
// In old and new script versions function with a change should have the
|
||||
// same indexes.
|
||||
var function_being_patched2 =
|
||||
FindChangedFunction(new_compile_info, change_pos, change_len_new);
|
||||
Assert(function_being_patched == function_being_patched2,
|
||||
"inconsistent old/new compile info");
|
||||
|
||||
// Check that function being patched has the same expectations in a new
|
||||
// version. Otherwise we cannot safely patch its behavior and should
|
||||
// choose the outer function instead.
|
||||
while (!liveedit.CompareFunctionExpectations(
|
||||
old_compile_info[function_being_patched],
|
||||
new_compile_info[function_being_patched])) {
|
||||
|
||||
Assert(old_compile_info[function_being_patched].outer_index ==
|
||||
new_compile_info[function_being_patched].outer_index);
|
||||
function_being_patched =
|
||||
old_compile_info[function_being_patched].outer_index;
|
||||
Assert(function_being_patched != -1);
|
||||
}
|
||||
|
||||
// Check that function being patched is not currently on stack.
|
||||
liveedit.CheckStackActivations(
|
||||
[ FindFunctionInfo(function_being_patched) ], change_log );
|
||||
|
||||
|
||||
// Committing all changes.
|
||||
var old_script_name = liveedit.CreateNameForOldScript(script);
|
||||
|
||||
// Update the script text and create a new script representing an old
|
||||
// version of the script.
|
||||
var old_script = %LiveEditReplaceScript(script, new_source, old_script_name);
|
||||
|
||||
PatchCode(new_compile_info[function_being_patched],
|
||||
FindFunctionInfo(function_being_patched));
|
||||
|
||||
var position_patch_report = new Array();
|
||||
change_log.push( {position_patched: position_patch_report} );
|
||||
|
||||
var position_change_array = [ change_pos,
|
||||
change_pos + change_len_old,
|
||||
change_pos + change_len_new ];
|
||||
|
||||
// Update positions of all outer functions (i.e. all functions, that
|
||||
// are partially below the function being patched).
|
||||
for (var i = new_compile_info[function_being_patched].outer_index;
|
||||
i != -1;
|
||||
i = new_compile_info[i].outer_index) {
|
||||
PatchPositions(new_compile_info[i], FindFunctionInfo(i));
|
||||
}
|
||||
|
||||
// Update positions of all functions that are fully below the function
|
||||
// being patched.
|
||||
var old_next_sibling =
|
||||
old_compile_info[function_being_patched].next_sibling_index;
|
||||
var new_next_sibling =
|
||||
new_compile_info[function_being_patched].next_sibling_index;
|
||||
|
||||
// We simply go over the tail of both old and new lists. Their tails should
|
||||
// have an identical structure.
|
||||
if (old_next_sibling == -1) {
|
||||
Assert(new_next_sibling == -1);
|
||||
} else {
|
||||
Assert(old_compile_info.length - old_next_sibling ==
|
||||
new_compile_info.length - new_next_sibling);
|
||||
|
||||
for (var i = old_next_sibling, j = new_next_sibling;
|
||||
i < old_compile_info.length; i++, j++) {
|
||||
PatchPositions(new_compile_info[j], FindFunctionInfo(i));
|
||||
}
|
||||
}
|
||||
|
||||
var link_to_old_script_report = new Array();
|
||||
change_log.push( { linked_to_old_script: link_to_old_script_report } );
|
||||
|
||||
// We need to link to old script all former nested functions.
|
||||
for (var i = function_being_patched + 1; i < old_next_sibling; i++) {
|
||||
LinkToOldScript(FindFunctionInfo(i), old_script);
|
||||
}
|
||||
}
|
||||
|
||||
Debug.LiveEditChangeScript.Assert = function(condition, message) {
|
||||
if (!condition) {
|
||||
if (message) {
|
||||
throw "Assert " + message;
|
||||
} else {
|
||||
throw "Assert";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// An object describing function compilation details. Its index fields
|
||||
// apply to indexes inside array that stores these objects.
|
||||
Debug.LiveEditChangeScript.FunctionCompileInfo = function(raw_array) {
|
||||
this.function_name = raw_array[0];
|
||||
this.start_position = raw_array[1];
|
||||
this.end_position = raw_array[2];
|
||||
this.param_num = raw_array[3];
|
||||
this.code = raw_array[4];
|
||||
this.scope_info = raw_array[5];
|
||||
this.outer_index = raw_array[6];
|
||||
this.next_sibling_index = null;
|
||||
this.raw_array = raw_array;
|
||||
}
|
||||
|
||||
// A structure describing SharedFunctionInfo.
|
||||
Debug.LiveEditChangeScript.SharedInfoWrapper = function(raw_array) {
|
||||
this.function_name = raw_array[0];
|
||||
this.start_position = raw_array[1];
|
||||
this.end_position = raw_array[2];
|
||||
this.info = raw_array[3];
|
||||
this.raw_array = raw_array;
|
||||
}
|
||||
|
||||
// Adds a suffix to script name to mark that it is old version.
|
||||
Debug.LiveEditChangeScript.CreateNameForOldScript = function(script) {
|
||||
// TODO(635): try better than this; support several changes.
|
||||
return script.name + " (old)";
|
||||
}
|
||||
|
||||
// Compares a function interface old and new version, whether it
|
||||
// changed or not.
|
||||
Debug.LiveEditChangeScript.CompareFunctionExpectations =
|
||||
function(function_info1, function_info2) {
|
||||
// Check that function has the same number of parameters (there may exist
|
||||
// an adapter, that won't survive function parameter number change).
|
||||
if (function_info1.param_num != function_info2.param_num) {
|
||||
return false;
|
||||
}
|
||||
var scope_info1 = function_info1.scope_info;
|
||||
var scope_info2 = function_info2.scope_info;
|
||||
|
||||
if (!scope_info1) {
|
||||
return !scope_info2;
|
||||
}
|
||||
|
||||
if (scope_info1.length != scope_info2.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check that outer scope structure is not changed. Otherwise the function
|
||||
// will not properly work with existing scopes.
|
||||
return scope_info1.toString() == scope_info2.toString();
|
||||
}
|
||||
|
||||
// For array of wrapped shared function infos checks that none of them
|
||||
// have activations on stack (of any thread). Throws a Failure exception
|
||||
// if this proves to be false.
|
||||
Debug.LiveEditChangeScript.CheckStackActivations = function(shared_wrapper_list,
|
||||
change_log) {
|
||||
var liveedit = Debug.LiveEditChangeScript;
|
||||
|
||||
var shared_list = new Array();
|
||||
for (var i = 0; i < shared_wrapper_list.length; i++) {
|
||||
shared_list[i] = shared_wrapper_list[i].info;
|
||||
}
|
||||
var result = %LiveEditCheckStackActivations(shared_list);
|
||||
var problems = new Array();
|
||||
for (var i = 0; i < shared_list.length; i++) {
|
||||
if (result[i] == liveedit.FunctionPatchabilityStatus.FUNCTION_BLOCKED_ON_STACK) {
|
||||
var shared = shared_list[i];
|
||||
var description = {
|
||||
name: shared.function_name,
|
||||
start_pos: shared.start_position,
|
||||
end_pos: shared.end_position
|
||||
};
|
||||
problems.push(description);
|
||||
}
|
||||
}
|
||||
if (problems.length > 0) {
|
||||
change_log.push( { functions_on_stack: problems } );
|
||||
throw new liveedit.Failure("Blocked by functions on stack");
|
||||
}
|
||||
}
|
||||
|
||||
// A copy of the FunctionPatchabilityStatus enum from liveedit.h
|
||||
Debug.LiveEditChangeScript.FunctionPatchabilityStatus = {
|
||||
FUNCTION_AVAILABLE_FOR_PATCH: 0,
|
||||
FUNCTION_BLOCKED_ON_STACK: 1
|
||||
}
|
||||
|
||||
|
||||
// A logical failure in liveedit process. This means that change_log
|
||||
// is valid and consistent description of what happened.
|
||||
Debug.LiveEditChangeScript.Failure = function(message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
Debug.LiveEditChangeScript.Failure.prototype.toString = function() {
|
||||
return "LiveEdit Failure: " + this.message;
|
||||
}
|
||||
|
||||
// A testing entry.
|
||||
Debug.LiveEditChangeScript.GetPcFromSourcePos = function(func, source_pos) {
|
||||
return %GetFunctionCodePositionFromSource(func, source_pos);
|
||||
}
|
2369
deps/v8/src/mirror-delay.js
vendored
2369
deps/v8/src/mirror-delay.js
vendored
File diff suppressed because it is too large
Load Diff
190
deps/v8/src/number-info.h
vendored
190
deps/v8/src/number-info.h
vendored
@ -1,190 +0,0 @@
|
||||
// Copyright 2010 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.
|
||||
|
||||
#ifndef V8_NUMBER_INFO_H_
|
||||
#define V8_NUMBER_INFO_H_
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
// Unknown
|
||||
// |
|
||||
// Number
|
||||
// / |
|
||||
// HeapNumber Integer32
|
||||
// | |
|
||||
// | Smi
|
||||
// | /
|
||||
// Uninitialized.
|
||||
|
||||
class NumberInfo {
|
||||
public:
|
||||
NumberInfo() { }
|
||||
|
||||
static inline NumberInfo Unknown();
|
||||
// We know it's a number of some sort.
|
||||
static inline NumberInfo Number();
|
||||
// We know it's signed or unsigned 32 bit integer.
|
||||
static inline NumberInfo Integer32();
|
||||
// We know it's a Smi.
|
||||
static inline NumberInfo Smi();
|
||||
// We know it's a heap number.
|
||||
static inline NumberInfo HeapNumber();
|
||||
// We haven't started collecting info yet.
|
||||
static inline NumberInfo Uninitialized();
|
||||
|
||||
// Return compact representation. Very sensitive to enum values below!
|
||||
int ThreeBitRepresentation() {
|
||||
ASSERT(type_ != kUninitializedType);
|
||||
int answer = type_ > 6 ? type_ -2 : type_;
|
||||
ASSERT(answer >= 0);
|
||||
ASSERT(answer <= 7);
|
||||
return answer;
|
||||
}
|
||||
|
||||
// Decode compact representation. Very sensitive to enum values below!
|
||||
static NumberInfo ExpandedRepresentation(int three_bit_representation) {
|
||||
Type t = static_cast<Type>(three_bit_representation >= 6 ?
|
||||
three_bit_representation + 2 :
|
||||
three_bit_representation);
|
||||
ASSERT(t == kUnknownType ||
|
||||
t == kNumberType ||
|
||||
t == kInteger32Type ||
|
||||
t == kSmiType ||
|
||||
t == kHeapNumberType);
|
||||
return NumberInfo(t);
|
||||
}
|
||||
|
||||
int ToInt() {
|
||||
return type_;
|
||||
}
|
||||
|
||||
static NumberInfo FromInt(int bit_representation) {
|
||||
Type t = static_cast<Type>(bit_representation);
|
||||
ASSERT(t == kUnknownType ||
|
||||
t == kNumberType ||
|
||||
t == kInteger32Type ||
|
||||
t == kSmiType ||
|
||||
t == kHeapNumberType);
|
||||
return NumberInfo(t);
|
||||
}
|
||||
|
||||
// Return the weakest (least precise) common type.
|
||||
static NumberInfo Combine(NumberInfo a, NumberInfo b) {
|
||||
return NumberInfo(static_cast<Type>(a.type_ & b.type_));
|
||||
}
|
||||
|
||||
inline bool IsUnknown() {
|
||||
return type_ == kUnknownType;
|
||||
}
|
||||
|
||||
inline bool IsNumber() {
|
||||
ASSERT(type_ != kUninitializedType);
|
||||
return ((type_ & kNumberType) == kNumberType);
|
||||
}
|
||||
|
||||
inline bool IsSmi() {
|
||||
ASSERT(type_ != kUninitializedType);
|
||||
return ((type_ & kSmiType) == kSmiType);
|
||||
}
|
||||
|
||||
inline bool IsInteger32() {
|
||||
ASSERT(type_ != kUninitializedType);
|
||||
return ((type_ & kInteger32Type) == kInteger32Type);
|
||||
}
|
||||
|
||||
inline bool IsHeapNumber() {
|
||||
ASSERT(type_ != kUninitializedType);
|
||||
return ((type_ & kHeapNumberType) == kHeapNumberType);
|
||||
}
|
||||
|
||||
inline bool IsUninitialized() {
|
||||
return type_ == kUninitializedType;
|
||||
}
|
||||
|
||||
const char* ToString() {
|
||||
switch (type_) {
|
||||
case kUnknownType: return "UnknownType";
|
||||
case kNumberType: return "NumberType";
|
||||
case kSmiType: return "SmiType";
|
||||
case kHeapNumberType: return "HeapNumberType";
|
||||
case kInteger32Type: return "Integer32Type";
|
||||
case kUninitializedType:
|
||||
UNREACHABLE();
|
||||
return "UninitializedType";
|
||||
}
|
||||
UNREACHABLE();
|
||||
return "Unreachable code";
|
||||
}
|
||||
|
||||
private:
|
||||
enum Type {
|
||||
kUnknownType = 0,
|
||||
kNumberType = 1,
|
||||
kInteger32Type = 3,
|
||||
kSmiType = 7,
|
||||
kHeapNumberType = 9,
|
||||
kUninitializedType = 15
|
||||
};
|
||||
explicit inline NumberInfo(Type t) : type_(t) { }
|
||||
|
||||
Type type_;
|
||||
};
|
||||
|
||||
|
||||
NumberInfo NumberInfo::Unknown() {
|
||||
return NumberInfo(kUnknownType);
|
||||
}
|
||||
|
||||
|
||||
NumberInfo NumberInfo::Number() {
|
||||
return NumberInfo(kNumberType);
|
||||
}
|
||||
|
||||
|
||||
NumberInfo NumberInfo::Integer32() {
|
||||
return NumberInfo(kInteger32Type);
|
||||
}
|
||||
|
||||
|
||||
NumberInfo NumberInfo::Smi() {
|
||||
return NumberInfo(kSmiType);
|
||||
}
|
||||
|
||||
|
||||
NumberInfo NumberInfo::HeapNumber() {
|
||||
return NumberInfo(kHeapNumberType);
|
||||
}
|
||||
|
||||
|
||||
NumberInfo NumberInfo::Uninitialized() {
|
||||
return NumberInfo(kUninitializedType);
|
||||
}
|
||||
|
||||
} } // namespace v8::internal
|
||||
|
||||
#endif // V8_NUMBER_INFO_H_
|
497
deps/v8/src/regexp-delay.js
vendored
497
deps/v8/src/regexp-delay.js
vendored
@ -1,497 +0,0 @@
|
||||
// Copyright 2006-2009 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.
|
||||
|
||||
// Expect $Object = global.Object;
|
||||
// Expect $Array = global.Array;
|
||||
|
||||
const $RegExp = global.RegExp;
|
||||
|
||||
// A recursive descent parser for Patterns according to the grammar of
|
||||
// ECMA-262 15.10.1, with deviations noted below.
|
||||
function DoConstructRegExp(object, pattern, flags, isConstructorCall) {
|
||||
// RegExp : Called as constructor; see ECMA-262, section 15.10.4.
|
||||
if (IS_REGEXP(pattern)) {
|
||||
if (!IS_UNDEFINED(flags)) {
|
||||
throw MakeTypeError('regexp_flags', []);
|
||||
}
|
||||
flags = (pattern.global ? 'g' : '')
|
||||
+ (pattern.ignoreCase ? 'i' : '')
|
||||
+ (pattern.multiline ? 'm' : '');
|
||||
pattern = pattern.source;
|
||||
}
|
||||
|
||||
pattern = IS_UNDEFINED(pattern) ? '' : ToString(pattern);
|
||||
flags = IS_UNDEFINED(flags) ? '' : ToString(flags);
|
||||
|
||||
var global = false;
|
||||
var ignoreCase = false;
|
||||
var multiline = false;
|
||||
|
||||
for (var i = 0; i < flags.length; i++) {
|
||||
var c = StringCharAt.call(flags, i);
|
||||
switch (c) {
|
||||
case 'g':
|
||||
// Allow duplicate flags to be consistent with JSC and others.
|
||||
global = true;
|
||||
break;
|
||||
case 'i':
|
||||
ignoreCase = true;
|
||||
break;
|
||||
case 'm':
|
||||
multiline = true;
|
||||
break;
|
||||
default:
|
||||
// Ignore flags that have no meaning to be consistent with
|
||||
// JSC.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isConstructorCall) {
|
||||
// ECMA-262, section 15.10.7.1.
|
||||
%SetProperty(object, 'source', pattern,
|
||||
DONT_DELETE | READ_ONLY | DONT_ENUM);
|
||||
|
||||
// ECMA-262, section 15.10.7.2.
|
||||
%SetProperty(object, 'global', global, DONT_DELETE | READ_ONLY | DONT_ENUM);
|
||||
|
||||
// ECMA-262, section 15.10.7.3.
|
||||
%SetProperty(object, 'ignoreCase', ignoreCase,
|
||||
DONT_DELETE | READ_ONLY | DONT_ENUM);
|
||||
|
||||
// ECMA-262, section 15.10.7.4.
|
||||
%SetProperty(object, 'multiline', multiline,
|
||||
DONT_DELETE | READ_ONLY | DONT_ENUM);
|
||||
|
||||
// ECMA-262, section 15.10.7.5.
|
||||
%SetProperty(object, 'lastIndex', 0, DONT_DELETE | DONT_ENUM);
|
||||
} else { // RegExp is being recompiled via RegExp.prototype.compile.
|
||||
%IgnoreAttributesAndSetProperty(object, 'source', pattern);
|
||||
%IgnoreAttributesAndSetProperty(object, 'global', global);
|
||||
%IgnoreAttributesAndSetProperty(object, 'ignoreCase', ignoreCase);
|
||||
%IgnoreAttributesAndSetProperty(object, 'multiline', multiline);
|
||||
%IgnoreAttributesAndSetProperty(object, 'lastIndex', 0);
|
||||
regExpCache.type = 'none';
|
||||
}
|
||||
|
||||
// Call internal function to compile the pattern.
|
||||
%RegExpCompile(object, pattern, flags);
|
||||
}
|
||||
|
||||
|
||||
function RegExpConstructor(pattern, flags) {
|
||||
if (%_IsConstructCall()) {
|
||||
DoConstructRegExp(this, pattern, flags, true);
|
||||
} else {
|
||||
// RegExp : Called as function; see ECMA-262, section 15.10.3.1.
|
||||
if (IS_REGEXP(pattern) && IS_UNDEFINED(flags)) {
|
||||
return pattern;
|
||||
}
|
||||
return new $RegExp(pattern, flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Deprecated RegExp.prototype.compile method. We behave like the constructor
|
||||
// were called again. In SpiderMonkey, this method returns the regexp object.
|
||||
// In JSC, it returns undefined. For compatibility with JSC, we match their
|
||||
// behavior.
|
||||
function CompileRegExp(pattern, flags) {
|
||||
// Both JSC and SpiderMonkey treat a missing pattern argument as the
|
||||
// empty subject string, and an actual undefined value passed as the
|
||||
// pattern as the string 'undefined'. Note that JSC is inconsistent
|
||||
// here, treating undefined values differently in
|
||||
// RegExp.prototype.compile and in the constructor, where they are
|
||||
// the empty string. For compatibility with JSC, we match their
|
||||
// behavior.
|
||||
if (IS_UNDEFINED(pattern) && %_ArgumentsLength() != 0) {
|
||||
DoConstructRegExp(this, 'undefined', flags, false);
|
||||
} else {
|
||||
DoConstructRegExp(this, pattern, flags, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function DoRegExpExec(regexp, string, index) {
|
||||
return %_RegExpExec(regexp, string, index, lastMatchInfo);
|
||||
}
|
||||
|
||||
|
||||
function RegExpCache() {
|
||||
this.type = 'none';
|
||||
this.regExp = 0;
|
||||
this.subject = 0;
|
||||
this.replaceString = 0;
|
||||
this.lastIndex = 0;
|
||||
this.answer = 0;
|
||||
}
|
||||
|
||||
|
||||
var regExpCache = new RegExpCache();
|
||||
|
||||
|
||||
function CloneRegexpAnswer(array) {
|
||||
var len = array.length;
|
||||
var answer = new $Array(len);
|
||||
for (var i = 0; i < len; i++) {
|
||||
answer[i] = array[i];
|
||||
}
|
||||
answer.index = array.index;
|
||||
answer.input = array.input;
|
||||
return answer;
|
||||
}
|
||||
|
||||
|
||||
function RegExpExec(string) {
|
||||
if (!IS_REGEXP(this)) {
|
||||
throw MakeTypeError('incompatible_method_receiver',
|
||||
['RegExp.prototype.exec', this]);
|
||||
}
|
||||
|
||||
var cache = regExpCache;
|
||||
|
||||
if (%_ObjectEquals(cache.type, 'exec') &&
|
||||
%_ObjectEquals(cache.lastIndex, this.lastIndex) &&
|
||||
%_ObjectEquals(cache.regExp, this) &&
|
||||
%_ObjectEquals(cache.subject, string)) {
|
||||
var last = cache.answer;
|
||||
if (last == null) {
|
||||
return last;
|
||||
} else {
|
||||
return CloneRegexpAnswer(last);
|
||||
}
|
||||
}
|
||||
|
||||
if (%_ArgumentsLength() == 0) {
|
||||
var regExpInput = LAST_INPUT(lastMatchInfo);
|
||||
if (IS_UNDEFINED(regExpInput)) {
|
||||
throw MakeError('no_input_to_regexp', [this]);
|
||||
}
|
||||
string = regExpInput;
|
||||
}
|
||||
var s;
|
||||
if (IS_STRING(string)) {
|
||||
s = string;
|
||||
} else {
|
||||
s = ToString(string);
|
||||
}
|
||||
var lastIndex = this.lastIndex;
|
||||
|
||||
var i = this.global ? TO_INTEGER(lastIndex) : 0;
|
||||
|
||||
if (i < 0 || i > s.length) {
|
||||
this.lastIndex = 0;
|
||||
return null;
|
||||
}
|
||||
|
||||
%_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, s, lastIndex]);
|
||||
// matchIndices is either null or the lastMatchInfo array.
|
||||
var matchIndices = %_RegExpExec(this, s, i, lastMatchInfo);
|
||||
|
||||
if (matchIndices == null) {
|
||||
if (this.global) this.lastIndex = 0;
|
||||
cache.lastIndex = lastIndex;
|
||||
cache.regExp = this;
|
||||
cache.subject = s;
|
||||
cache.answer = matchIndices; // Null.
|
||||
cache.type = 'exec';
|
||||
return matchIndices; // No match.
|
||||
}
|
||||
|
||||
var numResults = NUMBER_OF_CAPTURES(lastMatchInfo) >> 1;
|
||||
var result;
|
||||
if (numResults === 1) {
|
||||
var matchStart = lastMatchInfo[CAPTURE(0)];
|
||||
var matchEnd = lastMatchInfo[CAPTURE(1)];
|
||||
result = [SubString(s, matchStart, matchEnd)];
|
||||
} else {
|
||||
result = new $Array(numResults);
|
||||
for (var i = 0; i < numResults; i++) {
|
||||
var matchStart = lastMatchInfo[CAPTURE(i << 1)];
|
||||
var matchEnd = lastMatchInfo[CAPTURE((i << 1) + 1)];
|
||||
if (matchStart != -1 && matchEnd != -1) {
|
||||
result[i] = SubString(s, matchStart, matchEnd);
|
||||
} else {
|
||||
// Make sure the element is present. Avoid reading the undefined
|
||||
// property from the global object since this may change.
|
||||
result[i] = void 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result.index = lastMatchInfo[CAPTURE0];
|
||||
result.input = s;
|
||||
if (this.global) {
|
||||
this.lastIndex = lastMatchInfo[CAPTURE1];
|
||||
return result;
|
||||
} else {
|
||||
cache.regExp = this;
|
||||
cache.subject = s;
|
||||
cache.lastIndex = lastIndex;
|
||||
cache.answer = result;
|
||||
cache.type = 'exec';
|
||||
return CloneRegexpAnswer(result);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Section 15.10.6.3 doesn't actually make sense, but the intention seems to be
|
||||
// that test is defined in terms of String.prototype.exec. However, it probably
|
||||
// means the original value of String.prototype.exec, which is what everybody
|
||||
// else implements.
|
||||
function RegExpTest(string) {
|
||||
if (!IS_REGEXP(this)) {
|
||||
throw MakeTypeError('incompatible_method_receiver',
|
||||
['RegExp.prototype.test', this]);
|
||||
}
|
||||
if (%_ArgumentsLength() == 0) {
|
||||
var regExpInput = LAST_INPUT(lastMatchInfo);
|
||||
if (IS_UNDEFINED(regExpInput)) {
|
||||
throw MakeError('no_input_to_regexp', [this]);
|
||||
}
|
||||
string = regExpInput;
|
||||
}
|
||||
var s;
|
||||
if (IS_STRING(string)) {
|
||||
s = string;
|
||||
} else {
|
||||
s = ToString(string);
|
||||
}
|
||||
|
||||
var lastIndex = this.lastIndex;
|
||||
|
||||
var cache = regExpCache;
|
||||
|
||||
if (%_ObjectEquals(cache.type, 'test') &&
|
||||
%_ObjectEquals(cache.regExp, this) &&
|
||||
%_ObjectEquals(cache.subject, string) &&
|
||||
%_ObjectEquals(cache.lastIndex, lastIndex)) {
|
||||
return cache.answer;
|
||||
}
|
||||
|
||||
var length = s.length;
|
||||
var i = this.global ? TO_INTEGER(lastIndex) : 0;
|
||||
|
||||
cache.type = 'test';
|
||||
cache.regExp = this;
|
||||
cache.subject = s;
|
||||
cache.lastIndex = i;
|
||||
|
||||
if (i < 0 || i > s.length) {
|
||||
this.lastIndex = 0;
|
||||
cache.answer = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
%_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, s, lastIndex]);
|
||||
// matchIndices is either null or the lastMatchInfo array.
|
||||
var matchIndices = %_RegExpExec(this, s, i, lastMatchInfo);
|
||||
|
||||
if (matchIndices == null) {
|
||||
if (this.global) this.lastIndex = 0;
|
||||
cache.answer = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.global) this.lastIndex = lastMatchInfo[CAPTURE1];
|
||||
cache.answer = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
function RegExpToString() {
|
||||
// If this.source is an empty string, output /(?:)/.
|
||||
// http://bugzilla.mozilla.org/show_bug.cgi?id=225550
|
||||
// ecma_2/RegExp/properties-001.js.
|
||||
var src = this.source ? this.source : '(?:)';
|
||||
var result = '/' + src + '/';
|
||||
if (this.global)
|
||||
result += 'g';
|
||||
if (this.ignoreCase)
|
||||
result += 'i';
|
||||
if (this.multiline)
|
||||
result += 'm';
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// Getters for the static properties lastMatch, lastParen, leftContext, and
|
||||
// rightContext of the RegExp constructor. The properties are computed based
|
||||
// on the captures array of the last successful match and the subject string
|
||||
// of the last successful match.
|
||||
function RegExpGetLastMatch() {
|
||||
var regExpSubject = LAST_SUBJECT(lastMatchInfo);
|
||||
return SubString(regExpSubject,
|
||||
lastMatchInfo[CAPTURE0],
|
||||
lastMatchInfo[CAPTURE1]);
|
||||
}
|
||||
|
||||
|
||||
function RegExpGetLastParen() {
|
||||
var length = NUMBER_OF_CAPTURES(lastMatchInfo);
|
||||
if (length <= 2) return ''; // There were no captures.
|
||||
// We match the SpiderMonkey behavior: return the substring defined by the
|
||||
// last pair (after the first pair) of elements of the capture array even if
|
||||
// it is empty.
|
||||
var regExpSubject = LAST_SUBJECT(lastMatchInfo);
|
||||
var start = lastMatchInfo[CAPTURE(length - 2)];
|
||||
var end = lastMatchInfo[CAPTURE(length - 1)];
|
||||
if (start != -1 && end != -1) {
|
||||
return SubString(regExpSubject, start, end);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
function RegExpGetLeftContext() {
|
||||
return SubString(LAST_SUBJECT(lastMatchInfo),
|
||||
0,
|
||||
lastMatchInfo[CAPTURE0]);
|
||||
}
|
||||
|
||||
|
||||
function RegExpGetRightContext() {
|
||||
var subject = LAST_SUBJECT(lastMatchInfo);
|
||||
return SubString(subject,
|
||||
lastMatchInfo[CAPTURE1],
|
||||
subject.length);
|
||||
}
|
||||
|
||||
|
||||
// The properties $1..$9 are the first nine capturing substrings of the last
|
||||
// successful match, or ''. The function RegExpMakeCaptureGetter will be
|
||||
// called with indices from 1 to 9.
|
||||
function RegExpMakeCaptureGetter(n) {
|
||||
return function() {
|
||||
var index = n * 2;
|
||||
if (index >= NUMBER_OF_CAPTURES(lastMatchInfo)) return '';
|
||||
var matchStart = lastMatchInfo[CAPTURE(index)];
|
||||
var matchEnd = lastMatchInfo[CAPTURE(index + 1)];
|
||||
if (matchStart == -1 || matchEnd == -1) return '';
|
||||
return SubString(LAST_SUBJECT(lastMatchInfo), matchStart, matchEnd);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// Property of the builtins object for recording the result of the last
|
||||
// regexp match. The property lastMatchInfo includes the matchIndices
|
||||
// array of the last successful regexp match (an array of start/end index
|
||||
// pairs for the match and all the captured substrings), the invariant is
|
||||
// that there are at least two capture indeces. The array also contains
|
||||
// the subject string for the last successful match.
|
||||
var lastMatchInfo = [
|
||||
2, // REGEXP_NUMBER_OF_CAPTURES
|
||||
"", // Last subject.
|
||||
void 0, // Last input - settable with RegExpSetInput.
|
||||
0, // REGEXP_FIRST_CAPTURE + 0
|
||||
0, // REGEXP_FIRST_CAPTURE + 1
|
||||
];
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
function SetupRegExp() {
|
||||
%FunctionSetInstanceClassName($RegExp, 'RegExp');
|
||||
%FunctionSetPrototype($RegExp, new $Object());
|
||||
%SetProperty($RegExp.prototype, 'constructor', $RegExp, DONT_ENUM);
|
||||
%SetCode($RegExp, RegExpConstructor);
|
||||
|
||||
InstallFunctions($RegExp.prototype, DONT_ENUM, $Array(
|
||||
"exec", RegExpExec,
|
||||
"test", RegExpTest,
|
||||
"toString", RegExpToString,
|
||||
"compile", CompileRegExp
|
||||
));
|
||||
|
||||
// The length of compile is 1 in SpiderMonkey.
|
||||
%FunctionSetLength($RegExp.prototype.compile, 1);
|
||||
|
||||
// The properties input, $input, and $_ are aliases for each other. When this
|
||||
// value is set the value it is set to is coerced to a string.
|
||||
// Getter and setter for the input.
|
||||
function RegExpGetInput() {
|
||||
var regExpInput = LAST_INPUT(lastMatchInfo);
|
||||
return IS_UNDEFINED(regExpInput) ? "" : regExpInput;
|
||||
}
|
||||
function RegExpSetInput(string) {
|
||||
regExpCache.type = 'none';
|
||||
LAST_INPUT(lastMatchInfo) = ToString(string);
|
||||
};
|
||||
|
||||
%DefineAccessor($RegExp, 'input', GETTER, RegExpGetInput, DONT_DELETE);
|
||||
%DefineAccessor($RegExp, 'input', SETTER, RegExpSetInput, DONT_DELETE);
|
||||
%DefineAccessor($RegExp, '$_', GETTER, RegExpGetInput, DONT_ENUM | DONT_DELETE);
|
||||
%DefineAccessor($RegExp, '$_', SETTER, RegExpSetInput, DONT_ENUM | DONT_DELETE);
|
||||
%DefineAccessor($RegExp, '$input', GETTER, RegExpGetInput, DONT_ENUM | DONT_DELETE);
|
||||
%DefineAccessor($RegExp, '$input', SETTER, RegExpSetInput, DONT_ENUM | DONT_DELETE);
|
||||
|
||||
// The properties multiline and $* are aliases for each other. When this
|
||||
// value is set in SpiderMonkey, the value it is set to is coerced to a
|
||||
// boolean. We mimic that behavior with a slight difference: in SpiderMonkey
|
||||
// the value of the expression 'RegExp.multiline = null' (for instance) is the
|
||||
// boolean false (ie, the value after coercion), while in V8 it is the value
|
||||
// null (ie, the value before coercion).
|
||||
|
||||
// Getter and setter for multiline.
|
||||
var multiline = false;
|
||||
function RegExpGetMultiline() { return multiline; };
|
||||
function RegExpSetMultiline(flag) { multiline = flag ? true : false; };
|
||||
|
||||
%DefineAccessor($RegExp, 'multiline', GETTER, RegExpGetMultiline, DONT_DELETE);
|
||||
%DefineAccessor($RegExp, 'multiline', SETTER, RegExpSetMultiline, DONT_DELETE);
|
||||
%DefineAccessor($RegExp, '$*', GETTER, RegExpGetMultiline, DONT_ENUM | DONT_DELETE);
|
||||
%DefineAccessor($RegExp, '$*', SETTER, RegExpSetMultiline, DONT_ENUM | DONT_DELETE);
|
||||
|
||||
|
||||
function NoOpSetter(ignored) {}
|
||||
|
||||
|
||||
// Static properties set by a successful match.
|
||||
%DefineAccessor($RegExp, 'lastMatch', GETTER, RegExpGetLastMatch, DONT_DELETE);
|
||||
%DefineAccessor($RegExp, 'lastMatch', SETTER, NoOpSetter, DONT_DELETE);
|
||||
%DefineAccessor($RegExp, '$&', GETTER, RegExpGetLastMatch, DONT_ENUM | DONT_DELETE);
|
||||
%DefineAccessor($RegExp, '$&', SETTER, NoOpSetter, DONT_ENUM | DONT_DELETE);
|
||||
%DefineAccessor($RegExp, 'lastParen', GETTER, RegExpGetLastParen, DONT_DELETE);
|
||||
%DefineAccessor($RegExp, 'lastParen', SETTER, NoOpSetter, DONT_DELETE);
|
||||
%DefineAccessor($RegExp, '$+', GETTER, RegExpGetLastParen, DONT_ENUM | DONT_DELETE);
|
||||
%DefineAccessor($RegExp, '$+', SETTER, NoOpSetter, DONT_ENUM | DONT_DELETE);
|
||||
%DefineAccessor($RegExp, 'leftContext', GETTER, RegExpGetLeftContext, DONT_DELETE);
|
||||
%DefineAccessor($RegExp, 'leftContext', SETTER, NoOpSetter, DONT_DELETE);
|
||||
%DefineAccessor($RegExp, '$`', GETTER, RegExpGetLeftContext, DONT_ENUM | DONT_DELETE);
|
||||
%DefineAccessor($RegExp, '$`', SETTER, NoOpSetter, DONT_ENUM | DONT_DELETE);
|
||||
%DefineAccessor($RegExp, 'rightContext', GETTER, RegExpGetRightContext, DONT_DELETE);
|
||||
%DefineAccessor($RegExp, 'rightContext', SETTER, NoOpSetter, DONT_DELETE);
|
||||
%DefineAccessor($RegExp, "$'", GETTER, RegExpGetRightContext, DONT_ENUM | DONT_DELETE);
|
||||
%DefineAccessor($RegExp, "$'", SETTER, NoOpSetter, DONT_ENUM | DONT_DELETE);
|
||||
|
||||
for (var i = 1; i < 10; ++i) {
|
||||
%DefineAccessor($RegExp, '$' + i, GETTER, RegExpMakeCaptureGetter(i), DONT_DELETE);
|
||||
%DefineAccessor($RegExp, '$' + i, SETTER, NoOpSetter, DONT_DELETE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SetupRegExp();
|
Loading…
x
Reference in New Issue
Block a user