зеркало из https://github.com/mozilla/pjs.git
Merge m-c to b-s.
This commit is contained in:
Коммит
f51605d70a
|
@ -54,8 +54,12 @@ EXTENSIONS = \
|
|||
$(NULL)
|
||||
|
||||
define _INSTALL_EXTENSION
|
||||
cd $(srcdir)/$(dir) && \
|
||||
$(ZIP) -r9XD $(DISTROEXT)/$(dir).xpi *
|
||||
$(NSINSTALL) -D $(dir) && \
|
||||
$(PYTHON) $(MOZILLA_DIR)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) $(srcdir)/$(dir)/install.rdf.in > $(dir)/install.rdf && \
|
||||
cd $(dir) && \
|
||||
$(ZIP) -r9XD $(DISTROEXT)/$(dir).xpi install.rdf && \
|
||||
cd $(srcdir)/$(dir) && \
|
||||
$(ZIP) -r9XD $(DISTROEXT)/$(dir).xpi * -x install.rdf.in
|
||||
|
||||
endef # do not remove the blank line!
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
<?xml version="1.0"?>
|
||||
|
||||
#filter substitution
|
||||
|
||||
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
|
||||
<Description about="urn:mozilla:install-manifest">
|
||||
|
@ -13,7 +15,7 @@
|
|||
<Description>
|
||||
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
|
||||
<em:minVersion>3.5</em:minVersion>
|
||||
<em:maxVersion>6.0</em:maxVersion>
|
||||
<em:maxVersion>@FIREFOX_VERSION@</em:maxVersion>
|
||||
</Description>
|
||||
</em:targetApplication>
|
||||
|
|
@ -643,6 +643,9 @@ var Scratchpad = {
|
|||
this._tabCharacter = expandtab ? (new Array(tabsize + 1)).join(" ") : "\t";
|
||||
this.textbox.style.MozTabSize = tabsize;
|
||||
|
||||
// Force LTR direction (otherwise the textbox inherits the locale direction)
|
||||
this.textbox.style.direction = "ltr";
|
||||
|
||||
this.insertIntro();
|
||||
|
||||
// Make the Tab key work.
|
||||
|
|
|
@ -191,9 +191,8 @@ function folderToJSON(aItemId) {
|
|||
* like dates.
|
||||
*/
|
||||
function compareJSON(aNodeJSON_1, aNodeJSON_2) {
|
||||
let JSON = Cc["@mozilla.org/dom/json;1"].createInstance(Ci.nsIJSON);
|
||||
node1 = JSON.decode(aNodeJSON_1);
|
||||
node2 = JSON.decode(aNodeJSON_2);
|
||||
let node1 = JSON.parse(aNodeJSON_1);
|
||||
let node2 = JSON.parse(aNodeJSON_2);
|
||||
|
||||
// List of properties we should not compare (expected to be different).
|
||||
const SKIP_PROPS = ["dateAdded", "lastModified", "id"];
|
||||
|
|
|
@ -92,6 +92,10 @@ ifdef WIN32_OLD_STYLE_JEMALLOC
|
|||
DEFINES += -DWIN32_OLD_STYLE_JEMALLOC=1
|
||||
endif
|
||||
|
||||
ifneq (,$(filter aurora beta,$(MOZ_UPDATE_CHANNEL)))
|
||||
DEFINES += -DSHIP_FEEDBACK=1
|
||||
endif
|
||||
|
||||
ifdef MOZ_PKG_MANIFEST_P
|
||||
MOZ_PKG_MANIFEST = package-manifest
|
||||
|
||||
|
|
|
@ -10,12 +10,6 @@
|
|||
|
||||
#filter substitution
|
||||
|
||||
#if MOZ_UPDATE_CHANNEL == aurora
|
||||
#define SHIP_FEEDBACK
|
||||
#elif MOZ_UPDATE_CHANNEL == beta
|
||||
#define SHIP_FEEDBACK
|
||||
#endif
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
; Mac bundle stuff
|
||||
@APPNAME@/Contents/Info.plist
|
||||
|
|
|
@ -3,11 +3,6 @@
|
|||
# These files are in alphabetical order, except that files removed only on
|
||||
# certain platforms are after all of the regular files and obsolete Talkback and
|
||||
# Inspector files are at the very end.
|
||||
#if MOZ_UPDATE_CHANNEL == aurora
|
||||
#define SHIP_FEEDBACK
|
||||
#elif MOZ_UPDATE_CHANNEL == beta
|
||||
#define SHIP_FEEDBACK
|
||||
#endif
|
||||
.autoreg
|
||||
@DLL_PREFIX@jsj@DLL_SUFFIX@
|
||||
@DLL_PREFIX@sqlite3@DLL_SUFFIX@
|
||||
|
@ -960,6 +955,7 @@ xpicleanup@BIN_SUFFIX@
|
|||
modules/PluralForm.jsm
|
||||
modules/PopupNotifications.jsm
|
||||
modules/PropertyPanel.jsm
|
||||
modules/reflect.jsm
|
||||
modules/Services.jsm
|
||||
modules/services-sync/auth.js
|
||||
modules/services-sync/base_records/collection.js
|
||||
|
|
|
@ -215,9 +215,7 @@ nsFrameMessageManager::GetParamsForMessage(nsAString& aMessageName,
|
|||
|
||||
if (argc >= 2) {
|
||||
jsval v = argv[1];
|
||||
if (JS_TryJSON(ctx, &v)) {
|
||||
JS_Stringify(ctx, &v, nsnull, JSVAL_NULL, JSONCreator, &aJSON);
|
||||
}
|
||||
JS_Stringify(ctx, &v, nsnull, JSVAL_NULL, JSONCreator, &aJSON);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -455,8 +453,7 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
|
|||
funval, 1, argv.jsval_addr(), &rval);
|
||||
if (aJSONRetVal) {
|
||||
nsString json;
|
||||
if (JS_TryJSON(ctx, &rval) &&
|
||||
JS_Stringify(ctx, &rval, nsnull, JSVAL_NULL,
|
||||
if (JS_Stringify(ctx, &rval, nsnull, JSVAL_NULL,
|
||||
JSONCreator, &json)) {
|
||||
aJSONRetVal->AppendElement(json);
|
||||
}
|
||||
|
|
|
@ -1314,11 +1314,12 @@ void
|
|||
nsScriptLoader::PreloadURI(nsIURI *aURI, const nsAString &aCharset,
|
||||
const nsAString &aType)
|
||||
{
|
||||
nsRefPtr<nsScriptLoadRequest> request = new nsScriptLoadRequest(nsnull, 0);
|
||||
if (!request) {
|
||||
// Check to see if scripts has been turned off.
|
||||
if (!mEnabled || !mDocument->IsScriptEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<nsScriptLoadRequest> request = new nsScriptLoadRequest(nsnull, 0);
|
||||
request->mURI = aURI;
|
||||
request->mIsInline = PR_FALSE;
|
||||
request->mLoading = PR_TRUE;
|
||||
|
|
|
@ -23,6 +23,18 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=666604
|
|||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function hitEventLoop(times, next)
|
||||
{
|
||||
if (times == 0) {
|
||||
next();
|
||||
return;
|
||||
}
|
||||
|
||||
SimpleTest.executeSoon(function() {
|
||||
hitEventLoop(times - 1, next);
|
||||
});
|
||||
}
|
||||
|
||||
var activationListener;
|
||||
|
||||
function dispatchClick(target, ctrl) {
|
||||
|
@ -71,7 +83,7 @@ function test3() {
|
|||
test4();
|
||||
}
|
||||
dispatchClick(testlink, true);
|
||||
setTimeout(test4, 1000);
|
||||
hitEventLoop(10, test4);
|
||||
}
|
||||
|
||||
function test4() {
|
||||
|
@ -81,7 +93,7 @@ function test4() {
|
|||
test5();
|
||||
}
|
||||
dispatchReturn(testlink, true);
|
||||
setTimeout(test5, 1000);
|
||||
hitEventLoop(10, test5);
|
||||
}
|
||||
|
||||
function test5() {
|
||||
|
@ -102,18 +114,36 @@ function test6() {
|
|||
dispatchDOMActivate(testlink);
|
||||
}
|
||||
|
||||
var oldPref;
|
||||
function test7() {
|
||||
oldPref = SpecialPowers.getBoolPref("dom.disable_open_during_load");
|
||||
SpecialPowers.setBoolPref("dom.disable_open_during_load", false);
|
||||
testlink.href = "javascript:opener.activationListener(); window.close();";
|
||||
testlink.target = "_blank";
|
||||
activationListener =
|
||||
function() {
|
||||
ok(true, "Click() should activate a link");
|
||||
setTimeout(test9, 0);
|
||||
setTimeout(test8, 0);
|
||||
}
|
||||
testlink.click();
|
||||
}
|
||||
|
||||
function test8() {
|
||||
SpecialPowers.setBoolPref("dom.disable_open_during_load", true);
|
||||
testlink.href = "javascript:opener.activationListener(); window.close();";
|
||||
testlink.target = "_blank";
|
||||
activationListener =
|
||||
function() {
|
||||
ok(false, "Click() should not activate a link");
|
||||
setTimeout(test9, 0);
|
||||
}
|
||||
testlink.click();
|
||||
hitEventLoop(10, test9);
|
||||
}
|
||||
|
||||
|
||||
function test9() {
|
||||
SpecialPowers.setBoolPref("dom.disable_open_during_load", oldPref);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
|
|
|
@ -907,6 +907,8 @@ nsHTMLInputElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
|||
UpdateTooLongValidityState();
|
||||
} else if (aName == nsGkAtoms::pattern) {
|
||||
UpdatePatternMismatchValidityState();
|
||||
} else if (aName == nsGkAtoms::multiple) {
|
||||
UpdateTypeMismatchValidityState();
|
||||
}
|
||||
|
||||
UpdateEditableState(aNotify);
|
||||
|
|
|
@ -241,7 +241,6 @@ _TEST_FILES = \
|
|||
test_bug297761.html \
|
||||
file_bug297761.html \
|
||||
test_bug607145.html \
|
||||
test_bug601061.html \
|
||||
test_bug596511.html \
|
||||
reflect.js \
|
||||
test_bug611189.html \
|
||||
|
@ -262,7 +261,6 @@ _TEST_FILES = \
|
|||
test_bug622558.html \
|
||||
test_bug622597.html \
|
||||
test_bug636336.html \
|
||||
test_bug630889.html \
|
||||
test_bug610212.html \
|
||||
test_bug633058.html \
|
||||
test_bug641219.html \
|
||||
|
|
|
@ -58,6 +58,7 @@ _TEST_FILES = \
|
|||
test_label_control_attribute.html \
|
||||
test_output_element.html \
|
||||
test_button_attributes_reflection.html \
|
||||
test_textarea_attributes_reflection.html \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
|
|
|
@ -21,11 +21,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=551670
|
|||
/** Test for Bug 551670 **/
|
||||
|
||||
// .type
|
||||
reflectLimitedEnumerated(document.createElement("button"),
|
||||
"type",
|
||||
[ "submit", "reset", "button" ],
|
||||
[ "this-is-probably-a-wrong-type", "", "tulip" ],
|
||||
"submit");
|
||||
reflectLimitedEnumerated({
|
||||
element: document.createElement("button"),
|
||||
attribute: "type",
|
||||
validValues: [ "submit", "reset", "button" ],
|
||||
invalidValues: [ "this-is-probably-a-wrong-type", "", "tulip" ],
|
||||
defaultValue: "submit",
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
|
|
|
@ -1,38 +1,44 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=551670
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 551670</title>
|
||||
<title>Test for HTMLInputElement attributes reflection</title>
|
||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="../reflect.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=551670">Mozilla Bug 551670</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 551670 **/
|
||||
/** Test for HTMLInputElement attributes reflection **/
|
||||
|
||||
// TODO: maybe make those reflections be tested against all input types.
|
||||
|
||||
// .accept
|
||||
reflectString(document.createElement("input"), "accept",
|
||||
[ "audio/*", "video/*", "image/*", "image/png",
|
||||
"application/msword", "appplication/pdf" ]);
|
||||
reflectString({
|
||||
element: document.createElement("input"),
|
||||
attribute: "accept",
|
||||
otherValues: [ "audio/*", "video/*", "image/*", "image/png",
|
||||
"application/msword", "appplication/pdf" ],
|
||||
});
|
||||
|
||||
// .alt
|
||||
reflectString(document.createElement("input"), "alt");
|
||||
reflectString({
|
||||
element: document.createElement("input"),
|
||||
attribute: "alt",
|
||||
});
|
||||
|
||||
// .autocomplete
|
||||
reflectLimitedEnumerated(document.createElement("input"), "autocomplete",
|
||||
[ "on", "off" ], [ "", "default", "foo", "tulip" ]);
|
||||
reflectLimitedEnumerated({
|
||||
element: document.createElement("input"),
|
||||
attribute: "autocomplete",
|
||||
validValues: [ "on", "off" ],
|
||||
invalidValues: [ "", "default", "foo", "tulip" ],
|
||||
});
|
||||
|
||||
// TODO: autofocus (boolean)
|
||||
// TODO: defaultChecked (boolean)
|
||||
|
@ -44,21 +50,32 @@ reflectLimitedEnumerated(document.createElement("input"), "autocomplete",
|
|||
// TODO: formAction (URL)
|
||||
|
||||
// .formEnctype
|
||||
reflectLimitedEnumerated(document.createElement("input"), "formEnctype",
|
||||
[ "application/x-www-form-urlencoded",
|
||||
"multipart/form-data", "text/plain" ],
|
||||
[ "", "foo", "tulip", "multipart/foo" ],
|
||||
"application/x-www-form-urlencoded");
|
||||
reflectLimitedEnumerated({
|
||||
element: document.createElement("input"),
|
||||
attribute: "formEnctype",
|
||||
validValues: [ "application/x-www-form-urlencoded", "multipart/form-data",
|
||||
"text/plain" ],
|
||||
invalidValues: [ "", "foo", "tulip", "multipart/foo" ],
|
||||
defaultValue: "application/x-www-form-urlencoded"
|
||||
});
|
||||
|
||||
// .formMethod
|
||||
reflectLimitedEnumerated(document.createElement("input"), "formMethod",
|
||||
[ "get", "post" ], [ "", "foo", "tulip" ], "get");
|
||||
reflectLimitedEnumerated({
|
||||
element: document.createElement("input"),
|
||||
attribute: "formMethod",
|
||||
validValues: [ "get", "post" ],
|
||||
invalidValues: [ "", "foo", "tulip" ],
|
||||
defaultValue: "get"
|
||||
});
|
||||
|
||||
// TODO: formNoValidate (boolean)
|
||||
|
||||
// .formTarget
|
||||
reflectString(document.createElement("input"), "formTarget",
|
||||
[ "_blank", "_self", "_parent", "_top" ]);
|
||||
reflectString({
|
||||
element: document.createElement("input"),
|
||||
attribute: "formTarget",
|
||||
otherValues: [ "_blank", "_self", "_parent", "_top" ],
|
||||
});
|
||||
|
||||
// TODO: height (non-negative integer)
|
||||
// TODO: indeterminate (boolean)
|
||||
|
@ -69,35 +86,60 @@ reflectString(document.createElement("input"), "formTarget",
|
|||
// TODO: multiple (boolean)
|
||||
|
||||
// .name
|
||||
reflectString(document.createElement("input"), "name",
|
||||
[ "isindex", "_charset_" ]);
|
||||
reflectString({
|
||||
element: document.createElement("input"),
|
||||
attribute: "name",
|
||||
otherValues: [ "isindex", "_charset_" ],
|
||||
});
|
||||
|
||||
// .pattern
|
||||
reflectString(document.createElement("input"), "pattern",
|
||||
[ "[0-9][A-Z]{3}" ]);
|
||||
reflectString({
|
||||
element: document.createElement("input"),
|
||||
attribute: "pattern",
|
||||
otherValues: [ "[0-9][A-Z]{3}" ],
|
||||
});
|
||||
|
||||
// .placeholder
|
||||
reflectString(document.createElement("input"), "placeholder",
|
||||
[ "foo\nbar", "foo\rbar", "foo\r\nbar" ]);
|
||||
reflectString({
|
||||
element: document.createElement("input"),
|
||||
attribute: "placeholder",
|
||||
otherValues: [ "foo\nbar", "foo\rbar", "foo\r\nbar" ],
|
||||
});
|
||||
|
||||
// TODO: readOnly (boolean)
|
||||
// TODO: required (boolean)
|
||||
// TODO: size (unsigned long)
|
||||
|
||||
// .size
|
||||
reflectUnsignedInt({
|
||||
element: document.createElement("input"),
|
||||
attribute: "size",
|
||||
nonZero: true,
|
||||
defaultValue: 20,
|
||||
});
|
||||
|
||||
// TODO: src (URL)
|
||||
// TODO: step (not implemented)
|
||||
|
||||
// .type
|
||||
reflectLimitedEnumerated(document.createElement("input"),
|
||||
"type",
|
||||
[ "hidden", "text", "search", "tel", "url", "email",
|
||||
"password", "checkbox", "radio", "file", "submit",
|
||||
"image", "reset", "button" ],
|
||||
[ "this-is-probably-a-wrong-type", "", "tulip" ],
|
||||
"text",
|
||||
[ "datetime", "date", "month", "week", "time",
|
||||
"datetime-local", "number", "range", "color" ]);
|
||||
reflectLimitedEnumerated({
|
||||
element: document.createElement("input"),
|
||||
attribute: "type",
|
||||
validValues: [ "hidden", "text", "search", "tel", "url", "email", "password",
|
||||
"checkbox", "radio", "file", "submit", "image", "reset",
|
||||
"button" ],
|
||||
invalidValues: [ "this-is-probably-a-wrong-type", "", "tulip" ],
|
||||
defaultValue: "text",
|
||||
unsupportedValues: [ "datetime", "date", "month", "week", "time",
|
||||
"datetime-local", "number", "range", "color" ]
|
||||
});
|
||||
|
||||
// .defaultValue
|
||||
reflectString({
|
||||
element: document.createElement("input"),
|
||||
attribute: { idl: "defaultValue", content: "value" },
|
||||
otherValues: [ "foo\nbar", "foo\rbar", "foo\r\nbar" ],
|
||||
});
|
||||
|
||||
// TODO: defaultValue (reflects @value)
|
||||
// .value doesn't reflect a content attribute.
|
||||
// TODO: valueAsDate (not implemented)
|
||||
// TODO: valueAsNumber (not implemented)
|
||||
|
|
|
@ -2,20 +2,17 @@
|
|||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=555559
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=668817
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 555559</title>
|
||||
<title>Test for <input type='email'> validity</title>
|
||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<style>
|
||||
input { background-color: rgb(0,0,0) !important; }
|
||||
input:valid { background-color: rgb(0,255,0) !important; }
|
||||
input:invalid { background-color: rgb(255,0,0) !important; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=555559">Mozilla Bug 555559</a>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=668817">Mozilla Bug 668817</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
<form>
|
||||
|
@ -25,9 +22,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=555559
|
|||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 555559 **/
|
||||
|
||||
// More checks are done in test_bug551670.html.
|
||||
/** Test for <input type='email'> validity **/
|
||||
|
||||
var gInvalid = false;
|
||||
|
||||
|
@ -47,8 +42,7 @@ function checkValidEmailAddress(element)
|
|||
ok(!gInvalid, "The invalid event should not have been thrown");
|
||||
is(element.validationMessage, '',
|
||||
"Validation message should be the empty string");
|
||||
is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
|
||||
"rgb(0, 255, 0)", ":valid pseudo-class should apply");
|
||||
ok(element.mozMatchesSelector(":valid"), ":valid pseudo-class should apply");
|
||||
}
|
||||
|
||||
function checkInvalidEmailAddress(element)
|
||||
|
@ -61,180 +55,133 @@ function checkInvalidEmailAddress(element)
|
|||
ok(gInvalid, "The invalid event should have been thrown");
|
||||
is(element.validationMessage, "Please enter an email address.",
|
||||
"Validation message is not valid");
|
||||
is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
|
||||
"rgb(255, 0, 0)", ":invalid pseudo-class should apply");
|
||||
ok(element.mozMatchesSelector(":invalid"), ":invalid pseudo-class should apply");
|
||||
}
|
||||
|
||||
function testEmailAddress(aElement, aValue, aMultiple, aValidity)
|
||||
{
|
||||
aElement.multiple = aMultiple;
|
||||
aElement.value = aValue;
|
||||
|
||||
if (aValidity) {
|
||||
checkValidEmailAddress(aElement);
|
||||
} else {
|
||||
checkInvalidEmailAddress(aElement);
|
||||
}
|
||||
}
|
||||
|
||||
var email = document.forms[0].elements[0];
|
||||
is(email.type, 'email', "email state should be recognized");
|
||||
|
||||
// This is not really a valid email address
|
||||
// but it should not be considered as invalid.
|
||||
email.value = '';
|
||||
checkValidEmailAddress(email);
|
||||
// Simple values, checking the e-mail syntax validity.
|
||||
var values = [
|
||||
[ '', true ], // The empty string shouldn't be considered as invalid.
|
||||
[ 'foo@bar.com', true ],
|
||||
[ ' foo@bar.com', false ],
|
||||
[ 'foo@bar.com ', false ],
|
||||
[ 'tulip', false ],
|
||||
// Some checks on the user part of the address.
|
||||
[ '@bar.com', false ],
|
||||
[ 'f\noo@bar.com', true ],
|
||||
[ 'f\roo@bar.com', true ],
|
||||
[ 'f\r\noo@bar.com', true ],
|
||||
// Some checks for the domain part.
|
||||
[ 'foo@bar', true ],
|
||||
[ 'foo@b', true ],
|
||||
[ 'foo@', false ],
|
||||
[ 'foo@bar.', false ],
|
||||
[ 'foo@foo.bar', true ],
|
||||
[ 'foo@foo..bar', false ],
|
||||
[ 'foo@.bar', false ],
|
||||
[ 'foo@tulip.foo.bar', true ],
|
||||
[ 'foo@tulip.foo-bar', true ],
|
||||
[ 'foo@1.2', true ],
|
||||
[ 'foo@127.0.0.1', true ],
|
||||
[ 'foo@1.2.3', true ],
|
||||
[ 'foo@b\nar.com', true ],
|
||||
[ 'foo@b\rar.com', true ],
|
||||
[ 'foo@b\r\nar.com', true ],
|
||||
[ 'foo@.', false ],
|
||||
];
|
||||
|
||||
email.value = 'foo@bar.com';
|
||||
checkValidEmailAddress(email);
|
||||
// Multiple values, we don't check e-mail validity, only multiple stuff.
|
||||
var multipleValues = [
|
||||
[ 'foo@bar.com, foo@bar.com', true ],
|
||||
[ 'foo@bar.com,foo@bar.com', true ],
|
||||
[ 'foo@bar.com,foo@bar.com,foo@bar.com', true ],
|
||||
[ ' foo@bar.com , foo@bar.com ', true ],
|
||||
[ '\tfoo@bar.com\t,\tfoo@bar.com\t', true ],
|
||||
[ '\rfoo@bar.com\r,\rfoo@bar.com\r', true ],
|
||||
[ '\nfoo@bar.com\n,\nfoo@bar.com\n', true ],
|
||||
[ '\ffoo@bar.com\f,\ffoo@bar.com\f', true ],
|
||||
[ '\t foo@bar.com\r,\nfoo@bar.com\f', true ],
|
||||
[ 'foo@b,ar.com,foo@bar.com', false ],
|
||||
[ 'foo@bar.com,foo@bar.com,', false ],
|
||||
[ ' foo@bar.com , foo@bar.com , ', false ],
|
||||
[ ',foo@bar.com,foo@bar.com', false ],
|
||||
[ ',foo@bar.com,foo@bar.com', false ],
|
||||
[ 'foo@bar.com,,,foo@bar.com', false ],
|
||||
[ 'foo@bar.com;foo@bar.com', false ],
|
||||
[ '<foo@bar.com>, <foo@bar.com>', false ],
|
||||
[ 'foo@bar, foo@bar.com', true ],
|
||||
[ 'foo@bar.com, foo', false ],
|
||||
[ 'foo, foo@bar.com', false ],
|
||||
];
|
||||
|
||||
email.value = ' foo@bar.com';
|
||||
checkInvalidEmailAddress(email);
|
||||
|
||||
email.value = 'foo@bar.com ';
|
||||
checkInvalidEmailAddress(email);
|
||||
|
||||
email.value = 'tulip';
|
||||
checkInvalidEmailAddress(email);
|
||||
|
||||
// Some checks on the user part of the address.
|
||||
email.value = '@bar.com';
|
||||
checkInvalidEmailAddress(email);
|
||||
/* Additional username checks. */
|
||||
|
||||
var legalCharacters = "abcdefghijklmnopqrstuvwxyz";
|
||||
legalCharacters += "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
legalCharacters += "0123456789";
|
||||
legalCharacters += "!#$%&'*+-/=?^_`{|}~.";
|
||||
|
||||
for each (c in legalCharacters)
|
||||
{
|
||||
email.value = c + '@bar.com';
|
||||
checkValidEmailAddress(email);
|
||||
// Add all username legal characters individually to the list.
|
||||
for each (c in legalCharacters) {
|
||||
values.push([c + "@bar.com", true]);
|
||||
}
|
||||
// Add the concatenation of all legal characters too.
|
||||
values.push([legalCharacters + "@bar.com", true]);
|
||||
|
||||
// Add username illegal characters, the same way.
|
||||
var illegalCharacters = "()<>[]:;@\\, \t";
|
||||
for each (c in illegalCharacters) {
|
||||
values.push([illegalCharacters + "@bar.com", false]);
|
||||
}
|
||||
|
||||
email.value = legalCharacters + '@bar.com';
|
||||
checkValidEmailAddress(email);
|
||||
/* Additional domain checks. */
|
||||
|
||||
// Checking stripped characters.
|
||||
email.value = 'f\noo@bar.com';
|
||||
checkValidEmailAddress(email);
|
||||
legalCharacters = "abcdefghijklmnopqrstuvwxyz";
|
||||
legalCharacters += "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
legalCharacters += "0123456789";
|
||||
legalCharacters += "-";
|
||||
|
||||
email.value = 'f\roo@bar.com';
|
||||
checkValidEmailAddress(email);
|
||||
// Add domain legal characters (except '.' because it's special).
|
||||
for each (c in legalCharacters) {
|
||||
values.push(["foo@foo.bar" + c, true]);
|
||||
}
|
||||
// Add the concatenation of all legal characters too.
|
||||
values.push(["foo@bar.com" + legalCharacters, true]);
|
||||
|
||||
// Testing some illegal characters.
|
||||
var illegalCharacters = "()<>[]:;@\, \t";
|
||||
|
||||
for each (c in illegalCharacters)
|
||||
{
|
||||
email.value = c + '@bar.com';
|
||||
checkInvalidEmailAddress(email);
|
||||
// Add domain illegal characters.
|
||||
illegalCharacters = "()<>[]:;@\\,!#$%&'*+/=?^_`{|}~ \t";
|
||||
for each (c in illegalCharacters) {
|
||||
values.push(['foo@foo.bar' + c, false]);
|
||||
}
|
||||
|
||||
// Some checks on the domain part of the address.
|
||||
email.value = 'foo@bar';
|
||||
checkValidEmailAddress(email);
|
||||
values.forEach(function([value, valid]) {
|
||||
testEmailAddress(email, value, false, valid);
|
||||
});
|
||||
|
||||
email.value = 'foo@b';
|
||||
checkValidEmailAddress(email);
|
||||
multipleValues.forEach(function([value, valid]) {
|
||||
testEmailAddress(email, value, true, valid);
|
||||
});
|
||||
|
||||
email.value = 'foo@';
|
||||
// Make sure setting multiple changes the value.
|
||||
email.multiple = false;
|
||||
email.value = "foo@bar.com, foo@bar.com";
|
||||
checkInvalidEmailAddress(email);
|
||||
|
||||
email.value = 'foo@bar.';
|
||||
checkInvalidEmailAddress(email);
|
||||
|
||||
email.value = 'foo@foo.bar';
|
||||
checkValidEmailAddress(email);
|
||||
|
||||
email.value = 'foo@foo..bar';
|
||||
checkInvalidEmailAddress(email);
|
||||
|
||||
email.value = 'foo@.bar';
|
||||
checkInvalidEmailAddress(email);
|
||||
|
||||
email.value = 'foo@tulip.foo.bar';
|
||||
checkValidEmailAddress(email);
|
||||
|
||||
email.value = 'foo@tulip.foo-bar';
|
||||
checkValidEmailAddress(email);
|
||||
|
||||
email.value = 'foo@1.2';
|
||||
checkValidEmailAddress(email);
|
||||
|
||||
email.value = 'foo@127.0.0.1';
|
||||
checkValidEmailAddress(email);
|
||||
|
||||
email.value = 'foo@1.2.3.';
|
||||
checkInvalidEmailAddress(email);
|
||||
|
||||
// Checking stripped characters.
|
||||
email.value = 'foo@b\nar.com';
|
||||
checkValidEmailAddress(email);
|
||||
|
||||
email.value = 'foo@b\rar.com';
|
||||
checkValidEmailAddress(email);
|
||||
|
||||
// Testing some illegal characters.
|
||||
illegalCharacters = "()<>[]:;@\,!#$%&'*+/=?^_`{|}~ \t";
|
||||
|
||||
for each (c in illegalCharacters)
|
||||
{
|
||||
email.value = 'foo@foo.bar' + c;
|
||||
checkInvalidEmailAddress(email);
|
||||
}
|
||||
|
||||
// Testing multiple: we are not going to re-test email validity, just multiple.
|
||||
email.multiple = true;
|
||||
|
||||
email.value = 'foo@bar.com, foo@bar.com';
|
||||
checkValidEmailAddress(email);
|
||||
|
||||
email.value = 'foo@bar.com,foo@bar.com';
|
||||
checkValidEmailAddress(email);
|
||||
|
||||
email.value = 'foo@bar.com,foo@bar.com,foo@bar.com';
|
||||
checkValidEmailAddress(email);
|
||||
|
||||
email.value = ' foo@bar.com , foo@bar.com ';
|
||||
checkValidEmailAddress(email);
|
||||
|
||||
email.value = '\tfoo@bar.com\t,\tfoo@bar.com\t';
|
||||
checkValidEmailAddress(email);
|
||||
|
||||
email.value = '\rfoo@bar.com\r,\rfoo@bar.com\r';
|
||||
checkValidEmailAddress(email);
|
||||
|
||||
email.value = '\nfoo@bar.com\n,\nfoo@bar.com\n';
|
||||
checkValidEmailAddress(email);
|
||||
|
||||
email.value = '\ffoo@bar.com\f,\ffoo@bar.com\f';
|
||||
checkValidEmailAddress(email);
|
||||
|
||||
email.value = '\t foo@bar.com\r,\nfoo@bar.com\f';
|
||||
checkValidEmailAddress(email);
|
||||
|
||||
email.value = 'foo@b,ar.com,foo@bar.com';
|
||||
checkInvalidEmailAddress(email);
|
||||
|
||||
email.value = 'foo@bar.com,foo@bar.com,';
|
||||
checkInvalidEmailAddress(email);
|
||||
|
||||
email.value = ' foo@bar.com , foo@bar.com , ';
|
||||
checkInvalidEmailAddress(email);
|
||||
|
||||
email.value = ',foo@bar.com,foo@bar.com';
|
||||
checkInvalidEmailAddress(email);
|
||||
|
||||
email.value = ',foo@bar.com,foo@bar.com';
|
||||
checkInvalidEmailAddress(email);
|
||||
|
||||
email.value = 'foo@bar.com,,,foo@bar.com';
|
||||
checkInvalidEmailAddress(email);
|
||||
|
||||
email.value = 'foo@bar.com;foo@bar.com';
|
||||
checkInvalidEmailAddress(email);
|
||||
|
||||
email.value = '<foo@bar.com>, <foo@bar.com>';
|
||||
checkInvalidEmailAddress(email);
|
||||
|
||||
email.value = 'foo@bar, foo@bar.com';
|
||||
checkValidEmailAddress(email);
|
||||
|
||||
email.value = 'foo@bar.com, foo';
|
||||
checkInvalidEmailAddress(email);
|
||||
|
||||
email.value = 'foo, foo@bar.com';
|
||||
checkInvalidEmailAddress(email);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for HTMLTextAreaElement attributes reflection</title>
|
||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="../reflect.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for HTMLTextAreaElement attributes reflection **/
|
||||
|
||||
var textarea = document.createElement("textarea");
|
||||
|
||||
reflectUnsignedInt({
|
||||
element: textarea,
|
||||
attribute: "rows",
|
||||
nonZero: true,
|
||||
defaultValue: 2,
|
||||
});
|
||||
|
||||
reflectUnsignedInt({
|
||||
element: textarea,
|
||||
attribute: "cols",
|
||||
nonZero: true,
|
||||
defaultValue: 20,
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -8,47 +8,58 @@
|
|||
* http://www.whatwg.org/html/#reflecting-content-attributes-in-idl-attributes
|
||||
*
|
||||
* Do not forget to add these line at the beginning of each new reflect* method:
|
||||
* ok(aAttr in aElement, aAttr + " should be an IDL attribute of this element");
|
||||
* is(typeof aElement[aAttr], <type>, aAttr + " IDL attribute should be a <type>");
|
||||
* ok(attr in element, attr + " should be an IDL attribute of this element");
|
||||
* is(typeof element[attr], <type>, attr + " IDL attribute should be a <type>");
|
||||
*/
|
||||
|
||||
/**
|
||||
* Checks that a given attribute is correctly reflected as a string.
|
||||
*
|
||||
* @param aElement Element node to test
|
||||
* @param aAttr String name of the attribute
|
||||
* @param aOtherValues Array other values to test in addition of the default ones [optional]
|
||||
* @param aParameters Object object containing the parameters, which are:
|
||||
* - element Element node to test
|
||||
* - attribute String name of the attribute
|
||||
* OR
|
||||
* attribute Object object containing two attributes, 'content' and 'idl'
|
||||
* - otherValues Array [optional] other values to test in addition of the default ones
|
||||
*/
|
||||
function reflectString(aElement, aAttr, aOtherValues)
|
||||
function reflectString(aParameters)
|
||||
{
|
||||
var otherValues = aOtherValues !== undefined ? aOtherValues : [];
|
||||
var element = aParameters.element;
|
||||
var contentAttr = typeof aParameters.attribute === "string"
|
||||
? aParameters.attribute : aParameters.attribute.content;
|
||||
var idlAttr = typeof aParameters.attribute === "string"
|
||||
? aParameters.attribute : aParameters.attribute.idl;
|
||||
var otherValues = aParameters.otherValues !== undefined
|
||||
? aParameters.otherValues : [];
|
||||
|
||||
ok(aAttr in aElement, aAttr + " should be an IDL attribute of this element");
|
||||
is(typeof aElement[aAttr], "string", aAttr + " IDL attribute should be a string");
|
||||
ok(idlAttr in element,
|
||||
idlAttr + " should be an IDL attribute of this element");
|
||||
is(typeof element[idlAttr], "string",
|
||||
idlAttr + " IDL attribute should be a string");
|
||||
|
||||
// Tests when the attribute isn't set.
|
||||
is(aElement.getAttribute(aAttr), null,
|
||||
"When not set, the content attribute should be undefined.");
|
||||
is(aElement[aAttr], "",
|
||||
is(element.getAttribute(contentAttr), null,
|
||||
"When not set, the content attribute should be null.");
|
||||
is(element[idlAttr], "",
|
||||
"When not set, the IDL attribute should return the empty string");
|
||||
|
||||
/**
|
||||
* TODO: as long as null stringification doesn't fallow the webidl specs,
|
||||
* don't add it to the loop below and keep it here.
|
||||
* TODO: as long as null stringification doesn't follow the WebIDL
|
||||
* specifications, don't add it to the loop below and keep it here.
|
||||
*/
|
||||
aElement.setAttribute(aAttr, null);
|
||||
todo_is(aElement.getAttribute(aAttr), "null",
|
||||
element.setAttribute(contentAttr, null);
|
||||
todo_is(element.getAttribute(contentAttr), "null",
|
||||
"null should have been stringified to 'null'");
|
||||
todo_is(aElement[aAttr], "null",
|
||||
todo_is(element[idlAttr], "null",
|
||||
"null should have been stringified to 'null'");
|
||||
aElement.removeAttribute(aAttr);
|
||||
element.removeAttribute(contentAttr);
|
||||
|
||||
aElement[aAttr] = null;
|
||||
todo_is(aElement.getAttribute(aAttr), "null",
|
||||
element[idlAttr] = null;
|
||||
todo_is(element.getAttribute(contentAttr), "null",
|
||||
"null should have been stringified to 'null'");
|
||||
todo_is(aElement[aAttr], "null",
|
||||
todo_is(element[idlAttr], "null",
|
||||
"null should have been stringified to 'null'");
|
||||
aElement.removeAttribute(aAttr);
|
||||
element.removeAttribute(contentAttr);
|
||||
|
||||
// Tests various strings.
|
||||
var stringsToTest = [
|
||||
|
@ -57,7 +68,8 @@ function reflectString(aElement, aAttr, aOtherValues)
|
|||
[ "null", "null" ],
|
||||
[ "undefined", "undefined" ],
|
||||
[ "foo", "foo" ],
|
||||
[ aAttr, aAttr ],
|
||||
[ contentAttr, contentAttr ],
|
||||
[ idlAttr, idlAttr ],
|
||||
// TODO: uncomment this when null stringification will follow the specs.
|
||||
// [ null, "null" ],
|
||||
[ undefined, "undefined" ],
|
||||
|
@ -80,77 +92,86 @@ function reflectString(aElement, aAttr, aOtherValues)
|
|||
otherValues.forEach(function(v) { stringsToTest.push([v, v]) });
|
||||
|
||||
stringsToTest.forEach(function([v, r]) {
|
||||
aElement.setAttribute(aAttr, v);
|
||||
is(aElement[aAttr], r,
|
||||
element.setAttribute(contentAttr, v);
|
||||
is(element[idlAttr], r,
|
||||
"IDL attribute should return the value it has been set to.");
|
||||
is(aElement.getAttribute(aAttr), r,
|
||||
is(element.getAttribute(contentAttr), r,
|
||||
"Content attribute should return the value it has been set to.");
|
||||
aElement.removeAttribute(aAttr);
|
||||
element.removeAttribute(contentAttr);
|
||||
|
||||
aElement[aAttr] = v;
|
||||
is(aElement[aAttr], r,
|
||||
element[idlAttr] = v;
|
||||
is(element[idlAttr], r,
|
||||
"IDL attribute should return the value it has been set to.");
|
||||
is(aElement.getAttribute(aAttr), r,
|
||||
is(element.getAttribute(contentAttr), r,
|
||||
"Content attribute should return the value it has been set to.");
|
||||
aElement.removeAttribute(aAttr);
|
||||
element.removeAttribute(contentAttr);
|
||||
});
|
||||
|
||||
// Tests after removeAttribute() is called. Should be equivalent with not set.
|
||||
is(aElement.getAttribute(aAttr), null,
|
||||
"When not set, the content attribute should be undefined.");
|
||||
is(aElement[aAttr], "",
|
||||
is(element.getAttribute(contentAttr), null,
|
||||
"When not set, the content attribute should be null.");
|
||||
is(element[idlAttr], "",
|
||||
"When not set, the IDL attribute should return the empty string");
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that a given attribute name for a given element is correctly reflected
|
||||
* as an unsigned int.
|
||||
*
|
||||
* @param aParameters Object object containing the parameters, which are:
|
||||
* - element Element node to test on
|
||||
* - attribute String name of the attribute
|
||||
* - nonZero Boolean whether the attribute should be non-null
|
||||
* - defaultValue Integer [optional] default value, if different from the default one
|
||||
*/
|
||||
function reflectUnsignedInt(aElement, aAttr, aNonNull, aDefault)
|
||||
function reflectUnsignedInt(aParameters)
|
||||
{
|
||||
function checkGetter(aElement, aAttr, aValue)
|
||||
{
|
||||
is(aElement[aAttr], aValue, "." + aAttr + " should be equals " + aValue);
|
||||
is(aElement.getAttribute(aAttr), aValue,
|
||||
"@" + aAttr + " should be equals " + aValue);
|
||||
}
|
||||
var element = aParameters.element;
|
||||
var attr = aParameters.attribute;
|
||||
var nonZero = aParameters.nonZero;
|
||||
var defaultValue = aParameters.defaultValue;
|
||||
|
||||
if (!aDefault) {
|
||||
if (aNonNull) {
|
||||
aDefault = 1;
|
||||
if (defaultValue === undefined) {
|
||||
if (nonZero) {
|
||||
defaultValue = 1;
|
||||
} else {
|
||||
aDefault = 0;
|
||||
defaultValue = 0;
|
||||
}
|
||||
}
|
||||
|
||||
ok(aAttr in aElement, aAttr + " should be an IDL attribute of this element");
|
||||
is(typeof aElement[aAttr], "number", aAttr + " IDL attribute should be a string");
|
||||
ok(attr in element, attr + " should be an IDL attribute of this element");
|
||||
is(typeof element[attr], "number", attr + " IDL attribute should be a number");
|
||||
|
||||
// Check default value.
|
||||
is(aElement[aAttr], aDefault, "default value should be " + aDefault);
|
||||
ok(!aElement.hasAttribute(aAttr), aAttr + " shouldn't be present");
|
||||
is(element[attr], defaultValue, "default value should be " + defaultValue);
|
||||
ok(!element.hasAttribute(attr), attr + " shouldn't be present");
|
||||
|
||||
var values = [ 1, 3, 42, 2147483647 ];
|
||||
|
||||
for each (var value in values) {
|
||||
aElement[aAttr] = value;
|
||||
checkGetter(aElement, aAttr, value);
|
||||
}
|
||||
element[attr] = value;
|
||||
is(element[attr], value, "." + attr + " should be equals " + value);
|
||||
is(element.getAttribute(attr), value,
|
||||
"@" + attr + " should be equals " + value);
|
||||
|
||||
for each (var value in values) {
|
||||
aElement.setAttribute(aAttr, value);
|
||||
checkGetter(aElement, aAttr, value);
|
||||
element.setAttribute(attr, value);
|
||||
is(element[attr], value, "." + attr + " should be equals " + value);
|
||||
is(element.getAttribute(attr), value,
|
||||
"@" + attr + " should be equals " + value);
|
||||
}
|
||||
|
||||
// -3000000000 is equivalent to 1294967296 when using the IDL attribute.
|
||||
aElement[aAttr] = -3000000000;
|
||||
checkGetter(aElement, aAttr, 1294967296);
|
||||
element[attr] = -3000000000;
|
||||
is(element[attr], 1294967296, "." + attr + " should be equals to 1294967296");
|
||||
is(element.getAttribute(attr), 1294967296,
|
||||
"@" + attr + " should be equals to 1294967296");
|
||||
|
||||
// When setting the content atribute, it's a string so it will be unvalid.
|
||||
aElement.setAttribute(aAttr, -3000000000);
|
||||
is(aElement.getAttribute(aAttr), -3000000000,
|
||||
"@" + aAttr + " should be equals to " + -3000000000);
|
||||
is(aElement[aAttr], aDefault,
|
||||
"." + aAttr + " should be equals to " + aDefault);
|
||||
element.setAttribute(attr, -3000000000);
|
||||
is(element.getAttribute(attr), -3000000000,
|
||||
"@" + attr + " should be equals to " + -3000000000);
|
||||
is(element[attr], defaultValue,
|
||||
"." + attr + " should be equals to " + defaultValue);
|
||||
|
||||
var nonValidValues = [
|
||||
/* invalid value, value in the unsigned int range */
|
||||
|
@ -160,148 +181,156 @@ function reflectUnsignedInt(aElement, aAttr, aNonNull, aDefault)
|
|||
];
|
||||
|
||||
for each (var values in nonValidValues) {
|
||||
aElement[aAttr] = values[0];
|
||||
is(aElement.getAttribute(aAttr), values[1],
|
||||
"@" + aAttr + " should be equals to " + values[1]);
|
||||
is(aElement[aAttr], aDefault,
|
||||
"." + aAttr + " should be equals to " + aDefault);
|
||||
element[attr] = values[0];
|
||||
is(element.getAttribute(attr), values[1],
|
||||
"@" + attr + " should be equals to " + values[1]);
|
||||
is(element[attr], defaultValue,
|
||||
"." + attr + " should be equals to " + defaultValue);
|
||||
}
|
||||
|
||||
for each (var values in nonValidValues) {
|
||||
aElement.setAttribute(aAttr, values[0]);
|
||||
is(aElement.getAttribute(aAttr), values[0],
|
||||
"@" + aAttr + " should be equals to " + values[0]);
|
||||
is(aElement[aAttr], aDefault,
|
||||
"." + aAttr + " should be equals to " + aDefault);
|
||||
element.setAttribute(attr, values[0]);
|
||||
is(element.getAttribute(attr), values[0],
|
||||
"@" + attr + " should be equals to " + values[0]);
|
||||
is(element[attr], defaultValue,
|
||||
"." + attr + " should be equals to " + defaultValue);
|
||||
}
|
||||
|
||||
// Setting to 0 should throw an error if aNonNull is true.
|
||||
// Setting to 0 should throw an error if nonZero is true.
|
||||
var caught = false;
|
||||
try {
|
||||
aElement[aAttr] = 0;
|
||||
element[attr] = 0;
|
||||
} catch(e) {
|
||||
caught = true;
|
||||
is(e.code, DOMException.INDEX_SIZE_ERR, "exception should be INDEX_SIZE_ERR");
|
||||
}
|
||||
|
||||
if (aNonNull) {
|
||||
if (nonZero) {
|
||||
ok(caught, "an exception should have been caught");
|
||||
} else {
|
||||
ok(!caught, "no exception should have been caught");
|
||||
}
|
||||
|
||||
// If 0 is set in @aAttr, it will be ignored when calling .aAttr.
|
||||
aElement.setAttribute(aAttr, 0);
|
||||
is(aElement.getAttribute(aAttr), 0, "@" + aAttr + " should be equals to 0");
|
||||
if (aNonNull) {
|
||||
is(aElement[aAttr], aDefault,
|
||||
"." + aAttr + " should be equals to " + aDefault);
|
||||
// If 0 is set in @attr, it will be ignored when calling .attr.
|
||||
element.setAttribute(attr, 0);
|
||||
is(element.getAttribute(attr), 0, "@" + attr + " should be equals to 0");
|
||||
if (nonZero) {
|
||||
is(element[attr], defaultValue,
|
||||
"." + attr + " should be equals to " + defaultValue);
|
||||
} else {
|
||||
is(aElement[aAttr], 0, "." + aAttr + " should be equals to 0");
|
||||
is(element[attr], 0, "." + attr + " should be equals to 0");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param aElement Element node to test on
|
||||
* @param aAttr String name of the attribute
|
||||
* @param aValidValues Array valid values we support
|
||||
* @param aInvalidValues Array invalid values
|
||||
* @param aDefaultValue String default value when no valid value is set [optional]
|
||||
* @param aUnsupportedValues Array valid values we do not support [optional]
|
||||
* Checks that a given attribute is correctly reflected as limited to known
|
||||
* values enumerated attribute.
|
||||
*
|
||||
* @param aParameters Object object containing the parameters, which are:
|
||||
* - element Element node to test on
|
||||
* - attribute String name of the attribute
|
||||
* - validValues Array valid values we support
|
||||
* - invalidValues Array invalid values
|
||||
* - defaultValue String [optional] default value when no valid value is set
|
||||
* - unsupportedValues Array [optional] valid values we do not support
|
||||
*/
|
||||
function reflectLimitedEnumerated(aElement, aAttr, aValidValues, aInvalidValues,
|
||||
aDefaultValue, aUnsupportedValues)
|
||||
function reflectLimitedEnumerated(aParameters)
|
||||
{
|
||||
var defaultValue = aDefaultValue !== undefined ? aDefaultValue : "";
|
||||
var unsupportedValues = aUnsupportedValues !== undefined ? aUnsupportedValues
|
||||
: [];
|
||||
var element = aParameters.element;
|
||||
var attr = aParameters.attribute;
|
||||
var validValues = aParameters.validValues;
|
||||
var invalidValues = aParameters.invalidValues;
|
||||
var defaultValue = aParameters.defaultValue !== undefined
|
||||
? aParameters.defaultValue : "";
|
||||
var unsupportedValues = aParameters.unsupportedValues !== undefined
|
||||
? aParameters.unsupportedValues : [];
|
||||
|
||||
ok(aAttr in aElement, aAttr + " should be an IDL attribute of this element");
|
||||
is(typeof aElement[aAttr], "string", aAttr + " IDL attribute should be a string");
|
||||
ok(attr in element, attr + " should be an IDL attribute of this element");
|
||||
is(typeof element[attr], "string", attr + " IDL attribute should be a string");
|
||||
|
||||
// Explicitly check the default value.
|
||||
aElement.removeAttribute(aAttr);
|
||||
is(aElement[aAttr], defaultValue,
|
||||
element.removeAttribute(attr);
|
||||
is(element[attr], defaultValue,
|
||||
"When no attribute is set, the value should be the default value.");
|
||||
|
||||
// Check valid values.
|
||||
aValidValues.forEach(function (v) {
|
||||
aElement.setAttribute(aAttr, v);
|
||||
is(aElement[aAttr], v,
|
||||
v + " should be accepted as a valid value for " + aAttr);
|
||||
is(aElement.getAttribute(aAttr), v,
|
||||
validValues.forEach(function (v) {
|
||||
element.setAttribute(attr, v);
|
||||
is(element[attr], v,
|
||||
v + " should be accepted as a valid value for " + attr);
|
||||
is(element.getAttribute(attr), v,
|
||||
"Content attribute should return the value it has been set to.");
|
||||
aElement.removeAttribute(aAttr);
|
||||
element.removeAttribute(attr);
|
||||
|
||||
aElement.setAttribute(aAttr, v.toUpperCase());
|
||||
is(aElement[aAttr], v,
|
||||
element.setAttribute(attr, v.toUpperCase());
|
||||
is(element[attr], v,
|
||||
"Enumerated attributes should be case-insensitive.");
|
||||
is(aElement.getAttribute(aAttr), v.toUpperCase(),
|
||||
is(element.getAttribute(attr), v.toUpperCase(),
|
||||
"Content attribute should not be lower-cased.");
|
||||
aElement.removeAttribute(aAttr);
|
||||
element.removeAttribute(attr);
|
||||
|
||||
aElement[aAttr] = v;
|
||||
is(aElement[aAttr], v,
|
||||
v + " should be accepted as a valid value for " + aAttr);
|
||||
is(aElement.getAttribute(aAttr), v,
|
||||
element[attr] = v;
|
||||
is(element[attr], v,
|
||||
v + " should be accepted as a valid value for " + attr);
|
||||
is(element.getAttribute(attr), v,
|
||||
"Content attribute should return the value it has been set to.");
|
||||
aElement.removeAttribute(aAttr);
|
||||
element.removeAttribute(attr);
|
||||
|
||||
aElement[aAttr] = v.toUpperCase();
|
||||
is(aElement[aAttr], v,
|
||||
element[attr] = v.toUpperCase();
|
||||
is(element[attr], v,
|
||||
"Enumerated attributes should be case-insensitive.");
|
||||
is(aElement.getAttribute(aAttr), v.toUpperCase(),
|
||||
is(element.getAttribute(attr), v.toUpperCase(),
|
||||
"Content attribute should not be lower-cased.");
|
||||
aElement.removeAttribute(aAttr);
|
||||
element.removeAttribute(attr);
|
||||
});
|
||||
|
||||
// Check invalid values.
|
||||
aInvalidValues.forEach(function (v) {
|
||||
aElement.setAttribute(aAttr, v);
|
||||
is(aElement[aAttr], defaultValue,
|
||||
invalidValues.forEach(function (v) {
|
||||
element.setAttribute(attr, v);
|
||||
is(element[attr], defaultValue,
|
||||
"When the content attribute is set to an invalid value, the default value should be returned.");
|
||||
is(aElement.getAttribute(aAttr), v,
|
||||
is(element.getAttribute(attr), v,
|
||||
"Content attribute should not have been changed.");
|
||||
aElement.removeAttribute(aAttr);
|
||||
element.removeAttribute(attr);
|
||||
|
||||
aElement[aAttr] = v;
|
||||
is(aElement[aAttr], defaultValue,
|
||||
element[attr] = v;
|
||||
is(element[attr], defaultValue,
|
||||
"When the value is set to an invalid value, the default value should be returned.");
|
||||
is(aElement.getAttribute(aAttr), v,
|
||||
is(element.getAttribute(attr), v,
|
||||
"Content attribute should not have been changed.");
|
||||
aElement.removeAttribute(aAttr);
|
||||
element.removeAttribute(attr);
|
||||
});
|
||||
|
||||
// Check valid values we currently do not support.
|
||||
// Basically, it's like the checks for the valid values but with some todo's.
|
||||
unsupportedValues.forEach(function (v) {
|
||||
aElement.setAttribute(aAttr, v);
|
||||
todo_is(aElement[aAttr], v,
|
||||
v + " should be accepted as a valid value for " + aAttr);
|
||||
is(aElement.getAttribute(aAttr), v,
|
||||
element.setAttribute(attr, v);
|
||||
todo_is(element[attr], v,
|
||||
v + " should be accepted as a valid value for " + attr);
|
||||
is(element.getAttribute(attr), v,
|
||||
"Content attribute should return the value it has been set to.");
|
||||
aElement.removeAttribute(aAttr);
|
||||
element.removeAttribute(attr);
|
||||
|
||||
aElement.setAttribute(aAttr, v.toUpperCase());
|
||||
todo_is(aElement[aAttr], v,
|
||||
element.setAttribute(attr, v.toUpperCase());
|
||||
todo_is(element[attr], v,
|
||||
"Enumerated attributes should be case-insensitive.");
|
||||
is(aElement.getAttribute(aAttr), v.toUpperCase(),
|
||||
is(element.getAttribute(attr), v.toUpperCase(),
|
||||
"Content attribute should not be lower-cased.");
|
||||
aElement.removeAttribute(aAttr);
|
||||
element.removeAttribute(attr);
|
||||
|
||||
aElement[aAttr] = v;
|
||||
todo_is(aElement[aAttr], v,
|
||||
v + " should be accepted as a valid value for " + aAttr);
|
||||
is(aElement.getAttribute(aAttr), v,
|
||||
element[attr] = v;
|
||||
todo_is(element[attr], v,
|
||||
v + " should be accepted as a valid value for " + attr);
|
||||
is(element.getAttribute(attr), v,
|
||||
"Content attribute should return the value it has been set to.");
|
||||
aElement.removeAttribute(aAttr);
|
||||
element.removeAttribute(attr);
|
||||
|
||||
aElement[aAttr] = v.toUpperCase();
|
||||
todo_is(aElement[aAttr], v,
|
||||
element[attr] = v.toUpperCase();
|
||||
todo_is(element[attr], v,
|
||||
"Enumerated attributes should be case-insensitive.");
|
||||
is(aElement.getAttribute(aAttr), v.toUpperCase(),
|
||||
is(element.getAttribute(attr), v.toUpperCase(),
|
||||
"Content attribute should not be lower-cased.");
|
||||
aElement.removeAttribute(aAttr);
|
||||
element.removeAttribute(attr);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=601061
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 601061</title>
|
||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="reflect.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=601061">Mozilla Bug 601061</a>
|
||||
<p id="display"></p>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 601061 **/
|
||||
|
||||
reflectUnsignedInt(document.createElement("input"), "size", true, 20);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -22,8 +22,20 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=610212
|
|||
/** Test for Bug 610212 **/
|
||||
|
||||
var canvas = document.createElement('canvas');
|
||||
reflectUnsignedInt(canvas, "width", false, 300);
|
||||
reflectUnsignedInt(canvas, "height", false, 150);
|
||||
|
||||
reflectUnsignedInt({
|
||||
element: canvas,
|
||||
attribute: "width",
|
||||
nonZero: false,
|
||||
defaultValue: 300,
|
||||
});
|
||||
|
||||
reflectUnsignedInt({
|
||||
element: canvas,
|
||||
attribute: "height",
|
||||
nonZero: false,
|
||||
defaultValue: 150,
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=630889
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 630889</title>
|
||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="reflect.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=630889">Mozilla Bug 630889</a>
|
||||
<p id="display"></p>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 630889 **/
|
||||
|
||||
var textarea = document.createElement('textarea');
|
||||
reflectUnsignedInt(textarea, "rows", true, 2);
|
||||
reflectUnsignedInt(textarea, "cols", true, 20);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -19,12 +19,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=660663
|
|||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
/** Test for Bug 660663 **/
|
||||
reflectLimitedEnumerated(document.createElement("div"),
|
||||
"dir",
|
||||
["ltr", "rtl"],
|
||||
["cheesecake", ""],
|
||||
undefined, // There is no default value.
|
||||
["auto"]);
|
||||
reflectLimitedEnumerated({
|
||||
element: document.createElement("div"),
|
||||
attribute: "dir",
|
||||
validValues: ["ltr", "rtl"],
|
||||
invalidValues: ["cheesecake", ""],
|
||||
unsupportedValues: ["auto"]
|
||||
});
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
|
|
|
@ -95,24 +95,27 @@ ConsoleAPI.prototype = {
|
|||
|
||||
// We need to return an actual content object here, instead of a wrapped
|
||||
// chrome object. This allows things like console.log.bind() to work.
|
||||
let sandbox = Cu.Sandbox(aWindow);
|
||||
let contentObject = Cu.evalInSandbox(
|
||||
"(function(x) {\
|
||||
var bind = Function.bind;\
|
||||
var obj = {\
|
||||
log: bind.call(x.log, x),\
|
||||
info: bind.call(x.info, x),\
|
||||
warn: bind.call(x.warn, x),\
|
||||
error: bind.call(x.error, x),\
|
||||
debug: bind.call(x.debug, x),\
|
||||
trace: bind.call(x.trace, x),\
|
||||
__noSuchMethod__: function() {}\
|
||||
};\
|
||||
Object.defineProperty(obj, '__mozillaConsole__', { value: true });\
|
||||
return obj;\
|
||||
})", sandbox)(chromeObject);
|
||||
let contentObj = Cu.createObjectIn(aWindow);
|
||||
function genPropDesc(fun) {
|
||||
return { enumerable: true, configurable: true, writable: true,
|
||||
value: chromeObject[fun].bind(chromeObject) };
|
||||
}
|
||||
const properties = {
|
||||
log: genPropDesc('log'),
|
||||
info: genPropDesc('info'),
|
||||
warn: genPropDesc('warn'),
|
||||
error: genPropDesc('error'),
|
||||
debug: genPropDesc('debug'),
|
||||
trace: genPropDesc('trace'),
|
||||
__noSuchMethod__: { enumerable: true, configurable: true, writable: true,
|
||||
value: function() {} },
|
||||
__mozillaConsole__: { value: true }
|
||||
};
|
||||
|
||||
return contentObject;
|
||||
Object.defineProperties(contentObj, properties);
|
||||
Cu.makeObjectPropsNormal(contentObj);
|
||||
|
||||
return contentObj;
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -52,18 +52,14 @@ interface nsIScriptGlobalObject;
|
|||
/**
|
||||
* Encode and decode JSON text.
|
||||
*/
|
||||
[scriptable, uuid(a4d68b4e-0c0b-4c7c-b540-ef2f9834171f)]
|
||||
[scriptable, uuid(98f12947-5eac-4512-8325-7c9e6a9d8509)]
|
||||
interface nsIJSON : nsISupports
|
||||
{
|
||||
AString encode(/* in JSObject value */);
|
||||
|
||||
void encodeToStream(in nsIOutputStream stream,
|
||||
in string charset,
|
||||
in boolean writeBOM
|
||||
/* in JSObject value */);
|
||||
|
||||
void /* JSObject */ decode(in AString str);
|
||||
|
||||
void /* JSObject */ decodeFromStream(in nsIInputStream stream,
|
||||
in long contentLength);
|
||||
|
||||
|
@ -79,15 +75,17 @@ interface nsIJSON : nsISupports
|
|||
*
|
||||
* This method is provided only as a temporary transition path for users of
|
||||
* the old code who depended on the ability to decode leniently; new users
|
||||
* should use the non-legacy decoding methods.
|
||||
* should use JSON.parse.
|
||||
*
|
||||
* This method must only be called from script.
|
||||
*
|
||||
* @param str the string to parse
|
||||
*/
|
||||
void /* JSObject */ legacyDecode(in AString str);
|
||||
void /* jsval */ legacyDecode(in AString str);
|
||||
|
||||
/* Identical to legacyDecode, but decode the contents of stream. */
|
||||
void /* JSObject */ legacyDecodeFromStream(in nsIInputStream stream,
|
||||
in long contentLength);
|
||||
void /* jsval */ legacyDecodeFromStream(in nsIInputStream stream,
|
||||
in long contentLength);
|
||||
|
||||
/* Identical to legacyDecode, but decode into a jsval. */
|
||||
// Make sure you GCroot the result of this function before using it.
|
||||
|
|
|
@ -75,34 +75,6 @@ nsJSON::~nsJSON()
|
|||
{
|
||||
}
|
||||
|
||||
//
|
||||
// AString encode(in JSObject value, [optional] in JSObject whitelist);
|
||||
//
|
||||
NS_IMETHODIMP
|
||||
nsJSON::Encode(nsAString &aJSON)
|
||||
{
|
||||
// This function should only be called from JS.
|
||||
nsresult rv;
|
||||
|
||||
nsJSONWriter writer;
|
||||
rv = EncodeInternal(&writer);
|
||||
|
||||
// FIXME: bug 408838. Get exception types sorted out
|
||||
if (NS_SUCCEEDED(rv) || rv == NS_ERROR_INVALID_ARG) {
|
||||
rv = NS_OK;
|
||||
// if we didn't consume anything, it's not JSON, so return null
|
||||
if (!writer.DidWrite()) {
|
||||
aJSON.Truncate();
|
||||
aJSON.SetIsVoid(PR_TRUE);
|
||||
} else {
|
||||
writer.FlushBuffer();
|
||||
aJSON.Append(writer.mOutputString);
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static const char UTF8BOM[] = "\xEF\xBB\xBF";
|
||||
static const char UTF16LEBOM[] = "\xFF\xFE";
|
||||
static const char UTF16BEBOM[] = "\xFE\xFF";
|
||||
|
@ -247,35 +219,22 @@ nsJSON::EncodeInternal(nsJSONWriter *writer)
|
|||
rv = cc->GetArgc(&argc);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Now fish for the JS arguments. If it's a call to encode, we'll
|
||||
// want the first two arguments. If it's a call to encodeToStream,
|
||||
// we'll want the fourth and fifth;
|
||||
PRUint32 firstArg = writer->mStream ? 3 : 0;
|
||||
// Now fish for the JS arguments. We want the fourth and fifth arguments to
|
||||
// encodeToStream.
|
||||
NS_ABORT_IF_FALSE(writer->mStream != NULL, "should have a stream");
|
||||
PRUint32 firstArg = 3;
|
||||
|
||||
// Get the object we're going to serialize.
|
||||
JSObject *inputObj = nsnull;
|
||||
jsval *argv = nsnull;
|
||||
rv = cc->GetArgvPtr(&argv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (argc <= firstArg ||
|
||||
!(JSVAL_IS_OBJECT(argv[firstArg]) &&
|
||||
(inputObj = JSVAL_TO_OBJECT(argv[firstArg])))) {
|
||||
// return if it's not something we can deal with
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
// If the argument wasn't provided, there's nothing to serialize.
|
||||
if (argc <= firstArg)
|
||||
return NS_OK;
|
||||
|
||||
jsval *vp = &argv[firstArg];
|
||||
JSBool ok = JS_TryJSON(cx, vp);
|
||||
JSType type;
|
||||
if (!(ok && !JSVAL_IS_PRIMITIVE(*vp) &&
|
||||
(type = JS_TypeOfValue(cx, *vp)) != JSTYPE_FUNCTION &&
|
||||
type != JSTYPE_XML)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
ok = JS_Stringify(cx, vp, NULL, JSVAL_NULL, WriteCallback, writer);
|
||||
if (!ok)
|
||||
if (!JS_Stringify(cx, vp, NULL, JSVAL_NULL, WriteCallback, writer))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
return NS_OK;
|
||||
|
@ -392,20 +351,6 @@ nsJSONWriter::WriteToStream(nsIOutputStream *aStream,
|
|||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsJSON::Decode(const nsAString& json)
|
||||
{
|
||||
const PRUnichar *data;
|
||||
PRUint32 len = NS_StringGetData(json, &data);
|
||||
nsCOMPtr<nsIInputStream> stream;
|
||||
nsresult rv = NS_NewByteInputStream(getter_AddRefs(stream),
|
||||
(const char*) data,
|
||||
len * sizeof(PRUnichar),
|
||||
NS_ASSIGNMENT_DEPEND);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return DecodeInternal(stream, len, PR_FALSE);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsJSON::DecodeFromStream(nsIInputStream *aStream, PRInt32 aContentLength)
|
||||
{
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -17,22 +17,6 @@ if (!outputDir.exists()) {
|
|||
do_throw(outputName + " is not a directory?")
|
||||
}
|
||||
|
||||
function testStringEncode()
|
||||
{
|
||||
do_check_eq(nativeJSON.encode(), null);
|
||||
|
||||
// useless roots are dropped
|
||||
do_check_eq(nativeJSON.encode(null), null);
|
||||
do_check_eq(nativeJSON.encode(""), null);
|
||||
do_check_eq(nativeJSON.encode(undefined), null);
|
||||
do_check_eq(nativeJSON.encode(5), null);
|
||||
do_check_eq(nativeJSON.encode(function(){}), null);
|
||||
do_check_eq(nativeJSON.encode(dump), null);
|
||||
|
||||
// All other testing should occur in js/src/tests/ecma_5/JSON/ using
|
||||
// the otherwise-exactly-identical JSON.stringify.
|
||||
}
|
||||
|
||||
function testOutputStreams() {
|
||||
function writeToFile(obj, charset, writeBOM) {
|
||||
var jsonFile = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
|
||||
|
@ -87,25 +71,8 @@ function testOutputStreams() {
|
|||
outputDir.remove(true);
|
||||
}
|
||||
|
||||
function throwingToJSON() {
|
||||
var a = {
|
||||
"b": 1,
|
||||
"c": 2,
|
||||
toJSON: function() { throw("uh oh"); }
|
||||
}
|
||||
try {
|
||||
var y = nativeJSON.encode(a);
|
||||
throw "didn't throw";
|
||||
} catch (ex) {
|
||||
do_check_eq(ex, "uh oh");
|
||||
}
|
||||
}
|
||||
|
||||
function run_test()
|
||||
{
|
||||
testStringEncode();
|
||||
throwingToJSON();
|
||||
|
||||
testOutputStreams();
|
||||
|
||||
}
|
||||
|
|
|
@ -3,6 +3,5 @@ head =
|
|||
tail =
|
||||
|
||||
[test_decodeFromStream.js]
|
||||
[test_decode_long_input.js]
|
||||
[test_encode.js]
|
||||
|
||||
|
|
|
@ -461,23 +461,21 @@ reverse_range (hb_buffer_t *buffer,
|
|||
unsigned int start,
|
||||
unsigned int end)
|
||||
{
|
||||
unsigned int i, j;
|
||||
|
||||
for (i = start, j = end - 1; i < j; i++, j--) {
|
||||
hb_glyph_info_t t;
|
||||
|
||||
t = buffer->info[i];
|
||||
buffer->info[i] = buffer->info[j];
|
||||
buffer->info[j] = t;
|
||||
hb_glyph_info_t *i = buffer->info + start;
|
||||
hb_glyph_info_t *j = buffer->info + end - 1;
|
||||
while (i < j) {
|
||||
hb_glyph_info_t t = *i;
|
||||
*i++ = *j;
|
||||
*j-- = t;
|
||||
}
|
||||
|
||||
if (buffer->pos) {
|
||||
for (i = 0, j = end - 1; i < j; i++, j--) {
|
||||
hb_glyph_position_t t;
|
||||
|
||||
t = buffer->pos[i];
|
||||
buffer->pos[i] = buffer->pos[j];
|
||||
buffer->pos[j] = t;
|
||||
hb_glyph_position_t *ii = buffer->pos + start;
|
||||
hb_glyph_position_t *jj = buffer->pos + end - 1;
|
||||
while (ii < jj) {
|
||||
hb_glyph_position_t tt = *ii;
|
||||
*ii++ = *jj;
|
||||
*jj-- = tt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,8 +44,9 @@
|
|||
#include "nsIDirectoryEnumerator.h"
|
||||
#include "nsDirectoryServiceDefs.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsIPrefService.h"
|
||||
#include "nsIPrefBranch.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
#define INTL_HYPHENATIONALIAS_PREFIX "intl.hyphenation-alias."
|
||||
|
||||
|
@ -225,30 +226,25 @@ nsHyphenationManager::LoadPatternListFromDir(nsIFile *aDir)
|
|||
void
|
||||
nsHyphenationManager::LoadAliases()
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIPrefBranch> prefBranch =
|
||||
do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
nsIPrefBranch* prefRootBranch = Preferences::GetRootBranch();
|
||||
if (!prefRootBranch) {
|
||||
return;
|
||||
}
|
||||
PRUint32 prefCount;
|
||||
char **prefNames;
|
||||
rv = prefBranch->GetChildList(INTL_HYPHENATIONALIAS_PREFIX,
|
||||
&prefCount, &prefNames);
|
||||
nsresult rv = prefRootBranch->GetChildList(INTL_HYPHENATIONALIAS_PREFIX,
|
||||
&prefCount, &prefNames);
|
||||
if (NS_SUCCEEDED(rv) && prefCount > 0) {
|
||||
for (PRUint32 i = 0; i < prefCount; ++i) {
|
||||
char *prefValue;
|
||||
rv = prefBranch->GetCharPref(prefNames[i], &prefValue);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsAdoptingCString value = Preferences::GetCString(prefNames[i]);
|
||||
if (value) {
|
||||
nsCAutoString alias(prefNames[i]);
|
||||
alias.Cut(0, strlen(INTL_HYPHENATIONALIAS_PREFIX));
|
||||
ToLowerCase(alias);
|
||||
nsCAutoString value(prefValue);
|
||||
ToLowerCase(value);
|
||||
nsCOMPtr<nsIAtom> aliasAtom = do_GetAtom(alias);
|
||||
nsCOMPtr<nsIAtom> valueAtom = do_GetAtom(value);
|
||||
mHyphAliases.Put(aliasAtom, valueAtom);
|
||||
NS_Free(prefValue);
|
||||
}
|
||||
}
|
||||
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(prefCount, prefNames);
|
||||
|
|
|
@ -45,9 +45,6 @@
|
|||
#include "nsIPlatformCharset.h"
|
||||
#include "nsPosixLocale.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIPrefBranch.h"
|
||||
#include "nsIPrefService.h"
|
||||
#include "nsIPrefLocalizedString.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsCRT.h"
|
||||
//#define DEBUG_UNIX_COLLATION
|
||||
|
|
|
@ -531,6 +531,15 @@ else
|
|||
SDK_LIBRARY = $(SHARED_LIBRARY)
|
||||
endif
|
||||
|
||||
# for compiler bug (http://support.microsoft.com/kb/982107) for MSVC x64
|
||||
ifdef _MSC_VER
|
||||
ifneq (,$(filter 1400 1500,$(_MSC_VER)))
|
||||
ifeq ($(OS_TEST),x86_64)
|
||||
ASFILES += jswin64.asm
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
|
||||
EXTRA_DSO_LDOPTS += $(NSPR_LIBS)
|
||||
|
|
|
@ -1011,7 +1011,7 @@
|
|||
|
||||
/* The JIT is enabled by default on all x86, x64-64, ARM & MIPS platforms. */
|
||||
#if !defined(ENABLE_JIT) \
|
||||
&& (WTF_CPU_X86 || WTF_CPU_X86_64 || WTF_CPU_ARM || WTF_CPU_MIPS) \
|
||||
&& (WTF_CPU_X86 || WTF_CPU_X86_64 || WTF_CPU_ARM || WTF_CPU_MIPS || WTF_CPU_SPARC32) \
|
||||
&& (WTF_OS_DARWIN || !WTF_COMPILER_GCC || GCC_VERSION_AT_LEAST(4, 1, 0)) \
|
||||
&& !WTF_OS_WINCE
|
||||
#define ENABLE_JIT 1
|
||||
|
|
|
@ -301,12 +301,14 @@ class AtomDecls
|
|||
bool addHoist(JSAtom *atom, JSDefinition *defn);
|
||||
|
||||
/* Updating the definition for an entry that is known to exist is infallible. */
|
||||
void update(JSAtom *atom, JSDefinition *defn) {
|
||||
void updateFirst(JSAtom *atom, JSDefinition *defn) {
|
||||
JS_ASSERT(map);
|
||||
AtomDOHMap::Ptr p = map->lookup(atom);
|
||||
JS_ASSERT(p);
|
||||
JS_ASSERT(!p.value().isHeader());
|
||||
p.value() = DefnOrHeader(defn);
|
||||
if (p.value().isHeader())
|
||||
p.value().header()->defn = defn;
|
||||
else
|
||||
p.value() = DefnOrHeader(defn);
|
||||
}
|
||||
|
||||
/* Remove the node at the head of the chain for |atom|. */
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
for (var x in x)
|
||||
let(x) {}
|
||||
function x() {}
|
|
@ -0,0 +1,4 @@
|
|||
var x;
|
||||
for (var a = 0; a < 8; a++) {
|
||||
Function.prototype()
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
var caught = false;
|
||||
try {
|
||||
evalcx("eval(\"throw<x/>\")", Function.a)
|
||||
} catch (e) {
|
||||
caught = true;
|
||||
}
|
||||
assertEq(caught, true);
|
|
@ -0,0 +1 @@
|
|||
assertEq(["a"].map(escape)[0], ["a"].map(function(s) {return escape(s);})[0]);
|
|
@ -75,8 +75,12 @@
|
|||
*
|
||||
* "Rhino is not a member of the Monkey family"
|
||||
*
|
||||
* Before adding a new MSG_DEF at the end, look for JSMSG_UNUSED<n> free
|
||||
* index placeholders in the middle of the list.
|
||||
* When removing MSG_DEFs, convert them to JSMSG_UNUSED<n> placeholders:
|
||||
*
|
||||
* MSG_DEF(JSMSG_UNUSED7, 7, 0, JSEXN_NONE, "")
|
||||
*
|
||||
* Before adding a new MSG_DEF at the end, look for existing JSMSG_UNUSED<n>
|
||||
* free index placeholders in the middle of the list.
|
||||
*/
|
||||
|
||||
MSG_DEF(JSMSG_NOT_AN_ERROR, 0, 0, JSEXN_NONE, "<Error #0 is reserved>")
|
||||
|
@ -140,7 +144,7 @@ MSG_DEF(JSMSG_BAD_CLASS_RANGE, 57, 0, JSEXN_SYNTAXERR, "invalid range in
|
|||
MSG_DEF(JSMSG_BAD_REGEXP_FLAG, 58, 1, JSEXN_SYNTAXERR, "invalid regular expression flag {0}")
|
||||
MSG_DEF(JSMSG_NO_INPUT, 59, 5, JSEXN_SYNTAXERR, "no input for /{0}/{1}{2}{3}{4}")
|
||||
MSG_DEF(JSMSG_CANT_OPEN, 60, 2, JSEXN_ERR, "can't open {0}: {1}")
|
||||
MSG_DEF(JSMSG_BAD_STRING_MASK, 61, 1, JSEXN_ERR, "invalid string escape mask {0}")
|
||||
MSG_DEF(JSMSG_UNUSED61, 61, 0, JSEXN_NONE, "")
|
||||
MSG_DEF(JSMSG_UNMATCHED_RIGHT_PAREN, 62, 0, JSEXN_SYNTAXERR, "unmatched ) in regular expression")
|
||||
MSG_DEF(JSMSG_END_OF_DATA, 63, 0, JSEXN_INTERNALERR, "unexpected end of data")
|
||||
MSG_DEF(JSMSG_SEEK_BEYOND_START, 64, 0, JSEXN_INTERNALERR, "illegal seek beyond start")
|
||||
|
|
|
@ -61,6 +61,7 @@ CPPSRCS = \
|
|||
testDefineProperty.cpp \
|
||||
testExtendedEq.cpp \
|
||||
testFuncCallback.cpp \
|
||||
testFunctionProperties.cpp \
|
||||
testGCChunkAlloc.cpp \
|
||||
testGetPropertyDefault.cpp \
|
||||
testIntString.cpp \
|
||||
|
|
|
@ -73,8 +73,8 @@ BEGIN_TEST(testCustomIterator_bug612523)
|
|||
"j;", &result);
|
||||
|
||||
CHECK(JSVAL_IS_INT(result));
|
||||
CHECK(JSVAL_TO_INT(result) == 100);
|
||||
CHECK(count == 101);
|
||||
CHECK_EQUAL(JSVAL_TO_INT(result), 100);
|
||||
CHECK_EQUAL(count, 101);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -26,8 +26,8 @@ BEGIN_TEST(testDebugger_bug519719)
|
|||
"function f(g) { for (var i = 0; i < 9; i++) call(g); }\n"
|
||||
"f(Math.sin);\n" // record loop, starting in f
|
||||
"f(Math.cos);\n"); // side exit in f -> call
|
||||
CHECK(callCount[0] == 20);
|
||||
CHECK(callCount[1] == 20);
|
||||
CHECK_EQUAL(callCount[0], 20);
|
||||
CHECK_EQUAL(callCount[1], 20);
|
||||
return true;
|
||||
}
|
||||
END_TEST(testDebugger_bug519719)
|
||||
|
|
|
@ -61,37 +61,46 @@ BEGIN_TEST(testFuncCallback_bug507012)
|
|||
|
||||
// Check whether JS_Execute() tracking works
|
||||
EXEC("42");
|
||||
CHECK(enters == 1 && leaves == 1 && depth == 0);
|
||||
CHECK_EQUAL(enters, 1);
|
||||
CHECK_EQUAL(leaves, 1);
|
||||
CHECK_EQUAL(depth, 0);
|
||||
interpreted = enters = leaves = depth = 0;
|
||||
|
||||
// Check whether the basic function tracking works
|
||||
EXEC("f(1)");
|
||||
CHECK(enters == 1+1 && leaves == 1+1 && depth == 0);
|
||||
CHECK_EQUAL(enters, 1+1);
|
||||
CHECK_EQUAL(leaves, 1+1);
|
||||
CHECK_EQUAL(depth, 0);
|
||||
|
||||
// Can we switch to a different callback?
|
||||
enters = 777;
|
||||
JS_SetFunctionCallback(cx, funcTransition2);
|
||||
EXEC("f(1)");
|
||||
CHECK(called2 && enters == 777);
|
||||
CHECK(called2);
|
||||
CHECK_EQUAL(enters, 777);
|
||||
|
||||
// Check whether we can turn off function tracing
|
||||
JS_SetFunctionCallback(cx, NULL);
|
||||
EXEC("f(1)");
|
||||
CHECK(enters == 777);
|
||||
CHECK_EQUAL(enters, 777);
|
||||
interpreted = enters = leaves = depth = 0;
|
||||
|
||||
// Check nested invocations
|
||||
JS_SetFunctionCallback(cx, funcTransition);
|
||||
enters = leaves = depth = 0;
|
||||
EXEC("f(3)");
|
||||
CHECK(enters == 1+3 && leaves == 1+3 && depth == 0);
|
||||
CHECK_EQUAL(enters, 1+3);
|
||||
CHECK_EQUAL(leaves, 1+3);
|
||||
CHECK_EQUAL(depth, 0);
|
||||
interpreted = enters = leaves = depth = 0;
|
||||
|
||||
// Check calls invoked while running on trace
|
||||
EXEC("function g () { ++x; }");
|
||||
interpreted = enters = leaves = depth = 0;
|
||||
EXEC("for (i = 0; i < 50; ++i) { g(); }");
|
||||
CHECK(enters == 1+50 && leaves == 1+50 && depth == 0);
|
||||
CHECK_EQUAL(enters, 1+50);
|
||||
CHECK_EQUAL(leaves, 1+50);
|
||||
CHECK_EQUAL(depth, 0);
|
||||
|
||||
// If this fails, it means that the code was interpreted rather
|
||||
// than trace-JITted, and so is not testing what it's supposed to
|
||||
|
@ -111,13 +120,18 @@ BEGIN_TEST(testFuncCallback_bug507012)
|
|||
interpreted = enters = leaves = depth = overlays = 0;
|
||||
|
||||
EXEC("42.5");
|
||||
CHECK(enters == 1);
|
||||
CHECK(leaves == 1);
|
||||
CHECK(depth == 0);
|
||||
CHECK(overlays == enters + leaves);
|
||||
CHECK_EQUAL(enters, 1);
|
||||
CHECK_EQUAL(leaves, 1);
|
||||
CHECK_EQUAL(depth, 0);
|
||||
CHECK_EQUAL(overlays, enters + leaves);
|
||||
interpreted = enters = leaves = depth = overlays = 0;
|
||||
#endif
|
||||
|
||||
// Uncomment this to validate whether you're hitting all runmodes (interp,
|
||||
// tjit, mjit, ...?) Unfortunately, that still doesn't cover all
|
||||
// transitions between the various runmodes, but it's a start.
|
||||
//JS_DumpAllProfiles(cx);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -131,7 +145,7 @@ JSContext *createContext()
|
|||
{
|
||||
JSContext *cx = JSAPITest::createContext();
|
||||
if (cx)
|
||||
JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_JIT);
|
||||
JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_JIT | JSOPTION_METHODJIT | JSOPTION_PCCOUNT);
|
||||
return cx;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99:
|
||||
*/
|
||||
|
||||
#include "tests.h"
|
||||
|
||||
BEGIN_TEST(testFunctionProperties)
|
||||
{
|
||||
jsvalRoot x(cx);
|
||||
EVAL("(function f() {})", x.addr());
|
||||
|
||||
JSObject *obj = JSVAL_TO_OBJECT(x.value());
|
||||
jsvalRoot y(cx);
|
||||
|
||||
CHECK(JS_GetProperty(cx, obj, "arguments", y.addr()));
|
||||
CHECK_SAME(y, JSVAL_NULL);
|
||||
|
||||
CHECK(JS_GetProperty(cx, obj, "caller", y.addr()));
|
||||
CHECK_SAME(y, JSVAL_NULL);
|
||||
|
||||
return true;
|
||||
}
|
||||
END_TEST(testFunctionProperties)
|
|
@ -80,7 +80,7 @@ BEGIN_TEST(testGCChunkAlloc)
|
|||
/* Check that we get OOM. */
|
||||
CHECK(!ok);
|
||||
CHECK(!JS_IsExceptionPending(cx));
|
||||
CHECK(errorCount == 1);
|
||||
CHECK_EQUAL(errorCount, 1);
|
||||
CHECK(!customGCChunkAllocator.pool[0]);
|
||||
CHECK(!customGCChunkAllocator.pool[1]);
|
||||
JS_GC(cx);
|
||||
|
@ -92,7 +92,7 @@ BEGIN_TEST(testGCChunkAlloc)
|
|||
" array.push({});"
|
||||
" }"
|
||||
"})();", root.addr());
|
||||
CHECK(errorCount == 1);
|
||||
CHECK_EQUAL(errorCount, 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ BEGIN_TEST(testIsAboutToBeFinalized_bug528645)
|
|||
--checkPointersStaticStrings;
|
||||
}
|
||||
}
|
||||
CHECK(checkPointersStaticStrings == 0);
|
||||
CHECK_EQUAL(checkPointersStaticStrings, 0);
|
||||
|
||||
free(checkPointers);
|
||||
checkPointers = NULL;
|
||||
|
|
|
@ -57,7 +57,7 @@ BEGIN_TEST(testNewObject_1)
|
|||
CHECK(JS_IsArrayObject(cx, obj));
|
||||
jsuint len;
|
||||
CHECK(JS_GetArrayLength(cx, obj, &len));
|
||||
CHECK(len == 0);
|
||||
CHECK_EQUAL(len, 0);
|
||||
|
||||
// With one argument.
|
||||
argv[0] = INT_TO_JSVAL(4);
|
||||
|
@ -66,7 +66,7 @@ BEGIN_TEST(testNewObject_1)
|
|||
rt = OBJECT_TO_JSVAL(obj);
|
||||
CHECK(JS_IsArrayObject(cx, obj));
|
||||
CHECK(JS_GetArrayLength(cx, obj, &len));
|
||||
CHECK(len == 4);
|
||||
CHECK_EQUAL(len, 4);
|
||||
|
||||
// With N arguments.
|
||||
for (size_t i = 0; i < N; i++)
|
||||
|
@ -76,7 +76,7 @@ BEGIN_TEST(testNewObject_1)
|
|||
rt = OBJECT_TO_JSVAL(obj);
|
||||
CHECK(JS_IsArrayObject(cx, obj));
|
||||
CHECK(JS_GetArrayLength(cx, obj, &len));
|
||||
CHECK(len == N);
|
||||
CHECK_EQUAL(len, N);
|
||||
CHECK(JS_GetElement(cx, obj, N - 1, &v));
|
||||
CHECK_SAME(v, INT_TO_JSVAL(N - 1));
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ BEGIN_TEST(testPropCache_bug505798)
|
|||
EXEC("var arr = [x, y];\n"
|
||||
"for (var i = 0; i < arr.length; i++)\n"
|
||||
" arr[i].p = 1;\n");
|
||||
CHECK(g_counter == 1);
|
||||
CHECK_EQUAL(g_counter, 1);
|
||||
return true;
|
||||
}
|
||||
END_TEST(testPropCache_bug505798)
|
||||
|
|
|
@ -24,15 +24,15 @@ BEGIN_TEST(testGetRegExpFlags)
|
|||
|
||||
EVAL("/foopy/", val.addr());
|
||||
obj = JSVAL_TO_OBJECT(val.value());
|
||||
CHECK(JS_GetRegExpFlags(cx, obj) == 0);
|
||||
CHECK_EQUAL(JS_GetRegExpFlags(cx, obj), 0);
|
||||
|
||||
EVAL("/foopy/g", val.addr());
|
||||
obj = JSVAL_TO_OBJECT(val.value());
|
||||
CHECK(JS_GetRegExpFlags(cx, obj) == JSREG_GLOB);
|
||||
CHECK_EQUAL(JS_GetRegExpFlags(cx, obj), JSREG_GLOB);
|
||||
|
||||
EVAL("/foopy/gi", val.addr());
|
||||
obj = JSVAL_TO_OBJECT(val.value());
|
||||
CHECK(JS_GetRegExpFlags(cx, obj) == (JSREG_FOLD | JSREG_GLOB));
|
||||
CHECK_EQUAL(JS_GetRegExpFlags(cx, obj), (JSREG_FOLD | JSREG_GLOB));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -22,14 +22,14 @@ BEGIN_TEST(testRegExpInstanceProperties)
|
|||
|
||||
JS_GC(cx);
|
||||
|
||||
CHECK(regexpProto->getCompartment()->initialRegExpShape == NULL);
|
||||
CHECK_EQUAL(regexpProto->getCompartment()->initialRegExpShape, NULL);
|
||||
|
||||
jsval regexp;
|
||||
EVAL("/foopy/", ®exp);
|
||||
JSObject *robj = JSVAL_TO_OBJECT(regexp);
|
||||
|
||||
CHECK(robj->lastProperty());
|
||||
CHECK(robj->getCompartment()->initialRegExpShape == robj->lastProperty());
|
||||
CHECK_EQUAL(robj->getCompartment()->initialRegExpShape, robj->lastProperty());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -42,9 +42,9 @@ BEGIN_TEST(testResolveRecursion)
|
|||
/* Start the essence of the test via invoking the first resolve hook. */
|
||||
jsval v;
|
||||
EVAL("obj1.x", &v);
|
||||
CHECK(v == JSVAL_FALSE);
|
||||
CHECK(resolveEntryCount == 4);
|
||||
CHECK(resolveExitCount == 4);
|
||||
CHECK_SAME(v, JSVAL_FALSE);
|
||||
CHECK_EQUAL(resolveEntryCount, 4);
|
||||
CHECK_EQUAL(resolveExitCount, 4);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -69,9 +69,9 @@ struct AutoIncrCounters {
|
|||
bool
|
||||
doResolve(JSObject *obj, jsid id, uintN flags, JSObject **objp)
|
||||
{
|
||||
CHECK(resolveExitCount == 0);
|
||||
CHECK_EQUAL(resolveExitCount, 0);
|
||||
AutoIncrCounters incr(this);
|
||||
CHECK(obj == obj1 || obj == obj2);
|
||||
CHECK_EQUAL(obj, obj1 || obj == obj2);
|
||||
|
||||
CHECK(JSID_IS_STRING(id));
|
||||
|
||||
|
@ -81,31 +81,31 @@ doResolve(JSObject *obj, jsid id, uintN flags, JSObject **objp)
|
|||
if (JS_FlatStringEqualsAscii(str, "x")) {
|
||||
if (obj == obj1) {
|
||||
/* First resolve hook invocation. */
|
||||
CHECK(resolveEntryCount == 1);
|
||||
CHECK_EQUAL(resolveEntryCount, 1);
|
||||
EVAL("obj2.y = true", &v);
|
||||
CHECK(v == JSVAL_TRUE);
|
||||
CHECK_SAME(v, JSVAL_TRUE);
|
||||
CHECK(JS_DefinePropertyById(cx, obj, id, JSVAL_FALSE, NULL, NULL, 0));
|
||||
*objp = obj;
|
||||
return true;
|
||||
}
|
||||
if (obj == obj2) {
|
||||
CHECK(resolveEntryCount == 4);
|
||||
CHECK_EQUAL(resolveEntryCount, 4);
|
||||
*objp = NULL;
|
||||
return true;
|
||||
}
|
||||
} else if (JS_FlatStringEqualsAscii(str, "y")) {
|
||||
if (obj == obj2) {
|
||||
CHECK(resolveEntryCount == 2);
|
||||
CHECK_EQUAL(resolveEntryCount, 2);
|
||||
CHECK(JS_DefinePropertyById(cx, obj, id, JSVAL_NULL, NULL, NULL, 0));
|
||||
EVAL("obj1.x", &v);
|
||||
CHECK(JSVAL_IS_VOID(v));
|
||||
EVAL("obj1.y", &v);
|
||||
CHECK(v == JSVAL_ZERO);
|
||||
CHECK_SAME(v, JSVAL_ZERO);
|
||||
*objp = obj;
|
||||
return true;
|
||||
}
|
||||
if (obj == obj1) {
|
||||
CHECK(resolveEntryCount == 3);
|
||||
CHECK_EQUAL(resolveEntryCount, 3);
|
||||
EVAL("obj1.x", &v);
|
||||
CHECK(JSVAL_IS_VOID(v));
|
||||
EVAL("obj1.y", &v);
|
||||
|
@ -115,7 +115,7 @@ doResolve(JSObject *obj, jsid id, uintN flags, JSObject **objp)
|
|||
EVAL("obj2.x", &v);
|
||||
CHECK(JSVAL_IS_VOID(v));
|
||||
EVAL("obj1.y = 0", &v);
|
||||
CHECK(v == JSVAL_ZERO);
|
||||
CHECK_SAME(v, JSVAL_ZERO);
|
||||
*objp = obj;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ BEGIN_TEST(testStringBuffer_finishString)
|
|||
|
||||
JSAtom *finishedAtom = buffer.finishAtom();
|
||||
CHECK(finishedAtom);
|
||||
CHECK(atom == finishedAtom);
|
||||
CHECK_EQUAL(atom, finishedAtom);
|
||||
return true;
|
||||
}
|
||||
END_TEST(testStringBuffer_finishString)
|
||||
|
|
|
@ -37,7 +37,7 @@ BEGIN_TEST(testTrap_gc)
|
|||
jsvalRoot v2(cx);
|
||||
CHECK(JS_ExecuteScript(cx, global, scriptObj, v2.addr()));
|
||||
CHECK(JSVAL_IS_OBJECT(v2));
|
||||
CHECK(emptyTrapCallCount == 0);
|
||||
CHECK_EQUAL(emptyTrapCallCount, 0);
|
||||
|
||||
// Disable JIT for debugging
|
||||
JS_SetOptions(cx, JS_GetOptions(cx) & ~JSOPTION_JIT);
|
||||
|
@ -70,7 +70,7 @@ BEGIN_TEST(testTrap_gc)
|
|||
|
||||
// execute
|
||||
CHECK(JS_ExecuteScript(cx, global, scriptObj, v2.addr()));
|
||||
CHECK(emptyTrapCallCount == 11);
|
||||
CHECK_EQUAL(emptyTrapCallCount, 11);
|
||||
|
||||
JS_GC(cx);
|
||||
|
||||
|
|
|
@ -11,10 +11,10 @@ BEGIN_TEST(testUTF8_bug589917)
|
|||
size_t utf8_len = sizeof(output_buffer);
|
||||
|
||||
CHECK(JS_EncodeCharacters(cx, surrogate_pair, 2, output_buffer, &utf8_len));
|
||||
CHECK(utf8_len == 4);
|
||||
CHECK_EQUAL(utf8_len, 4);
|
||||
|
||||
CHECK(JS_EncodeCharacters(cx, surrogate_pair, 2, NULL, &utf8_len));
|
||||
CHECK(utf8_len == 4);
|
||||
CHECK_EQUAL(utf8_len, 4);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -101,9 +101,9 @@ struct VersionFixture : public JSAPITest
|
|||
}
|
||||
|
||||
bool toggleXML(bool shouldEnable) {
|
||||
CHECK(hasXML() == !shouldEnable);
|
||||
CHECK_EQUAL(hasXML(), !shouldEnable);
|
||||
JS_ToggleOptions(cx, JSOPTION_XML);
|
||||
CHECK(hasXML() == shouldEnable);
|
||||
CHECK_EQUAL(hasXML(), shouldEnable);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -218,13 +218,13 @@ END_FIXTURE_TEST(VersionFixture, testOptionsAreUsedForVersionFlags)
|
|||
BEGIN_FIXTURE_TEST(VersionFixture, testEntryLosesOverride)
|
||||
{
|
||||
EXEC("overrideVersion15(); evalScriptVersion16('checkOverride(false); captureVersion()');");
|
||||
CHECK(captured == JSVERSION_1_6);
|
||||
CHECK_EQUAL(captured, JSVERSION_1_6);
|
||||
|
||||
/*
|
||||
* Override gets propagated to default version as non-override when you leave the VM's execute
|
||||
* call.
|
||||
*/
|
||||
CHECK(JS_GetVersion(cx) == JSVERSION_1_5);
|
||||
CHECK_EQUAL(JS_GetVersion(cx), JSVERSION_1_5);
|
||||
CHECK(!cx->isVersionOverridden());
|
||||
return true;
|
||||
}
|
||||
|
@ -238,28 +238,28 @@ END_FIXTURE_TEST(VersionFixture, testEntryLosesOverride)
|
|||
*/
|
||||
BEGIN_FIXTURE_TEST(VersionFixture, testReturnLosesOverride)
|
||||
{
|
||||
CHECK(JS_GetVersion(cx) == JSVERSION_ECMA_5);
|
||||
CHECK_EQUAL(JS_GetVersion(cx), JSVERSION_ECMA_5);
|
||||
EXEC(
|
||||
"checkOverride(false);"
|
||||
"evalScriptVersion16('overrideVersion15();');"
|
||||
"checkOverride(false);"
|
||||
"captureVersion();"
|
||||
);
|
||||
CHECK(captured == JSVERSION_ECMA_5);
|
||||
CHECK_EQUAL(captured, JSVERSION_ECMA_5);
|
||||
return true;
|
||||
}
|
||||
END_FIXTURE_TEST(VersionFixture, testReturnLosesOverride)
|
||||
|
||||
BEGIN_FIXTURE_TEST(VersionFixture, testEvalPropagatesOverride)
|
||||
{
|
||||
CHECK(JS_GetVersion(cx) == JSVERSION_ECMA_5);
|
||||
CHECK_EQUAL(JS_GetVersion(cx), JSVERSION_ECMA_5);
|
||||
EXEC(
|
||||
"checkOverride(false);"
|
||||
"eval('overrideVersion15();');"
|
||||
"checkOverride(true);"
|
||||
"captureVersion();"
|
||||
);
|
||||
CHECK(captured == JSVERSION_1_5);
|
||||
CHECK_EQUAL(captured, JSVERSION_1_5);
|
||||
return true;
|
||||
}
|
||||
END_FIXTURE_TEST(VersionFixture, testEvalPropagatesOverride)
|
||||
|
|
|
@ -172,7 +172,7 @@ class JSAPITest
|
|||
fail(bytes, filename, lineno);
|
||||
}
|
||||
|
||||
JSAPITestString toSource(jsval v) {
|
||||
JSAPITestString jsvalToSource(jsval v) {
|
||||
JSString *str = JS_ValueToSource(cx, v);
|
||||
if (str) {
|
||||
JSAutoByteString bytes(cx, str);
|
||||
|
@ -183,9 +183,75 @@ class JSAPITest
|
|||
return JSAPITestString("<<error converting value to string>>");
|
||||
}
|
||||
|
||||
#define CHECK_SAME(actual, expected) \
|
||||
JSAPITestString toSource(long v) {
|
||||
char buf[40];
|
||||
sprintf(buf, "%ld", v);
|
||||
return JSAPITestString(buf);
|
||||
}
|
||||
|
||||
JSAPITestString toSource(unsigned long v) {
|
||||
char buf[40];
|
||||
sprintf(buf, "%lu", v);
|
||||
return JSAPITestString(buf);
|
||||
}
|
||||
|
||||
JSAPITestString toSource(long long v) {
|
||||
char buf[40];
|
||||
sprintf(buf, "%lld", v);
|
||||
return JSAPITestString(buf);
|
||||
}
|
||||
|
||||
JSAPITestString toSource(unsigned long long v) {
|
||||
char buf[40];
|
||||
sprintf(buf, "%llu", v);
|
||||
return JSAPITestString(buf);
|
||||
}
|
||||
|
||||
JSAPITestString toSource(unsigned int v) {
|
||||
return toSource((unsigned long)v);
|
||||
}
|
||||
|
||||
JSAPITestString toSource(int v) {
|
||||
return toSource((long)v);
|
||||
}
|
||||
|
||||
JSAPITestString toSource(bool v) {
|
||||
return JSAPITestString(v ? "true" : "false");
|
||||
}
|
||||
|
||||
JSAPITestString toSource(JSAtom *v) {
|
||||
return jsvalToSource(STRING_TO_JSVAL((JSString*)v));
|
||||
}
|
||||
|
||||
JSAPITestString toSource(JSVersion v) {
|
||||
return JSAPITestString(JS_VersionToString(v));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool checkEqual(const T &actual, const T &expected,
|
||||
const char *actualExpr, const char *expectedExpr,
|
||||
const char *filename, int lineno) {
|
||||
return (actual == expected) ||
|
||||
fail(JSAPITestString("CHECK_EQUAL failed: expected (") +
|
||||
expectedExpr + ") = " + toSource(expected) +
|
||||
", got (" + actualExpr + ") = " + toSource(actual), filename, lineno);
|
||||
}
|
||||
|
||||
// There are many cases where the static types of 'actual' and 'expected'
|
||||
// are not identical, and C++ is understandably cautious about automatic
|
||||
// coercions. So catch those cases and forcibly coerce, then use the
|
||||
// identical-type specialization. This may do bad things if the types are
|
||||
// actually *not* compatible.
|
||||
template<typename T, typename U>
|
||||
bool checkEqual(const T &actual, const U &expected,
|
||||
const char *actualExpr, const char *expectedExpr,
|
||||
const char *filename, int lineno) {
|
||||
return checkEqual(U(actual), expected, actualExpr, expectedExpr, filename, lineno);
|
||||
}
|
||||
|
||||
#define CHECK_EQUAL(actual, expected) \
|
||||
do { \
|
||||
if (!checkSame(actual, expected, #actual, #expected, __FILE__, __LINE__)) \
|
||||
if (!checkEqual(actual, expected, #actual, #expected, __FILE__, __LINE__)) \
|
||||
return false; \
|
||||
} while (false)
|
||||
|
||||
|
@ -196,9 +262,15 @@ class JSAPITest
|
|||
return (JS_SameValue(cx, actual, expected, &same) && same) ||
|
||||
fail(JSAPITestString("CHECK_SAME failed: expected JS_SameValue(cx, ") +
|
||||
actualExpr + ", " + expectedExpr + "), got !JS_SameValue(cx, " +
|
||||
toSource(actual) + ", " + toSource(expected) + ")", filename, lineno);
|
||||
jsvalToSource(actual) + ", " + jsvalToSource(expected) + ")", filename, lineno);
|
||||
}
|
||||
|
||||
#define CHECK_SAME(actual, expected) \
|
||||
do { \
|
||||
if (!checkSame(actual, expected, #actual, #expected, __FILE__, __LINE__)) \
|
||||
return false; \
|
||||
} while (false)
|
||||
|
||||
#define CHECK(expr) \
|
||||
do { \
|
||||
if (!(expr)) \
|
||||
|
|
|
@ -4092,14 +4092,6 @@ JS_SetArrayLength(JSContext *cx, JSObject *obj, jsuint length)
|
|||
return js_SetLengthProperty(cx, obj, length);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_HasArrayLength(JSContext *cx, JSObject *obj, jsuint *lengthp)
|
||||
{
|
||||
CHECK_REQUEST(cx);
|
||||
assertSameCompartment(cx, obj);
|
||||
return js_HasLengthProperty(cx, obj, lengthp);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
|
||||
jsval *vp, uintN *attrsp)
|
||||
|
@ -5505,17 +5497,13 @@ JS_Stringify(JSContext *cx, jsval *vp, JSObject *replacer, jsval space,
|
|||
Value spacev = Valueify(space);
|
||||
if (!js_Stringify(cx, Valueify(vp), replacer, spacev, sb))
|
||||
return false;
|
||||
if (sb.empty()) {
|
||||
JSAtom *nullAtom = cx->runtime->atomState.nullAtom;
|
||||
return callback(nullAtom->chars(), nullAtom->length(), data);
|
||||
}
|
||||
return callback(sb.begin(), sb.length(), data);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_TryJSON(JSContext *cx, jsval *vp)
|
||||
{
|
||||
CHECK_REQUEST(cx);
|
||||
assertSameCompartment(cx, *vp);
|
||||
return js_TryJSON(cx, Valueify(vp));
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_ParseJSON(JSContext *cx, const jschar *chars, uint32 len, jsval *vp)
|
||||
{
|
||||
|
@ -5770,7 +5758,7 @@ JS_NewRegExpObject(JSContext *cx, JSObject *obj, char *bytes, size_t length, uin
|
|||
if (!chars)
|
||||
return NULL;
|
||||
RegExpStatics *res = RegExpStatics::extractFrom(obj->asGlobal());
|
||||
JSObject *reobj = RegExp::createObject(cx, res, chars, length, flags);
|
||||
JSObject *reobj = RegExp::createObject(cx, res, chars, length, flags, NULL);
|
||||
cx->free_(chars);
|
||||
return reobj;
|
||||
}
|
||||
|
@ -5780,7 +5768,7 @@ JS_NewUCRegExpObject(JSContext *cx, JSObject *obj, jschar *chars, size_t length,
|
|||
{
|
||||
CHECK_REQUEST(cx);
|
||||
RegExpStatics *res = RegExpStatics::extractFrom(obj->asGlobal());
|
||||
return RegExp::createObject(cx, res, chars, length, flags);
|
||||
return RegExp::createObject(cx, res, chars, length, flags, NULL);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
|
@ -5826,7 +5814,7 @@ JS_NewRegExpObjectNoStatics(JSContext *cx, char *bytes, size_t length, uintN fla
|
|||
jschar *chars = InflateString(cx, bytes, &length);
|
||||
if (!chars)
|
||||
return NULL;
|
||||
JSObject *obj = RegExp::createObjectNoStatics(cx, chars, length, flags);
|
||||
JSObject *obj = RegExp::createObjectNoStatics(cx, chars, length, flags, NULL);
|
||||
cx->free_(chars);
|
||||
return obj;
|
||||
}
|
||||
|
@ -5835,7 +5823,7 @@ JS_PUBLIC_API(JSObject *)
|
|||
JS_NewUCRegExpObjectNoStatics(JSContext *cx, jschar *chars, size_t length, uintN flags)
|
||||
{
|
||||
CHECK_REQUEST(cx);
|
||||
return RegExp::createObjectNoStatics(cx, chars, length, flags);
|
||||
return RegExp::createObjectNoStatics(cx, chars, length, flags, NULL);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
|
|
|
@ -1140,6 +1140,12 @@ JS_GetGlobalForObject(JSContext *cx, JSObject *obj);
|
|||
extern JS_PUBLIC_API(JSObject *)
|
||||
JS_GetGlobalForScopeChain(JSContext *cx);
|
||||
|
||||
/*
|
||||
* Initialize the 'Reflect' object on a global object.
|
||||
*/
|
||||
extern JS_PUBLIC_API(JSObject *)
|
||||
JS_InitReflect(JSContext *cx, JSObject *global);
|
||||
|
||||
#ifdef JS_HAS_CTYPES
|
||||
/*
|
||||
* Initialize the 'ctypes' object on a global variable 'obj'. The 'ctypes'
|
||||
|
@ -2470,9 +2476,6 @@ JS_GetArrayLength(JSContext *cx, JSObject *obj, jsuint *lengthp);
|
|||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_SetArrayLength(JSContext *cx, JSObject *obj, jsuint length);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_HasArrayLength(JSContext *cx, JSObject *obj, jsuint *lengthp);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_DefineElement(JSContext *cx, JSObject *obj, jsint index, jsval value,
|
||||
JSPropertyOp getter, JSStrictPropertyOp setter, uintN attrs);
|
||||
|
@ -3306,12 +3309,6 @@ JS_PUBLIC_API(JSBool)
|
|||
JS_Stringify(JSContext *cx, jsval *vp, JSObject *replacer, jsval space,
|
||||
JSONWriteCallback callback, void *data);
|
||||
|
||||
/*
|
||||
* Retrieve a toJSON function. If found, set vp to its result.
|
||||
*/
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_TryJSON(JSContext *cx, jsval *vp);
|
||||
|
||||
/*
|
||||
* JSON.parse as specified by ES5.
|
||||
*/
|
||||
|
|
|
@ -179,40 +179,6 @@ js_StringIsIndex(JSLinearString *str, jsuint *indexp)
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
ValueToLength(JSContext *cx, Value* vp, jsuint* plength)
|
||||
{
|
||||
if (vp->isInt32()) {
|
||||
int32_t i = vp->toInt32();
|
||||
if (i < 0)
|
||||
goto error;
|
||||
|
||||
*plength = (jsuint)(i);
|
||||
return true;
|
||||
}
|
||||
|
||||
jsdouble d;
|
||||
if (!ValueToNumber(cx, *vp, &d))
|
||||
goto error;
|
||||
|
||||
if (JSDOUBLE_IS_NaN(d))
|
||||
goto error;
|
||||
|
||||
jsuint length;
|
||||
length = (jsuint) d;
|
||||
if (d != (jsdouble) length)
|
||||
goto error;
|
||||
|
||||
|
||||
*plength = length;
|
||||
return true;
|
||||
|
||||
error:
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
||||
JSMSG_BAD_ARRAY_LENGTH);
|
||||
return false;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_GetLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp)
|
||||
{
|
||||
|
@ -556,23 +522,6 @@ js_SetLengthProperty(JSContext *cx, JSObject *obj, jsdouble length)
|
|||
return obj->setProperty(cx, id, &v, false);
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_HasLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp)
|
||||
{
|
||||
JSErrorReporter older = JS_SetErrorReporter(cx, NULL);
|
||||
AutoValueRooter tvr(cx);
|
||||
jsid id = ATOM_TO_JSID(cx->runtime->atomState.lengthAtom);
|
||||
JSBool ok = obj->getProperty(cx, id, tvr.addr());
|
||||
JS_SetErrorReporter(cx, older);
|
||||
if (!ok)
|
||||
return false;
|
||||
|
||||
if (!ValueToLength(cx, tvr.addr(), lengthp))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Since SpiderMonkey supports cross-class prototype-based delegation, we have
|
||||
* to be careful about the length getter and setter being called on an object
|
||||
|
@ -595,20 +544,26 @@ array_length_getter(JSContext *cx, JSObject *obj, jsid id, Value *vp)
|
|||
static JSBool
|
||||
array_length_setter(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
|
||||
{
|
||||
jsuint newlen, oldlen, gap, index;
|
||||
Value junk;
|
||||
|
||||
if (!obj->isArray()) {
|
||||
jsid lengthId = ATOM_TO_JSID(cx->runtime->atomState.lengthAtom);
|
||||
|
||||
return obj->defineProperty(cx, lengthId, *vp, NULL, NULL, JSPROP_ENUMERATE);
|
||||
}
|
||||
|
||||
if (!ValueToLength(cx, vp, &newlen))
|
||||
uint32 newlen;
|
||||
if (!ValueToECMAUint32(cx, *vp, &newlen))
|
||||
return false;
|
||||
|
||||
oldlen = obj->getArrayLength();
|
||||
jsdouble d;
|
||||
if (!ValueToNumber(cx, *vp, &d))
|
||||
return false;
|
||||
|
||||
if (d != newlen) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_ARRAY_LENGTH);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 oldlen = obj->getArrayLength();
|
||||
if (oldlen == newlen)
|
||||
return true;
|
||||
|
||||
|
@ -658,12 +613,14 @@ array_length_setter(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value
|
|||
/* Protect iter against GC under JSObject::deleteProperty. */
|
||||
AutoObjectRooter tvr(cx, iter);
|
||||
|
||||
gap = oldlen - newlen;
|
||||
jsuint gap = oldlen - newlen;
|
||||
for (;;) {
|
||||
if (!JS_CHECK_OPERATION_LIMIT(cx) || !JS_NextProperty(cx, iter, &id))
|
||||
return false;
|
||||
if (JSID_IS_VOID(id))
|
||||
break;
|
||||
jsuint index;
|
||||
Value junk;
|
||||
if (js_IdIsIndex(id, &index) && index - newlen < gap &&
|
||||
!obj->deleteProperty(cx, id, &junk, false)) {
|
||||
return false;
|
||||
|
@ -2104,8 +2061,10 @@ array_push1_dense(JSContext* cx, JSObject* obj, const Value &v, Value *rval)
|
|||
}
|
||||
|
||||
JS_ALWAYS_INLINE JSBool
|
||||
ArrayCompPushImpl(JSContext *cx, JSObject *obj, const Value &v)
|
||||
NewbornArrayPushImpl(JSContext *cx, JSObject *obj, const Value &v)
|
||||
{
|
||||
JS_ASSERT(!v.isMagic());
|
||||
|
||||
uint32 length = obj->getArrayLength();
|
||||
if (obj->isSlowArray()) {
|
||||
/* This can happen in one evil case. See bug 630377. */
|
||||
|
@ -2117,45 +2076,34 @@ ArrayCompPushImpl(JSContext *cx, JSObject *obj, const Value &v)
|
|||
JS_ASSERT(obj->isDenseArray());
|
||||
JS_ASSERT(length <= obj->getDenseArrayCapacity());
|
||||
|
||||
if (length == obj->getDenseArrayCapacity()) {
|
||||
if (length > JS_ARGS_LENGTH_MAX) {
|
||||
JS_ReportErrorNumberUC(cx, js_GetErrorMessage, NULL,
|
||||
JSMSG_ARRAY_INIT_TOO_BIG);
|
||||
return false;
|
||||
}
|
||||
if (length == obj->getDenseArrayCapacity() && !obj->ensureSlots(cx, length + 1))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* An array comprehension cannot add holes to the array. So we can use
|
||||
* ensureSlots instead of ensureDenseArrayElements.
|
||||
*/
|
||||
if (!obj->ensureSlots(cx, length + 1))
|
||||
return false;
|
||||
}
|
||||
obj->setArrayLength(length + 1);
|
||||
obj->setDenseArrayElement(length, v);
|
||||
return true;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_ArrayCompPush(JSContext *cx, JSObject *obj, const Value &vp)
|
||||
js_NewbornArrayPush(JSContext *cx, JSObject *obj, const Value &vp)
|
||||
{
|
||||
return ArrayCompPushImpl(cx, obj, vp);
|
||||
return NewbornArrayPushImpl(cx, obj, vp);
|
||||
}
|
||||
|
||||
#ifdef JS_TRACER
|
||||
JSBool JS_FASTCALL
|
||||
js_ArrayCompPush_tn(JSContext *cx, JSObject *obj, ValueArgType v)
|
||||
js_NewbornArrayPush_tn(JSContext *cx, JSObject *obj, ValueArgType v)
|
||||
{
|
||||
TraceMonitor *tm = JS_TRACE_MONITOR_ON_TRACE(cx);
|
||||
|
||||
if (!ArrayCompPushImpl(cx, obj, ValueArgToConstRef(v))) {
|
||||
if (!NewbornArrayPushImpl(cx, obj, ValueArgToConstRef(v))) {
|
||||
SetBuiltinError(tm);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
return WasBuiltinSuccessful(tm);
|
||||
}
|
||||
JS_DEFINE_CALLINFO_3(extern, BOOL_FAIL, js_ArrayCompPush_tn, CONTEXT, OBJECT,
|
||||
JS_DEFINE_CALLINFO_3(extern, BOOL_FAIL, js_NewbornArrayPush_tn, CONTEXT, OBJECT,
|
||||
VALUE, 0, nanojit::ACCSET_STORE_ANY)
|
||||
#endif
|
||||
|
||||
|
@ -2547,8 +2495,6 @@ array_concat(JSContext *cx, uintN argc, Value *vp)
|
|||
length = 0;
|
||||
}
|
||||
|
||||
AutoValueRooter tvr(cx);
|
||||
|
||||
/* Loop over [0, argc] to concat args into nobj, expanding all Arrays. */
|
||||
for (uintN i = 0; i <= argc; i++) {
|
||||
if (!JS_CHECK_OPERATION_LIMIT(cx))
|
||||
|
@ -2556,29 +2502,22 @@ array_concat(JSContext *cx, uintN argc, Value *vp)
|
|||
const Value &v = p[i];
|
||||
if (v.isObject()) {
|
||||
aobj = &v.toObject();
|
||||
if (aobj->isArray() ||
|
||||
(aobj->isWrapper() && aobj->unwrap()->isArray())) {
|
||||
jsid id = ATOM_TO_JSID(cx->runtime->atomState.lengthAtom);
|
||||
if (!aobj->getProperty(cx, id, tvr.addr()))
|
||||
return false;
|
||||
if (aobj->isArray() || (aobj->isWrapper() && aobj->unwrap()->isArray())) {
|
||||
jsuint alength;
|
||||
if (!ValueToLength(cx, tvr.addr(), &alength))
|
||||
if (!js_GetLengthProperty(cx, aobj, &alength))
|
||||
return false;
|
||||
for (jsuint slot = 0; slot < alength; slot++) {
|
||||
for (uint32 slot = 0; slot < alength; slot++) {
|
||||
JSBool hole;
|
||||
if (!JS_CHECK_OPERATION_LIMIT(cx) ||
|
||||
!GetElement(cx, aobj, slot, &hole, tvr.addr())) {
|
||||
Value tmp;
|
||||
if (!JS_CHECK_OPERATION_LIMIT(cx) || !GetElement(cx, aobj, slot, &hole, &tmp))
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Per ECMA 262, 15.4.4.4, step 9, ignore nonexistent
|
||||
* properties.
|
||||
*/
|
||||
if (!hole &&
|
||||
!SetArrayElement(cx, nobj, length+slot, tvr.value())) {
|
||||
if (!hole && !SetArrayElement(cx, nobj, length + slot, tmp))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
length += alength;
|
||||
continue;
|
||||
|
@ -3046,29 +2985,42 @@ static JSFunctionSpec array_static_methods[] = {
|
|||
JS_FS_END
|
||||
};
|
||||
|
||||
/* ES5 15.4.2 */
|
||||
JSBool
|
||||
js_Array(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
JSObject *obj;
|
||||
|
||||
if (argc == 0) {
|
||||
obj = NewDenseEmptyArray(cx);
|
||||
} else if (argc > 1) {
|
||||
obj = NewDenseCopiedArray(cx, argc, vp + 2);
|
||||
} else if (!vp[2].isNumber()) {
|
||||
obj = NewDenseCopiedArray(cx, 1, vp + 2);
|
||||
} else {
|
||||
jsuint length;
|
||||
if (!ValueToLength(cx, vp + 2, &length))
|
||||
return JS_FALSE;
|
||||
obj = NewDenseUnallocatedArray(cx, length);
|
||||
if (argc != 1 || !vp[2].isNumber()) {
|
||||
JSObject *obj = (argc == 0)
|
||||
? NewDenseEmptyArray(cx)
|
||||
: NewDenseCopiedArray(cx, argc, vp + 2);
|
||||
if (!obj)
|
||||
return false;
|
||||
vp->setObject(*obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
vp->setObject(*obj);
|
||||
uint32 length;
|
||||
if (vp[2].isInt32()) {
|
||||
int32_t i = vp[2].toInt32();
|
||||
if (i < 0) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_ARRAY_LENGTH);
|
||||
return false;
|
||||
}
|
||||
length = uint32(i);
|
||||
} else {
|
||||
jsdouble d = vp[2].toDouble();
|
||||
length = js_DoubleToECMAUint32(d);
|
||||
if (d != jsdouble(length)) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_ARRAY_LENGTH);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return JS_TRUE;
|
||||
JSObject *obj = NewDenseUnallocatedArray(cx, length);
|
||||
if (!obj)
|
||||
return false;
|
||||
vp->setObject(*obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
JSObject *
|
||||
|
|
|
@ -193,9 +193,6 @@ js_GetLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp);
|
|||
extern JSBool
|
||||
js_SetLengthProperty(JSContext *cx, JSObject *obj, jsdouble length);
|
||||
|
||||
extern JSBool
|
||||
js_HasLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp);
|
||||
|
||||
namespace js {
|
||||
|
||||
extern JSBool
|
||||
|
@ -253,8 +250,15 @@ extern JSBool
|
|||
js_ArrayInfo(JSContext *cx, uintN argc, jsval *vp);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Append the given (non-hole) value to the end of an array. The array must be
|
||||
* a newborn array -- that is, one which has not been exposed to script for
|
||||
* arbitrary manipulation. (This method optimizes on the assumption that
|
||||
* extending the array to accommodate the element will never make the array
|
||||
* sparse, which requires that the array be completely filled.)
|
||||
*/
|
||||
extern JSBool
|
||||
js_ArrayCompPush(JSContext *cx, JSObject *obj, const js::Value &vp);
|
||||
js_NewbornArrayPush(JSContext *cx, JSObject *obj, const js::Value &v);
|
||||
|
||||
JSBool
|
||||
js_PrototypeHasIndexedProperties(JSContext *cx, JSObject *obj);
|
||||
|
|
|
@ -581,7 +581,7 @@ JS_DECLARE_CALLINFO(NewDenseEmptyArray)
|
|||
JS_DECLARE_CALLINFO(NewDenseAllocatedArray)
|
||||
JS_DECLARE_CALLINFO(NewDenseUnallocatedArray)
|
||||
}
|
||||
JS_DECLARE_CALLINFO(js_ArrayCompPush_tn)
|
||||
JS_DECLARE_CALLINFO(js_NewbornArrayPush_tn)
|
||||
JS_DECLARE_CALLINFO(js_EnsureDenseArrayCapacity)
|
||||
|
||||
/* Defined in jsbuiltins.cpp. */
|
||||
|
|
|
@ -771,7 +771,7 @@ JSStructuredCloneReader::startRead(Value *vp)
|
|||
const jschar *chars = str->getChars(context());
|
||||
if (!chars)
|
||||
return false;
|
||||
JSObject *obj = RegExp::createObjectNoStatics(context(), chars, length, data);
|
||||
JSObject *obj = RegExp::createObjectNoStatics(context(), chars, length, data, NULL);
|
||||
if (!obj)
|
||||
return false;
|
||||
vp->setObject(*obj);
|
||||
|
|
|
@ -1934,37 +1934,6 @@ class AutoReleaseNullablePtr {
|
|||
~AutoReleaseNullablePtr() { if (ptr) cx->free_(ptr); }
|
||||
};
|
||||
|
||||
class AutoLocalNameArray {
|
||||
public:
|
||||
explicit AutoLocalNameArray(JSContext *cx, JSFunction *fun
|
||||
JS_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: context(cx),
|
||||
mark(JS_ARENA_MARK(&cx->tempPool)),
|
||||
names(fun->script()->bindings.getLocalNameArray(cx, &cx->tempPool)),
|
||||
count(fun->script()->bindings.countLocalNames())
|
||||
{
|
||||
JS_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
|
||||
~AutoLocalNameArray() {
|
||||
JS_ARENA_RELEASE(&context->tempPool, mark);
|
||||
}
|
||||
|
||||
operator bool() const { return !!names; }
|
||||
|
||||
uint32 length() const { return count; }
|
||||
|
||||
const jsuword &operator [](unsigned i) const { return names[i]; }
|
||||
|
||||
private:
|
||||
JSContext *context;
|
||||
void *mark;
|
||||
jsuword *names;
|
||||
uint32 count;
|
||||
|
||||
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
};
|
||||
|
||||
template <class RefCountable>
|
||||
class AlreadyIncRefed
|
||||
{
|
||||
|
|
|
@ -547,7 +547,7 @@ struct JS_FRIEND_API(JSCompartment) {
|
|||
* executing. cx must be a context on the current thread.
|
||||
*/
|
||||
static inline bool
|
||||
JS_ON_TRACE(JSContext *cx)
|
||||
JS_ON_TRACE(const JSContext *cx)
|
||||
{
|
||||
#ifdef JS_TRACER
|
||||
if (JS_THREAD_DATA(cx)->onTraceCompartment)
|
||||
|
|
|
@ -70,6 +70,7 @@
|
|||
#include "jsnum.h"
|
||||
#include "jsobj.h"
|
||||
#include "jsstr.h"
|
||||
#include "jslibmath.h"
|
||||
|
||||
#include "jsobjinlines.h"
|
||||
|
||||
|
|
|
@ -127,8 +127,6 @@ ScriptDebugPrologue(JSContext *cx, StackFrame *fp)
|
|||
if (JSInterpreterHook hook = cx->debugHooks->callHook)
|
||||
fp->setHookData(hook(cx, Jsvalify(fp), true, 0, cx->debugHooks->callHookData));
|
||||
}
|
||||
|
||||
Probes::enterJSFun(cx, fp->maybeFun(), fp->script());
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -136,8 +134,6 @@ ScriptDebugEpilogue(JSContext *cx, StackFrame *fp, bool okArg)
|
|||
{
|
||||
JSBool ok = okArg;
|
||||
|
||||
Probes::exitJSFun(cx, fp->maybeFun(), fp->script());
|
||||
|
||||
if (void *hookData = fp->maybeHookData()) {
|
||||
if (fp->isFramePushedByExecute()) {
|
||||
if (JSInterpreterHook hook = cx->debugHooks->executeHook)
|
||||
|
@ -1367,8 +1363,22 @@ JS_FunctionHasLocalNames(JSContext *cx, JSFunction *fun)
|
|||
extern JS_PUBLIC_API(jsuword *)
|
||||
JS_GetFunctionLocalNameArray(JSContext *cx, JSFunction *fun, void **markp)
|
||||
{
|
||||
Vector<JSAtom *> localNames(cx);
|
||||
if (!fun->script()->bindings.getLocalNameArray(cx, &localNames))
|
||||
return NULL;
|
||||
|
||||
/* Munge data into the API this method implements. Avert your eyes! */
|
||||
*markp = JS_ARENA_MARK(&cx->tempPool);
|
||||
return fun->script()->bindings.getLocalNameArray(cx, &cx->tempPool);
|
||||
|
||||
jsuword *names;
|
||||
JS_ARENA_ALLOCATE_CAST(names, jsuword *, &cx->tempPool, localNames.length() * sizeof *names);
|
||||
if (!names) {
|
||||
js_ReportOutOfMemory(cx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(names, localNames.begin(), localNames.length() * sizeof(jsuword));
|
||||
return names;
|
||||
}
|
||||
|
||||
extern JS_PUBLIC_API(JSAtom *)
|
||||
|
@ -1578,6 +1588,7 @@ JS_GetValidFrameCalleeObject(JSContext *cx, JSStackFrame *fp, jsval *vp)
|
|||
|
||||
if (!Valueify(fp)->getValidCalleeObject(cx, &v))
|
||||
return false;
|
||||
*vp = v.isObject() ? Jsvalify(v) : JSVAL_VOID;
|
||||
*vp = Jsvalify(v);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1427,7 +1427,7 @@ bool
|
|||
StackFrame::getValidCalleeObject(JSContext *cx, Value *vp)
|
||||
{
|
||||
if (!isFunctionFrame()) {
|
||||
vp->setUndefined();
|
||||
vp->setNull();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1560,6 +1560,9 @@ fun_getProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp)
|
|||
|
||||
/* Find fun's top-most activation record. */
|
||||
StackFrame *fp = js_GetTopStackFrame(cx);
|
||||
if (!fp)
|
||||
return true;
|
||||
|
||||
while (!fp->isFunctionFrame() || fp->fun() != fun) {
|
||||
fp = fp->prev();
|
||||
if (!fp)
|
||||
|
@ -1572,9 +1575,11 @@ fun_getProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp)
|
|||
NULL, JSMSG_DEPRECATED_USAGE, js_arguments_str)) {
|
||||
return false;
|
||||
}
|
||||
if (!js_GetArgsValue(cx, fp, vp))
|
||||
return false;
|
||||
} else if (JSID_IS_ATOM(id, cx->runtime->atomState.callerAtom)) {
|
||||
|
||||
return js_GetArgsValue(cx, fp, vp);
|
||||
}
|
||||
|
||||
if (JSID_IS_ATOM(id, cx->runtime->atomState.callerAtom)) {
|
||||
if (!fp->prev())
|
||||
return true;
|
||||
|
||||
|
@ -1582,26 +1587,29 @@ fun_getProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp)
|
|||
if (frame && !frame->getValidCalleeObject(cx, vp))
|
||||
return false;
|
||||
|
||||
if (vp->isObject()) {
|
||||
JSObject &caller = vp->toObject();
|
||||
if (!vp->isObject()) {
|
||||
JS_ASSERT(vp->isNull());
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Censor the caller if it is from another compartment. */
|
||||
if (caller.compartment() != cx->compartment) {
|
||||
vp->setNull();
|
||||
} else if (caller.isFunction()) {
|
||||
JSFunction *callerFun = caller.getFunctionPrivate();
|
||||
if (callerFun->isInterpreted() && callerFun->inStrictMode()) {
|
||||
JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, js_GetErrorMessage, NULL,
|
||||
JSMSG_CALLER_IS_STRICT);
|
||||
return false;
|
||||
}
|
||||
/* Censor the caller if it is from another compartment. */
|
||||
JSObject &caller = vp->toObject();
|
||||
if (caller.compartment() != cx->compartment) {
|
||||
vp->setNull();
|
||||
} else if (caller.isFunction()) {
|
||||
JSFunction *callerFun = caller.getFunctionPrivate();
|
||||
if (callerFun->isInterpreted() && callerFun->inStrictMode()) {
|
||||
JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, js_GetErrorMessage, NULL,
|
||||
JSMSG_CALLER_IS_STRICT);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
JS_NOT_REACHED("fun_getProperty");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
JS_NOT_REACHED("fun_getProperty");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -906,7 +906,7 @@ Execute(JSContext *cx, JSScript *script, JSObject &scopeChain, const Value &this
|
|||
|
||||
AutoPreserveEnumerators preserve(cx);
|
||||
JSBool ok = RunScript(cx, script, fp);
|
||||
if (result)
|
||||
if (result && ok)
|
||||
*result = fp->returnValue();
|
||||
|
||||
Probes::stopExecution(cx, script);
|
||||
|
@ -4077,6 +4077,8 @@ BEGIN_CASE(JSOP_FUNAPPLY)
|
|||
|
||||
JSObject *callee;
|
||||
JSFunction *fun;
|
||||
|
||||
/* Don't bother trying to fast-path calls to scripted non-constructors. */
|
||||
if (!IsFunctionObject(args.calleev(), &callee, &fun) || !fun->isInterpretedConstructor()) {
|
||||
if (construct) {
|
||||
if (!InvokeConstructor(cx, args))
|
||||
|
@ -4588,12 +4590,12 @@ BEGIN_CASE(JSOP_CALLUPVAR_DBG)
|
|||
jsid id;
|
||||
JSAtom *atom;
|
||||
{
|
||||
AutoLocalNameArray names(cx, fun);
|
||||
if (!names)
|
||||
Vector<JSAtom *> names(cx);
|
||||
if (!fun->script()->bindings.getLocalNameArray(cx, &names))
|
||||
goto error;
|
||||
|
||||
uintN index = fun->script()->bindings.countArgsAndVars() + GET_UINT16(regs.pc);
|
||||
atom = JS_LOCAL_NAME_TO_ATOM(names[index]);
|
||||
atom = names[index];
|
||||
id = ATOM_TO_JSID(atom);
|
||||
|
||||
if (!js_FindProperty(cx, id, &obj, &obj2, &prop))
|
||||
|
@ -5961,7 +5963,7 @@ BEGIN_CASE(JSOP_ARRAYPUSH)
|
|||
JS_ASSERT(script->nfixed <= slot);
|
||||
JS_ASSERT(slot < script->nslots);
|
||||
JSObject *obj = ®s.fp()->slots()[slot].toObject();
|
||||
if (!js_ArrayCompPush(cx, obj, regs.sp[-1]))
|
||||
if (!js_NewbornArrayPush(cx, obj, regs.sp[-1]))
|
||||
goto error;
|
||||
regs.sp--;
|
||||
}
|
||||
|
@ -6245,7 +6247,16 @@ END_CASE(JSOP_ARRAYPUSH)
|
|||
# endif
|
||||
#endif
|
||||
|
||||
JS_ASSERT_IF(!regs.fp()->isGeneratorFrame(), !js_IsActiveWithOrBlock(cx, ®s.fp()->scopeChain(), 0));
|
||||
JS_ASSERT_IF(!regs.fp()->isGeneratorFrame(),
|
||||
!js_IsActiveWithOrBlock(cx, ®s.fp()->scopeChain(), 0));
|
||||
|
||||
#ifdef JS_METHODJIT
|
||||
/*
|
||||
* This path is used when it's guaranteed the method can be finished
|
||||
* inside the JIT.
|
||||
*/
|
||||
leave_on_safe_point:
|
||||
#endif
|
||||
|
||||
return interpReturnOK;
|
||||
|
||||
|
@ -6256,15 +6267,6 @@ END_CASE(JSOP_ARRAYPUSH)
|
|||
js_ReportIsNotDefined(cx, printable.ptr());
|
||||
}
|
||||
goto error;
|
||||
|
||||
/*
|
||||
* This path is used when it's guaranteed the method can be finished
|
||||
* inside the JIT.
|
||||
*/
|
||||
#if defined(JS_METHODJIT)
|
||||
leave_on_safe_point:
|
||||
#endif
|
||||
return interpReturnOK;
|
||||
}
|
||||
|
||||
} /* namespace js */
|
||||
|
|
|
@ -353,14 +353,17 @@ ScriptPrologue(JSContext *cx, StackFrame *fp)
|
|||
fp->functionThis().setObject(*obj);
|
||||
}
|
||||
|
||||
Probes::enterJSFun(cx, fp->maybeFun(), fp->script());
|
||||
if (cx->compartment->debugMode)
|
||||
ScriptDebugPrologue(cx, fp);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ScriptEpilogue(JSContext *cx, StackFrame *fp, bool ok)
|
||||
{
|
||||
Probes::exitJSFun(cx, fp->maybeFun(), fp->script());
|
||||
if (cx->compartment->debugMode)
|
||||
ok = ScriptDebugEpilogue(cx, fp, ok);
|
||||
|
||||
|
|
|
@ -65,6 +65,12 @@ extern double js_copysign(double, double);
|
|||
#define js_copysign copysign
|
||||
#endif
|
||||
|
||||
#if defined(_M_X64) && _MSC_VER <= 1500
|
||||
// This is a workaround for fmod bug (http://support.microsoft.com/kb/982107)
|
||||
extern "C" double js_myfmod(double x, double y);
|
||||
#define fmod js_myfmod
|
||||
#endif
|
||||
|
||||
/* Consistency wrapper for platform deviations in fmod() */
|
||||
static inline double
|
||||
js_fmod(double d, double d2)
|
||||
|
|
|
@ -70,6 +70,7 @@
|
|||
#include "jsstr.h"
|
||||
#include "jstracer.h"
|
||||
#include "jsvector.h"
|
||||
#include "jslibmath.h"
|
||||
|
||||
#include "jsinterpinlines.h"
|
||||
#include "jsnuminlines.h"
|
||||
|
|
|
@ -2519,19 +2519,18 @@ obj_create(JSContext *cx, uintN argc, Value *vp)
|
|||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if (JSObject *proto = v.toObjectOrNull()) {
|
||||
if (proto->isXML()) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_XML_PROTO_FORBIDDEN);
|
||||
return false;
|
||||
}
|
||||
JSObject *proto = v.toObjectOrNull();
|
||||
if (proto && proto->isXML()) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_XML_PROTO_FORBIDDEN);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Use the callee's global as the parent of the new object to avoid dynamic
|
||||
* scoping (i.e., using the caller's global).
|
||||
*/
|
||||
JSObject *obj = NewNonFunction<WithProto::Given>(cx, &js_ObjectClass, v.toObjectOrNull(),
|
||||
vp->toObject().getGlobal());
|
||||
JSObject *obj = NewNonFunction<WithProto::Given>(cx, &js_ObjectClass, proto,
|
||||
vp->toObject().getGlobal());
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
vp->setObject(*obj); /* Root and prepare for eventual return. */
|
||||
|
|
|
@ -137,25 +137,6 @@ js_json_stringify(JSContext *cx, uintN argc, Value *vp)
|
|||
return true;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_TryJSON(JSContext *cx, Value *vp)
|
||||
{
|
||||
if (!vp->isObject())
|
||||
return true;
|
||||
|
||||
JSObject *obj = &vp->toObject();
|
||||
Value fval;
|
||||
jsid id = ATOM_TO_JSID(cx->runtime->atomState.toJSONAtom);
|
||||
if (!js_GetMethod(cx, obj, id, JSGET_NO_METHOD_BARRIER, &fval))
|
||||
return false;
|
||||
if (js_IsCallable(fval)) {
|
||||
if (!ExternalInvoke(cx, ObjectValue(*obj), fval, 0, NULL, vp))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static inline bool IsQuoteSpecialCharacter(jschar c)
|
||||
{
|
||||
JS_STATIC_ASSERT('\b' < ' ');
|
||||
|
|
|
@ -55,8 +55,6 @@ extern JSBool
|
|||
js_Stringify(JSContext *cx, js::Value *vp, JSObject *replacer, js::Value space,
|
||||
js::StringBuffer &sb);
|
||||
|
||||
extern JSBool js_TryJSON(JSContext *cx, js::Value *vp);
|
||||
|
||||
/* Aargh, Windows. */
|
||||
#ifdef STRICT
|
||||
#undef STRICT
|
||||
|
|
|
@ -584,7 +584,7 @@ JSONParser::parse(Value *vp)
|
|||
|
||||
case FinishArrayElement: {
|
||||
Value v = valueStack.popCopy();
|
||||
if (!js_ArrayCompPush(cx, &valueStack.back().toObject(), v))
|
||||
if (!js_NewbornArrayPush(cx, &valueStack.back().toObject(), v))
|
||||
return false;
|
||||
token = advanceAfterArrayElement();
|
||||
if (token == Comma) {
|
||||
|
|
|
@ -849,7 +849,7 @@ struct JSPrinter {
|
|||
jsbytecode *dvgfence; /* DecompileExpression fencepost */
|
||||
jsbytecode **pcstack; /* DecompileExpression modeled stack */
|
||||
JSFunction *fun; /* interpreted function */
|
||||
jsuword *localNames; /* argument and variable names */
|
||||
Vector<JSAtom *> *localNames; /* argument and variable names */
|
||||
};
|
||||
|
||||
JSPrinter *
|
||||
|
@ -873,8 +873,8 @@ js_NewPrinter(JSContext *cx, const char *name, JSFunction *fun,
|
|||
jp->fun = fun;
|
||||
jp->localNames = NULL;
|
||||
if (fun && fun->isInterpreted() && fun->script()->bindings.hasLocalNames()) {
|
||||
jp->localNames = fun->script()->bindings.getLocalNameArray(cx, &jp->pool);
|
||||
if (!jp->localNames) {
|
||||
jp->localNames = cx->new_<Vector<JSAtom *> >(cx);
|
||||
if (!jp->localNames || !fun->script()->bindings.getLocalNameArray(cx, jp->localNames)) {
|
||||
js_DestroyPrinter(jp);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -886,6 +886,7 @@ void
|
|||
js_DestroyPrinter(JSPrinter *jp)
|
||||
{
|
||||
JS_FinishArenaPool(&jp->pool);
|
||||
Foreground::delete_(jp->localNames);
|
||||
jp->sprinter.context->free_(jp);
|
||||
}
|
||||
|
||||
|
@ -1379,11 +1380,9 @@ DecompileSwitch(SprintStack *ss, TableEntry *table, uintN tableLength,
|
|||
static JSAtom *
|
||||
GetArgOrVarAtom(JSPrinter *jp, uintN slot)
|
||||
{
|
||||
JSAtom *name;
|
||||
|
||||
LOCAL_ASSERT_RV(jp->fun, NULL);
|
||||
LOCAL_ASSERT_RV(slot < jp->fun->script()->bindings.countLocalNames(), NULL);
|
||||
name = JS_LOCAL_NAME_TO_ATOM(jp->localNames[slot]);
|
||||
JSAtom *name = (*jp->localNames)[slot];
|
||||
#if !JS_HAS_DESTRUCTURING
|
||||
LOCAL_ASSERT_RV(name, NULL);
|
||||
#endif
|
||||
|
@ -2925,8 +2924,12 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
|||
|
||||
if (!jp->localNames) {
|
||||
JS_ASSERT(fun == jp->fun);
|
||||
jp->localNames =
|
||||
jp->fun->script()->bindings.getLocalNameArray(cx, &jp->pool);
|
||||
jp->localNames = cx->new_<Vector<JSAtom *> >(cx);
|
||||
if (!jp->localNames ||
|
||||
!jp->fun->script()->bindings.getLocalNameArray(cx, jp->localNames))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
uintN index = GET_UINT16(pc);
|
||||
|
@ -4098,7 +4101,8 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
|||
sn = js_GetSrcNote(jp->script, pc);
|
||||
if (sn && SN_TYPE(sn) == SRC_GENEXP) {
|
||||
void *mark;
|
||||
jsuword *innerLocalNames, *outerLocalNames;
|
||||
Vector<JSAtom *> *innerLocalNames;
|
||||
Vector<JSAtom *> *outerLocalNames;
|
||||
JSScript *inner, *outer;
|
||||
SprintStack ss2;
|
||||
JSFunction *outerfun;
|
||||
|
@ -4113,10 +4117,12 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
|||
*/
|
||||
mark = JS_ARENA_MARK(&cx->tempPool);
|
||||
if (fun->script()->bindings.hasLocalNames()) {
|
||||
innerLocalNames =
|
||||
fun->script()->bindings.getLocalNameArray(cx, &cx->tempPool);
|
||||
if (!innerLocalNames)
|
||||
innerLocalNames = cx->new_<Vector<JSAtom *> >(cx);
|
||||
if (!innerLocalNames ||
|
||||
fun->script()->bindings.getLocalNameArray(cx, innerLocalNames))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
innerLocalNames = NULL;
|
||||
}
|
||||
|
|
|
@ -1821,13 +1821,12 @@ Compiler::compileFunctionBody(JSContext *cx, JSFunction *fun, JSPrincipals *prin
|
|||
* NB: do not use AutoLocalNameArray because it will release space
|
||||
* allocated from cx->tempPool by DefineArg.
|
||||
*/
|
||||
jsuword *names = funcg.bindings.getLocalNameArray(cx, &cx->tempPool);
|
||||
if (!names) {
|
||||
Vector<JSAtom *> names(cx);
|
||||
if (!funcg.bindings.getLocalNameArray(cx, &names)) {
|
||||
fn = NULL;
|
||||
} else {
|
||||
for (uintN i = 0; i < nargs; i++) {
|
||||
JSAtom *name = JS_LOCAL_NAME_TO_ATOM(names[i]);
|
||||
if (!DefineArg(fn, name, i, &funcg)) {
|
||||
if (!DefineArg(fn, names[i], i, &funcg)) {
|
||||
fn = NULL;
|
||||
break;
|
||||
}
|
||||
|
@ -3077,9 +3076,9 @@ Parser::functionDef(JSAtom *funAtom, FunctionType type, FunctionSyntaxKind kind)
|
|||
}
|
||||
|
||||
if (bodyLevel) {
|
||||
tc->decls.update(funAtom, (JSDefinition *) pn);
|
||||
tc->decls.updateFirst(funAtom, (JSDefinition *) pn);
|
||||
pn->pn_defn = true;
|
||||
pn->dn_uses = dn; /* dn->dn_uses is now pn_link */
|
||||
pn->dn_uses = dn; /* dn->dn_uses is now pn_link */
|
||||
|
||||
if (!MakeDefIntoUse(dn, pn, funAtom, tc))
|
||||
return NULL;
|
||||
|
@ -6676,12 +6675,20 @@ class CompExprTransplanter {
|
|||
|
||||
/*
|
||||
* A helper for lazily checking for the presence of illegal |yield| or |arguments|
|
||||
* tokens inside of generator expressions.
|
||||
* tokens inside of generator expressions. This must be done lazily since we don't
|
||||
* know whether we're in a generator expression until we see the "for" token after
|
||||
* we've already parsed the body expression.
|
||||
*
|
||||
* Use when entering a parenthesized context. If the nested expression is followed
|
||||
* by a |for| token (indicating that the parenthesized expression is a generator
|
||||
* expression), use the checkValidBody() method to see if any illegal tokens were
|
||||
* found.
|
||||
* Use in any context which may turn out to be inside a generator expression. This
|
||||
* includes parenthesized expressions and argument lists, and it includes the tail
|
||||
* of generator expressions.
|
||||
*
|
||||
* The guard will keep track of any |yield| or |arguments| tokens that occur while
|
||||
* parsing the body. As soon as the parser reaches the end of the body expression,
|
||||
* call endBody() to reset the context's state, and then immediately call:
|
||||
*
|
||||
* - checkValidBody() if this *did* turn out to be a generator expression
|
||||
* - maybeNoteGenerator() if this *did not* turn out to be a generator expression
|
||||
*/
|
||||
class GenexpGuard {
|
||||
JSTreeContext *tc;
|
||||
|
@ -6703,6 +6710,7 @@ class GenexpGuard {
|
|||
|
||||
void endBody();
|
||||
bool checkValidBody(JSParseNode *pn);
|
||||
bool maybeNoteGenerator();
|
||||
};
|
||||
|
||||
void
|
||||
|
@ -6711,6 +6719,13 @@ GenexpGuard::endBody()
|
|||
tc->parenDepth--;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether a |yield| or |arguments| token has been encountered in the
|
||||
* body expression, and if so, report an error.
|
||||
*
|
||||
* Call this after endBody() when determining that the body *was* in a
|
||||
* generator expression.
|
||||
*/
|
||||
bool
|
||||
GenexpGuard::checkValidBody(JSParseNode *pn)
|
||||
{
|
||||
|
@ -6733,6 +6748,27 @@ GenexpGuard::checkValidBody(JSParseNode *pn)
|
|||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether a |yield| token has been encountered in the body expression,
|
||||
* and if so, note that the current function is a generator function.
|
||||
*
|
||||
* Call this after endBody() when determining that the body *was not* in a
|
||||
* generator expression.
|
||||
*/
|
||||
bool
|
||||
GenexpGuard::maybeNoteGenerator()
|
||||
{
|
||||
if (tc->yieldCount > 0) {
|
||||
tc->flags |= TCF_FUN_IS_GENERATOR;
|
||||
if (!tc->inFunction()) {
|
||||
tc->parser->reportErrorNumber(NULL, JSREPORT_ERROR, JSMSG_BAD_RETURN_OR_YIELD,
|
||||
js_yield_str);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Any definitions nested within the comprehension expression of a generator
|
||||
* expression must move "down" one static level, which of course increases the
|
||||
|
@ -6874,33 +6910,42 @@ CompExprTransplanter::transplant(JSParseNode *pn)
|
|||
if (genexp && PN_OP(dn) != JSOP_CALLEE) {
|
||||
JS_ASSERT(!tc->decls.lookupFirst(atom));
|
||||
|
||||
if (dn->pn_pos < root->pn_pos || dn->isPlaceholder()) {
|
||||
if (dn->pn_pos >= root->pn_pos) {
|
||||
tc->parent->lexdeps->remove(atom);
|
||||
} else {
|
||||
JSDefinition *dn2 = (JSDefinition *)NameNode::create(atom, tc);
|
||||
if (!dn2)
|
||||
return false;
|
||||
if (dn->pn_pos < root->pn_pos) {
|
||||
/*
|
||||
* The variable originally appeared to be a use of a
|
||||
* definition or placeholder outside the generator, but now
|
||||
* we know it is scoped within the comprehension tail's
|
||||
* clauses. Make it (along with any other uses within the
|
||||
* generator) a use of a new placeholder in the generator's
|
||||
* lexdeps.
|
||||
*/
|
||||
AtomDefnAddPtr p = tc->lexdeps->lookupForAdd(atom);
|
||||
JSDefinition *dn2 = MakePlaceholder(p, pn, tc);
|
||||
if (!dn2)
|
||||
return false;
|
||||
dn2->pn_pos = root->pn_pos;
|
||||
|
||||
dn2->pn_type = TOK_NAME;
|
||||
dn2->pn_op = JSOP_NOP;
|
||||
dn2->pn_defn = true;
|
||||
dn2->pn_dflags |= PND_PLACEHOLDER;
|
||||
dn2->pn_pos = root->pn_pos;
|
||||
|
||||
JSParseNode **pnup = &dn->dn_uses;
|
||||
JSParseNode *pnu;
|
||||
while ((pnu = *pnup) != NULL && pnu->pn_pos >= root->pn_pos) {
|
||||
pnu->pn_lexdef = dn2;
|
||||
dn2->pn_dflags |= pnu->pn_dflags & PND_USE2DEF_FLAGS;
|
||||
pnup = &pnu->pn_link;
|
||||
}
|
||||
dn2->dn_uses = dn->dn_uses;
|
||||
dn->dn_uses = *pnup;
|
||||
*pnup = NULL;
|
||||
|
||||
dn = dn2;
|
||||
/*
|
||||
* Change all uses of |dn| that lie within the generator's
|
||||
* |yield| expression into uses of dn2.
|
||||
*/
|
||||
JSParseNode **pnup = &dn->dn_uses;
|
||||
JSParseNode *pnu;
|
||||
while ((pnu = *pnup) != NULL && pnu->pn_pos >= root->pn_pos) {
|
||||
pnu->pn_lexdef = dn2;
|
||||
dn2->pn_dflags |= pnu->pn_dflags & PND_USE2DEF_FLAGS;
|
||||
pnup = &pnu->pn_link;
|
||||
}
|
||||
dn2->dn_uses = dn->dn_uses;
|
||||
dn->dn_uses = *pnup;
|
||||
*pnup = NULL;
|
||||
} else if (dn->isPlaceholder()) {
|
||||
/*
|
||||
* The variable first occurs free in the 'yield' expression;
|
||||
* move the existing placeholder node (and all its uses)
|
||||
* from the parent's lexdeps into the generator's lexdeps.
|
||||
*/
|
||||
tc->parent->lexdeps->remove(atom);
|
||||
if (!tc->lexdeps->put(atom, dn))
|
||||
return false;
|
||||
}
|
||||
|
@ -7055,8 +7100,12 @@ Parser::comprehensionTail(JSParseNode *kid, uintN blockid, bool isGenexp,
|
|||
|
||||
guard.endBody();
|
||||
|
||||
if (isGenexp && !guard.checkValidBody(pn2))
|
||||
if (isGenexp) {
|
||||
if (!guard.checkValidBody(pn2))
|
||||
return NULL;
|
||||
} else if (!guard.maybeNoteGenerator()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (tt) {
|
||||
#if JS_HAS_DESTRUCTURING
|
||||
|
@ -7107,9 +7156,6 @@ Parser::comprehensionTail(JSParseNode *kid, uintN blockid, bool isGenexp,
|
|||
pnp = &pn2->pn_kid2;
|
||||
}
|
||||
|
||||
if (!maybeNoteGenerator())
|
||||
return NULL;
|
||||
|
||||
pn2 = UnaryNode::create(tc);
|
||||
if (!pn2)
|
||||
return NULL;
|
||||
|
@ -7229,27 +7275,6 @@ static const char js_generator_str[] = "generator";
|
|||
#endif /* JS_HAS_GENERATOR_EXPRS */
|
||||
#endif /* JS_HAS_GENERATORS */
|
||||
|
||||
/*
|
||||
* Check whether a |yield| token has been encountered since the last reset point
|
||||
* (the creation of the tree context or the current GenexpGuard), and if so,
|
||||
* note that the current function is a generator function.
|
||||
*
|
||||
* Call this after the current GenexpGuard has determined whether it was inside
|
||||
* of a generator expression.
|
||||
*/
|
||||
bool
|
||||
Parser::maybeNoteGenerator()
|
||||
{
|
||||
if (tc->yieldCount > 0) {
|
||||
tc->flags |= TCF_FUN_IS_GENERATOR;
|
||||
if (!tc->inFunction()) {
|
||||
reportErrorNumber(NULL, JSREPORT_ERROR, JSMSG_BAD_RETURN_OR_YIELD, js_yield_str);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
JSBool
|
||||
Parser::argumentList(JSParseNode *listNode)
|
||||
{
|
||||
|
@ -7263,10 +7288,8 @@ Parser::argumentList(JSParseNode *listNode)
|
|||
JSParseNode *argNode = assignExpr();
|
||||
if (!argNode)
|
||||
return JS_FALSE;
|
||||
if (arg0) {
|
||||
if (arg0)
|
||||
guard.endBody();
|
||||
arg0 = false;
|
||||
}
|
||||
|
||||
#if JS_HAS_GENERATORS
|
||||
if (argNode->pn_type == TOK_YIELD &&
|
||||
|
@ -7289,14 +7312,16 @@ Parser::argumentList(JSParseNode *listNode)
|
|||
js_generator_str);
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
if (arg0 && !guard.maybeNoteGenerator())
|
||||
return JS_FALSE;
|
||||
|
||||
arg0 = false;
|
||||
|
||||
listNode->append(argNode);
|
||||
} while (tokenStream.matchToken(TOK_COMMA));
|
||||
|
||||
if (!maybeNoteGenerator())
|
||||
return JS_FALSE;
|
||||
|
||||
if (tokenStream.getToken() != TOK_RP) {
|
||||
reportErrorNumber(NULL, JSREPORT_ERROR, JSMSG_PAREN_AFTER_ARGS);
|
||||
return JS_FALSE;
|
||||
|
@ -8807,12 +8832,14 @@ Parser::primaryExpr(TokenKind tt, JSBool afterDot)
|
|||
obj = RegExp::createObject(context, context->regExpStatics(),
|
||||
tokenStream.getTokenbuf().begin(),
|
||||
tokenStream.getTokenbuf().length(),
|
||||
tokenStream.currentToken().t_reflags);
|
||||
tokenStream.currentToken().t_reflags,
|
||||
&tokenStream);
|
||||
} else {
|
||||
obj = RegExp::createObjectNoStatics(context,
|
||||
tokenStream.getTokenbuf().begin(),
|
||||
tokenStream.getTokenbuf().length(),
|
||||
tokenStream.currentToken().t_reflags);
|
||||
tokenStream.currentToken().t_reflags,
|
||||
&tokenStream);
|
||||
}
|
||||
|
||||
if (!obj)
|
||||
|
@ -8898,10 +8925,10 @@ Parser::parenExpr(JSBool *genexp)
|
|||
pn->pn_pos.end = tokenStream.currentToken().pos.end;
|
||||
*genexp = JS_TRUE;
|
||||
}
|
||||
}
|
||||
} else
|
||||
#endif /* JS_HAS_GENERATOR_EXPRS */
|
||||
|
||||
if (!maybeNoteGenerator())
|
||||
if (!guard.maybeNoteGenerator())
|
||||
return NULL;
|
||||
|
||||
return pn;
|
||||
|
|
|
@ -1145,8 +1145,6 @@ struct Parser : private js::AutoGCRooter
|
|||
inline bool reportErrorNumber(JSParseNode *pn, uintN flags, uintN errorNumber, ...);
|
||||
|
||||
private:
|
||||
bool maybeNoteGenerator();
|
||||
|
||||
/*
|
||||
* JS parsers, from lowest to highest precedence.
|
||||
*
|
||||
|
|
|
@ -190,9 +190,6 @@ Probes::startExecution(JSContext *cx, JSScript *script)
|
|||
JAVASCRIPT_EXECUTE_START((script->filename ? (char *)script->filename : nullName),
|
||||
script->lineno);
|
||||
#endif
|
||||
#ifdef MOZ_TRACE_JSCALLS
|
||||
cx->doFunctionCallback(NULL, script, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void
|
||||
|
@ -203,9 +200,6 @@ Probes::stopExecution(JSContext *cx, JSScript *script)
|
|||
JAVASCRIPT_EXECUTE_DONE((script->filename ? (char *)script->filename : nullName),
|
||||
script->lineno);
|
||||
#endif
|
||||
#ifdef MOZ_TRACE_JSCALLS
|
||||
cx->doFunctionCallback(NULL, script, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -75,32 +75,30 @@ JS_PROTO(RegExp, 10, js_InitRegExpClass)
|
|||
JS_PROTO(XML, 11, XML_INIT)
|
||||
JS_PROTO(Namespace, 12, NAMESPACE_INIT)
|
||||
JS_PROTO(QName, 13, QNAME_INIT)
|
||||
JS_PROTO(Reflect, 14, js_InitReflectClass)
|
||||
JS_PROTO(ASTNode, 15, js_InitReflectClass)
|
||||
JS_PROTO(Error, 16, js_InitExceptionClasses)
|
||||
JS_PROTO(InternalError, 17, js_InitExceptionClasses)
|
||||
JS_PROTO(EvalError, 18, js_InitExceptionClasses)
|
||||
JS_PROTO(RangeError, 19, js_InitExceptionClasses)
|
||||
JS_PROTO(ReferenceError, 20, js_InitExceptionClasses)
|
||||
JS_PROTO(SyntaxError, 21, js_InitExceptionClasses)
|
||||
JS_PROTO(TypeError, 22, js_InitExceptionClasses)
|
||||
JS_PROTO(URIError, 23, js_InitExceptionClasses)
|
||||
JS_PROTO(Generator, 24, GENERATOR_INIT)
|
||||
JS_PROTO(Iterator, 25, js_InitIteratorClasses)
|
||||
JS_PROTO(StopIteration, 26, js_InitIteratorClasses)
|
||||
JS_PROTO(ArrayBuffer, 27, js_InitTypedArrayClasses)
|
||||
JS_PROTO(Int8Array, 28, js_InitTypedArrayClasses)
|
||||
JS_PROTO(Uint8Array, 29, js_InitTypedArrayClasses)
|
||||
JS_PROTO(Int16Array, 30, js_InitTypedArrayClasses)
|
||||
JS_PROTO(Uint16Array, 31, js_InitTypedArrayClasses)
|
||||
JS_PROTO(Int32Array, 32, js_InitTypedArrayClasses)
|
||||
JS_PROTO(Uint32Array, 33, js_InitTypedArrayClasses)
|
||||
JS_PROTO(Float32Array, 34, js_InitTypedArrayClasses)
|
||||
JS_PROTO(Float64Array, 35, js_InitTypedArrayClasses)
|
||||
JS_PROTO(Uint8ClampedArray, 36, js_InitTypedArrayClasses)
|
||||
JS_PROTO(Proxy, 37, js_InitProxyClass)
|
||||
JS_PROTO(AnyName, 38, js_InitNullClass)
|
||||
JS_PROTO(WeakMap, 39, js_InitWeakMapClass)
|
||||
JS_PROTO(Error, 14, js_InitExceptionClasses)
|
||||
JS_PROTO(InternalError, 15, js_InitExceptionClasses)
|
||||
JS_PROTO(EvalError, 16, js_InitExceptionClasses)
|
||||
JS_PROTO(RangeError, 17, js_InitExceptionClasses)
|
||||
JS_PROTO(ReferenceError, 18, js_InitExceptionClasses)
|
||||
JS_PROTO(SyntaxError, 19, js_InitExceptionClasses)
|
||||
JS_PROTO(TypeError, 20, js_InitExceptionClasses)
|
||||
JS_PROTO(URIError, 21, js_InitExceptionClasses)
|
||||
JS_PROTO(Generator, 22, GENERATOR_INIT)
|
||||
JS_PROTO(Iterator, 23, js_InitIteratorClasses)
|
||||
JS_PROTO(StopIteration, 24, js_InitIteratorClasses)
|
||||
JS_PROTO(ArrayBuffer, 25, js_InitTypedArrayClasses)
|
||||
JS_PROTO(Int8Array, 26, js_InitTypedArrayClasses)
|
||||
JS_PROTO(Uint8Array, 27, js_InitTypedArrayClasses)
|
||||
JS_PROTO(Int16Array, 28, js_InitTypedArrayClasses)
|
||||
JS_PROTO(Uint16Array, 29, js_InitTypedArrayClasses)
|
||||
JS_PROTO(Int32Array, 30, js_InitTypedArrayClasses)
|
||||
JS_PROTO(Uint32Array, 31, js_InitTypedArrayClasses)
|
||||
JS_PROTO(Float32Array, 32, js_InitTypedArrayClasses)
|
||||
JS_PROTO(Float64Array, 33, js_InitTypedArrayClasses)
|
||||
JS_PROTO(Uint8ClampedArray, 34, js_InitTypedArrayClasses)
|
||||
JS_PROTO(Proxy, 35, js_InitProxyClass)
|
||||
JS_PROTO(AnyName, 36, js_InitNullClass)
|
||||
JS_PROTO(WeakMap, 37, js_InitWeakMapClass)
|
||||
|
||||
#undef XML_INIT
|
||||
#undef NAMESPACE_INIT
|
||||
|
|
|
@ -907,29 +907,20 @@ bool
|
|||
NodeBuilder::tryStatement(Value body, NodeVector &catches, Value finally,
|
||||
TokenPos *pos, Value *dst)
|
||||
{
|
||||
Value handler;
|
||||
Value handlers;
|
||||
|
||||
Value cb = callbacks[AST_TRY_STMT];
|
||||
if (!cb.isNull()) {
|
||||
return newArray(catches, &handler) &&
|
||||
callback(cb, body, handler, opt(finally), pos, dst);
|
||||
return newArray(catches, &handlers) &&
|
||||
callback(cb, body, handlers, opt(finally), pos, dst);
|
||||
}
|
||||
|
||||
switch (catches.length()) {
|
||||
case 0:
|
||||
handler.setNull();
|
||||
break;
|
||||
case 1:
|
||||
handler = catches[0];
|
||||
break;
|
||||
default:
|
||||
if (!newArray(catches, &handler))
|
||||
return false;
|
||||
}
|
||||
if (!newArray(catches, &handlers))
|
||||
return false;
|
||||
|
||||
return newNode(AST_TRY_STMT, pos,
|
||||
"block", body,
|
||||
"handler", handler,
|
||||
"handlers", handlers,
|
||||
"finalizer", finally,
|
||||
dst);
|
||||
}
|
||||
|
@ -3148,20 +3139,6 @@ ASTSerializer::functionBody(JSParseNode *pn, TokenPos *pos, Value *dst)
|
|||
|
||||
} /* namespace js */
|
||||
|
||||
/* Reflect class */
|
||||
|
||||
Class js_ReflectClass = {
|
||||
js_Reflect_str,
|
||||
JSCLASS_HAS_CACHED_PROTO(JSProto_Reflect),
|
||||
PropertyStub,
|
||||
PropertyStub,
|
||||
PropertyStub,
|
||||
StrictPropertyStub,
|
||||
EnumerateStub,
|
||||
ResolveStub,
|
||||
ConvertStub
|
||||
};
|
||||
|
||||
static JSBool
|
||||
reflect_parse(JSContext *cx, uint32 argc, jsval *vp)
|
||||
{
|
||||
|
@ -3285,14 +3262,16 @@ static JSFunctionSpec static_methods[] = {
|
|||
};
|
||||
|
||||
|
||||
JSObject *
|
||||
js_InitReflectClass(JSContext *cx, JSObject *obj)
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
JS_PUBLIC_API(JSObject *)
|
||||
JS_InitReflect(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JSObject *Reflect = NewNonFunction<WithProto::Class>(cx, &js_ReflectClass, NULL, obj);
|
||||
JSObject *Reflect = NewNonFunction<WithProto::Class>(cx, &js_ObjectClass, NULL, obj);
|
||||
if (!Reflect)
|
||||
return NULL;
|
||||
|
||||
if (!JS_DefineProperty(cx, obj, js_Reflect_str, OBJECT_TO_JSVAL(Reflect),
|
||||
if (!JS_DefineProperty(cx, obj, "Reflect", OBJECT_TO_JSVAL(Reflect),
|
||||
JS_PropertyStub, JS_StrictPropertyStub, 0)) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -3300,7 +3279,7 @@ js_InitReflectClass(JSContext *cx, JSObject *obj)
|
|||
if (!JS_DefineFunctions(cx, Reflect, static_methods))
|
||||
return NULL;
|
||||
|
||||
MarkStandardClassInitializedNoProto(obj, &js_ReflectClass);
|
||||
|
||||
return Reflect;
|
||||
}
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
|
|
@ -130,10 +130,5 @@ extern char const *nodeTypeNames[];
|
|||
|
||||
} /* namespace js */
|
||||
|
||||
extern js::Class js_ReflectClass;
|
||||
|
||||
extern JSObject *
|
||||
js_InitReflectClass(JSContext *cx, JSObject *obj);
|
||||
|
||||
|
||||
#endif /* jsreflect_h___ */
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
#include "jsnum.h"
|
||||
#include "jsobj.h"
|
||||
#include "jsregexp.h"
|
||||
#include "jsscan.h"
|
||||
#include "jsstr.h"
|
||||
#include "jsvector.h"
|
||||
|
||||
|
@ -161,7 +162,8 @@ js_CloneRegExpObject(JSContext *cx, JSObject *obj, JSObject *proto)
|
|||
* This regex is lacking flags from the statics, so we must recompile with the new
|
||||
* flags instead of increffing.
|
||||
*/
|
||||
AlreadyIncRefed<RegExp> clone = RegExp::create(cx, re->getSource(), origFlags | staticsFlags);
|
||||
AlreadyIncRefed<RegExp> clone = RegExp::create(cx, re->getSource(),
|
||||
origFlags | staticsFlags, NULL);
|
||||
if (!clone)
|
||||
return NULL;
|
||||
re = clone.get();
|
||||
|
@ -191,15 +193,18 @@ js_ObjectIsRegExp(JSObject *obj)
|
|||
*/
|
||||
|
||||
void
|
||||
RegExp::reportYarrError(JSContext *cx, JSC::Yarr::ErrorCode error)
|
||||
RegExp::reportYarrError(JSContext *cx, TokenStream *ts, JSC::Yarr::ErrorCode error)
|
||||
{
|
||||
switch (error) {
|
||||
case JSC::Yarr::NoError:
|
||||
JS_NOT_REACHED("Called reportYarrError with value for no error");
|
||||
return;
|
||||
#define COMPILE_EMSG(__code, __msg) \
|
||||
case JSC::Yarr::__code: \
|
||||
JS_ReportErrorFlagsAndNumberUC(cx, JSREPORT_ERROR, js_GetErrorMessage, NULL, __msg); \
|
||||
#define COMPILE_EMSG(__code, __msg) \
|
||||
case JSC::Yarr::__code: \
|
||||
if (ts) \
|
||||
ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR, __msg); \
|
||||
else \
|
||||
JS_ReportErrorFlagsAndNumberUC(cx, JSREPORT_ERROR, js_GetErrorMessage, NULL, __msg); \
|
||||
return
|
||||
COMPILE_EMSG(PatternTooLarge, JSMSG_REGEXP_TOO_COMPLEX);
|
||||
COMPILE_EMSG(QuantifierOutOfOrder, JSMSG_BAD_QUANTIFIER);
|
||||
|
@ -256,14 +261,14 @@ RegExp::parseFlags(JSContext *cx, JSString *flagStr, uintN *flagsOut)
|
|||
}
|
||||
|
||||
AlreadyIncRefed<RegExp>
|
||||
RegExp::createFlagged(JSContext *cx, JSString *str, JSString *opt)
|
||||
RegExp::createFlagged(JSContext *cx, JSString *str, JSString *opt, TokenStream *ts)
|
||||
{
|
||||
if (!opt)
|
||||
return create(cx, str, 0);
|
||||
return create(cx, str, 0, ts);
|
||||
uintN flags = 0;
|
||||
if (!parseFlags(cx, opt, &flags))
|
||||
return AlreadyIncRefed<RegExp>(NULL);
|
||||
return create(cx, str, flags);
|
||||
return create(cx, str, flags, ts);
|
||||
}
|
||||
|
||||
const Shape *
|
||||
|
@ -426,7 +431,7 @@ js_XDRRegExpObject(JSXDRState *xdr, JSObject **objp)
|
|||
* be from the malloc-allocated GC-invisible re. So we must anchor.
|
||||
*/
|
||||
JS::Anchor<JSString *> anchor(source);
|
||||
AlreadyIncRefed<RegExp> re = RegExp::create(xdr->cx, source, flagsword);
|
||||
AlreadyIncRefed<RegExp> re = RegExp::create(xdr->cx, source, flagsword, NULL);
|
||||
if (!re)
|
||||
return false;
|
||||
if (!obj->initRegExp(xdr->cx, re.get()))
|
||||
|
@ -567,7 +572,7 @@ static bool
|
|||
SwapRegExpInternals(JSContext *cx, JSObject *obj, Value *rval, JSString *str, uint32 flags = 0)
|
||||
{
|
||||
flags |= cx->regExpStatics()->getFlags();
|
||||
AlreadyIncRefed<RegExp> re = RegExp::create(cx, str, flags);
|
||||
AlreadyIncRefed<RegExp> re = RegExp::create(cx, str, flags, NULL);
|
||||
if (!re)
|
||||
return false;
|
||||
SwapObjectRegExp(cx, obj, re);
|
||||
|
@ -824,7 +829,7 @@ js_InitRegExpClass(JSContext *cx, JSObject *global)
|
|||
if (!proto)
|
||||
return NULL;
|
||||
|
||||
AlreadyIncRefed<RegExp> re = RegExp::create(cx, cx->runtime->emptyString, 0);
|
||||
AlreadyIncRefed<RegExp> re = RegExp::create(cx, cx->runtime->emptyString, 0, NULL);
|
||||
if (!re)
|
||||
return NULL;
|
||||
#ifdef DEBUG
|
||||
|
|
|
@ -132,10 +132,10 @@ class RegExp
|
|||
Foreground::delete_<JSC::Yarr::BytecodePattern>(byteCode);
|
||||
}
|
||||
|
||||
bool compileHelper(JSContext *cx, JSLinearString &pattern);
|
||||
bool compile(JSContext *cx);
|
||||
bool compileHelper(JSContext *cx, JSLinearString &pattern, TokenStream *ts);
|
||||
bool compile(JSContext *cx, TokenStream *ts);
|
||||
static const uint32 allFlags = JSREG_FOLD | JSREG_GLOB | JSREG_MULTILINE | JSREG_STICKY;
|
||||
void reportYarrError(JSContext *cx, JSC::Yarr::ErrorCode error);
|
||||
void reportYarrError(JSContext *cx, TokenStream *ts, JSC::Yarr::ErrorCode error);
|
||||
static inline bool initArena(JSContext *cx);
|
||||
static inline void checkMatchPairs(JSString *input, int *buf, size_t matchItemCount);
|
||||
static JSObject *createResult(JSContext *cx, JSString *input, int *buf, size_t matchItemCount);
|
||||
|
@ -174,10 +174,10 @@ class RegExp
|
|||
|
||||
/* Factories */
|
||||
|
||||
static AlreadyIncRefed<RegExp> create(JSContext *cx, JSString *source, uint32 flags);
|
||||
static AlreadyIncRefed<RegExp> create(JSContext *cx, JSString *source, uint32 flags, TokenStream *ts);
|
||||
|
||||
/* Would overload |create|, but |0| resolves ambiguously against pointer and uint. */
|
||||
static AlreadyIncRefed<RegExp> createFlagged(JSContext *cx, JSString *source, JSString *flags);
|
||||
static AlreadyIncRefed<RegExp> createFlagged(JSContext *cx, JSString *source, JSString *flags, TokenStream *ts);
|
||||
|
||||
/*
|
||||
* Create an object with new regular expression internals.
|
||||
|
@ -186,9 +186,9 @@ class RegExp
|
|||
* execution, as opposed to during something like XDR.
|
||||
*/
|
||||
static JSObject *createObject(JSContext *cx, RegExpStatics *res, const jschar *chars,
|
||||
size_t length, uint32 flags);
|
||||
size_t length, uint32 flags, TokenStream *ts);
|
||||
static JSObject *createObjectNoStatics(JSContext *cx, const jschar *chars, size_t length,
|
||||
uint32 flags);
|
||||
uint32 flags, TokenStream *ts);
|
||||
static RegExp *extractFrom(JSObject *obj);
|
||||
|
||||
/* Mutators */
|
||||
|
@ -407,7 +407,7 @@ RegExp::executeInternal(JSContext *cx, RegExpStatics *res, JSString *inputstr,
|
|||
}
|
||||
|
||||
inline AlreadyIncRefed<RegExp>
|
||||
RegExp::create(JSContext *cx, JSString *source, uint32 flags)
|
||||
RegExp::create(JSContext *cx, JSString *source, uint32 flags, TokenStream *ts)
|
||||
{
|
||||
typedef AlreadyIncRefed<RegExp> RetType;
|
||||
JSLinearString *flatSource = source->ensureLinear(cx);
|
||||
|
@ -416,7 +416,7 @@ RegExp::create(JSContext *cx, JSString *source, uint32 flags)
|
|||
RegExp *self = cx->new_<RegExp>(flatSource, flags, cx->compartment);
|
||||
if (!self)
|
||||
return RetType(NULL);
|
||||
if (!self->compile(cx)) {
|
||||
if (!self->compile(cx, ts)) {
|
||||
Foreground::delete_(self);
|
||||
return RetType(NULL);
|
||||
}
|
||||
|
@ -425,14 +425,14 @@ RegExp::create(JSContext *cx, JSString *source, uint32 flags)
|
|||
|
||||
inline JSObject *
|
||||
RegExp::createObject(JSContext *cx, RegExpStatics *res, const jschar *chars, size_t length,
|
||||
uint32 flags)
|
||||
uint32 flags, TokenStream *ts)
|
||||
{
|
||||
uint32 staticsFlags = res->getFlags();
|
||||
return createObjectNoStatics(cx, chars, length, flags | staticsFlags);
|
||||
return createObjectNoStatics(cx, chars, length, flags | staticsFlags, ts);
|
||||
}
|
||||
|
||||
inline JSObject *
|
||||
RegExp::createObjectNoStatics(JSContext *cx, const jschar *chars, size_t length, uint32 flags)
|
||||
RegExp::createObjectNoStatics(JSContext *cx, const jschar *chars, size_t length, uint32 flags, TokenStream *ts)
|
||||
{
|
||||
JS_ASSERT((flags & allFlags) == flags);
|
||||
JSString *str = js_NewStringCopyN(cx, chars, length);
|
||||
|
@ -444,7 +444,7 @@ RegExp::createObjectNoStatics(JSContext *cx, const jschar *chars, size_t length,
|
|||
* could be from the malloc-allocated GC-invisible re. So we must anchor.
|
||||
*/
|
||||
JS::Anchor<JSString *> anchor(str);
|
||||
AlreadyIncRefed<RegExp> re = RegExp::create(cx, str, flags);
|
||||
AlreadyIncRefed<RegExp> re = RegExp::create(cx, str, flags, ts);
|
||||
if (!re)
|
||||
return NULL;
|
||||
JSObject *obj = NewBuiltinClassInstance(cx, &js_RegExpClass);
|
||||
|
@ -469,12 +469,12 @@ EnableYarrJIT(JSContext *cx)
|
|||
}
|
||||
|
||||
inline bool
|
||||
RegExp::compileHelper(JSContext *cx, JSLinearString &pattern)
|
||||
RegExp::compileHelper(JSContext *cx, JSLinearString &pattern, TokenStream *ts)
|
||||
{
|
||||
JSC::Yarr::ErrorCode yarrError;
|
||||
JSC::Yarr::YarrPattern yarrPattern(pattern, ignoreCase(), multiline(), &yarrError);
|
||||
if (yarrError) {
|
||||
reportYarrError(cx, yarrError);
|
||||
reportYarrError(cx, ts, yarrError);
|
||||
return false;
|
||||
}
|
||||
parenCount = yarrPattern.m_numSubpatterns;
|
||||
|
@ -498,14 +498,14 @@ RegExp::compileHelper(JSContext *cx, JSLinearString &pattern)
|
|||
}
|
||||
|
||||
inline bool
|
||||
RegExp::compile(JSContext *cx)
|
||||
RegExp::compile(JSContext *cx, TokenStream *ts)
|
||||
{
|
||||
/* Flatten source early for the rest of compilation. */
|
||||
if (!source->ensureLinear(cx))
|
||||
return false;
|
||||
|
||||
if (!sticky())
|
||||
return compileHelper(cx, *source);
|
||||
return compileHelper(cx, *source, ts);
|
||||
|
||||
/*
|
||||
* The sticky case we implement hackily by prepending a caret onto the front
|
||||
|
@ -524,7 +524,7 @@ RegExp::compile(JSContext *cx)
|
|||
JSLinearString *fakeySource = sb.finishString();
|
||||
if (!fakeySource)
|
||||
return false;
|
||||
return compileHelper(cx, *fakeySource);
|
||||
return compileHelper(cx, *fakeySource, ts);
|
||||
}
|
||||
|
||||
inline bool
|
||||
|
|
|
@ -166,32 +166,28 @@ Bindings::add(JSContext *cx, JSAtom *name, BindingKind kind)
|
|||
return true;
|
||||
}
|
||||
|
||||
jsuword *
|
||||
Bindings::getLocalNameArray(JSContext *cx, JSArenaPool *pool)
|
||||
bool
|
||||
Bindings::getLocalNameArray(JSContext *cx, Vector<JSAtom *> *namesp)
|
||||
{
|
||||
JS_ASSERT(lastBinding);
|
||||
JS_ASSERT(lastBinding);
|
||||
JS_ASSERT(hasLocalNames());
|
||||
|
||||
JS_ASSERT(hasLocalNames());
|
||||
Vector<JSAtom *> &names = *namesp;
|
||||
JS_ASSERT(names.empty());
|
||||
|
||||
uintN n = countLocalNames();
|
||||
jsuword *names;
|
||||
|
||||
JS_ASSERT(SIZE_MAX / size_t(n) > sizeof *names);
|
||||
JS_ARENA_ALLOCATE_CAST(names, jsuword *, pool, size_t(n) * sizeof *names);
|
||||
if (!names) {
|
||||
js_ReportOutOfMemory(cx);
|
||||
return NULL;
|
||||
}
|
||||
if (!names.growByUninitialized(n))
|
||||
return false;
|
||||
|
||||
#ifdef DEBUG
|
||||
for (uintN i = 0; i != n; i++)
|
||||
names[i] = 0xdeadbeef;
|
||||
JSAtom * const POISON = reinterpret_cast<JSAtom *>(0xdeadbeef);
|
||||
for (uintN i = 0; i < n; i++)
|
||||
names[i] = POISON;
|
||||
#endif
|
||||
|
||||
for (Shape::Range r = lastBinding; !r.empty(); r.popFront()) {
|
||||
const Shape &shape = r.front();
|
||||
uintN index = uint16(shape.shortid);
|
||||
jsuword constFlag = 0;
|
||||
|
||||
if (shape.getter() == GetCallArg) {
|
||||
JS_ASSERT(index < nargs);
|
||||
|
@ -201,27 +197,23 @@ Bindings::getLocalNameArray(JSContext *cx, JSArenaPool *pool)
|
|||
} else {
|
||||
JS_ASSERT(index < nvars);
|
||||
index += nargs;
|
||||
if (!shape.writable())
|
||||
constFlag = 1;
|
||||
}
|
||||
|
||||
JSAtom *atom;
|
||||
if (JSID_IS_ATOM(shape.propid)) {
|
||||
atom = JSID_TO_ATOM(shape.propid);
|
||||
names[index] = JSID_TO_ATOM(shape.propid);
|
||||
} else {
|
||||
JS_ASSERT(JSID_IS_INT(shape.propid));
|
||||
JS_ASSERT(shape.getter() == GetCallArg);
|
||||
atom = NULL;
|
||||
names[index] = NULL;
|
||||
}
|
||||
|
||||
names[index] = jsuword(atom);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
for (uintN i = 0; i != n; i++)
|
||||
JS_ASSERT(names[i] != 0xdeadbeef);
|
||||
for (uintN i = 0; i < n; i++)
|
||||
JS_ASSERT(names[i] != POISON);
|
||||
#endif
|
||||
return names;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const Shape *
|
||||
|
@ -394,26 +386,16 @@ js_XDRScript(JSXDRState *xdr, JSScript **scriptp)
|
|||
return false;
|
||||
}
|
||||
|
||||
jsuword *names;
|
||||
Vector<JSAtom *> names(cx);
|
||||
if (xdr->mode == JSXDR_ENCODE) {
|
||||
names = script->bindings.getLocalNameArray(cx, &cx->tempPool);
|
||||
if (!names)
|
||||
if (!script->bindings.getLocalNameArray(cx, &names))
|
||||
return false;
|
||||
PodZero(bitmap, bitmapLength);
|
||||
for (uintN i = 0; i < nameCount; i++) {
|
||||
if (i < nargs
|
||||
? JS_LOCAL_NAME_TO_ATOM(names[i]) != NULL
|
||||
: JS_LOCAL_NAME_IS_CONST(names[i]))
|
||||
{
|
||||
if (i < nargs && names[i])
|
||||
bitmap[i >> JS_BITS_PER_UINT32_LOG2] |= JS_BIT(i & (JS_BITS_PER_UINT32 - 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef __GNUC__
|
||||
else {
|
||||
names = NULL; /* quell GCC uninitialized warning */
|
||||
}
|
||||
#endif
|
||||
for (uintN i = 0; i < bitmapLength; ++i) {
|
||||
if (!JS_XDRUint32(xdr, &bitmap[i]))
|
||||
return false;
|
||||
|
@ -428,14 +410,14 @@ js_XDRScript(JSXDRState *xdr, JSScript **scriptp)
|
|||
if (!bindings.addDestructuring(cx, &dummy))
|
||||
return false;
|
||||
} else {
|
||||
JS_ASSERT(!JS_LOCAL_NAME_TO_ATOM(names[i]));
|
||||
JS_ASSERT(!names[i]);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
JSAtom *name;
|
||||
if (xdr->mode == JSXDR_ENCODE)
|
||||
name = JS_LOCAL_NAME_TO_ATOM(names[i]);
|
||||
name = names[i];
|
||||
if (!js_XDRAtom(xdr, &name))
|
||||
return false;
|
||||
if (xdr->mode == JSXDR_DECODE) {
|
||||
|
|
|
@ -266,24 +266,15 @@ class Bindings {
|
|||
}
|
||||
|
||||
/*
|
||||
* Function and macros to work with local names as an array of words.
|
||||
* getLocalNameArray returns the array, or null if we are out of memory.
|
||||
* This function must be called only when hasLocalNames().
|
||||
* This method returns the local variable, argument, etc. names used by a
|
||||
* script. This function must be called only when hasLocalNames().
|
||||
*
|
||||
* The supplied pool is used to allocate the returned array, so the caller
|
||||
* is obligated to mark and release to free it.
|
||||
*
|
||||
* The elements of the array with index less than nargs correspond to the
|
||||
* the names of arguments. An index >= nargs addresses a var binding. Use
|
||||
* JS_LOCAL_NAME_TO_ATOM to convert array's element to an atom pointer.
|
||||
* This pointer can be null when the element is for an argument
|
||||
* The elements of the vector with index less than nargs correspond to the
|
||||
* the names of arguments. An index >= nargs addresses a var binding.
|
||||
* The name at an element will be null when the element is for an argument
|
||||
* corresponding to a destructuring pattern.
|
||||
*
|
||||
* If nameWord does not name an argument, use JS_LOCAL_NAME_IS_CONST to
|
||||
* check if nameWord corresponds to the const declaration.
|
||||
*/
|
||||
jsuword *
|
||||
getLocalNameArray(JSContext *cx, JSArenaPool *pool);
|
||||
bool getLocalNameArray(JSContext *cx, Vector<JSAtom *> *namesp);
|
||||
|
||||
/*
|
||||
* Returns the slot where the sharp array is stored, or a value < 0 if no
|
||||
|
@ -353,9 +344,7 @@ class Bindings {
|
|||
* oldest (i.e., last or right-most to first or left-most in source order).
|
||||
*
|
||||
* Sometimes iteration order must be from oldest to youngest, however. For
|
||||
* such cases, use js::Bindings::getLocalNameArray. The RAII class
|
||||
* js::AutoLocalNameArray, defined in jscntxt.h, should be used where
|
||||
* possible instead of direct calls to getLocalNameArray.
|
||||
* such cases, use js::Bindings::getLocalNameArray.
|
||||
*/
|
||||
const js::Shape *lastArgument() const;
|
||||
const js::Shape *lastVariable() const;
|
||||
|
|
124
js/src/jsstr.cpp
124
js/src/jsstr.cpp
|
@ -148,68 +148,17 @@ static uint32
|
|||
Utf8ToOneUcs4Char(const uint8 *utf8Buffer, int utf8Length);
|
||||
|
||||
/*
|
||||
* Contributions from the String class to the set of methods defined for the
|
||||
* global object. escape and unescape used to be defined in the Mocha library,
|
||||
* but as ECMA decided to spec them, they've been moved to the core engine
|
||||
* and made ECMA-compliant. (Incomplete escapes are interpreted as literal
|
||||
* characters by unescape.)
|
||||
* Global string methods
|
||||
*/
|
||||
|
||||
/*
|
||||
* Stuff to emulate the old libmocha escape, which took a second argument
|
||||
* giving the type of escape to perform. Retained for compatibility, and
|
||||
* copied here to avoid reliance on net.h, mkparse.c/NET_EscapeBytes.
|
||||
*/
|
||||
|
||||
#define URL_XALPHAS ((uint8) 1)
|
||||
#define URL_XPALPHAS ((uint8) 2)
|
||||
#define URL_PATH ((uint8) 4)
|
||||
|
||||
static const uint8 urlCharType[256] =
|
||||
/* Bit 0 xalpha -- the alphas
|
||||
* Bit 1 xpalpha -- as xalpha but
|
||||
* converts spaces to plus and plus to %20
|
||||
* Bit 2 ... path -- as xalphas but doesn't escape '/'
|
||||
*/
|
||||
/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
|
||||
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x */
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 1x */
|
||||
0,0,0,0,0,0,0,0,0,0,7,4,0,7,7,4, /* 2x !"#$%&'()*+,-./ */
|
||||
7,7,7,7,7,7,7,7,7,7,0,0,0,0,0,0, /* 3x 0123456789:;<=>? */
|
||||
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, /* 4x @ABCDEFGHIJKLMNO */
|
||||
7,7,7,7,7,7,7,7,7,7,7,0,0,0,0,7, /* 5X PQRSTUVWXYZ[\]^_ */
|
||||
0,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, /* 6x `abcdefghijklmno */
|
||||
7,7,7,7,7,7,7,7,7,7,7,0,0,0,0,0, /* 7X pqrstuvwxyz{\}~ DEL */
|
||||
0, };
|
||||
|
||||
/* This matches the ECMA escape set when mask is 7 (default.) */
|
||||
|
||||
#define IS_OK(C, mask) (urlCharType[((uint8) (C))] & (mask))
|
||||
|
||||
/* See ECMA-262 Edition 3 B.2.1 */
|
||||
JSBool
|
||||
js_str_escape(JSContext *cx, uintN argc, Value *vp, Value *rval)
|
||||
/* ES5 B.2.1 */
|
||||
static JSBool
|
||||
str_escape(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
const char digits[] = {'0', '1', '2', '3', '4', '5', '6', '7',
|
||||
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
|
||||
|
||||
jsint mask = URL_XALPHAS | URL_XPALPHAS | URL_PATH;
|
||||
if (argc > 1) {
|
||||
double d;
|
||||
if (!ValueToNumber(cx, vp[3], &d))
|
||||
return JS_FALSE;
|
||||
if (!JSDOUBLE_IS_FINITE(d) ||
|
||||
(mask = (jsint)d) != d ||
|
||||
mask & ~(URL_XALPHAS | URL_XPALPHAS | URL_PATH))
|
||||
{
|
||||
char numBuf[12];
|
||||
JS_snprintf(numBuf, sizeof numBuf, "%lx", (unsigned long) mask);
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
||||
JSMSG_BAD_STRING_MASK, numBuf);
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
JSLinearString *str = ArgToRootedString(cx, argc, vp, 0);
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
|
@ -217,19 +166,38 @@ js_str_escape(JSContext *cx, uintN argc, Value *vp, Value *rval)
|
|||
size_t length = str->length();
|
||||
const jschar *chars = str->chars();
|
||||
|
||||
static const uint8 shouldPassThrough[256] = {
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,1,1,0,1,1,1, /* !"#$%&'()*+,-./ */
|
||||
1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0, /* 0123456789:;<=>? */
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* @ABCDEFGHIJKLMNO */
|
||||
1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1, /* PQRSTUVWXYZ[\]^_ */
|
||||
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* `abcdefghijklmno */
|
||||
1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0, /* pqrstuvwxyz{\}~ DEL */
|
||||
};
|
||||
|
||||
/* In step 7, exactly 69 characters should pass through unencoded. */
|
||||
#ifdef DEBUG
|
||||
int count = 0;
|
||||
for (uint i = 0; i < sizeof(shouldPassThrough); i++) {
|
||||
if (shouldPassThrough[i]) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
JS_ASSERT(count == 69);
|
||||
#endif
|
||||
|
||||
|
||||
/* Take a first pass and see how big the result string will need to be. */
|
||||
size_t newlength = length;
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
jschar ch;
|
||||
if ((ch = chars[i]) < 128 && IS_OK(ch, mask))
|
||||
jschar ch = chars[i];
|
||||
if (ch < 128 && shouldPassThrough[ch])
|
||||
continue;
|
||||
if (ch < 256) {
|
||||
if (mask == URL_XPALPHAS && ch == ' ')
|
||||
continue; /* The character will be encoded as '+' */
|
||||
newlength += 2; /* The character will be encoded as %XX */
|
||||
} else {
|
||||
newlength += 5; /* The character will be encoded as %uXXXX */
|
||||
}
|
||||
|
||||
/* The character will be encoded as %XX or %uXXXX. */
|
||||
newlength += (ch < 256) ? 2 : 5;
|
||||
|
||||
/*
|
||||
* This overflow test works because newlength is incremented by at
|
||||
|
@ -251,17 +219,13 @@ js_str_escape(JSContext *cx, uintN argc, Value *vp, Value *rval)
|
|||
return JS_FALSE;
|
||||
size_t i, ni;
|
||||
for (i = 0, ni = 0; i < length; i++) {
|
||||
jschar ch;
|
||||
if ((ch = chars[i]) < 128 && IS_OK(ch, mask)) {
|
||||
jschar ch = chars[i];
|
||||
if (ch < 128 && shouldPassThrough[ch]) {
|
||||
newchars[ni++] = ch;
|
||||
} else if (ch < 256) {
|
||||
if (mask == URL_XPALPHAS && ch == ' ') {
|
||||
newchars[ni++] = '+'; /* convert spaces to pluses */
|
||||
} else {
|
||||
newchars[ni++] = '%';
|
||||
newchars[ni++] = digits[ch >> 4];
|
||||
newchars[ni++] = digits[ch & 0xF];
|
||||
}
|
||||
newchars[ni++] = '%';
|
||||
newchars[ni++] = digits[ch >> 4];
|
||||
newchars[ni++] = digits[ch & 0xF];
|
||||
} else {
|
||||
newchars[ni++] = '%';
|
||||
newchars[ni++] = 'u';
|
||||
|
@ -279,18 +243,11 @@ js_str_escape(JSContext *cx, uintN argc, Value *vp, Value *rval)
|
|||
cx->free_(newchars);
|
||||
return JS_FALSE;
|
||||
}
|
||||
rval->setString(retstr);
|
||||
vp->setString(retstr);
|
||||
return JS_TRUE;
|
||||
}
|
||||
#undef IS_OK
|
||||
|
||||
static JSBool
|
||||
str_escape(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
return js_str_escape(cx, argc, vp, vp);
|
||||
}
|
||||
|
||||
/* See ECMA-262 Edition 3 B.2.2 */
|
||||
/* ES5 B.2.2 */
|
||||
static JSBool
|
||||
str_unescape(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
|
@ -309,6 +266,7 @@ str_unescape(JSContext *cx, uintN argc, Value *vp)
|
|||
while (i < length) {
|
||||
jschar ch = chars[i++];
|
||||
if (ch == '%') {
|
||||
/* Incomplete escapes are interpreted as literal characters. */
|
||||
if (i + 1 < length &&
|
||||
JS7_ISHEX(chars[i]) && JS7_ISHEX(chars[i + 1]))
|
||||
{
|
||||
|
@ -1460,7 +1418,7 @@ class RegExpGuard
|
|||
}
|
||||
JS_ASSERT(patstr);
|
||||
|
||||
AlreadyIncRefed<RegExp> re = RegExp::createFlagged(cx, patstr, opt);
|
||||
AlreadyIncRefed<RegExp> re = RegExp::createFlagged(cx, patstr, opt, NULL);
|
||||
if (!re)
|
||||
return NULL;
|
||||
rep.reset(re);
|
||||
|
|
|
@ -486,10 +486,6 @@ DeflateStringToUTF8Buffer(JSContext *cx, const jschar *chars,
|
|||
|
||||
} /* namespace js */
|
||||
|
||||
/* Export a few natives and a helper to other files in SpiderMonkey. */
|
||||
extern JSBool
|
||||
js_str_escape(JSContext *cx, uintN argc, js::Value *argv, js::Value *rval);
|
||||
|
||||
/*
|
||||
* The String.prototype.replace fast-native entry point is exported for joined
|
||||
* function optimization in js{interp,tracer}.cpp.
|
||||
|
|
|
@ -3652,23 +3652,22 @@ TraceRecorder::importImpl(Address addr, const void* p, JSValueType t,
|
|||
#ifdef DEBUG
|
||||
char name[64];
|
||||
JS_ASSERT(strlen(prefix) < 11);
|
||||
void* mark = NULL;
|
||||
jsuword* localNames = NULL;
|
||||
Vector<JSAtom *> localNames(cx);
|
||||
const char* funName = NULL;
|
||||
JSAutoByteString funNameBytes;
|
||||
if (*prefix == 'a' || *prefix == 'v') {
|
||||
mark = JS_ARENA_MARK(&cx->tempPool);
|
||||
JSFunction *fun = fp->fun();
|
||||
Bindings &bindings = fun->script()->bindings;
|
||||
if (bindings.hasLocalNames())
|
||||
localNames = bindings.getLocalNameArray(cx, &cx->tempPool);
|
||||
if (bindings.hasLocalNames()) {
|
||||
JS_ASSERT(bindings.getLocalNameArray(cx, &localNames));
|
||||
}
|
||||
funName = fun->atom
|
||||
? js_AtomToPrintableString(cx, fun->atom, &funNameBytes)
|
||||
: "<anonymous>";
|
||||
}
|
||||
if (!strcmp(prefix, "argv")) {
|
||||
if (index < fp->numFormalArgs()) {
|
||||
JSAtom *atom = JS_LOCAL_NAME_TO_ATOM(localNames[index]);
|
||||
JSAtom *atom = localNames[index];
|
||||
JSAutoByteString atomBytes;
|
||||
JS_snprintf(name, sizeof name, "$%s.%s", funName,
|
||||
js_AtomToPrintableString(cx, atom, &atomBytes));
|
||||
|
@ -3676,7 +3675,7 @@ TraceRecorder::importImpl(Address addr, const void* p, JSValueType t,
|
|||
JS_snprintf(name, sizeof name, "$%s.<arg%d>", funName, index);
|
||||
}
|
||||
} else if (!strcmp(prefix, "vars")) {
|
||||
JSAtom *atom = JS_LOCAL_NAME_TO_ATOM(localNames[fp->numFormalArgs() + index]);
|
||||
JSAtom *atom = localNames[fp->numFormalArgs() + index];
|
||||
JSAutoByteString atomBytes;
|
||||
JS_snprintf(name, sizeof name, "$%s.%s", funName,
|
||||
js_AtomToPrintableString(cx, atom, &atomBytes));
|
||||
|
@ -3684,8 +3683,6 @@ TraceRecorder::importImpl(Address addr, const void* p, JSValueType t,
|
|||
JS_snprintf(name, sizeof name, "$%s%d", prefix, index);
|
||||
}
|
||||
|
||||
if (mark)
|
||||
JS_ARENA_RELEASE(&cx->tempPool, mark);
|
||||
w.name(ins, name);
|
||||
|
||||
debug_only_printf(LC_TMTracer, "import vp=%p name=%s type=%c\n",
|
||||
|
@ -13750,6 +13747,10 @@ TraceRecorder::interpretedFunctionCall(Value& fval, JSFunction* fun, uintN argc,
|
|||
if (fval.toObject().getGlobal() != globalObj)
|
||||
RETURN_STOP("JSOP_CALL or JSOP_NEW crosses global scopes");
|
||||
|
||||
JS_ASSERT(fun->isInterpreted());
|
||||
if (!fun->isInterpretedConstructor())
|
||||
RETURN_STOP("Non-interpreted constructors get called via Invoke");
|
||||
|
||||
StackFrame* const fp = cx->fp();
|
||||
|
||||
if (constructing) {
|
||||
|
@ -16268,7 +16269,7 @@ TraceRecorder::record_JSOP_ARRAYPUSH()
|
|||
enterDeepBailCall();
|
||||
|
||||
LIns *args[] = { elt_ins, array_ins, cx_ins };
|
||||
pendingGuardCondition = w.call(&js_ArrayCompPush_tn_ci, args);
|
||||
pendingGuardCondition = w.call(&js_NewbornArrayPush_tn_ci, args);
|
||||
|
||||
leaveDeepBailCall();
|
||||
return ARECORD_CONTINUE;
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
#include "jsbit.h"
|
||||
#include "jsvector.h"
|
||||
#include "jstypedarray.h"
|
||||
#include "jsutil.h"
|
||||
|
||||
#include "jsobjinlines.h"
|
||||
#include "jstypedarrayinlines.h"
|
||||
|
@ -105,10 +106,16 @@ ValueIsLength(JSContext *cx, const Value &v, jsuint *len)
|
|||
* access. It can be created explicitly and passed to a TypedArray, or
|
||||
* can be created implicitly by constructing a TypedArray with a size.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Walks up the prototype chain to find the actual ArrayBuffer data.
|
||||
* This MAY return NULL. Callers should always use js_IsArrayBuffer()
|
||||
* first.
|
||||
*/
|
||||
JSObject *
|
||||
ArrayBuffer::getArrayBuffer(JSObject *obj)
|
||||
{
|
||||
while (!js_IsArrayBuffer(obj))
|
||||
while (obj && !js_IsArrayBuffer(obj))
|
||||
obj = obj->getProto();
|
||||
return obj;
|
||||
}
|
||||
|
@ -117,6 +124,10 @@ JSBool
|
|||
ArrayBuffer::prop_getByteLength(JSContext *cx, JSObject *obj, jsid id, Value *vp)
|
||||
{
|
||||
JSObject *arrayBuffer = getArrayBuffer(obj);
|
||||
if (!arrayBuffer) {
|
||||
vp->setInt32(0);
|
||||
return true;
|
||||
}
|
||||
vp->setInt32(jsint(ArrayBuffer::getByteLength(arrayBuffer)));
|
||||
return true;
|
||||
}
|
||||
|
@ -157,7 +168,7 @@ static JSObject *
|
|||
DelegateObject(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
if (!obj->getPrivate()) {
|
||||
JSObject *delegate = NewNonFunction<WithProto::Class>(cx, &js_ObjectClass, NULL, NULL);
|
||||
JSObject *delegate = NewNonFunction<WithProto::Given>(cx, &js_ObjectClass, obj->getProto(), NULL);
|
||||
obj->setPrivate(delegate);
|
||||
return delegate;
|
||||
}
|
||||
|
@ -230,8 +241,11 @@ ArrayBuffer::obj_lookupProperty(JSContext *cx, JSObject *obj, jsid id,
|
|||
if (!delegateResult)
|
||||
return false;
|
||||
|
||||
if (*propp != NULL)
|
||||
if (*propp != NULL) {
|
||||
if (*objp == delegate)
|
||||
*objp = obj;
|
||||
return true;
|
||||
}
|
||||
|
||||
JSObject *proto = obj->getProto();
|
||||
if (!proto) {
|
||||
|
@ -277,6 +291,29 @@ ArrayBuffer::obj_setProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, J
|
|||
if (JSID_IS_ATOM(id, cx->runtime->atomState.byteLengthAtom))
|
||||
return true;
|
||||
|
||||
if (JSID_IS_ATOM(id, cx->runtime->atomState.protoAtom)) {
|
||||
if (!vp->isObjectOrNull())
|
||||
return JS_TRUE;
|
||||
|
||||
JSObject *pobj = vp->toObjectOrNull();
|
||||
|
||||
JSObject *delegate = DelegateObject(cx, obj);
|
||||
if (!delegate)
|
||||
return false;
|
||||
|
||||
// save the old prototype
|
||||
JSObject *oldDelegateProto = delegate->getProto();
|
||||
if (!SetProto(cx, delegate, pobj, true))
|
||||
return false;
|
||||
|
||||
if (!SetProto(cx, obj, pobj, true)) {
|
||||
// restore proto on delegate
|
||||
JS_ALWAYS_TRUE(SetProto(cx, delegate, oldDelegateProto, true));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
JSObject *delegate = DelegateObject(cx, obj);
|
||||
if (!delegate)
|
||||
return false;
|
||||
|
|
|
@ -85,15 +85,46 @@ namespace js {
|
|||
//
|
||||
// bool keyMarked(Key &k)
|
||||
// bool valueMarked(Value &v)
|
||||
// Return true if k/v has been marked as reachable by the collector, false otherwise.
|
||||
// void markKey(Key &k, const char *description)
|
||||
// void markValue(Value &v, const char *description)
|
||||
// Mark k/v as reachable by the collector, using trc. Use description to identify
|
||||
// k/v in debugging. (markKey is used only for non-marking tracers, other code
|
||||
// using the GC heap tracing functions to map the heap for some purpose or other.)
|
||||
// Return true if k/v has been marked as live by the garbage collector.
|
||||
//
|
||||
// If omitted, this parameter defaults to js::DefaultMarkPolicy<Key, Value>, a policy
|
||||
// template with the obvious definitions for some typical SpiderMonkey type combinations.
|
||||
// bool markEntryIfLive(Key &k, Value &v)
|
||||
// If a table entry whose key is k should be retained, ensure its key and
|
||||
// value are marked. Return true if any previously unmarked objects
|
||||
// became marked.
|
||||
//
|
||||
// To ensure that the WeakMap's behavior isn't visibly affected by
|
||||
// garbage collection, this should leave k unmarked only when no key
|
||||
// matching k could ever be produced after this GC cycle completes ---
|
||||
// removing entries whose keys this function leaves unmarked should never
|
||||
// make future lookups fail.
|
||||
//
|
||||
// A typical definition of markIteratively would be:
|
||||
//
|
||||
// if (keyMarked(k) && !valueMarked(v)) {
|
||||
// markObject(*v, "WeakMap entry value");
|
||||
// return true;
|
||||
// }
|
||||
// return false;
|
||||
//
|
||||
// This meets the above constraint when, for example, Key is JSObject *:
|
||||
// if k isn't marked, it won't exist once the collection cycle completes,
|
||||
// and thus can't be supplied as a key.
|
||||
//
|
||||
// Note that this may mark entries where keyMarked(k) is not initially
|
||||
// true. For example, you could have a table whose keys match when the
|
||||
// values of one of their properties are equal: k1.x === k2.x. An entry
|
||||
// in such a table could be live even when its key is not marked. The
|
||||
// markEntryIfLive function for such a table would generally mark both k and v.
|
||||
//
|
||||
// void markEntry(Key &k, Value &v)
|
||||
// Mark the table entry's key and value, k and v, as reachable by the
|
||||
// collector. WeakMap uses this function for non-marking tracers: other
|
||||
// code using the GC heap tracing functions to map the heap for some
|
||||
// purpose or other.
|
||||
//
|
||||
// If omitted, the MarkPolicy parameter defaults to js::DefaultMarkPolicy<Key,
|
||||
// Value>, a policy template with the obvious definitions for some typical
|
||||
// SpiderMonkey type combinations.
|
||||
|
||||
// A policy template holding default marking algorithms for common type combinations. This
|
||||
// provides default types for WeakMap's MarkPolicy template parameter.
|
||||
|
@ -163,34 +194,38 @@ class WeakMap : public HashMap<Key, Value, HashPolicy, RuntimeAllocPolicy>, publ
|
|||
private:
|
||||
void nonMarkingTrace(JSTracer *tracer) {
|
||||
MarkPolicy t(tracer);
|
||||
for (Range r = Base::all(); !r.empty(); r.popFront()) {
|
||||
t.markKey(r.front().key, "WeakMap entry key");
|
||||
t.markValue(r.front().value, "WeakMap entry value");
|
||||
}
|
||||
for (Range r = Base::all(); !r.empty(); r.popFront())
|
||||
t.markEntry(r.front().key, r.front().value);
|
||||
}
|
||||
|
||||
bool markIteratively(JSTracer *tracer) {
|
||||
MarkPolicy t(tracer);
|
||||
bool markedAny = false;
|
||||
for (Range r = Base::all(); !r.empty(); r.popFront()) {
|
||||
/* If the key is alive, mark the value if needed. */
|
||||
if (!t.valueMarked(r.front().value) && t.keyMarked(r.front().key)) {
|
||||
t.markValue(r.front().value, "WeakMap entry with live key");
|
||||
/* If the entry is live, ensure its key and value are marked. */
|
||||
if (t.markEntryIfLive(r.front().key, r.front().value)) {
|
||||
/* We revived a value with children, we have to iterate again. */
|
||||
markedAny = true;
|
||||
}
|
||||
JS_ASSERT_IF(t.keyMarked(r.front().key), t.valueMarked(r.front().value));
|
||||
}
|
||||
return markedAny;
|
||||
}
|
||||
|
||||
void sweep(JSTracer *tracer) {
|
||||
MarkPolicy t(tracer);
|
||||
|
||||
/* Remove all entries whose keys remain unmarked. */
|
||||
for (Enum e(*this); !e.empty(); e.popFront()) {
|
||||
if (!t.keyMarked(e.front().key))
|
||||
e.removeFront();
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
// Once we've swept, all edges should stay within the known-live part of the graph.
|
||||
/*
|
||||
* Once we've swept, all remaining edges should stay within the
|
||||
* known-live part of the graph.
|
||||
*/
|
||||
for (Range r = Base::all(); !r.empty(); r.popFront()) {
|
||||
JS_ASSERT(t.keyMarked(r.front().key));
|
||||
JS_ASSERT(t.valueMarked(r.front().value));
|
||||
|
@ -212,11 +247,16 @@ class DefaultMarkPolicy<JSObject *, Value> {
|
|||
return !IsAboutToBeFinalized(tracer->context, v.toGCThing());
|
||||
return true;
|
||||
}
|
||||
void markKey(JSObject *k, const char *description) {
|
||||
js::gc::MarkObject(tracer, *k, description);
|
||||
bool markEntryIfLive(JSObject *k, const Value &v) {
|
||||
if (keyMarked(k) && !valueMarked(v)) {
|
||||
js::gc::MarkValue(tracer, v, "WeakMap entry value");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void markValue(const Value &v, const char *description) {
|
||||
js::gc::MarkValue(tracer, v, description);
|
||||
void markEntry(JSObject *k, const Value &v) {
|
||||
js::gc::MarkObject(tracer, *k, "WeakMap entry key");
|
||||
js::gc::MarkValue(tracer, v, "WeakMap entry value");
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
; ***** BEGIN LICENSE BLOCK *****
|
||||
; Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
;
|
||||
; The contents of this file are subject to the Mozilla Public License Version
|
||||
; 1.1 (the "License"); you may not use this file except in compliance with
|
||||
; the License. You may obtain a copy of the License at
|
||||
; http://www.mozilla.org/MPL/
|
||||
;
|
||||
; Software distributed under the License is distributed on an "AS IS" basis,
|
||||
; WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
; for the specific language governing rights and limitations under the
|
||||
; License.
|
||||
;
|
||||
; The Original Code is mozilla.org code.
|
||||
;
|
||||
; The Initial Developer of the Original Code is The Mozilla Foundation.
|
||||
; Portions created by the Initial Developer are Copyright (C) 2011
|
||||
; the Initial Developer. All Rights Reserved.
|
||||
;
|
||||
; Contributor(s):
|
||||
; Makoto Kato <m_kato@ga2.so-net.ne.jp> (Original Author)
|
||||
;
|
||||
; Alternatively, the contents of this file may be used under the terms of
|
||||
; either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
; the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
; in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
; of those above. If you wish to allow use of your version of this file only
|
||||
; under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
; use your version of this file under the terms of the MPL, indicate your
|
||||
; decision by deleting the provisions above and replace them with the notice
|
||||
; and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
; the provisions above, a recipient may use your version of this file under
|
||||
; the terms of any one of the MPL, the GPL or the LGPL.
|
||||
;
|
||||
; ***** END LICENSE BLOCK *****
|
||||
|
||||
|
||||
.CODE
|
||||
|
||||
extern fmod:PROC
|
||||
|
||||
; This is a workaround for KB982107 (http://support.microsoft.com/kb/982107)
|
||||
js_myfmod PROC FRAME
|
||||
.ENDPROLOG
|
||||
fnclex
|
||||
jmp fmod
|
||||
js_myfmod ENDP
|
||||
|
||||
END
|
|
@ -122,6 +122,14 @@ JSWrapper::getPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id,
|
|||
static bool
|
||||
GetOwnPropertyDescriptor(JSContext *cx, JSObject *obj, jsid id, uintN flags, JSPropertyDescriptor *desc)
|
||||
{
|
||||
// If obj is a proxy, we can do better than just guessing. This is
|
||||
// important for certain types of wrappers that wrap other wrappers.
|
||||
if (obj->isProxy()) {
|
||||
return JSProxy::getOwnPropertyDescriptor(cx, obj, id,
|
||||
flags & JSRESOLVE_ASSIGNING,
|
||||
Valueify(desc));
|
||||
}
|
||||
|
||||
if (!JS_GetPropertyDescriptorById(cx, obj, id, flags, desc))
|
||||
return false;
|
||||
if (desc->obj != obj)
|
||||
|
@ -133,7 +141,7 @@ bool
|
|||
JSWrapper::getOwnPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id, bool set,
|
||||
PropertyDescriptor *desc)
|
||||
{
|
||||
desc->obj= NULL; // default result if we refuse to perform this action
|
||||
desc->obj = NULL; // default result if we refuse to perform this action
|
||||
CHECKED(GetOwnPropertyDescriptor(cx, wrappedObject(wrapper), id, JSRESOLVE_QUALIFIED,
|
||||
Jsvalify(desc)), set ? SET : GET);
|
||||
}
|
||||
|
|
|
@ -222,7 +222,7 @@ JS_XDRFindClassById(JSXDRState *xdr, uint32 id);
|
|||
* before deserialization of bytecode. If the saved version does not match
|
||||
* the current version, abort deserialization and invalidate the file.
|
||||
*/
|
||||
#define JSXDR_BYTECODE_VERSION (0xb973c0de - 88)
|
||||
#define JSXDR_BYTECODE_VERSION (0xb973c0de - 89)
|
||||
|
||||
/*
|
||||
* Library-private functions.
|
||||
|
|
|
@ -379,8 +379,10 @@ mjit::Compiler::generatePrologue()
|
|||
if (isConstructing)
|
||||
constructThis();
|
||||
|
||||
if (debugMode() || Probes::callTrackingActive(cx))
|
||||
if (debugMode())
|
||||
INLINE_STUBCALL(stubs::ScriptDebugPrologue);
|
||||
else if (Probes::callTrackingActive(cx))
|
||||
INLINE_STUBCALL(stubs::ScriptProbeOnlyPrologue);
|
||||
|
||||
return Compile_Okay;
|
||||
}
|
||||
|
|
|
@ -546,16 +546,30 @@ stubs::CreateThis(VMFrame &f, JSObject *proto)
|
|||
void JS_FASTCALL
|
||||
stubs::ScriptDebugPrologue(VMFrame &f)
|
||||
{
|
||||
Probes::enterJSFun(f.cx, f.fp()->maybeFun(), f.fp()->script());
|
||||
js::ScriptDebugPrologue(f.cx, f.fp());
|
||||
}
|
||||
|
||||
void JS_FASTCALL
|
||||
stubs::ScriptDebugEpilogue(VMFrame &f)
|
||||
{
|
||||
Probes::exitJSFun(f.cx, f.fp()->maybeFun(), f.fp()->script());
|
||||
if (!js::ScriptDebugEpilogue(f.cx, f.fp(), JS_TRUE))
|
||||
THROW();
|
||||
}
|
||||
|
||||
void JS_FASTCALL
|
||||
stubs::ScriptProbeOnlyPrologue(VMFrame &f)
|
||||
{
|
||||
Probes::enterJSFun(f.cx, f.fp()->fun(), f.fp()->script());
|
||||
}
|
||||
|
||||
void JS_FASTCALL
|
||||
stubs::ScriptProbeOnlyEpilogue(VMFrame &f)
|
||||
{
|
||||
Probes::exitJSFun(f.cx, f.fp()->fun(), f.fp()->script());
|
||||
}
|
||||
|
||||
#ifdef JS_TRACER
|
||||
|
||||
/*
|
||||
|
|
|
@ -73,6 +73,8 @@ void * JS_FASTCALL UncachedCall(VMFrame &f, uint32 argc);
|
|||
void JS_FASTCALL Eval(VMFrame &f, uint32 argc);
|
||||
void JS_FASTCALL ScriptDebugPrologue(VMFrame &f);
|
||||
void JS_FASTCALL ScriptDebugEpilogue(VMFrame &f);
|
||||
void JS_FASTCALL ScriptProbeOnlyPrologue(VMFrame &f);
|
||||
void JS_FASTCALL ScriptProbeOnlyEpilogue(VMFrame &f);
|
||||
|
||||
/*
|
||||
* Result struct for UncachedXHelper.
|
||||
|
|
|
@ -1 +1 @@
|
|||
8eec2117b714ec754c483b681acb3737f63b994c
|
||||
4cc8b8ebd44b989e08935ed8ffae7e9cb4eb4ae9
|
||||
|
|
|
@ -283,7 +283,6 @@ namespace nanojit
|
|||
InsSet incoming(_alloc); // running list of incoming edges into the block
|
||||
bool last = true; // true, when we're processing the last instruction of a block
|
||||
LIns* priorBlock = 0; // prior block that was just processed.
|
||||
LIns* priorIns = 0; // last instruction encountered
|
||||
|
||||
LirReader rdr(finalIns());
|
||||
LIns* ins = rdr.read();
|
||||
|
@ -323,8 +322,6 @@ namespace nanojit
|
|||
n.insert(ins);
|
||||
if ( _alt.containsKey(ins) )
|
||||
incoming.put(ins,true);
|
||||
|
||||
priorIns = ins;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2319,16 +2319,15 @@ DisassembleValue(JSContext *cx, jsval v, bool lines, bool recursive, Sprinter *s
|
|||
if (script->bindings.hasUpvars()) {
|
||||
Sprint(sp, "\nupvars: {\n");
|
||||
|
||||
void *mark = JS_ARENA_MARK(&cx->tempPool);
|
||||
jsuword *localNames = script->bindings.getLocalNameArray(cx, &cx->tempPool);
|
||||
if (!localNames)
|
||||
Vector<JSAtom *> localNames(cx);
|
||||
if (!script->bindings.getLocalNameArray(cx, &localNames))
|
||||
return false;
|
||||
|
||||
JSUpvarArray *uva = script->upvars();
|
||||
uintN upvar_base = script->bindings.countArgsAndVars();
|
||||
|
||||
for (uint32 i = 0, n = uva->length; i < n; i++) {
|
||||
JSAtom *atom = JS_LOCAL_NAME_TO_ATOM(localNames[upvar_base + i]);
|
||||
JSAtom *atom = localNames[upvar_base + i];
|
||||
UpvarCookie cookie = uva->vector[i];
|
||||
JSAutoByteString printable;
|
||||
if (js_AtomToPrintableString(cx, atom, &printable)) {
|
||||
|
@ -2337,7 +2336,6 @@ DisassembleValue(JSContext *cx, jsval v, bool lines, bool recursive, Sprinter *s
|
|||
}
|
||||
}
|
||||
|
||||
JS_ARENA_RELEASE(&cx->tempPool, mark);
|
||||
Sprint(sp, "}");
|
||||
}
|
||||
}
|
||||
|
@ -3295,24 +3293,6 @@ split_enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
|
|||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
ResolveClass(JSContext *cx, JSObject *obj, jsid id, JSBool *resolved)
|
||||
{
|
||||
if (!JS_ResolveStandardClass(cx, obj, id, resolved))
|
||||
return JS_FALSE;
|
||||
|
||||
if (!*resolved) {
|
||||
if (JSID_IS_ATOM(id, CLASS_ATOM(cx, Reflect))) {
|
||||
if (!IsStandardClassResolved(obj, &js_ReflectClass) &&
|
||||
!js_InitReflectClass(cx, obj))
|
||||
return JS_FALSE;
|
||||
*resolved = JS_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
split_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags, JSObject **objp)
|
||||
{
|
||||
|
@ -3335,7 +3315,7 @@ split_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags, JSObject **obj
|
|||
if (!(flags & JSRESOLVE_ASSIGNING)) {
|
||||
JSBool resolved;
|
||||
|
||||
if (!ResolveClass(cx, obj, id, &resolved))
|
||||
if (!JS_ResolveStandardClass(cx, obj, id, &resolved))
|
||||
return JS_FALSE;
|
||||
|
||||
if (resolved) {
|
||||
|
@ -3567,7 +3547,7 @@ sandbox_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags,
|
|||
|
||||
JS_ValueToBoolean(cx, v, &b);
|
||||
if (b && (flags & JSRESOLVE_ASSIGNING) == 0) {
|
||||
if (!ResolveClass(cx, obj, id, &resolved))
|
||||
if (!JS_ResolveStandardClass(cx, obj, id, &resolved))
|
||||
return JS_FALSE;
|
||||
if (resolved) {
|
||||
*objp = obj;
|
||||
|
@ -3654,13 +3634,15 @@ EvalInContext(JSContext *cx, uintN argc, jsval *vp)
|
|||
return false;
|
||||
}
|
||||
|
||||
*vp = OBJECT_TO_JSVAL(sobj);
|
||||
if (srclen == 0)
|
||||
if (srclen == 0) {
|
||||
JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(sobj));
|
||||
return true;
|
||||
}
|
||||
|
||||
JSStackFrame *fp = JS_GetScriptedCaller(cx, NULL);
|
||||
JSScript *script = JS_GetFrameScript(cx, fp);
|
||||
jsbytecode *pc = JS_GetFramePC(cx, fp);
|
||||
jsval rval;
|
||||
{
|
||||
JSAutoEnterCompartment ac;
|
||||
uintN flags;
|
||||
|
@ -3681,11 +3663,16 @@ EvalInContext(JSContext *cx, uintN argc, jsval *vp)
|
|||
if (!JS_EvaluateUCScript(cx, sobj, src, srclen,
|
||||
script->filename,
|
||||
JS_PCToLineNumber(cx, script, pc),
|
||||
vp)) {
|
||||
&rval)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return cx->compartment->wrap(cx, Valueify(vp));
|
||||
|
||||
if (!cx->compartment->wrap(cx, Valueify(&rval)))
|
||||
return false;
|
||||
|
||||
JS_SET_RVAL(cx, vp, rval);
|
||||
return true;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
|
@ -5669,7 +5656,7 @@ global_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags,
|
|||
#ifdef LAZY_STANDARD_CLASSES
|
||||
JSBool resolved;
|
||||
|
||||
if (!ResolveClass(cx, obj, id, &resolved))
|
||||
if (!JS_ResolveStandardClass(cx, obj, id, &resolved))
|
||||
return JS_FALSE;
|
||||
if (resolved) {
|
||||
*objp = obj;
|
||||
|
@ -5931,6 +5918,8 @@ NewGlobalObject(JSContext *cx, CompartmentKind compartment)
|
|||
if (!JS_InitCTypesClass(cx, glob))
|
||||
return NULL;
|
||||
#endif
|
||||
if (!JS_InitReflect(cx, glob))
|
||||
return NULL;
|
||||
if (!JS::RegisterPerfMeasurement(cx, glob))
|
||||
return NULL;
|
||||
if (!JS_DefineFunctions(cx, glob, shell_functions) ||
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче