Merge inbound to m-c.

This commit is contained in:
Ryan VanderMeulen 2014-01-22 15:15:22 -05:00
commit ad273b968e
70 changed files with 1268 additions and 771 deletions

View File

@ -22,5 +22,4 @@
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
# don't change CLOBBER for WebIDL changes any more.
CLOBBER due to recent changes to JS build files that were causing
"STOP! configure has changed and needs to be run in this build directory." bustage
JS build system changes are apparently requiring clobbers.

View File

@ -678,6 +678,32 @@ this.BrailleGenerator = {
let output = OutputGenerator.genForContext.apply(this, arguments);
let acc = aContext.accessible;
// add the static text indicating a list item; do this for both listitems or
// direct first children of listitems, because these are both common browsing
// scenarios
let addListitemIndicator = function addListitemIndicator(indicator = '*') {
output.output.unshift(indicator);
};
if (acc.indexInParent === 1 &&
acc.parent.role == Roles.LISTITEM &&
acc.previousSibling.role == Roles.STATICTEXT) {
if (acc.parent.parent && acc.parent.parent.DOMNode &&
acc.parent.parent.DOMNode.nodeName == 'UL') {
addListitemIndicator();
} else {
addListitemIndicator(acc.previousSibling.name.trim());
}
} else if (acc.role == Roles.LISTITEM && acc.firstChild &&
acc.firstChild.role == Roles.STATICTEXT) {
if (acc.parent.DOMNode.nodeName == 'UL') {
addListitemIndicator();
} else {
addListitemIndicator(acc.firstChild.name.trim());
}
}
if (acc instanceof Ci.nsIAccessibleText) {
output.endOffset = this.outputOrder === OUTPUT_DESC_FIRST ?
output.output.join(' ').length : acc.characterCount;
@ -692,20 +718,7 @@ this.BrailleGenerator = {
__proto__: OutputGenerator.objectOutputFunctions,
defaultFunc: function defaultFunc(aAccessible, aRoleStr, aStates, aFlags) {
let braille = this.objectOutputFunctions._generateBaseOutput.apply(this, arguments);
if (aAccessible.indexInParent === 1 &&
aAccessible.parent.role == Roles.LISTITEM &&
aAccessible.previousSibling.role == Roles.STATICTEXT) {
if (aAccessible.parent.parent && aAccessible.parent.parent.DOMNode &&
aAccessible.parent.parent.DOMNode.nodeName == 'UL') {
braille.unshift('*');
} else {
braille.unshift(aAccessible.previousSibling.name);
}
}
return braille;
return this.objectOutputFunctions._generateBaseOutput.apply(this, arguments);
},
listitem: function listitem(aAccessible, aRoleStr, aStates, aFlags) {

View File

@ -5,10 +5,9 @@ support-files =
doc_traversal.html
[test_alive.html]
[test_braille.html]
[test_explicit_names.html]
[test_landmarks.html]
[test_live_regions.html]
[test_output.html]
[test_tables.html]
[test_traversal.html]
[test_utterance_order.html]

View File

@ -1,122 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=876475
-->
<head>
<title>[AccessFu] braille generation test</title>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="./output.js"></script>
<script type="application/javascript">
function doTest() {
// Test the following accOrElmOrID (with optional old accOrElmOrID).
// Note: each accOrElmOrID entry maps to a unique object braille
// generator function within the BrailleGenerator.
var tests = [{
accOrElmOrID: "link",
expected: [["lnk", "Link"], ["Link", "lnk"]]
},{
accOrElmOrID: "button",
expected: [["btn", "I am a button"], ["I am a button", "btn"]]
},{
accOrElmOrID: "password_input",
expected: [["passwdtxt", "Secret Password"], ["Secret Password", "passwdtxt"]]
},{
accOrElmOrID: "checkbox_unchecked",
expected: [["( )", "checkboxtext"], ["checkboxtext", "( )"]]
},{
accOrElmOrID: "checkbox_checked",
expected: [["(x)", "some more checkbox text"], ["some more checkbox text", "(x)"]]
},{
accOrElmOrID: "radio_unselected",
expected: [["( )", "any old radio button"], ["any old radio button", "( )"]]
},{
accOrElmOrID: "radio_selected",
expected: [["(x)", "a unique radio button"], ["a unique radio button", "(x)"]]
},{
accOrElmOrID: "togglebutton_notpressed",
expected: [["( )", "I ain't pressed"], ["I ain't pressed", "( )"]]
},{
accOrElmOrID: "togglebutton_pressed",
expected: [["(x)", "I am pressed!"], ["I am pressed!", "(x)"]]
},{
accOrElmOrID: "ul_li_one",
expected: [["*", "ul item 1"], ["*", "ul item 1"]]
},{
accOrElmOrID: "ol_li_one",
expected: [["1.", "ol item 1"], ["1.", "ol item 1"]]
},{
accOrElmOrID: "textarea",
expected: [["txtarea", "Here lies treasure."], ["Here lies treasure.", "txtarea"]]
},{
accOrElmOrID: "textentry",
expected: [["entry", "Mario", "First name:"], ["First name:", "Mario", "entry"]]
},{
accOrElmOrID: "range",
expected: [["slider", "3", "Points:"], ["Points:", "3", "slider"]]
}];
// Test all possible braille order preference values.
tests.forEach(function run(test) {
var brailleOrderValues = [0, 1];
brailleOrderValues.forEach(
function testBrailleOrder(brailleOrder) {
SpecialPowers.setIntPref(PREF_UTTERANCE_ORDER, brailleOrder);
var expected = test.expected[brailleOrder];
testOutput(expected, test.accOrElmOrID, test.oldAccOrElmOrID, 2);
}
);
});
// If there was an original utterance order preference, revert to it.
SpecialPowers.clearUserPref(PREF_UTTERANCE_ORDER);
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
</script>
</head>
<body>
<div id="root">
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
<a href="example.com" id="link">Link</a>
<button id="button">I am a button</button>
<label for="password_input">Secret Password</label><input id="password_input" type="password"></input>
<label for="checkbox_unchecked">checkboxtext</label><input id="checkbox_unchecked" type="checkbox"></input>
<label for="checkbox_checked">some more checkbox text</label><input id="checkbox_checked" type="checkbox" checked></input>
<label for="radio_unselected">any old radio button</label><input id="radio_unselected" type="radio"></input>
<label for="radio_selected">a unique radio button</label><input id="radio_selected" type="radio" checked></input>
<div id="togglebutton_notpressed" aria-pressed="false" role="button" tabindex="-1">I ain't pressed</div>
<div id="togglebutton_pressed" aria-pressed="true" role="button" tabindex="-1">I am pressed!</div>
<ol id="ordered_list">
<li id="ol_li_one">ol item 1</li>
<li id="ol_li_two">ol item 2</li>
<li id="ol_li_three">ol item 3</li>
<li id="ol_li_three">ol item 4</li>
</ol>
<ul id="unordered_list">
<li id="ul_li_one">ul item 1</li>
<li id="ul_li_two">ul item 2</li>
<li id="ul_li_three">ul item 3</li>
<li id="ul_li_three">ul item 4</li>
</ul>
<textarea id="textarea" cols="80" rows="5">
Here lies treasure.
</textarea>
<label>First name: <input id="textentry" value="Mario"></label>
<label>Points: <input id="range" type="range" name="points" min="1" max="10" value="3"></label>
</div>
</body>
</html>

View File

@ -75,9 +75,7 @@
expectedUtterance: [["list 1 item", "complementary", "First item",
"A complementary"], ["A complementary", "First item",
"complementary", "list 1 item"]],
// XXX: The '*' should probably come before all of the context
// utterance.
expectedBraille: [["complementary", "*", "A complementary"], ["*",
expectedBraille: [["*", "complementary", "A complementary"], ["*",
"A complementary", "complementary"]]
}, {
accOrElmOrID: "parent_main",
@ -151,4 +149,4 @@
</main>
</div>
</body>
</html>
</html>

View File

@ -0,0 +1,459 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=753984
-->
<head>
<title>[AccessFu] utterance order test</title>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="./output.js"></script>
<script type="application/javascript">
function doTest() {
// Test the following accOrElmOrID (with optional old accOrElmOrID).
// Note: each accOrElmOrID entry maps to a unique object utterance
// generator function within the UtteranceGenerator.
var tests = [{
accOrElmOrID: "anchor",
expectedUtterance: [["link", "title"], ["title", "link"]],
expectedBraille: [["lnk", "title"], ["title", "lnk"]]
}, {
accOrElmOrID: "anchor_titleandtext",
expectedUtterance: [["link", "goes to the tests -", "Tests"],
["Tests", "- goes to the tests", "link"]],
expectedBraille: [["lnk", "goes to the tests -", "Tests"],
["Tests", "- goes to the tests", "lnk"]],
}, {
accOrElmOrID: "anchor_duplicatedtitleandtext",
expectedUtterance: [["link", "Tests"], ["Tests", "link"]],
expectedBraille: [["lnk", "Tests"], ["Tests", "lnk"]]
}, {
accOrElmOrID: "anchor_arialabelandtext",
expectedUtterance: [["link", "goes to the tests - Tests"],
["Tests - goes to the tests", "link"]],
expectedBraille: [["lnk", "goes to the tests - Tests"],
["Tests - goes to the tests", "lnk"]],
}, {
accOrElmOrID: "textarea",
expectedUtterance: [[
"text area", "This is the text area text."
], [
"This is the text area text.", "text area"
],],
expectedBraille: [[
"txtarea", "This is the text area text."
], [
"This is the text area text.", "txtarea"
],],
}, {
accOrElmOrID: "heading",
expectedUtterance: [
["heading level 1", "Test heading"],
["Test heading", "heading level 1"]
],
expectedBraille: [
["heading", "Test heading"],
["Test heading", "heading"]
]
}, {
accOrElmOrID: "list",
expectedUtterance: [
["list 1 item", "First item", "1.", "list one"],
["1.", "list one", "First item", "list 1 item"]
],
expectedBraille: [
["list", "list one"],
["list one", "list"]
]
}, {
accOrElmOrID: "dlist",
expectedUtterance: [
["definition list 0.5 items", "dd one"],
["dd one", "definition list 0.5 items"]
],
expectedBraille: [
["definition list", "dd one"],
["dd one", "definition list"]
]
}, {
accOrElmOrID: "li_one",
expectedUtterance: [
["list 1 item", "First item", "1.", "list one"],
["1.", "list one", "First item", "list 1 item"]
],
expectedBraille: [
["1.", "list one"],
["1.", "list one"]
]
}, {
accOrElmOrID: "cell",
expectedUtterance: [[
"table with 1 column and 1 row", "Fruits and vegetables",
"Column 1 Row 1", "list 4 items", "First item", "link", "Apples",
"link", "Bananas", "link", "Peaches", "Last item", "link", "Plums"
], [
"Apples", "link", "First item", "Bananas", "link", "Peaches",
"link", "Plums", "link", "Last item", "list 4 items",
"Column 1 Row 1", "Fruits and vegetables",
"table with 1 column and 1 row"
]],
expectedBraille: [[
"c1r1", "list", "lnk", "Apples", "lnk", "Bananas", "lnk",
"Peaches", "lnk", "Plums"
], [
"Apples", "lnk", "Bananas", "lnk", "Peaches", "lnk", "Plums",
"lnk", "list", "c1r1"
]]
}, {
accOrElmOrID: "date",
expectedUtterance: [["date entry", "2011-09-29"], ["2011-09-29", "date entry"]],
expectedBraille: [["date entry", "2011-09-29"], ["2011-09-29", "date entry"]]
}, {
accOrElmOrID: "email",
expectedUtterance: [
["e-mail entry", "test@example.com"],
["test@example.com", "e-mail entry"]
],
expectedBraille: [
["e-mail entry", "test@example.com"],
["test@example.com", "e-mail entry"]
]
}, {
accOrElmOrID: "search",
expectedUtterance: [
["search entry", "This is a search"],
["This is a search", "search entry"]
],
expectedBraille: [
["search entry", "This is a search"],
["This is a search", "search entry"]
]
}, {
accOrElmOrID: "tel",
expectedUtterance: [
["telephone entry", "555-5555"], ["555-5555", "telephone entry"]
],
expectedBraille: [
["telephone entry", "555-5555"], ["555-5555", "telephone entry"]
]
}, {
accOrElmOrID: "url",
expectedUtterance: [
["URL entry", "http://example.com"],
["http://example.com", "URL entry"]
],
expectedBraille: [
["URL entry", "http://example.com"],
["http://example.com", "URL entry"]
]
}, {
accOrElmOrID: "textInput",
expectedUtterance: [["entry", "This is text."], ["This is text.", "entry"]],
expectedBraille: [["entry", "This is text."], ["This is text.", "entry"]]
}, {
// Test pivot to list from li_one.
accOrElmOrID: "list",
oldAccOrElmOrID: "li_one",
expectedUtterance: [
["list 1 item", "First item", "1.", "list one"],
["1.", "list one", "First item", "list 1 item"]
],
expectedBraille: [
["list", "list one"],
["list one", "list"]
]
}, {
// Test pivot to "apples" link from the table cell.
accOrElmOrID: "apples",
oldAccOrElmOrID: "cell",
expectedUtterance: [
["list 4 items", "First item", "link", "Apples"],
["Apples", "link", "First item", "list 4 items"]
],
expectedBraille: [
["*", "lnk", "Apples"],
["*", "Apples", "lnk"]
]
}, {
// Test pivot to 'bananas' link from 'apples' link.
accOrElmOrID: "bananas",
oldAccOrElmOrID: "apples",
expectedUtterance: [["link", "Bananas"], ["Bananas", "link"]],
expectedBraille: [["*", "lnk", "Bananas"], ["*", "Bananas", "lnk"]]
}, {
// test unavailable state utterance
accOrElmOrID: 'unavailableButton',
expectedUtterance: [["unavailable button", "I am unavailable"],
["I am unavailable", "unavailable button"]],
expectedBraille: [["btn", "I am unavailable"],
["I am unavailable", "btn"]]
}, {
// test expanded state utterance
accOrElmOrID: 'expandedButton',
expectedUtterance: [["expanded button", "I am expanded"],
["I am expanded", "expanded button"]],
expectedBraille: [["btn", "I am expanded"],
["I am expanded", "btn"]]
}, {
// test collapsed state utterance
accOrElmOrID: 'collapsedButton',
expectedUtterance: [["collapsed button", "I am collapsed"],
["I am collapsed", "collapsed button"]],
expectedBraille: [["btn", "I am collapsed"],
["I am collapsed", "btn"]]
}, {
// test required state utterance
accOrElmOrID: 'requiredInput',
expectedUtterance: [["required entry", "I am required"],
["I am required", "required entry"]],
expectedBraille: [["entry", "I am required"],
["I am required", "entry"]]
}, {
// test has popup state utterance
accOrElmOrID: 'hasPopupButton',
expectedUtterance: [["has pop up button menu", "I have a popup"],
["I have a popup", "has pop up button menu"]],
expectedBraille: [["button menu", "I have a popup"],
["I have a popup", "button menu"]]
}, {
// Test selected tab
accOrElmOrID: 'tab1',
expectedUtterance: [['tab list', 'selected tab 1 of 2', 'Account'],
['Account', 'selected tab 1 of 2', 'tab list']],
expectedBraille: [['tab 1 of 2', 'Account'],
['Account', 'tab 1 of 2']]
}, {
// Test unselected tab
accOrElmOrID: 'tab2',
expectedUtterance: [['tab list', 'tab 2 of 2', 'Advanced'],
['Advanced', 'tab 2 of 2', 'tab list']],
expectedBraille: [['tab 2 of 2', 'Advanced'],
['Advanced', 'tab 2 of 2']]
},
{
// Landing on this label should mimic landing on the checkbox.
accOrElmOrID: "label1",
expectedUtterance: [['not checked check button', 'Orange'],
['Orange', 'not checked check button']],
expectedBraille: [['( )', 'Orange'],
['Orange', '( )']]
},
{
// Here we get a top-level view of the form.
accOrElmOrID: "form1",
expectedUtterance: [['label', 'not checked check button', 'Orange', 'Orange',
'not checked check button', 'Blue', 'label', 'Blue'],
['Orange', 'not checked check button', 'Orange', 'label',
'Blue', 'not checked check button', 'Blue', 'label']],
expectedBraille: [['label', '( )', 'Orange', 'Orange',
'( )', 'Blue', 'label', 'Blue'],
['Orange', '( )', 'Orange', 'label',
'Blue', '( )', 'Blue', 'label']]
},
{
// This is a non-nesting label.
accOrElmOrID: "label2",
expectedUtterance: [['label', 'Blue'], ['Blue', 'label']],
expectedBraille: [['label', 'Blue'], ['Blue', 'label']]
},
{
// This is a distinct control.
accOrElmOrID: "input2",
expectedUtterance: [['not checked check button', 'Blue'],
['Blue', 'not checked check button']],
expectedBraille: [['( )', 'Blue'],
['Blue', '( )']]
},
{
// This is a nested control.
accOrElmOrID: "input1",
expectedUtterance: [['not checked check button', 'Orange'],
['Orange', 'not checked check button']],
expectedBraille: [['( )', 'Orange'],
['Orange', '( )']]
},
{
// Landing on this label should mimic landing on the entry.
accOrElmOrID: "label3",
expectedUtterance: [['entry', 'Joe', 'First name:'],
['First name:', 'Joe', 'entry']],
expectedBraille: [['entry', 'Joe', 'First name:'],
['First name:', 'Joe', 'entry']]
},
{
// This is a nested control with a value.
accOrElmOrID: "input3",
expectedUtterance: [['entry', 'Joe', 'First name:'],
['First name:', 'Joe', 'entry']],
expectedBraille: [['entry', 'Joe', 'First name:'],
['First name:', 'Joe', 'entry']]
},
{
// This is a nested control with a value.
accOrElmOrID: "input4",
expectedUtterance: [['slider', '3', 'Points:'],
['Points:', '3', 'slider']],
expectedBraille: [['slider', '3', 'Points:'],
['Points:', '3', 'slider']]
},{
accOrElmOrID: "password",
expectedUtterance: [["password text", "Secret Password"],
["Secret Password", "password text"]],
expectedBraille: [["passwdtxt", "Secret Password"],
["Secret Password", "passwdtxt"]]
},{
accOrElmOrID: "input5",
expectedUtterance: [["checked check button", "Boring label"],
["Boring label", "checked check button"]],
expectedBraille: [["(x)", "Boring label"],
["Boring label", "(x)"]]
},{
accOrElmOrID: "radio_unselected",
expectedUtterance: [["not checked radio button", "any old radio button"],
["any old radio button", "not checked radio button"]],
expectedBraille: [["( )", "any old radio button"],
["any old radio button", "( )"]]
},{
accOrElmOrID: "radio_selected",
expectedUtterance: [["checked radio button", "a unique radio button"],
["a unique radio button", "checked radio button"]],
expectedBraille: [["(x)", "a unique radio button"],
["a unique radio button", "(x)"]]
},{
accOrElmOrID: "togglebutton_notpressed",
expectedUtterance: [["not checked toggle button", "I ain't pressed"],
["I ain't pressed", "not checked toggle button"]],
expectedBraille: [["( )", "I ain't pressed"],
["I ain't pressed", "( )"]]
},{
accOrElmOrID: "togglebutton_pressed",
expectedUtterance: [["not checked toggle button", "I am pressed!"],
["I am pressed!", "not checked toggle button"]],
expectedBraille: [["(x)", "I am pressed!"],
["I am pressed!", "(x)"]]
}
];
// Test all possible utterance order preference values.
tests.forEach(function run(test) {
var utteranceOrderValues = [0, 1];
utteranceOrderValues.forEach(
function testUtteranceOrder(utteranceOrder) {
SpecialPowers.setIntPref(PREF_UTTERANCE_ORDER, utteranceOrder);
testOutput(test.expectedUtterance[utteranceOrder],
test.accOrElmOrID, test.oldAccOrElmOrID, 1);
testOutput(test.expectedBraille[utteranceOrder],
test.accOrElmOrID, test.oldAccOrElmOrID, 0);
}
);
});
// If there was an original utterance order preference, revert to it.
SpecialPowers.clearUserPref(PREF_UTTERANCE_ORDER);
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
</script>
</head>
<body>
<div id="root">
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=753984"
title="[AccessFu] utterance order test">
Mozilla Bug 753984</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=758675"
title="[AccessFu] Add support for accDescription">
Mozilla Bug 758675</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=876475"
title="[AccessFu] Make braille output less verbose">
Mozilla Bug 876475</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=924284"
title="[AccessFu] Output accessible values">
Mozilla Bug 924284</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=925845"
title="[AccessFu] Unify output tests">
Mozilla Bug 925845</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
<a id="anchor" href="#test" title="title"></a>
<a id="anchor_titleandtext" href="#test" title="goes to the tests">Tests</a>
<a id="anchor_duplicatedtitleandtext" href="#test" title="Tests">Tests</a>
<a id="anchor_arialabelandtext" href="#test" aria-label="Tests" title="goes to the tests">Tests</a>
<textarea id="textarea" cols="80" rows="5">
This is the text area text.
</textarea>
<h1 id="heading" title="Test heading"></h1>
<ol id="list">
<li id="li_one">list one</li>
</ol>
<dl id="dlist">
<dd id="dd_one">
dd one
</dd>
</dl>
<table>
<caption>Fruits and vegetables</caption>
<tr>
<td id="cell">
<ul style="list-style-type: none;">
<li><a id="apples" href="#">Apples</a></li>
<li><a id="bananas" href="#">Bananas</a></li>
<li><a href="#">Peaches</a></li>
<li>
<a href="#">
Plums
</a>
</li>
</ul>
</td>
</tr>
</table>
<button id="unavailableButton" disabled>I am unavailable</button>
<button id="expandedButton" aria-expanded="true">I am expanded</button>
<button id="collapsedButton" aria-expanded="false">I am collapsed</button>
<input id="requiredInput" required placeholder="I am required" />
<button id="hasPopupButton" aria-haspopup="true">I have a popup</button>
<div role="tablist">
<a id="tab1" href="#" role="tab" aria-selected="true">Account</a>
<a id="tab2" href="#" role="tab" aria-selected="false">Advanced</a>
</div>
<form id="form1">
<label id="label1"><input id="input1" type="checkbox">Orange</label>
<input id="input2" type="checkbox"><label id="label2" for="input2">Blue</label>
</form>
<label id="label3">First name: <input id="input3" value="Joe"></label>
<label id="label4">Points:
<input id="input4" type="range" name="points" min="1" max="10" value="3">
</label>
<label for="input5">Boring label</label><input id="input5" type="checkbox" checked></input>
<label for="password">Secret Password</label><input id="password" type="password"></input>
<label for="radio_unselected">any old radio button</label><input id="radio_unselected" type="radio"></input>
<label for="radio_selected">a unique radio button</label><input id="radio_selected" type="radio" checked></input>
<input id="date" type="date" value="2011-09-29" />
<input id="email" type="email" value="test@example.com" />
<input id="search" type="search" value="This is a search" />
<input id="tel" type="tel" value="555-5555" />
<input id="url" type="url" value="http://example.com" />
<input id="textInput" type="text" value="This is text." />
<label>Points: <input id="range" type="range" name="points" min="1" max="10" value="3"></label>
<div id="togglebutton_notpressed" aria-pressed="false" role="button" tabindex="-1">I ain't pressed</div>
<div id="togglebutton_pressed" aria-pressed="true" role="button" tabindex="-1">I am pressed!</div>
</div>
</body>
</html>

View File

@ -1,316 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=753984
-->
<head>
<title>[AccessFu] utterance order test</title>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="./output.js"></script>
<script type="application/javascript">
function doTest() {
// Test the following accOrElmOrID (with optional old accOrElmOrID).
// Note: each accOrElmOrID entry maps to a unique object utterance
// generator function within the UtteranceGenerator.
var tests = [{
accOrElmOrID: "anchor",
expected: [["link", "title"], ["title", "link"]]
}, {
accOrElmOrID: "anchor_titleandtext",
expected: [[
"link", "goes to the tests -", "Tests"
], [
"Tests", "- goes to the tests", "link"
]]
}, {
accOrElmOrID: "anchor_duplicatedtitleandtext",
expected: [["link", "Tests"], ["Tests", "link"]]
}, {
accOrElmOrID: "anchor_arialabelandtext",
expected: [[
"link", "goes to the tests - Tests"
], [
"Tests - goes to the tests", "link"
]]
}, {
accOrElmOrID: "textarea",
expected: [[
"text area", "This is the text area text."
], [
"This is the text area text.", "text area"
]]
}, {
accOrElmOrID: "heading",
expected: [
["heading level 1", "Test heading"],
["Test heading", "heading level 1"]
]
}, {
accOrElmOrID: "list",
expected: [
["list 1 item", "First item", "1.", "list one"],
["1.", "list one", "First item", "list 1 item"]
]
}, {
accOrElmOrID: "dlist",
expected: [
["definition list 0.5 items", "dd one"],
["dd one", "definition list 0.5 items"]
]
}, {
accOrElmOrID: "li_one",
expected: [
["list 1 item", "First item", "1.", "list one"],
["1.", "list one", "First item", "list 1 item"]
]
}, {
accOrElmOrID: "cell",
expected: [[
"table with 1 column and 1 row", "Fruits and vegetables",
"Column 1 Row 1", "list 4 items", "First item", "link", "Apples",
"link", "Bananas", "link", "Peaches", "Last item", "link", "Plums"
], [
"Apples", "link", "First item", "Bananas", "link", "Peaches",
"link", "Plums", "link", "Last item", "list 4 items",
"Column 1 Row 1", "Fruits and vegetables",
"table with 1 column and 1 row"
]]
}, {
accOrElmOrID: "date",
expected: [["date entry", "2011-09-29"], ["2011-09-29", "date entry"]]
}, {
accOrElmOrID: "email",
expected: [
["e-mail entry", "test@example.com"],
["test@example.com", "e-mail entry"]
]
}, {
accOrElmOrID: "search",
expected: [
["search entry", "This is a search"],
["This is a search", "search entry"]
]
}, {
accOrElmOrID: "tel",
expected: [
["telephone entry", "555-5555"], ["555-5555", "telephone entry"]
]
}, {
accOrElmOrID: "url",
expected: [
["URL entry", "http://example.com"],
["http://example.com", "URL entry"]
]
}, {
accOrElmOrID: "textInput",
expected: [["entry", "This is text."], ["This is text.", "entry"]]
}, {
// Test pivot to list from li_one.
accOrElmOrID: "list",
oldAccOrElmOrID: "li_one",
expected: [
["list 1 item", "First item", "1.", "list one"],
["1.", "list one", "First item", "list 1 item"]
]
}, {
// Test pivot to "apples" link from the table cell.
accOrElmOrID: "apples",
oldAccOrElmOrID: "cell",
expected: [
["list 4 items", "First item", "link", "Apples"],
["Apples", "link", "First item", "list 4 items"]
]
}, {
// Test pivot to 'bananas' link from 'apples' link.
accOrElmOrID: "bananas",
oldAccOrElmOrID: "apples",
expected: [["link", "Bananas"], ["Bananas", "link"]]
}, {
// test unavailable state utterance
accOrElmOrID: 'unavailableButton',
expected: [["unavailable button", "I am unavailable"],
["I am unavailable", "unavailable button"]]
}, {
// test expanded state utterance
accOrElmOrID: 'expandedButton',
expected: [["expanded button", "I am expanded"],
["I am expanded", "expanded button"]]
}, {
// test collapsed state utterance
accOrElmOrID: 'collapsedButton',
expected: [["collapsed button", "I am collapsed"],
["I am collapsed", "collapsed button"]]
}, {
// test required state utterance
accOrElmOrID: 'requiredInput',
expected: [["required entry", "I am required"],
["I am required", "required entry"]]
}, {
// test has popup state utterance
accOrElmOrID: 'hasPopupButton',
expected: [["has pop up button menu", "I have a popup"],
["I have a popup", "has pop up button menu"]]
}, {
// Test selected tab
accOrElmOrID: 'tab1',
expected: [['tab list', 'selected tab 1 of 2', 'Account'],
['Account', 'selected tab 1 of 2', 'tab list']]
}, {
// Test unselected tab
accOrElmOrID: 'tab2',
expected: [['tab list', 'tab 2 of 2', 'Advanced'],
['Advanced', 'tab 2 of 2', 'tab list']]
},
{
// Landing on this label should mimic landing on the checkbox.
accOrElmOrID: "label1",
expected: [['not checked check button', 'Orange'],
['Orange', 'not checked check button']]
},
{
// Here we get a top-level view of the form.
accOrElmOrID: "form1",
expected: [['label', 'not checked check button', 'Orange', 'Orange',
'not checked check button', 'Blue', 'label', 'Blue'],
['Orange', 'not checked check button', 'Orange', 'label',
'Blue', 'not checked check button', 'Blue', 'label']]
},
{
// This is a non-nesting label.
accOrElmOrID: "label2",
expected: [['label', 'Blue'], ['Blue', 'label']]
},
{
// This is a distinct control.
accOrElmOrID: "input2",
expected: [['not checked check button', 'Blue'],
['Blue', 'not checked check button']]
},
{
// This is a nested control.
accOrElmOrID: "input1",
expected: [['not checked check button', 'Orange'],
['Orange', 'not checked check button']]
},
{
// Landing on this label should mimic landing on the entry.
accOrElmOrID: "label3",
expected: [['entry', 'Joe', 'First name:'],
['First name:', 'Joe', 'entry']]
},
{
// This is a nested control with a value.
accOrElmOrID: "input3",
expected: [['entry', 'Joe', 'First name:'],
['First name:', 'Joe', 'entry']]
},
{
// This is a nested control with a value.
accOrElmOrID: "input4",
expected: [['slider', '3', 'Points:'],
['Points:', '3', 'slider']]
}];
// Test all possible utterance order preference values.
tests.forEach(function run(test) {
var utteranceOrderValues = [0, 1];
utteranceOrderValues.forEach(
function testUtteranceOrder(utteranceOrder) {
SpecialPowers.setIntPref(PREF_UTTERANCE_ORDER, utteranceOrder);
var expected = test.expected[utteranceOrder];
testOutput(expected, test.accOrElmOrID, test.oldAccOrElmOrID, 1);
}
);
});
// If there was an original utterance order preference, revert to it.
SpecialPowers.clearUserPref(PREF_UTTERANCE_ORDER);
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
</script>
</head>
<body>
<div id="root">
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=753984"
title="[AccessFu] utterance order test">
Mozilla Bug 753984</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=758675"
title="[AccessFu] Add support for accDescription">
Mozilla Bug 758675</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
<a id="anchor" href="#test" title="title"></a>
<a id="anchor_titleandtext" href="#test" title="goes to the tests">Tests</a>
<a id="anchor_duplicatedtitleandtext" href="#test" title="Tests">Tests</a>
<a id="anchor_arialabelandtext" href="#test" aria-label="Tests" title="goes to the tests">Tests</a>
<textarea id="textarea" cols="80" rows="5">
This is the text area text.
</textarea>
<h1 id="heading" title="Test heading"></h1>
<ol id="list">
<li id="li_one">list one</li>
</ol>
<dl id="dlist">
<dd id="dd_one">
dd one
</dd>
</dl>
<table>
<caption>Fruits and vegetables</caption>
<tr>
<td id="cell">
<ul style="list-style-type: none;">
<li><a id="apples" href="#">Apples</a></li>
<li><a id="bananas" href="#">Bananas</a></li>
<li><a href="#">Peaches</a></li>
<li>
<a href="#">
Plums
</a>
</li>
</ul>
</td>
</tr>
</table>
<button id="unavailableButton" disabled>I am unavailable</button>
<button id="expandedButton" aria-expanded="true">I am expanded</button>
<button id="collapsedButton" aria-expanded="false">I am collapsed</button>
<input id="requiredInput" required placeholder="I am required" />
<button id="hasPopupButton" aria-haspopup="true">I have a popup</button>
<div role="tablist">
<a id="tab1" href="#" role="tab" aria-selected="true">Account</a>
<a id="tab2" href="#" role="tab" aria-selected="false">Advanced</a>
</div>
<form id="form1">
<label id="label1"><input id="input1" type="checkbox">Orange</label>
<input id="input2" type="checkbox"><label id="label2" for="input2">Blue</label>
</form>
<label id="label3">First name: <input id="input3" value="Joe"></label>
<label id="label4">Points:
<input id="input4" type="range" name="points" min="1" max="10" value="3">
</label>
<input id="date" type="date" value="2011-09-29" />
<input id="email" type="email" value="test@example.com" />
<input id="search" type="search" value="This is a search" />
<input id="tel" type="tel" value="555-5555" />
<input id="url" type="url" value="http://example.com" />
<input id="textInput" type="text" value="This is text." />
</div>
</body>
</html>

View File

@ -1351,12 +1351,14 @@ if test "$GNU_CC"; then
# -Wpointer-arith - good to have
# -Wdeclaration-after-statement - MSVC doesn't like these
# -Werror=return-type - catches missing returns, zero false positives
# -Werror=int-to-pointer-cast - catches cast to pointer from integer of different size
# -Wtype-limits - catches overflow bugs, few false positives
# -Wempty-body - catches bugs, e.g. "if (c); foo();", few false positives
# -Wsign-compare - catches comparison of signed and unsigned types
#
_WARNINGS_CFLAGS="${_WARNINGS_CFLAGS} -Wall -Wpointer-arith -Wdeclaration-after-statement"
MOZ_C_SUPPORTS_WARNING(-W, error=return-type, ac_c_has_werror_return_type)
MOZ_C_SUPPORTS_WARNING(-W, error=int-to-pointer-cast, ac_c_has_werror_int_to_pointer_cast)
MOZ_C_SUPPORTS_WARNING(-W, type-limits, ac_c_has_wtype_limits)
MOZ_C_SUPPORTS_WARNING(-W, empty-body, ac_c_has_wempty_body)
MOZ_C_SUPPORTS_WARNING(-W, sign-compare, ac_c_has_sign_compare)
@ -1415,12 +1417,14 @@ if test "$GNU_CXX"; then
# -Wpointer-arith - good to have
# -Woverloaded-virtual - ???
# -Werror=return-type - catches missing returns, zero false positives
# -Werror=int-to-pointer-cast - catches cast to pointer from integer of different size
# -Wtype-limits - catches overflow bugs, few false positives
# -Wempty-body - catches bugs, e.g. "if (c); foo();", few false positives
# -Wsign-compare - catches comparison of signed and unsigned types
#
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wall -Wpointer-arith -Woverloaded-virtual"
MOZ_CXX_SUPPORTS_WARNING(-W, error=return-type, ac_cxx_has_werror_return_type)
MOZ_CXX_SUPPORTS_WARNING(-W, error=int-to-pointer-cast, ac_cxx_has_werror_int_to_pointer_cast)
MOZ_CXX_SUPPORTS_WARNING(-W, type-limits, ac_cxx_has_wtype_limits)
MOZ_CXX_SUPPORTS_WARNING(-W, empty-body, ac_cxx_has_wempty_body)
MOZ_CXX_SUPPORTS_WARNING(-W, sign-compare, ac_cxx_has_sign_compare)
@ -7742,8 +7746,14 @@ else
else
echo '#include <stdio.h>' > dummy-hello.c
changequote(,)
CL_INCLUDES_PREFIX=`${CC} -showIncludes -c -Fonul dummy-hello.c 2>&1 | sed -ne 's/^\([^:]*:[^:]*:\).*stdio.h$/\1/p'`
dnl This output is localized, split at the first double space or colon and space.
_CL_PREFIX_REGEX="^\([^:]*:.*[ :] \)\(.*stdio.h\)$"
CL_INCLUDES_PREFIX=`${CC} -showIncludes -c -Fonul dummy-hello.c 2>&1 | sed -ne 's/'"$_CL_PREFIX_REGEX"'/\1/p'`
_CL_STDIO_PATH=`${CC} -showIncludes -c -Fonul dummy-hello.c 2>&1 | sed -ne 's/'"$_CL_PREFIX_REGEX"'/\2/p'`
changequote([,])
if ! test -e "$_CL_STDIO_PATH"; then
AC_MSG_ERROR([Unable to parse cl -showIncludes prefix. This compiler's locale has an unsupported formatting.])
fi
if test -z "$CL_INCLUDES_PREFIX"; then
AC_MSG_ERROR([Cannot find cl -showIncludes prefix.])
fi

View File

@ -40,7 +40,7 @@ bool WebGLQuery::IsActive() const
MOZ_ASSERT(targetSlot, "unknown query object's type");
return *targetSlot == this;
return targetSlot && *targetSlot == this;
}

View File

@ -629,6 +629,25 @@ ManifestHelper.prototype = {
return {};
},
get biggestIconURL() {
let icons = this._localeProp("icons");
if (!icons) {
return null;
}
let iconSizes = Object.keys(icons);
if (iconSizes.length == 0) {
return null;
}
iconSizes.sort((a, b) => a - b);
let biggestIconSize = iconSizes.pop();
let biggestIcon = icons[biggestIconSize];
let biggestIconURL = this._origin.resolve(biggestIcon);
return biggestIconURL;
},
iconURLForSize: function(aSize) {
let icons = this._localeProp("icons");
if (!icons)

View File

@ -2546,7 +2546,8 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
// make sure the cached document property gets updated.
// XXXmarkh - tell other languages about this?
::JS_DeleteProperty(cx, currentInner->mJSObject, "document");
JS::Rooted<JSObject*> obj(cx, currentInner->mJSObject);
::JS_DeleteProperty(cx, obj, "document");
}
} else {
newInnerWindow->InnerSetNewDocument(aDocument);
@ -10865,7 +10866,9 @@ nsGlobalWindow::Observe(nsISupports* aSubject, const char* aTopic,
nsCOMPtr<nsIDOMStorageManager> storageManager = do_QueryInterface(GetDocShell());
if (storageManager) {
rv = storageManager->CheckStorage(principal, changingStorage, &check);
NS_ENSURE_SUCCESS(rv, rv);
if (NS_FAILED(rv)) {
return rv;
}
}
if (!check) {

View File

@ -2350,6 +2350,36 @@ CreateGlobal(JSContext* aCx, T* aObject, nsWrapperCache* aCache,
return global;
}
/*
* Holds a jsid that is initialized to an interned string, with conversion to
* Handle<jsid>.
*/
class InternedStringId
{
jsid id;
public:
InternedStringId() : id(JSID_VOID) {}
bool init(JSContext *cx, const char *string) {
MOZ_ASSERT(id == JSID_VOID);
JSString* str = JS_InternString(cx, string);
if (!str)
return false;
id = INTERNED_STRING_TO_JSID(cx, str);
return true;
}
operator const jsid& () {
return id;
}
operator JS::Handle<jsid> () {
/* This is safe because we have interned the string. */
return JS::Handle<jsid>::fromMarkedLocation(&id);
}
};
} // namespace dom
} // namespace mozilla

View File

@ -38,7 +38,8 @@ DOMProxyShadows(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id)
JS::Value v = js::GetProxyExtra(proxy, JSPROXYSLOT_EXPANDO);
if (v.isObject()) {
bool hasOwn;
if (!JS_AlreadyHasOwnPropertyById(cx, &v.toObject(), id, &hasOwn))
Rooted<JSObject*> object(cx, &v.toObject());
if (!JS_AlreadyHasOwnPropertyById(cx, object, id, &hasOwn))
return js::ShadowCheckFailed;
return hasOwn ? js::Shadows : js::DoesntShadow;

View File

@ -68,8 +68,12 @@ this.DataStoreChangeNotifier = {
receiveMessage: function(aMessage) {
debug("receiveMessage");
// No check has to be done when the message is 'child-process-shutdown'
// because at this point the target is already disconnected from
// nsFrameMessageManager, so that assertAppHasStatus will always fail.
let prefName = 'dom.testing.datastore_enabled_for_hosted_apps';
if ((Services.prefs.getPrefType(prefName) == Services.prefs.PREF_INVALID ||
if (aMessage.name != 'child-process-shutdown' &&
(Services.prefs.getPrefType(prefName) == Services.prefs.PREF_INVALID ||
!Services.prefs.getBoolPref(prefName)) &&
!aMessage.target.assertAppHasStatus(Ci.nsIPrincipal.APP_STATUS_CERTIFIED)) {
return;

View File

@ -711,7 +711,7 @@ nsJSObjWrapper::NP_InvokeDefault(NPObject *npobj, const NPVariant *args,
// static
bool
nsJSObjWrapper::NP_HasProperty(NPObject *npobj, NPIdentifier id)
nsJSObjWrapper::NP_HasProperty(NPObject *npobj, NPIdentifier npid)
{
NPP npp = NPPStack::Peek();
JSContext *cx = GetJSContext(npp);
@ -733,11 +733,13 @@ nsJSObjWrapper::NP_HasProperty(NPObject *npobj, NPIdentifier id)
nsCxPusher pusher;
pusher.Push(cx);
AutoJSExceptionReporter reporter(cx);
JSAutoCompartment ac(cx, npjsobj->mJSObj);
JS::Rooted<JSObject*> jsobj(cx, npjsobj->mJSObj);
JSAutoCompartment ac(cx, jsobj);
NS_ASSERTION(NPIdentifierIsInt(id) || NPIdentifierIsString(id),
NS_ASSERTION(NPIdentifierIsInt(npid) || NPIdentifierIsString(npid),
"id must be either string or int!\n");
ok = ::JS_HasPropertyById(cx, npjsobj->mJSObj, NPIdentifierToJSId(id), &found);
JS::Rooted<jsid> id(cx, NPIdentifierToJSId(npid));
ok = ::JS_HasPropertyById(cx, jsobj, id, &found);
return ok && found;
}
@ -810,7 +812,7 @@ nsJSObjWrapper::NP_SetProperty(NPObject *npobj, NPIdentifier id,
// static
bool
nsJSObjWrapper::NP_RemoveProperty(NPObject *npobj, NPIdentifier id)
nsJSObjWrapper::NP_RemoveProperty(NPObject *npobj, NPIdentifier npid)
{
NPP npp = NPPStack::Peek();
JSContext *cx = GetJSContext(npp);
@ -833,17 +835,19 @@ nsJSObjWrapper::NP_RemoveProperty(NPObject *npobj, NPIdentifier id)
pusher.Push(cx);
AutoJSExceptionReporter reporter(cx);
bool deleted = false;
JSAutoCompartment ac(cx, npjsobj->mJSObj);
JS::Rooted<JSObject*> obj(cx, npjsobj->mJSObj);
JSAutoCompartment ac(cx, obj);
NS_ASSERTION(NPIdentifierIsInt(id) || NPIdentifierIsString(id),
NS_ASSERTION(NPIdentifierIsInt(npid) || NPIdentifierIsString(npid),
"id must be either string or int!\n");
ok = ::JS_DeletePropertyById2(cx, npjsobj->mJSObj, NPIdentifierToJSId(id), &deleted);
JS::Rooted<jsid> id(cx, NPIdentifierToJSId(npid));
ok = ::JS_DeletePropertyById2(cx, obj, id, &deleted);
if (ok && deleted) {
// FIXME: See bug 425823, we shouldn't need to do this, and once
// that bug is fixed we can remove this code.
bool hasProp;
ok = ::JS_HasPropertyById(cx, npjsobj->mJSObj, NPIdentifierToJSId(id), &hasProp);
ok = ::JS_HasPropertyById(cx, obj, id, &hasProp);
if (ok && hasProp) {
// The property might have been deleted, but it got

View File

@ -457,7 +457,9 @@ DOMStorageManager::CheckStorage(nsIPrincipal* aPrincipal,
nsAutoCString scope;
nsresult rv = CreateScopeKey(aPrincipal, scope);
NS_ENSURE_SUCCESS(rv, rv);
if (NS_FAILED(rv)) {
return rv;
}
DOMStorageCache* cache = GetCache(scope);
if (cache != pstorage->GetCache()) {

View File

@ -28,6 +28,7 @@
#if defined(XP_WIN)
#include <windows.h>
#include <accctrl.h>
#endif // defined(XP_WIN)
#include "jsapi.h"
@ -680,6 +681,11 @@ static const dom::ConstantSpec gWinProperties[] =
// GetFileAttributes error constant
INT_CONSTANT(INVALID_FILE_ATTRIBUTES),
// GetNamedSecurityInfo and SetNamedSecurityInfo constants
INT_CONSTANT(UNPROTECTED_DACL_SECURITY_INFORMATION),
INT_CONSTANT(SE_FILE_OBJECT),
INT_CONSTANT(DACL_SECURITY_INFORMATION),
// Errors
INT_CONSTANT(ERROR_ACCESS_DENIED),
INT_CONSTANT(ERROR_DIR_NOT_EMPTY),

View File

@ -320,7 +320,9 @@ APZCTreeManager::ReceiveInputEvent(const InputData& aEvent,
case MULTITOUCH_INPUT: {
const MultiTouchInput& multiTouchInput = aEvent.AsMultiTouchInput();
if (multiTouchInput.mType == MultiTouchInput::MULTITOUCH_START) {
mTouchCount++;
// MULTITOUCH_START input contains all active touches of the current
// session thus resetting mTouchCount.
mTouchCount = multiTouchInput.mTouches.Length();
mApzcForInputBlock = GetTargetAPZC(ScreenPoint(multiTouchInput.mTouches[0].mScreenPoint));
if (multiTouchInput.mTouches.Length() == 1) {
// If we have one touch point, this might be the start of a pan.
@ -363,6 +365,7 @@ APZCTreeManager::ReceiveInputEvent(const InputData& aEvent,
if (multiTouchInput.mType == MultiTouchInput::MULTITOUCH_CANCEL ||
multiTouchInput.mType == MultiTouchInput::MULTITOUCH_END) {
if (mTouchCount >= multiTouchInput.mTouches.Length()) {
// MULTITOUCH_END input contains only released touches thus decrementing.
mTouchCount -= multiTouchInput.mTouches.Length();
} else {
NS_WARNING("Got an unexpected touchend/touchcancel");
@ -438,7 +441,9 @@ APZCTreeManager::ProcessTouchEvent(const WidgetTouchEvent& aEvent,
return ret;
}
if (aEvent.message == NS_TOUCH_START) {
mTouchCount++;
// NS_TOUCH_START event contains all active touches of the current
// session thus resetting mTouchCount.
mTouchCount = aEvent.touches.Length();
mApzcForInputBlock = GetTouchInputBlockAPZC(aEvent);
if (mApzcForInputBlock) {
// Cache apz transform so it can be used for future events in this block.
@ -477,6 +482,7 @@ APZCTreeManager::ProcessTouchEvent(const WidgetTouchEvent& aEvent,
if (aEvent.message == NS_TOUCH_CANCEL ||
aEvent.message == NS_TOUCH_END) {
if (mTouchCount >= aEvent.touches.Length()) {
// NS_TOUCH_END event contains only released touches thus decrementing.
mTouchCount -= aEvent.touches.Length();
} else {
NS_WARNING("Got an unexpected touchend/touchcancel");

View File

@ -541,6 +541,20 @@ AsyncCompositionManager::ApplyAsyncContentTransformToTree(TimeStamp aCurrentFram
return appliedTransform;
}
static bool
LayerHasNonContainerDescendants(ContainerLayer* aContainer)
{
for (Layer* child = aContainer->GetFirstChild();
child; child = child->GetNextSibling()) {
ContainerLayer* container = child->AsContainerLayer();
if (!container || LayerHasNonContainerDescendants(container)) {
return true;
}
}
return false;
}
void
AsyncCompositionManager::ApplyAsyncTransformToScrollbar(ContainerLayer* aLayer)
{
@ -551,6 +565,11 @@ AsyncCompositionManager::ApplyAsyncTransformToScrollbar(ContainerLayer* aLayer)
// Note that it is possible that the content layer is no longer there; in
// this case we don't need to do anything because there can't be an async
// transform on the content.
// We only apply the transform if the scroll-target layer has non-container
// children (i.e. when it has some possibly-visible content). This is to
// avoid moving scroll-bars in the situation that only a scroll information
// layer has been built for a scroll frame, as this would result in a
// disparity between scrollbars and visible content.
for (Layer* scrollTarget = aLayer->GetPrevSibling();
scrollTarget;
scrollTarget = scrollTarget->GetPrevSibling()) {
@ -565,6 +584,9 @@ AsyncCompositionManager::ApplyAsyncTransformToScrollbar(ContainerLayer* aLayer)
if (metrics.mScrollId != aLayer->GetScrollbarTargetContainerId()) {
continue;
}
if (!LayerHasNonContainerDescendants(scrollTarget->AsContainerLayer())) {
return;
}
gfx3DMatrix asyncTransform = gfx3DMatrix(apzc->GetCurrentAsyncTransform());
gfx3DMatrix nontransientTransform = apzc->GetNontransientAsyncTransform();

View File

@ -1552,6 +1552,10 @@ void
CompositorOGL::Pause()
{
#ifdef MOZ_WIDGET_ANDROID
if (!gl() || gl()->IsDestroyed())
return;
// ReleaseSurface internally calls MakeCurrent.
gl()->ReleaseSurface();
#endif
}
@ -1560,6 +1564,10 @@ bool
CompositorOGL::Resume()
{
#ifdef MOZ_WIDGET_ANDROID
if (!gl() || gl()->IsDestroyed())
return false;
// RenewSurface internally calls MakeCurrent.
return gl()->RenewSurface();
#endif
return true;

View File

@ -18,8 +18,6 @@
#define SS2 0x4e
#define SS3 0x4f
using namespace mozilla;
class nsISO2022CNToUnicode : public nsBasicDecoderSupport
{
public:
@ -28,7 +26,8 @@ public:
mPlaneID(0),
mRunLength(0)
{
Telemetry::Accumulate(Telemetry::DECODER_INSTANTIATED_ISO2022CN, true);
mozilla::Telemetry::Accumulate(
mozilla::Telemetry::DECODER_INSTANTIATED_ISO2022CN, true);
}
virtual ~nsISO2022CNToUnicode() {}

View File

@ -7,8 +7,6 @@
#include "nsUCSupport.h"
#include "mozilla/Telemetry.h"
using namespace mozilla;
class nsShiftJISToUnicode : public nsBasicDecoderSupport
{
public:
@ -85,7 +83,8 @@ public:
mGB2312Decoder = nullptr;
mEUCKRDecoder = nullptr;
mISO88597Decoder = nullptr;
Telemetry::Accumulate(Telemetry::DECODER_INSTANTIATED_ISO2022JP, true);
mozilla::Telemetry::Accumulate(
mozilla::Telemetry::DECODER_INSTANTIATED_ISO2022JP, true);
}
virtual ~nsISO2022JPToUnicodeV2()
{

View File

@ -7,8 +7,6 @@
#include "nsUCSupport.h"
#include "mozilla/Telemetry.h"
using namespace mozilla;
class nsISO2022KRToUnicode : public nsBasicDecoderSupport
{
public:
@ -19,7 +17,8 @@ public:
mData = 0;
mEUCKRDecoder = nullptr;
mRunLength = 0;
Telemetry::Accumulate(Telemetry::DECODER_INSTANTIATED_ISO2022KR, true);
mozilla::Telemetry::Accumulate(
mozilla::Telemetry::DECODER_INSTANTIATED_ISO2022KR, true);
}
virtual ~nsISO2022KRToUnicode()

View File

@ -138,6 +138,7 @@ struct NullPtr
namespace gc {
struct Cell;
struct PersistentRootedMarker;
} /* namespace gc */
} /* namespace js */
@ -1098,7 +1099,6 @@ MutableHandle<T>::MutableHandle(PersistentRooted<T> *root)
ptr = root->address();
}
/*
* A copyable, assignable global GC root type with arbitrary lifetime, an
* infallible constructor, and automatic unrooting on destruction.
@ -1132,9 +1132,10 @@ MutableHandle<T>::MutableHandle(PersistentRooted<T> *root)
* marked when the object itself is marked.
*/
template<typename T>
class PersistentRooted : public mozilla::LinkedListElement<PersistentRooted<T> > {
typedef mozilla::LinkedList<PersistentRooted> List;
typedef mozilla::LinkedListElement<PersistentRooted> Element;
class PersistentRooted : private mozilla::LinkedListElement<PersistentRooted<T> > {
friend class mozilla::LinkedList<PersistentRooted>;
friend class mozilla::LinkedListElement<PersistentRooted>;
friend class js::gc::PersistentRootedMarker;
void registerWithRuntime(JSRuntime *rt) {
JS::shadow::Runtime *srt = JS::shadow::Runtime::asShadowRuntime(rt);

View File

@ -1137,12 +1137,14 @@ if test "$GNU_CC"; then
# -Wpointer-arith - good to have
# -Wdeclaration-after-statement - MSVC doesn't like these
# -Werror=return-type - catches missing returns, zero false positives
# -Werror=int-to-pointer-cast - catches cast to pointer from integer of different size
# -Wtype-limits - catches overflow bugs, few false positives
# -Wempty-body - catches bugs, e.g. "if (c); foo();", few false positives
# -Wsign-compare - catches comparison of signed and unsigned types
#
_WARNINGS_CFLAGS="${_WARNINGS_CFLAGS} -Wall -Wpointer-arith -Wdeclaration-after-statement"
MOZ_C_SUPPORTS_WARNING(-W, error=return-type, ac_c_has_werror_return_type)
MOZ_C_SUPPORTS_WARNING(-W, error=int-to-pointer-cast, ac_c_has_werror_int_to_pointer_cast)
MOZ_C_SUPPORTS_WARNING(-W, empty-body, ac_c_has_wempty_body)
MOZ_C_SUPPORTS_WARNING(-W, sign-compare, ac_c_has_sign_compare)
@ -1196,6 +1198,7 @@ if test "$GNU_CXX"; then
# -Wpointer-arith - good to have
# -Woverloaded-virtual - ???
# -Werror=return-type - catches missing returns, zero false positives
# -Werror=int-to-pointer-cast - catches cast to pointer from integer of different size
# -Wtype-limits - catches overflow bugs, few false positives
# -Wempty-body - catches bugs, e.g. "if (c); foo();", few false positives
# -Werror=conversion-null - catches conversions between NULL and non-pointer types
@ -1203,6 +1206,7 @@ if test "$GNU_CXX"; then
#
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wall -Wpointer-arith -Woverloaded-virtual"
MOZ_CXX_SUPPORTS_WARNING(-W, error=return-type, ac_cxx_has_werror_return_type)
MOZ_CXX_SUPPORTS_WARNING(-W, error=int-to-pointer-cast, ac_cxx_has_werror_int_to_pointer_cast)
MOZ_CXX_SUPPORTS_WARNING(-W, type-limits, ac_cxx_has_wtype_limits)
MOZ_CXX_SUPPORTS_WARNING(-W, empty-body, ac_cxx_has_wempty_body)
MOZ_CXX_SUPPORTS_WARNING(-W, error=conversion-null, ac_cxx_has_werror_conversion_null)
@ -3820,8 +3824,14 @@ else
else
echo '#include <stdio.h>' > dummy-hello.c
changequote(,)
CL_INCLUDES_PREFIX=`${CC} -showIncludes -c -Fonul dummy-hello.c 2>&1 | sed -ne 's/^\([^:]*:[^:]*:\).*stdio.h$/\1/p'`
dnl This output is localized, split at the first double space or colon and space.
_CL_PREFIX_REGEX="^\([^:]*:.*[ :] \)\(.*stdio.h\)$"
CL_INCLUDES_PREFIX=`${CC} -showIncludes -c -Fonul dummy-hello.c 2>&1 | sed -ne 's/'"$_CL_PREFIX_REGEX"'/\1/p'`
_CL_STDIO_PATH=`${CC} -showIncludes -c -Fonul dummy-hello.c 2>&1 | sed -ne 's/'"$_CL_PREFIX_REGEX"'/\2/p'`
changequote([,])
if ! test -e "$_CL_STDIO_PATH"; then
AC_MSG_ERROR([Unable to parse cl -showIncludes prefix. This compiler's locale has an unsupported formatting.])
fi
if test -z "$CL_INCLUDES_PREFIX"; then
AC_MSG_ERROR([Cannot find cl -showIncludes prefix.])
fi

View File

@ -618,21 +618,35 @@ JSPropertyDescriptor::trace(JSTracer *trc)
}
}
// Mark a chain of PersistentRooted pointers that might be null.
template<typename Referent>
static void
MarkPersistentRootedChain(JSTracer *trc,
mozilla::LinkedList<PersistentRooted<Referent *> > &list,
void (*marker)(JSTracer *trc, Referent **ref, const char *name),
const char *name)
namespace js {
namespace gc {
struct PersistentRootedMarker
{
for (PersistentRooted<Referent *> *r = list.getFirst();
r != nullptr;
r = r->getNext())
template<typename Referent>
static void
markChainIfNotNull(JSTracer *trc,
mozilla::LinkedList<PersistentRooted<Referent *> > &list,
void (*marker)(JSTracer *trc, Referent **ref, const char *name),
const char *name)
{
if (r->get())
for (PersistentRooted<Referent *> *r = list.getFirst(); r; r = r->getNext()) {
if (r->get())
marker(trc, r->address(), name);
}
}
template<typename Referent>
static void
markChain(JSTracer *trc,
mozilla::LinkedList<PersistentRooted<Referent> > &list,
void (*marker)(JSTracer *trc, Referent *ref, const char *name),
const char *name)
{
for (PersistentRooted<Referent> *r = list.getFirst(); r; r = r->getNext())
marker(trc, r->address(), name);
}
};
}
}
void
@ -640,20 +654,21 @@ js::gc::MarkPersistentRootedChains(JSTracer *trc)
{
JSRuntime *rt = trc->runtime;
MarkPersistentRootedChain(trc, rt->functionPersistentRooteds, &MarkObjectRoot,
"PersistentRooted<JSFunction *>");
MarkPersistentRootedChain(trc, rt->objectPersistentRooteds, &MarkObjectRoot,
"PersistentRooted<JSObject *>");
MarkPersistentRootedChain(trc, rt->scriptPersistentRooteds, &MarkScriptRoot,
"PersistentRooted<JSScript *>");
MarkPersistentRootedChain(trc, rt->stringPersistentRooteds, &MarkStringRoot,
"PersistentRooted<JSString *>");
// Mark the PersistentRooted chains of types that may be null.
PersistentRootedMarker::markChainIfNotNull(trc, rt->functionPersistentRooteds, &MarkObjectRoot,
"PersistentRooted<JSFunction *>");
PersistentRootedMarker::markChainIfNotNull(trc, rt->objectPersistentRooteds, &MarkObjectRoot,
"PersistentRooted<JSObject *>");
PersistentRootedMarker::markChainIfNotNull(trc, rt->scriptPersistentRooteds, &MarkScriptRoot,
"PersistentRooted<JSScript *>");
PersistentRootedMarker::markChainIfNotNull(trc, rt->stringPersistentRooteds, &MarkStringRoot,
"PersistentRooted<JSString *>");
// Mark the PersistentRooted chains of types that are never null.
for (JS::PersistentRootedId *r = rt->idPersistentRooteds.getFirst(); r != nullptr; r = r->getNext())
MarkIdRoot(trc, r->address(), "PersistentRooted<jsid>");
for (JS::PersistentRootedValue *r = rt->valuePersistentRooteds.getFirst(); r != nullptr; r = r->getNext())
MarkValueRoot(trc, r->address(), "PersistentRooted<Value>");
PersistentRootedMarker::markChain(trc, rt->idPersistentRooteds, &MarkIdRoot,
"PersistentRooted<jsid>");
PersistentRootedMarker::markChain(trc, rt->valuePersistentRooteds, &MarkValueRoot,
"PersistentRooted<Value>");
}
void

View File

@ -87,17 +87,13 @@ class StoreBuffer
* type of edge: e.g. Value or Cell*.
*/
template<typename T>
class MonoTypeBuffer
struct MonoTypeBuffer
{
friend class StoreBuffer;
LifoAlloc *storage_;
explicit MonoTypeBuffer() : storage_(nullptr) {}
~MonoTypeBuffer() { js_delete(storage_); }
MonoTypeBuffer &operator=(const MonoTypeBuffer& other) MOZ_DELETE;
bool init() {
if (!storage_)
storage_ = js_new<LifoAlloc>(LifoAllocBlockSize);
@ -142,6 +138,9 @@ class StoreBuffer
/* Mark the source of all edges in the store buffer. */
void mark(StoreBuffer *owner, JSTracer *trc);
private:
MonoTypeBuffer &operator=(const MonoTypeBuffer& other) MOZ_DELETE;
};
/*
@ -149,10 +148,8 @@ class StoreBuffer
* memory outside of the GC's control.
*/
template <typename T>
class RelocatableMonoTypeBuffer : public MonoTypeBuffer<T>
struct RelocatableMonoTypeBuffer : public MonoTypeBuffer<T>
{
friend class StoreBuffer;
/* Override compaction to filter out removed items. */
void compactMoved(StoreBuffer *owner);
virtual void compact(StoreBuffer *owner) MOZ_OVERRIDE;
@ -163,17 +160,13 @@ class StoreBuffer
}
};
class GenericBuffer
struct GenericBuffer
{
friend class StoreBuffer;
LifoAlloc *storage_;
explicit GenericBuffer() : storage_(nullptr) {}
~GenericBuffer() { js_delete(storage_); }
GenericBuffer &operator=(const GenericBuffer& other) MOZ_DELETE;
bool init() {
if (!storage_)
storage_ = js_new<LifoAlloc>(LifoAllocBlockSize);
@ -215,14 +208,13 @@ class StoreBuffer
if (isAboutToOverflow())
owner->setAboutToOverflow();
}
private:
GenericBuffer &operator=(const GenericBuffer& other) MOZ_DELETE;
};
class CellPtrEdge
struct CellPtrEdge
{
friend class StoreBuffer;
friend class StoreBuffer::MonoTypeBuffer<CellPtrEdge>;
friend class StoreBuffer::RelocatableMonoTypeBuffer<CellPtrEdge>;
Cell **edge;
explicit CellPtrEdge(Cell **v) : edge(v) {}
@ -246,12 +238,8 @@ class StoreBuffer
bool isTagged() const { return bool(uintptr_t(edge) & 1); }
};
class ValueEdge
struct ValueEdge
{
friend class StoreBuffer;
friend class StoreBuffer::MonoTypeBuffer<ValueEdge>;
friend class StoreBuffer::RelocatableMonoTypeBuffer<ValueEdge>;
JS::Value *edge;
explicit ValueEdge(JS::Value *v) : edge(v) {}
@ -278,9 +266,6 @@ class StoreBuffer
struct SlotEdge
{
friend class StoreBuffer;
friend class StoreBuffer::MonoTypeBuffer<SlotEdge>;
JSObject *object;
uint32_t offset;
int kind; // this is really just HeapSlot::Kind, but we can't see that type easily here
@ -307,11 +292,8 @@ class StoreBuffer
void mark(JSTracer *trc);
};
class WholeCellEdges
struct WholeCellEdges
{
friend class StoreBuffer;
friend class StoreBuffer::MonoTypeBuffer<WholeCellEdges>;
Cell *tenured;
WholeCellEdges(Cell *cell) : tenured(cell) {
@ -332,9 +314,8 @@ class StoreBuffer
};
template <typename Key>
class CallbackRef : public BufferableRef
struct CallbackRef : public BufferableRef
{
public:
typedef void (*MarkCallback)(JSTracer *trc, Key *key, void *data);
CallbackRef(MarkCallback cb, Key *k, void *d) : callback(cb), key(k), data(d) {}

View File

@ -789,7 +789,7 @@ CodeGenerator::visitRegExpTest(LRegExpTest *lir)
}
typedef JSString *(*RegExpReplaceFn)(JSContext *, HandleString, HandleObject, HandleString);
static const VMFunction RegExpReplaceInfo = FunctionInfo<RegExpReplaceFn>(regexp_replace);
static const VMFunction RegExpReplaceInfo = FunctionInfo<RegExpReplaceFn>(RegExpReplace);
bool
CodeGenerator::visitRegExpReplace(LRegExpReplace *lir)
@ -799,7 +799,7 @@ CodeGenerator::visitRegExpReplace(LRegExpReplace *lir)
else
pushArg(ToRegister(lir->replacement()));
pushArg(ToRegister(lir->regexp()));
pushArg(ToRegister(lir->pattern()));
if (lir->string()->isConstant())
pushArg(ImmGCPtr(lir->string()->toConstant()->toString()));
@ -809,6 +809,31 @@ CodeGenerator::visitRegExpReplace(LRegExpReplace *lir)
return callVM(RegExpReplaceInfo, lir);
}
typedef JSString *(*StringReplaceFn)(JSContext *, HandleString, HandleString, HandleString);
static const VMFunction StringReplaceInfo = FunctionInfo<StringReplaceFn>(StringReplace);
bool
CodeGenerator::visitStringReplace(LStringReplace *lir)
{
if (lir->replacement()->isConstant())
pushArg(ImmGCPtr(lir->replacement()->toConstant()->toString()));
else
pushArg(ToRegister(lir->replacement()));
if (lir->pattern()->isConstant())
pushArg(ImmGCPtr(lir->pattern()->toConstant()->toString()));
else
pushArg(ToRegister(lir->pattern()));
if (lir->string()->isConstant())
pushArg(ImmGCPtr(lir->string()->toConstant()->toString()));
else
pushArg(ToRegister(lir->string()));
return callVM(StringReplaceInfo, lir);
}
typedef JSObject *(*LambdaFn)(JSContext *, HandleFunction, HandleObject);
static const VMFunction LambdaInfo =
FunctionInfo<LambdaFn>(js::Lambda);

View File

@ -93,6 +93,7 @@ class CodeGenerator : public CodeGeneratorSpecific
bool visitRegExpExec(LRegExpExec *lir);
bool visitRegExpTest(LRegExpTest *lir);
bool visitRegExpReplace(LRegExpReplace *lir);
bool visitStringReplace(LStringReplace *lir);
bool visitLambda(LLambda *lir);
bool visitLambdaForSingleton(LLambdaForSingleton *lir);
bool visitLambdaPar(LLambdaPar *lir);

View File

@ -11,8 +11,8 @@
#include "jsscriptinlines.h"
using namespace js;
using namespace jit;
namespace js {
namespace jit {
inline RegExpObject *
CompileInfo::getRegExp(jsbytecode *pc) const
@ -26,4 +26,7 @@ CompileInfo::getFunction(jsbytecode *pc) const
return script_->getFunction(GET_UINT32_INDEX(pc));
}
} // namespace jit
} // namespace js
#endif /* jit_CompileInfo_inl_h */

View File

@ -629,7 +629,7 @@ class IonBuilder : public MIRGenerator
InliningStatus inlineStrCharCodeAt(CallInfo &callInfo);
InliningStatus inlineStrFromCharCode(CallInfo &callInfo);
InliningStatus inlineStrCharAt(CallInfo &callInfo);
InliningStatus inlineStrReplaceRegExp(CallInfo &callInfo);
InliningStatus inlineStrReplace(CallInfo &callInfo);
// RegExp natives.
InliningStatus inlineRegExpExec(CallInfo &callInfo);

View File

@ -3246,34 +3246,61 @@ class LRegExpTest : public LCallInstructionHelper<1, 2, 0>
}
};
class LRegExpReplace : public LCallInstructionHelper<1, 3, 0>
class LStrReplace : public LCallInstructionHelper<1, 3, 0>
{
public:
LIR_HEADER(RegExpReplace)
LRegExpReplace(const LAllocation &string, const LAllocation &regexp,
LStrReplace(const LAllocation &string, const LAllocation &pattern,
const LAllocation &replacement)
{
setOperand(0, string);
setOperand(1, regexp);
setOperand(1, pattern);
setOperand(2, replacement);
}
const LAllocation *string() {
return getOperand(0);
}
const LAllocation *regexp() {
const LAllocation *pattern() {
return getOperand(1);
}
const LAllocation *replacement() {
return getOperand(2);
}
};
class LRegExpReplace: public LStrReplace
{
public:
LIR_HEADER(RegExpReplace);
LRegExpReplace(const LAllocation &string, const LAllocation &pattern,
const LAllocation &replacement)
: LStrReplace(string, pattern, replacement)
{
}
const MRegExpReplace *mir() const {
return mir_->toRegExpReplace();
}
};
class LStringReplace: public LStrReplace
{
public:
LIR_HEADER(StringReplace);
LStringReplace(const LAllocation &string, const LAllocation &pattern,
const LAllocation &replacement)
: LStrReplace(string, pattern, replacement)
{
}
const MStringReplace *mir() const {
return mir_->toStringReplace();
}
};
class LLambdaForSingleton : public LCallInstructionHelper<1, 1, 0>
{
public:

View File

@ -152,6 +152,7 @@
_(RegExpExec) \
_(RegExpTest) \
_(RegExpReplace) \
_(StringReplace) \
_(Lambda) \
_(LambdaForSingleton) \
_(LambdaPar) \

View File

@ -1939,12 +1939,25 @@ LIRGenerator::visitRegExpTest(MRegExpTest *ins)
bool
LIRGenerator::visitRegExpReplace(MRegExpReplace *ins)
{
JS_ASSERT(ins->regexp()->type() == MIRType_Object);
JS_ASSERT(ins->pattern()->type() == MIRType_Object);
JS_ASSERT(ins->string()->type() == MIRType_String);
JS_ASSERT(ins->replacement()->type() == MIRType_String);
LRegExpReplace *lir = new(alloc()) LRegExpReplace(useRegisterOrConstantAtStart(ins->string()),
useRegisterAtStart(ins->regexp()),
useRegisterAtStart(ins->pattern()),
useRegisterOrConstantAtStart(ins->replacement()));
return defineReturn(lir, ins) && assignSafepoint(lir, ins);
}
bool
LIRGenerator::visitStringReplace(MStringReplace *ins)
{
JS_ASSERT(ins->pattern()->type() == MIRType_String);
JS_ASSERT(ins->string()->type() == MIRType_String);
JS_ASSERT(ins->replacement()->type() == MIRType_String);
LStringReplace *lir = new(alloc()) LStringReplace(useRegisterOrConstantAtStart(ins->string()),
useRegisterAtStart(ins->pattern()),
useRegisterOrConstantAtStart(ins->replacement()));
return defineReturn(lir, ins) && assignSafepoint(lir, ins);
}

View File

@ -148,6 +148,7 @@ class LIRGenerator : public LIRGeneratorSpecific
bool visitRegExpExec(MRegExpExec *ins);
bool visitRegExpTest(MRegExpTest *ins);
bool visitRegExpReplace(MRegExpReplace *ins);
bool visitStringReplace(MStringReplace *ins);
bool visitLambda(MLambda *ins);
bool visitLambdaPar(MLambdaPar *ins);
bool visitImplicitThis(MImplicitThis *ins);

View File

@ -120,7 +120,7 @@ IonBuilder::inlineNativeCall(CallInfo &callInfo, JSNative native)
if (native == js_str_charAt)
return inlineStrCharAt(callInfo);
if (native == str_replace)
return inlineStrReplaceRegExp(callInfo);
return inlineStrReplace(callInfo);
// RegExp natives.
if (native == regexp_exec && CallResultEscapes(pc))
@ -1178,7 +1178,7 @@ IonBuilder::inlineRegExpTest(CallInfo &callInfo)
}
IonBuilder::InliningStatus
IonBuilder::inlineStrReplaceRegExp(CallInfo &callInfo)
IonBuilder::inlineStrReplace(CallInfo &callInfo)
{
if (callInfo.argc() != 2 || callInfo.constructing())
return InliningStatus_NotInlined;
@ -1194,7 +1194,7 @@ IonBuilder::inlineStrReplaceRegExp(CallInfo &callInfo)
// Arg 0: RegExp.
types::TemporaryTypeSet *arg0Type = callInfo.getArg(0)->resultTypeSet();
const Class *clasp = arg0Type ? arg0Type->getKnownClass() : nullptr;
if (clasp != &RegExpObject::class_)
if (clasp != &RegExpObject::class_ && callInfo.getArg(0)->type() != MIRType_String)
return InliningStatus_NotInlined;
// Arg 1: String.
@ -1203,13 +1203,18 @@ IonBuilder::inlineStrReplaceRegExp(CallInfo &callInfo)
callInfo.setImplicitlyUsedUnchecked();
MInstruction *cte = MRegExpReplace::New(alloc(), callInfo.thisArg(), callInfo.getArg(0),
callInfo.getArg(1));
MInstruction *cte;
if (callInfo.getArg(0)->type() == MIRType_String) {
cte = MStringReplace::New(alloc(), callInfo.thisArg(), callInfo.getArg(0),
callInfo.getArg(1));
} else {
cte = MRegExpReplace::New(alloc(), callInfo.thisArg(), callInfo.getArg(0),
callInfo.getArg(1));
}
current->add(cte);
current->push(cte);
if (!resumeAfter(cte))
if (cte->isEffectful() && !resumeAfter(cte))
return InliningStatus_Error;
return InliningStatus_Inlined;
}

View File

@ -4885,29 +4885,26 @@ class MRegExpTest
}
};
class MRegExpReplace
template <class Policy1>
class MStrReplace
: public MTernaryInstruction,
public Mix3Policy<StringPolicy<0>, ObjectPolicy<1>, StringPolicy<2> >
public Mix3Policy<StringPolicy<0>, Policy1, StringPolicy<2> >
{
private:
protected:
MRegExpReplace(MDefinition *string, MDefinition *regexp, MDefinition *replacement)
: MTernaryInstruction(string, regexp, replacement)
MStrReplace(MDefinition *string, MDefinition *pattern, MDefinition *replacement)
: MTernaryInstruction(string, pattern, replacement)
{
setMovable();
setResultType(MIRType_String);
}
public:
INSTRUCTION_HEADER(RegExpReplace)
static MRegExpReplace *New(TempAllocator &alloc, MDefinition *string, MDefinition *regexp, MDefinition *replacement) {
return new(alloc) MRegExpReplace(string, regexp, replacement);
}
MDefinition *string() const {
return getOperand(0);
}
MDefinition *regexp() const {
MDefinition *pattern() const {
return getOperand(1);
}
MDefinition *replacement() const {
@ -4923,6 +4920,46 @@ class MRegExpReplace
}
};
class MRegExpReplace
: public MStrReplace< ObjectPolicy<1> >
{
private:
MRegExpReplace(MDefinition *string, MDefinition *pattern, MDefinition *replacement)
: MStrReplace< ObjectPolicy<1> >(string, pattern, replacement)
{
}
public:
INSTRUCTION_HEADER(RegExpReplace);
static MRegExpReplace *New(TempAllocator &alloc, MDefinition *string, MDefinition *pattern, MDefinition *replacement) {
return new(alloc) MRegExpReplace(string, pattern, replacement);
}
};
class MStringReplace
: public MStrReplace< StringPolicy<1> >
{
private:
MStringReplace(MDefinition *string, MDefinition *pattern, MDefinition *replacement)
: MStrReplace< StringPolicy<1> >(string, pattern, replacement)
{
}
public:
INSTRUCTION_HEADER(StringReplace);
static MStringReplace *New(TempAllocator &alloc, MDefinition *string, MDefinition *pattern, MDefinition *replacement) {
return new(alloc) MStringReplace(string, pattern, replacement);
}
AliasSet getAliasSet() const {
return AliasSet::None();
}
};
struct LambdaFunctionInfo
{
// The functions used in lambdas are the canonical original function in

View File

@ -101,6 +101,7 @@ namespace jit {
_(RegExpExec) \
_(RegExpTest) \
_(RegExpReplace) \
_(StringReplace) \
_(Lambda) \
_(ImplicitThis) \
_(Slots) \

View File

@ -281,6 +281,7 @@ class ParallelSafetyVisitor : public MInstructionVisitor
UNSAFE_OP(RegExpTest)
UNSAFE_OP(RegExpExec)
UNSAFE_OP(RegExpReplace)
UNSAFE_OP(StringReplace)
UNSAFE_OP(CallInstanceOf)
UNSAFE_OP(FunctionBoundary)
UNSAFE_OP(GuardString)

View File

@ -914,10 +914,10 @@ JSObject *CreateDerivedTypedObj(JSContext *cx, HandleObject type,
}
JSString *
regexp_replace(JSContext *cx, HandleString string, HandleObject regexp, HandleString repl)
RegExpReplace(JSContext *cx, HandleString string, HandleObject regexp, HandleString repl)
{
JS_ASSERT(!!string);
JS_ASSERT(!!repl);
JS_ASSERT(string);
JS_ASSERT(repl);
RootedValue rval(cx);
if (!str_replace_regexp_raw(cx, string, regexp, repl, &rval))
@ -926,6 +926,20 @@ regexp_replace(JSContext *cx, HandleString string, HandleObject regexp, HandleSt
return rval.toString();
}
JSString *
StringReplace(JSContext *cx, HandleString string, HandleString pattern, HandleString repl)
{
JS_ASSERT(string);
JS_ASSERT(pattern);
JS_ASSERT(repl);
RootedValue rval(cx);
if (!str_replace_string_raw(cx, string, pattern, repl, &rval))
return nullptr;
return rval.toString();
}
bool
Recompile(JSContext *cx)
{

View File

@ -663,8 +663,10 @@ JSObject *CreateDerivedTypedObj(JSContext *cx, HandleObject type,
HandleObject owner, int32_t offset);
bool Recompile(JSContext *cx);
JSString *regexp_replace(JSContext *cx, HandleString string, HandleObject regexp,
HandleString repl);
JSString *RegExpReplace(JSContext *cx, HandleString string, HandleObject regexp,
HandleString repl);
JSString *StringReplace(JSContext *cx, HandleString string, HandleString pattern,
HandleString repl);
#ifdef DEBUG
void AssertValidObjectPtr(JSContext *cx, JSObject *obj);

View File

@ -76,11 +76,12 @@ class BailoutStack
uintptr_t tableOffset_;
};
private:
protected: // Silence Clang warning about unused private fields.
mozilla::Array<double, FloatRegisters::Total> fpregs_;
mozilla::Array<uintptr_t, Registers::Total> regs_;
uintptr_t snapshotOffset_;
uintptr_t padding_;
public:
FrameSizeClass frameClass() const {
@ -109,6 +110,9 @@ class BailoutStack
}
};
// Make sure the compiler doesn't add extra padding.
static_assert((sizeof(BailoutStack) % 8) == 0, "BailoutStack should be 8-byte aligned.");
} // namespace jit
} // namespace js

View File

@ -281,8 +281,8 @@ bool
CodeGeneratorARM::visitOutOfLineBailout(OutOfLineBailout *ool)
{
masm.ma_mov(Imm32(ool->snapshot()->snapshotOffset()), ScratchRegister);
masm.ma_push(ScratchRegister);
masm.ma_push(ScratchRegister);
masm.ma_push(ScratchRegister); // BailoutStack::padding_
masm.ma_push(ScratchRegister); // BailoutStack::snapshotOffset_
masm.ma_b(&deoptLabel_);
return true;
}

View File

@ -765,9 +765,10 @@ JitRuntime::generateVMWrapper(JSContext *cx, const VMFunction &f)
// Test for failure.
switch (f.failType()) {
case Type_Object:
masm.branchTestPtr(Assembler::Zero, r0, r0, masm.failureLabel(f.executionMode));
break;
case Type_Bool:
// Called functions return bools, which are 0/false and non-zero/true
masm.branch32(Assembler::Equal, r0, Imm32(0), masm.failureLabel(f.executionMode));
masm.branchIfFalseBool(r0, masm.failureLabel(f.executionMode));
break;
default:
MOZ_ASSUME_UNREACHABLE("unknown failure kind");

View File

@ -2814,10 +2814,8 @@ JS_LookupPropertyWithFlags(JSContext *cx, HandleObject obj, const char *name, un
}
JS_PUBLIC_API(bool)
JS_HasPropertyById(JSContext *cx, JSObject *objArg, jsid idArg, bool *foundp)
JS_HasPropertyById(JSContext *cx, HandleObject obj, HandleId id, bool *foundp)
{
RootedObject obj(cx, objArg);
RootedId id(cx, idArg);
RootedObject obj2(cx);
RootedShape prop(cx);
bool ok = LookupPropertyById(cx, obj, id, 0, &obj2, &prop);
@ -2826,9 +2824,8 @@ JS_HasPropertyById(JSContext *cx, JSObject *objArg, jsid idArg, bool *foundp)
}
JS_PUBLIC_API(bool)
JS_HasElement(JSContext *cx, JSObject *objArg, uint32_t index, bool *foundp)
JS_HasElement(JSContext *cx, HandleObject obj, uint32_t index, bool *foundp)
{
RootedObject obj(cx, objArg);
AssertHeapIsIdle(cx);
CHECK_REQUEST(cx);
RootedId id(cx);
@ -2838,26 +2835,28 @@ JS_HasElement(JSContext *cx, JSObject *objArg, uint32_t index, bool *foundp)
}
JS_PUBLIC_API(bool)
JS_HasProperty(JSContext *cx, JSObject *objArg, const char *name, bool *foundp)
JS_HasProperty(JSContext *cx, HandleObject obj, const char *name, bool *foundp)
{
RootedObject obj(cx, objArg);
JSAtom *atom = Atomize(cx, name, strlen(name));
return atom && JS_HasPropertyById(cx, obj, AtomToId(atom), foundp);
if (!atom)
return false;
RootedId id(cx, AtomToId(atom));
return JS_HasPropertyById(cx, obj, id, foundp);
}
JS_PUBLIC_API(bool)
JS_HasUCProperty(JSContext *cx, JSObject *objArg, const jschar *name, size_t namelen, bool *foundp)
JS_HasUCProperty(JSContext *cx, HandleObject obj, const jschar *name, size_t namelen, bool *foundp)
{
RootedObject obj(cx, objArg);
JSAtom *atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
return atom && JS_HasPropertyById(cx, obj, AtomToId(atom), foundp);
if (!atom)
return false;
RootedId id(cx, AtomToId(atom));
return JS_HasPropertyById(cx, obj, id, foundp);
}
JS_PUBLIC_API(bool)
JS_AlreadyHasOwnPropertyById(JSContext *cx, JSObject *objArg, jsid id_, bool *foundp)
JS_AlreadyHasOwnPropertyById(JSContext *cx, HandleObject obj, HandleId id, bool *foundp)
{
RootedObject obj(cx, objArg);
RootedId id(cx, id_);
AssertHeapIsIdle(cx);
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj, id);
@ -2882,9 +2881,8 @@ JS_AlreadyHasOwnPropertyById(JSContext *cx, JSObject *objArg, jsid id_, bool *fo
}
JS_PUBLIC_API(bool)
JS_AlreadyHasOwnElement(JSContext *cx, JSObject *objArg, uint32_t index, bool *foundp)
JS_AlreadyHasOwnElement(JSContext *cx, HandleObject obj, uint32_t index, bool *foundp)
{
RootedObject obj(cx, objArg);
AssertHeapIsIdle(cx);
CHECK_REQUEST(cx);
RootedId id(cx);
@ -2894,20 +2892,24 @@ JS_AlreadyHasOwnElement(JSContext *cx, JSObject *objArg, uint32_t index, bool *f
}
JS_PUBLIC_API(bool)
JS_AlreadyHasOwnProperty(JSContext *cx, JSObject *objArg, const char *name, bool *foundp)
JS_AlreadyHasOwnProperty(JSContext *cx, HandleObject obj, const char *name, bool *foundp)
{
RootedObject obj(cx, objArg);
JSAtom *atom = Atomize(cx, name, strlen(name));
return atom && JS_AlreadyHasOwnPropertyById(cx, obj, AtomToId(atom), foundp);
if (!atom)
return false;
RootedId id(cx, AtomToId(atom));
return JS_AlreadyHasOwnPropertyById(cx, obj, id, foundp);
}
JS_PUBLIC_API(bool)
JS_AlreadyHasOwnUCProperty(JSContext *cx, JSObject *objArg, const jschar *name, size_t namelen,
JS_AlreadyHasOwnUCProperty(JSContext *cx, HandleObject obj, const jschar *name, size_t namelen,
bool *foundp)
{
RootedObject obj(cx, objArg);
JSAtom *atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
return atom && JS_AlreadyHasOwnPropertyById(cx, obj, AtomToId(atom), foundp);
if (!atom)
return false;
RootedId id(cx, AtomToId(atom));
return JS_AlreadyHasOwnPropertyById(cx, obj, id, foundp);
}
/* Wrapper functions to create wrappers with no corresponding JSJitInfo from API
@ -3457,9 +3459,8 @@ JS_SetUCProperty(JSContext *cx, JSObject *objArg, const jschar *name, size_t nam
}
JS_PUBLIC_API(bool)
JS_DeletePropertyById2(JSContext *cx, JSObject *objArg, jsid id, bool *result)
JS_DeletePropertyById2(JSContext *cx, HandleObject obj, HandleId id, bool *result)
{
RootedObject obj(cx, objArg);
AssertHeapIsIdle(cx);
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj, id);
@ -3473,9 +3474,8 @@ JS_DeletePropertyById2(JSContext *cx, JSObject *objArg, jsid id, bool *result)
}
JS_PUBLIC_API(bool)
JS_DeleteElement2(JSContext *cx, JSObject *objArg, uint32_t index, bool *result)
JS_DeleteElement2(JSContext *cx, HandleObject obj, uint32_t index, bool *result)
{
RootedObject obj(cx, objArg);
AssertHeapIsIdle(cx);
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj);
@ -3485,9 +3485,8 @@ JS_DeleteElement2(JSContext *cx, JSObject *objArg, uint32_t index, bool *result)
}
JS_PUBLIC_API(bool)
JS_DeleteProperty2(JSContext *cx, JSObject *objArg, const char *name, bool *result)
JS_DeleteProperty2(JSContext *cx, HandleObject obj, const char *name, bool *result)
{
RootedObject obj(cx, objArg);
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj);
JSAutoResolveFlags rf(cx, 0);
@ -3514,24 +3513,24 @@ JS_DeleteUCProperty2(JSContext *cx, JSObject *objArg, const jschar *name, size_t
}
JS_PUBLIC_API(bool)
JS_DeletePropertyById(JSContext *cx, JSObject *objArg, jsid idArg)
JS_DeletePropertyById(JSContext *cx, HandleObject obj, HandleId id)
{
bool junk;
return JS_DeletePropertyById2(cx, objArg, idArg, &junk);
return JS_DeletePropertyById2(cx, obj, id, &junk);
}
JS_PUBLIC_API(bool)
JS_DeleteElement(JSContext *cx, JSObject *objArg, uint32_t index)
JS_DeleteElement(JSContext *cx, HandleObject obj, uint32_t index)
{
bool junk;
return JS_DeleteElement2(cx, objArg, index, &junk);
return JS_DeleteElement2(cx, obj, index, &junk);
}
JS_PUBLIC_API(bool)
JS_DeleteProperty(JSContext *cx, JSObject *objArg, const char *name)
JS_DeleteProperty(JSContext *cx, HandleObject obj, const char *name)
{
bool junk;
return JS_DeleteProperty2(cx, objArg, name, &junk);
return JS_DeleteProperty2(cx, obj, name, &junk);
}
static Shape *

View File

@ -2787,18 +2787,18 @@ JS_DefinePropertyWithTinyId(JSContext *cx, JSObject *obj, const char *name,
unsigned attrs);
extern JS_PUBLIC_API(bool)
JS_AlreadyHasOwnProperty(JSContext *cx, JSObject *obj, const char *name,
JS_AlreadyHasOwnProperty(JSContext *cx, JS::HandleObject obj, const char *name,
bool *foundp);
extern JS_PUBLIC_API(bool)
JS_AlreadyHasOwnPropertyById(JSContext *cx, JSObject *obj, jsid id,
JS_AlreadyHasOwnPropertyById(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
bool *foundp);
extern JS_PUBLIC_API(bool)
JS_HasProperty(JSContext *cx, JSObject *obj, const char *name, bool *foundp);
JS_HasProperty(JSContext *cx, JS::HandleObject obj, const char *name, bool *foundp);
extern JS_PUBLIC_API(bool)
JS_HasPropertyById(JSContext *cx, JSObject *obj, jsid id, bool *foundp);
JS_HasPropertyById(JSContext *cx, JS::HandleObject obj, JS::HandleId id, bool *foundp);
extern JS_PUBLIC_API(bool)
JS_LookupProperty(JSContext *cx, JSObject *obj, const char *name, JS::MutableHandleValue vp);
@ -3001,16 +3001,16 @@ extern JS_PUBLIC_API(bool)
JS_SetPropertyById(JSContext *cx, JSObject *obj, jsid id, JS::HandleValue v);
extern JS_PUBLIC_API(bool)
JS_DeleteProperty(JSContext *cx, JSObject *obj, const char *name);
JS_DeleteProperty(JSContext *cx, JS::HandleObject obj, const char *name);
extern JS_PUBLIC_API(bool)
JS_DeleteProperty2(JSContext *cx, JSObject *obj, const char *name, bool *succeeded);
JS_DeleteProperty2(JSContext *cx, JS::HandleObject obj, const char *name, bool *succeeded);
extern JS_PUBLIC_API(bool)
JS_DeletePropertyById(JSContext *cx, JSObject *obj, jsid id);
JS_DeletePropertyById(JSContext *cx, JS::HandleObject obj, jsid id);
extern JS_PUBLIC_API(bool)
JS_DeletePropertyById2(JSContext *cx, JSObject *obj, jsid id, bool *succeeded);
JS_DeletePropertyById2(JSContext *cx, JS::HandleObject obj, JS::HandleId id, bool *succeeded);
extern JS_PUBLIC_API(bool)
JS_DefineUCProperty(JSContext *cx, JSObject *obj,
@ -3026,11 +3026,11 @@ JS_DefineUCPropertyWithTinyId(JSContext *cx, JSObject *obj,
unsigned attrs);
extern JS_PUBLIC_API(bool)
JS_AlreadyHasOwnUCProperty(JSContext *cx, JSObject *obj, const jschar *name,
JS_AlreadyHasOwnUCProperty(JSContext *cx, JS::HandleObject obj, const jschar *name,
size_t namelen, bool *foundp);
extern JS_PUBLIC_API(bool)
JS_HasUCProperty(JSContext *cx, JSObject *obj,
JS_HasUCProperty(JSContext *cx, JS::HandleObject obj,
const jschar *name, size_t namelen,
bool *vp);
@ -3070,10 +3070,10 @@ JS_DefineElement(JSContext *cx, JSObject *obj, uint32_t index, jsval value,
JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs);
extern JS_PUBLIC_API(bool)
JS_AlreadyHasOwnElement(JSContext *cx, JSObject *obj, uint32_t index, bool *foundp);
JS_AlreadyHasOwnElement(JSContext *cx, JS::HandleObject obj, uint32_t index, bool *foundp);
extern JS_PUBLIC_API(bool)
JS_HasElement(JSContext *cx, JSObject *obj, uint32_t index, bool *foundp);
JS_HasElement(JSContext *cx, JS::HandleObject obj, uint32_t index, bool *foundp);
extern JS_PUBLIC_API(bool)
JS_LookupElement(JSContext *cx, JSObject *obj, uint32_t index, JS::MutableHandleValue vp);
@ -3089,10 +3089,10 @@ extern JS_PUBLIC_API(bool)
JS_SetElement(JSContext *cx, JSObject *obj, uint32_t index, JS::MutableHandleValue vp);
extern JS_PUBLIC_API(bool)
JS_DeleteElement(JSContext *cx, JSObject *obj, uint32_t index);
JS_DeleteElement(JSContext *cx, JS::HandleObject obj, uint32_t index);
extern JS_PUBLIC_API(bool)
JS_DeleteElement2(JSContext *cx, JSObject *obj, uint32_t index, bool *succeeded);
JS_DeleteElement2(JSContext *cx, JS::HandleObject obj, uint32_t index, bool *succeeded);
/*
* Remove all configurable properties from the given (non-global) object and

View File

@ -387,8 +387,10 @@ EnsureTrackPropertyTypes(JSContext *cx, JSObject *obj, jsid id)
cx->clearPendingException();
return;
}
if (!obj->type()->unknownProperties())
obj->type()->getProperty(cx, id);
if (!obj->type()->unknownProperties() && !obj->type()->getProperty(cx, id)) {
cx->compartment()->types.setPendingNukeTypes(cx);
return;
}
}
JS_ASSERT(obj->type()->unknownProperties() || TrackPropertyTypes(cx, obj, id));

View File

@ -447,22 +447,19 @@ js::XDRScript(XDRState<mode> *xdr, HandleObject enclosingScope, HandleScript enc
nconsts = nobjects = nregexps = ntrynotes = nblockscopes = 0;
/* XDR arguments and vars. */
uint16_t nargs = 0, nvars = 0;
uint32_t argsVars = 0;
uint16_t nargs = 0;
uint32_t nvars = 0;
if (mode == XDR_ENCODE) {
script = scriptp.get();
JS_ASSERT_IF(enclosingScript, enclosingScript->compartment() == script->compartment());
nargs = script->bindings.numArgs();
nvars = script->bindings.numVars();
argsVars = (nargs << 16) | nvars;
}
if (!xdr->codeUint32(&argsVars))
if (!xdr->codeUint16(&nargs))
return false;
if (!xdr->codeUint32(&nvars))
return false;
if (mode == XDR_DECODE) {
nargs = argsVars >> 16;
nvars = argsVars & 0xFFFF;
}
if (mode == XDR_ENCODE)
length = script->length();

View File

@ -1731,6 +1731,13 @@ class MOZ_STACK_CLASS StringRegExpGuard
return true;
}
bool init(JSContext *cx, HandleString pattern) {
fm.patstr = AtomizeString(cx, pattern);
if (!fm.patstr)
return false;
return true;
}
/*
* Attempt to match |patstr| to |textstr|. A flags argument, metachars in
* the pattern string, or a lengthy pattern string can thwart this process.
@ -2449,7 +2456,7 @@ ReplaceRegExp(JSContext *cx, RegExpStatics *res, ReplaceData &rdata)
static bool
BuildFlatReplacement(JSContext *cx, HandleString textstr, HandleString repstr,
const FlatMatch &fm, CallArgs *args)
const FlatMatch &fm, MutableHandleValue rval)
{
RopeBuilder builder(cx);
size_t match = fm.match();
@ -2521,7 +2528,7 @@ BuildFlatReplacement(JSContext *cx, HandleString textstr, HandleString repstr,
}
}
args->rval().setString(builder.result());
rval.setString(builder.result());
return true;
}
@ -2533,7 +2540,7 @@ BuildFlatReplacement(JSContext *cx, HandleString textstr, HandleString repstr,
*/
static inline bool
BuildDollarReplacement(JSContext *cx, JSString *textstrArg, JSLinearString *repstr,
const jschar *firstDollar, const FlatMatch &fm, CallArgs *args)
const jschar *firstDollar, const FlatMatch &fm, MutableHandleValue rval)
{
Rooted<JSLinearString*> textstr(cx, textstrArg->ensureLinear(cx));
if (!textstr)
@ -2605,7 +2612,7 @@ BuildDollarReplacement(JSContext *cx, JSString *textstrArg, JSLinearString *reps
builder.append(rightSide));
#undef ENSURE
args->rval().setString(builder.result());
rval.setString(builder.result());
return true;
}
@ -2860,11 +2867,47 @@ js::str_replace_regexp_raw(JSContext *cx, HandleString string, HandleObject rege
return StrReplaceRegExp(cx, rdata, rval);
}
static inline bool
StrReplaceString(JSContext *cx, ReplaceData &rdata, const FlatMatch &fm, MutableHandleValue rval)
{
/*
* Note: we could optimize the text.length == pattern.length case if we wanted,
* even in the presence of dollar metachars.
*/
if (rdata.dollar)
return BuildDollarReplacement(cx, rdata.str, rdata.repstr, rdata.dollar, fm, rval);
return BuildFlatReplacement(cx, rdata.str, rdata.repstr, fm, rval);
}
static const uint32_t ReplaceOptArg = 2;
bool
js::str_replace_string_raw(JSContext *cx, HandleString string, HandleString pattern,
HandleString replacement, MutableHandleValue rval)
{
ReplaceData rdata(cx);
rdata.str = string;
JSLinearString *repl = replacement->ensureLinear(cx);
if (!repl)
return false;
rdata.setReplacementString(repl);
if (!rdata.g.init(cx, pattern))
return false;
const FlatMatch *fm = rdata.g.tryFlatMatch(cx, rdata.str, ReplaceOptArg, ReplaceOptArg, false);
if (fm->match() < 0) {
rval.setString(string);
return true;
}
return StrReplaceString(cx, rdata, *fm, rval);
}
static inline bool
str_replace_flat_lambda(JSContext *cx, CallArgs outerArgs, ReplaceData &rdata, const FlatMatch &fm)
{
JS_ASSERT(fm.match() >= 0);
RootedString matchStr(cx, js_NewDependentString(cx, rdata.str, fm.match(), fm.patternLength()));
if (!matchStr)
return false;
@ -2911,8 +2954,6 @@ str_replace_flat_lambda(JSContext *cx, CallArgs outerArgs, ReplaceData &rdata, c
return true;
}
static const uint32_t ReplaceOptArg = 2;
/*
* Pattern match the script to check if it is is indexing into a particular
* object, e.g. 'function(a) { return b[a]; }'. Avoid calling the script in
@ -3017,6 +3058,7 @@ js::str_replace(JSContext *cx, unsigned argc, Value *vp)
*/
const FlatMatch *fm = rdata.g.tryFlatMatch(cx, rdata.str, ReplaceOptArg, args.length(), false);
if (!fm) {
if (cx->isExceptionPending()) /* oom in RopeMatch in tryFlatMatch */
return false;
@ -3030,15 +3072,7 @@ js::str_replace(JSContext *cx, unsigned argc, Value *vp)
if (rdata.lambda)
return str_replace_flat_lambda(cx, args, rdata, *fm);
/*
* Note: we could optimize the text.length == pattern.length case if we wanted,
* even in the presence of dollar metachars.
*/
if (rdata.dollar)
return BuildDollarReplacement(cx, rdata.str, rdata.repstr, rdata.dollar, *fm, &args);
return BuildFlatReplacement(cx, rdata.str, rdata.repstr, *fm, &args);
return StrReplaceString(cx, rdata, *fm, args.rval());
}
namespace {

View File

@ -370,6 +370,10 @@ bool
str_replace_regexp_raw(JSContext *cx, HandleString string, HandleObject regexp,
HandleString replacement, MutableHandleValue rval);
bool
str_replace_string_raw(JSContext *cx, HandleString string, HandleString pattern,
HandleString replacement, MutableHandleValue rval);
} /* namespace js */
extern bool

View File

@ -22,7 +22,7 @@ namespace js {
* and saved versions. If deserialization fails, the data should be
* invalidated if possible.
*/
static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - 163);
static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - 164);
class XDRBuffer {
public:

View File

@ -625,7 +625,8 @@ nsJSCID::NewID(const char* str)
NS_ENSURE_TRUE(registrar, nullptr);
nsCID *cid;
NS_ENSURE_SUCCESS(registrar->ContractIDToCID(str, &cid), nullptr);
if (NS_FAILED(registrar->ContractIDToCID(str, &cid)))
return nullptr;
bool success = idObj->mDetails.InitWithName(*cid, str);
nsMemory::Free(cid);
if (!success)

View File

@ -193,27 +193,20 @@ def print_cpp_file(fd, conf):
if not c in conf.exclude_automatic_type_include:
fd.write("#include \"%s.h\"\n" % c)
fd.write("\nusing namespace mozilla::idl;\n\n")
fd.write("\n"
"using namespace mozilla::idl;\n"
"using namespace mozilla::dom;\n\n")
for a in attrnames:
fd.write("static jsid %s = JSID_VOID;\n"% get_jsid(a))
fd.write("static InternedStringId %s;\n" % get_jsid(a))
fd.write("\n"
"static bool\n"
"InternStaticJSVal(JSContext* aCx, jsid &id, const char* aString)\n"
"{\n"
" if (JSString* str = JS_InternString(aCx, aString)) {\n"
" id = INTERNED_STRING_TO_JSID(aCx, str);\n"
" return true;\n"
" }\n"
" return false;\n"
"}\n\n"
"bool\n"
"InternStaticDictionaryJSVals(JSContext* aCx)\n"
"{\n"
" return\n")
for a in attrnames:
fd.write(" InternStaticJSVal(aCx, %s, \"%s\") &&\n"
fd.write(" %s.init(aCx, \"%s\") &&\n"
% (get_jsid(a), a))
fd.write(" true;\n")

View File

@ -155,16 +155,23 @@
/*
* MOZ_ASAN_BLACKLIST is a macro to tell AddressSanitizer (a compile-time
* instrumentation shipped with Clang) to not instrument the annotated function.
* Furthermore, it will prevent the compiler from inlining the function because
* inlining currently breaks the blacklisting mechanism of AddressSanitizer.
* instrumentation shipped with Clang and GCC) to not instrument the annotated
* function. Furthermore, it will prevent the compiler from inlining the
* function because inlining currently breaks the blacklisting mechanism of
* AddressSanitizer.
*/
#if defined(__has_feature)
# if __has_feature(address_sanitizer)
# define MOZ_ASAN_BLACKLIST MOZ_NEVER_INLINE __attribute__((no_sanitize_address))
# else
# define MOZ_ASAN_BLACKLIST /* nothing */
# define MOZ_HAVE_ASAN_BLACKLIST
# endif
#elif defined(__GNUC__)
# if defined(__SANITIZE_ADDRESS__)
# define MOZ_HAVE_ASAN_BLACKLIST
# endif
#endif
#if defined(MOZ_HAVE_ASAN_BLACKLIST)
# define MOZ_ASAN_BLACKLIST MOZ_NEVER_INLINE __attribute__((no_sanitize_address))
#else
# define MOZ_ASAN_BLACKLIST /* nothing */
#endif

View File

@ -12,6 +12,8 @@ Cu.import("resource://gre/modules/Services.jsm")
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/AppsUtils.jsm");
const DEFAULT_ICON = "chrome://browser/skin/images/default-app-icon.png";
let gStrings = Services.strings.createBundle("chrome://browser/locale/aboutApps.properties");
XPCOMUtils.defineLazyGetter(window, "gChromeWin", function()
@ -39,6 +41,7 @@ function openLink(aEvent) {
} catch (ex) {}
}
#ifndef MOZ_ANDROID_SYNTHAPKS
var ContextMenus = {
target: null,
@ -58,8 +61,7 @@ var ContextMenus = {
addToHomescreen: function() {
let manifest = this.target.manifest;
let origin = Services.io.newURI(this.target.app.origin, null, null);
gChromeWin.WebappsUI.createShortcut(manifest.name, manifest.fullLaunchPath(), gChromeWin.WebappsUI.getBiggestIcon(manifest.icons, origin), "webapp");
gChromeWin.WebappsUI.createShortcut(manifest.name, manifest.fullLaunchPath(), manifest.biggestIconURL || DEFAULT_ICON, "webapp");
this.target = null;
},
@ -77,15 +79,9 @@ var ContextMenus = {
this.target = null;
}
}
#endif
function onLoad(aEvent) {
try {
let formatter = Cc["@mozilla.org/toolkit/URLFormatterService;1"].getService(Ci.nsIURLFormatter);
let link = document.getElementById("marketplaceURL");
let url = formatter.formatURLPref(link.getAttribute("pref"));
link.setAttribute("href", url);
} catch (e) {}
let elmts = document.querySelectorAll("[pref]");
for (let i = 0; i < elmts.length; i++) {
elmts[i].addEventListener("click", openLink, false);
@ -95,7 +91,9 @@ function onLoad(aEvent) {
navigator.mozApps.mgmt.onuninstall = onUninstall;
updateList();
#ifndef MOZ_ANDROID_SYNTHAPKS
ContextMenus.init();
#endif
}
function updateList() {
@ -119,16 +117,21 @@ function addApplication(aApp) {
let container = document.createElement("div");
container.className = "app list-item";
#ifndef MOZ_ANDROID_SYNTHAPKS
container.setAttribute("contextmenu", "appmenu");
#endif
container.setAttribute("id", "app-" + aApp.origin);
container.setAttribute("mozApp", aApp.origin);
container.setAttribute("title", manifest.name);
let img = document.createElement("img");
let origin = Services.io.newURI(aApp.origin, null, null);
img.src = gChromeWin.WebappsUI.getBiggestIcon(manifest.icons, origin);
img.src = manifest.biggestIconURL || DEFAULT_ICON;
img.onerror = function() {
img.src = "chrome://browser/skin/images/default-app-icon.png";
// If the image failed to load, and it was not our default icon, attempt to
// use our default as a fallback.
if (img.src != DEFAULT_ICON) {
img.src = DEFAULT_ICON;
}
}
img.setAttribute("title", manifest.name);

View File

@ -29,11 +29,13 @@
<body dir="&locale.dir;">
#ifndef MOZ_ANDROID_SYNTHAPKS
<menu type="context" id="appmenu">
<menuitem id="addToHomescreenLabel" label="&aboutApps.addToHomescreen;"></menuitem>
<menuitem id="uninstallLabel" label="&aboutApps.uninstall;"></menuitem>
</menu>
#endif
<div class="header">
<div>&aboutApps.header;</div>
<div id="header-button" role="button" aria-label="&aboutApps.browseMarketplace;" pref="app.marketplaceURL"/>

View File

@ -418,9 +418,8 @@ var BrowserApp = {
this.isGuest = window.arguments[4];
}
let status = this.startupStatus();
if (pinned) {
this._initRuntime(status, url, aUrl => this.addTab(aUrl));
this._initRuntime(this._startupStatus, url, aUrl => this.addTab(aUrl));
} else {
SearchEngines.init();
this.initContextMenu();
@ -437,7 +436,7 @@ var BrowserApp = {
event.initEvent("UIReady", true, false);
window.dispatchEvent(event);
if (status)
if (this._startupStatus)
this.onAppUpdated();
// Store the low-precision buffer pref
@ -452,18 +451,22 @@ var BrowserApp = {
#endif
},
startupStatus: function() {
let savedmstone = null;
get _startupStatus() {
delete this._startupStatus;
let savedMilestone = null;
try {
savedmstone = Services.prefs.getCharPref("browser.startup.homepage_override.mstone");
savedMilestone = Services.prefs.getCharPref("browser.startup.homepage_override.mstone");
} catch (e) {
}
#expand let ourmstone = "__MOZ_APP_VERSION__";
if (ourmstone != savedmstone) {
Services.prefs.setCharPref("browser.startup.homepage_override.mstone", ourmstone);
return savedmstone ? "upgrade" : "new";
#expand let ourMilestone = "__MOZ_APP_VERSION__";
this._startupStatus = "";
if (ourMilestone != savedMilestone) {
Services.prefs.setCharPref("browser.startup.homepage_override.mstone", ourMilestone);
this._startupStatus = savedMilestone ? "upgrade" : "new";
}
return "";
return this._startupStatus;
},
/**
@ -916,8 +919,8 @@ var BrowserApp = {
#ifdef MOZ_ANDROID_SYNTHAPKS
_loadWebapp: function(aMessage) {
// TODO: figure out when (if ever) to pass "new" to the status parameter.
this._initRuntime("", aMessage.url, aUrl => {
this._initRuntime(this._startupStatus, aMessage.url, aUrl => {
this.manifestUrl = aMessage.url;
this.addTab(aUrl, { title: aMessage.name });
});
@ -7093,6 +7096,7 @@ var WebappsUI = {
Services.obs.removeObserver(this, "webapps-install-error");
},
DEFAULT_ICON: "chrome://browser/skin/images/default-app-icon.png",
DEFAULT_PREFS_FILENAME: "default-prefs.js",
observe: function observe(aSubject, aTopic, aData) {
@ -7134,39 +7138,6 @@ var WebappsUI = {
}
},
getBiggestIcon: function getBiggestIcon(aIcons, aOrigin) {
const DEFAULT_ICON = "chrome://browser/skin/images/default-app-icon.png";
if (!aIcons)
return DEFAULT_ICON;
let iconSizes = Object.keys(aIcons);
if (iconSizes.length == 0)
return DEFAULT_ICON;
iconSizes.sort(function(a, b) a - b);
let biggestIcon = aIcons[iconSizes.pop()];
let iconURI = null;
try {
iconURI = Services.io.newURI(biggestIcon, null, null);
if (iconURI.scheme == "data") {
return iconURI.spec;
}
} catch (ex) {
// we don't have a biggestIcon or its not a valid url
}
// if we have an origin, try to resolve biggestIcon as a relative url
if (!iconURI && aOrigin) {
try {
iconURI = Services.io.newURI(aOrigin.resolve(biggestIcon), null, null);
} catch (ex) {
console.log("Could not resolve url: " + aOrigin.spec + " " + biggestIcon + " - " + ex);
}
}
return iconURI ? iconURI.spec : DEFAULT_ICON;
},
doInstall: function doInstall(aData) {
let jsonManifest = aData.isPackage ? aData.app.updateManifest : aData.app.manifest;
let manifest = new ManifestHelper(jsonManifest, aData.app.origin);
@ -7192,7 +7163,7 @@ var WebappsUI = {
// the manifest argument is the manifest from within the zip file,
// TODO so now would be a good time to ask about permissions.
self.makeBase64Icon(self.getBiggestIcon(manifest.icons, Services.io.newURI(aData.app.origin, null, null)),
self.makeBase64Icon(localeManifest.biggestIconURL || this.DEFAULT_ICON,
function(scaledIcon, fullsizeIcon) {
// if java returned a profile path to us, try to use it to pre-populate the app cache
// also save the icon so that it can be used in the splash screen
@ -7322,9 +7293,8 @@ var WebappsUI = {
// if the image failed to load, and it was not our default icon, attempt to
// use our default as a fallback
let uri = Services.io.newURI(favicon.src, null, null);
if (!/^chrome$/.test(uri.scheme)) {
favicon.src = WebappsUI.getBiggestIcon(null);
if (favicon.src != WebappsUI.DEFAULT_ICON) {
favicon.src = WebappsUI.DEFAULT_ICON;
}
};

View File

@ -26,8 +26,8 @@ chrome.jar:
content/readerWorker.js (content/readerWorker.js)
content/aboutHome.xhtml (content/aboutHome.xhtml)
content/aboutRights.xhtml (content/aboutRights.xhtml)
content/aboutApps.xhtml (content/aboutApps.xhtml)
content/aboutApps.js (content/aboutApps.js)
* content/aboutApps.xhtml (content/aboutApps.xhtml)
* content/aboutApps.js (content/aboutApps.js)
content/blockedSite.xhtml (content/blockedSite.xhtml)
content/languages.properties (content/languages.properties)
content/browser.xul (content/browser.xul)

View File

@ -0,0 +1,37 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsCOMPtr.h"
#include "nsIPrefService.h"
#include "nsIX509CertDB.h"
#include "nsServiceManagerUtils.h"
int
main(int argc, char* argv[])
{
{
NS_InitXPCOM2(nullptr, nullptr, nullptr);
nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
if (!prefs) {
return -1;
}
// When NSS initializes, it attempts to get some localized strings.
// As a result, OS X and Windows flip out if this isn't set.
// (This isn't done automatically since this test doesn't have a
// lot of the other boilerplate components that would otherwise
// keep the certificate db alive longer than we want it to.)
nsresult rv = prefs->SetBoolPref("intl.locale.matchOS", true);
if (NS_FAILED(rv)) {
return -1;
}
nsCOMPtr<nsIX509CertDB> certdb(do_GetService(NS_X509CERTDB_CONTRACTID));
if (!certdb) {
return -1;
}
} // this scopes the nsCOMPtrs
// no nsCOMPtrs are allowed to be alive when you call NS_ShutdownXPCOM
NS_ShutdownXPCOM(nullptr);
return 0;
}

View File

@ -0,0 +1,9 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
CPP_UNIT_TESTS += [
'TestCertDB.cpp',
]

View File

@ -11,4 +11,8 @@ TEST_DIRS += [
'mochitest',
]
TEST_TOOL_DIRS += [
'compiled',
]
XPCSHELL_TESTS_MANIFESTS += ['unit/xpcshell.ini']

View File

@ -2,8 +2,9 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import traceback
class ErrorCodes(object):
SUCCESS = 0
NO_SUCH_ELEMENT = 7
NO_SUCH_FRAME = 8
@ -33,18 +34,26 @@ class ErrorCodes(object):
MARIONETTE_ERROR = 500
class MarionetteException(Exception):
def __init__(self, message=None, status=ErrorCodes.MARIONETTE_ERROR, stacktrace=None):
def __init__(self, message=None,
status=ErrorCodes.MARIONETTE_ERROR, cause=None,
stacktrace=None):
self.msg = message
self.status = status
self.cause = cause
self.stacktrace = stacktrace
def __str__(self):
msg = str(self.msg)
tb = None
if self.cause:
msg += ", caused by %r" % self.cause[0]
tb = self.cause[2]
if self.stacktrace:
return '%s\n\tstacktrace:\n%s' % (str(self.msg),
''.join(['\t%s\n' % x for x in self.stacktrace.split('\n')]))
else:
return str(self.msg)
stack = "".join(["\t%s\n" % x for x in self.stacktrace.splitlines()])
msg += "\nstacktrace:\n%s" % stack
return "".join(traceback.format_exception(self.__class__, msg, tb))
class InstallGeckoError(MarionetteException):
pass

View File

@ -509,6 +509,8 @@ class Marionette(object):
busybox=busybox)
def cleanup(self):
if self.session:
self.delete_session()
if self.emulator:
self.emulator.close()
if self.instance:

View File

@ -0,0 +1,46 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import sys
import errors
import marionette_test
from errors import ErrorCodes
def fake_cause():
try:
raise ValueError("bar")
except ValueError as e:
return sys.exc_info()
message = "foo"
status = ErrorCodes.TIMEOUT
cause = fake_cause()
stacktrace = "first\nsecond"
class TestMarionetteException(marionette_test.MarionetteTestCase):
def test_defaults(self):
exc = errors.MarionetteException()
self.assertIsNone(exc.msg)
self.assertEquals(exc.status, ErrorCodes.MARIONETTE_ERROR)
self.assertIsNone(exc.cause)
self.assertIsNone(exc.stacktrace)
def test_construction(self):
exc = errors.MarionetteException(
message=message, status=status, cause=cause, stacktrace=stacktrace)
self.assertEquals(exc.msg, message)
self.assertEquals(exc.status, status)
self.assertEquals(exc.cause, cause)
self.assertEquals(exc.stacktrace, stacktrace)
def test_str(self):
exc = errors.MarionetteException(
message=message, status=status, cause=cause, stacktrace=stacktrace)
s = str(exc)
self.assertIn(message, s)
self.assertIn(", caused by %r" % cause[0], s)
self.assertIn("\nstacktrace:\n\tfirst\n\tsecond\n", s)
self.assertIn("MarionetteException:", s)

View File

@ -73,10 +73,10 @@ class TestNavigate(MarionetteTestCase):
try:
self.marionette.navigate("thisprotocoldoesnotexist://")
self.fail("Should have thrown a MarionetteException")
except TimeoutException:
except TimeoutException:
self.fail("The socket shouldn't have timed out when navigating to a non-existent URL")
except MarionetteException as e:
self.assertEqual(str(e), 'Error loading page')
self.assertIn("Error loading page", str(e))
except Exception as inst:
import traceback
print traceback.format_exc()
@ -108,4 +108,3 @@ class TestNavigate(MarionetteTestCase):
self.marionette.navigate(test_iframe)
self.assertTrue('test_iframe.html' in self.marionette.get_url())
self.assertTrue(self.marionette.find_element("id", "test_iframe"))

View File

@ -2,7 +2,6 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import unittest
import time
import sys
@ -167,14 +166,29 @@ class WaitUntilTest(MarionetteTestCase):
self.assertEqual(self.clock.ticks, 10)
def test_exception_raises_immediately(self):
with self.assertRaises(Exception):
self.w.until(lambda x: x.exception())
with self.assertRaises(TypeError):
self.w.until(lambda x: x.exception(e=TypeError))
self.assertEqual(self.clock.ticks, 0)
def test_custom_ignored_exception(self):
self.w.exceptions = self.w.exceptions + (Exception,)
with self.assertRaises(Exception):
self.w.until(lambda x: x.exception(e=Exception))
def test_ignored_exception(self):
self.w.exceptions = (TypeError,)
with self.assertRaises(errors.TimeoutException):
self.w.until(lambda x: x.exception(e=TypeError))
def test_ignored_exception_wrapped_in_timeoutexception(self):
self.w.exceptions = (TypeError,)
exc = None
try:
self.w.until(lambda x: x.exception(e=TypeError))
except Exception as e:
exc = e
s = str(exc)
self.assertIsNotNone(exc)
self.assertIsInstance(exc, errors.TimeoutException)
self.assertIn(", caused by %r" % TypeError, s)
self.assertIn("self.w.until(lambda x: x.exception(e=TypeError))", s)
def test_ignored_exception_after_timeout_is_not_raised(self):
with self.assertRaises(errors.TimeoutException):

View File

@ -93,7 +93,6 @@ b2g = false
b2g = false
[test_implicit_waits.py]
[test_wait.py]
qemu = false
[test_date_time_value.py]
[test_getactiveframe_oop.py]
disabled = "Bug 925688"
@ -101,3 +100,4 @@ disabled = "Bug 925688"
[test_chrome_async_finish.js]
[test_screen_orientation.py]
browser = false
[test_errors.py]

View File

@ -4,6 +4,7 @@
import collections
import errors
import sys
import time
DEFAULT_TIMEOUT = 5
@ -108,7 +109,7 @@ class Wait(object):
except (KeyboardInterrupt, SystemExit) as e:
raise e
except self.exceptions as e:
last_exc = e
last_exc = sys.exc_info()
if isinstance(rv, bool) and not rv:
self.clock.sleep(self.interval)
@ -119,11 +120,9 @@ class Wait(object):
self.clock.sleep(self.interval)
if last_exc is not None:
raise last_exc
raise errors.TimeoutException(
"Timed out after %s seconds" % (self.clock.now - start))
"Timed out after %s seconds" % (self.clock.now - start),
cause=last_exc)
def until_pred(clock, end):
return clock.now >= end

View File

@ -39,6 +39,7 @@
let SysAll = require("resource://gre/modules/osfile/osfile_win_allthreads.jsm");
let LOG = SharedAll.LOG.bind(SharedAll, "Unix", "back");
let libc = SysAll.libc;
let advapi32 = new SharedAll.Library("advapi32", "advapi32.dll");
let Const = SharedAll.Constants.Win;
/**
@ -121,9 +122,30 @@
Type.zero_or_nothing =
Type.int.withName("zero_or_nothing");
/**
* A C integer holding flags related to NTFS security.
*/
Type.SECURITY_ATTRIBUTES =
Type.void_t.withName("SECURITY_ATTRIBUTES");
/**
* A C integer holding pointers related to NTFS security.
*/
Type.PSID =
Type.voidptr_t.withName("PSID");
Type.PACL =
Type.voidptr_t.withName("PACL");
Type.PSECURITY_DESCRIPTOR =
Type.voidptr_t.withName("PSECURITY_DESCRIPTOR");
/**
* A C integer holding Win32 local memory handle.
*/
Type.HLOCAL =
Type.voidptr_t.withName("HLOCAL");
Type.FILETIME =
new SharedAll.Type("FILETIME",
ctypes.StructType("FILETIME", [
@ -356,6 +378,34 @@
/*return*/ Type.zero_or_nothing,
/*fileName*/ Type.path,
/*fileAttributes*/ Type.DWORD);
advapi32.declareLazyFFI(SysFile, "GetNamedSecurityInfo",
"GetNamedSecurityInfoW", ctypes.winapi_abi,
/*return*/ Type.DWORD,
/*objectName*/ Type.path,
/*objectType*/ Type.DWORD,
/*securityInfo*/ Type.DWORD,
/*sidOwner*/ Type.PSID.out_ptr,
/*sidGroup*/ Type.PSID.out_ptr,
/*dacl*/ Type.PACL.out_ptr,
/*sacl*/ Type.PACL.out_ptr,
/*securityDesc*/ Type.PSECURITY_DESCRIPTOR.out_ptr);
advapi32.declareLazyFFI(SysFile, "SetNamedSecurityInfo",
"SetNamedSecurityInfoW", ctypes.winapi_abi,
/*return*/ Type.DWORD,
/*objectName*/ Type.path,
/*objectType*/ Type.DWORD,
/*securityInfo*/ Type.DWORD,
/*sidOwner*/ Type.PSID,
/*sidGroup*/ Type.PSID,
/*dacl*/ Type.PACL,
/*sacl*/ Type.PACL);
declareLazyFFI(SysFile, "LocalFree", libc,
"LocalFree", ctypes.winapi_abi,
/*return*/ Type.HLOCAL,
/*mem*/ Type.HLOCAL);
};
exports.OS.Win = {

View File

@ -516,6 +516,37 @@
throw_on_zero("move",
WinFile.MoveFileEx(sourcePath, destPath, flags)
);
// Inherit NTFS permissions from the destination directory
// if possible.
if (Path.dirname(sourcePath) === Path.dirname(destPath)) {
// Skip if the move operation was the simple rename,
return;
}
// The function may fail for various reasons (e.g. not all
// filesystems support NTFS permissions or the user may not
// have the enough rights to read/write permissions).
// However we can safely ignore errors. The file was already
// moved. Setting permissions is not mandatory.
let dacl = new ctypes.voidptr_t();
let sd = new ctypes.voidptr_t();
WinFile.GetNamedSecurityInfo(destPath, Const.SE_FILE_OBJECT,
Const.DACL_SECURITY_INFORMATION,
null /*sidOwner*/, null /*sidGroup*/,
dacl.address(), null /*sacl*/,
sd.address());
// dacl will be set only if the function succeeds.
if (!dacl.isNull()) {
WinFile.SetNamedSecurityInfo(destPath, Const.SE_FILE_OBJECT,
Const.DACL_SECURITY_INFORMATION |
Const.UNPROTECTED_DACL_SECURITY_INFORMATION,
null /*sidOwner*/, null /*sidGroup*/,
dacl, null /*sacl*/);
}
// sd will be set only if the function succeeds.
if (!sd.isNull()) {
WinFile.LocalFree(Type.HLOCAL.cast(sd));
}
};
/**