mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-30 08:12:05 +00:00
Merge m-c to fx-team
This commit is contained in:
commit
f56a925c1e
2
CLOBBER
2
CLOBBER
@ -22,4 +22,4 @@
|
||||
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
||||
# don't change CLOBBER for WebIDL changes any more.
|
||||
|
||||
Bug 1182727 - Update the clang toolchain
|
||||
No bug - unknown something produced intermittent OS X build failures in libstagefright and jemalloc and malloc
|
||||
|
@ -586,9 +586,8 @@ setCaretOffsetCB(AtkText *aText, gint aOffset)
|
||||
}
|
||||
|
||||
if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
|
||||
if (proxy->SetCaretOffset(aOffset)) {
|
||||
return TRUE;
|
||||
}
|
||||
proxy->SetCaretOffset(aOffset);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
|
@ -390,13 +390,10 @@ DocAccessibleChild::RecvCaretOffset(const uint64_t& aID, int32_t* aOffset)
|
||||
|
||||
bool
|
||||
DocAccessibleChild::RecvSetCaretOffset(const uint64_t& aID,
|
||||
const int32_t& aOffset,
|
||||
bool* aRetVal)
|
||||
const int32_t& aOffset)
|
||||
{
|
||||
HyperTextAccessible* acc = IdToHyperTextAccessible(aID);
|
||||
*aRetVal = false;
|
||||
if (acc && acc->IsTextRole() && acc->IsValidOffset(aOffset)) {
|
||||
*aRetVal = true;
|
||||
acc->SetCaretOffset(aOffset);
|
||||
}
|
||||
return true;
|
||||
|
@ -103,8 +103,8 @@ public:
|
||||
override;
|
||||
virtual bool RecvCaretOffset(const uint64_t& aID, int32_t* aOffset)
|
||||
override;
|
||||
virtual bool RecvSetCaretOffset(const uint64_t& aID, const int32_t& aOffset,
|
||||
bool* aValid) override;
|
||||
virtual bool RecvSetCaretOffset(const uint64_t& aID, const int32_t& aOffset)
|
||||
override;
|
||||
|
||||
virtual bool RecvCharacterCount(const uint64_t& aID, int32_t* aCount)
|
||||
override;
|
||||
|
@ -92,7 +92,7 @@ child:
|
||||
// TextSubstring is getText in IDL.
|
||||
prio(high) sync CaretLineNumber(uint64_t aID) returns(int32_t aLineNumber);
|
||||
prio(high) sync CaretOffset(uint64_t aID) returns(int32_t aOffset);
|
||||
prio(high) sync SetCaretOffset(uint64_t aID, int32_t aOffset) returns (bool aValid);
|
||||
async SetCaretOffset(uint64_t aID, int32_t aOffset);
|
||||
prio(high) sync CharacterCount(uint64_t aID) returns(int32_t aCount);
|
||||
prio(high) sync SelectionCount(uint64_t aID) returns(int32_t aCount);
|
||||
prio(high) sync TextSubstring(uint64_t aID, int32_t aStartOffset, int32_t
|
||||
|
@ -216,12 +216,10 @@ ProxyAccessible::CaretOffset()
|
||||
return offset;
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
ProxyAccessible::SetCaretOffset(int32_t aOffset)
|
||||
{
|
||||
bool valid = false;
|
||||
unused << mDoc->SendSetCaretOffset(mID, aOffset, &valid);
|
||||
return valid;
|
||||
unused << mDoc->SendSetCaretOffset(mID, aOffset);
|
||||
}
|
||||
|
||||
int32_t
|
||||
|
@ -132,7 +132,7 @@ public:
|
||||
|
||||
int32_t CaretLineNumber();
|
||||
int32_t CaretOffset();
|
||||
bool SetCaretOffset(int32_t aOffset);
|
||||
void SetCaretOffset(int32_t aOffset);
|
||||
|
||||
int32_t CharacterCount();
|
||||
int32_t SelectionCount();
|
||||
|
@ -73,7 +73,20 @@ var OutputGenerator = {
|
||||
[addOutput(node) for // jshint ignore:line
|
||||
(node of aContext.subtreeGenerator(false, ignoreSubtree))]; // jshint ignore:line
|
||||
addOutput(aContext.accessible);
|
||||
|
||||
// If there are any documents in new ancestry, find a first one and place
|
||||
// it in the beginning of the utterance.
|
||||
let doc, docIndex = contextStart.findIndex(
|
||||
ancestor => ancestor.role === Roles.DOCUMENT);
|
||||
|
||||
if (docIndex > -1) {
|
||||
doc = contextStart.splice(docIndex, 1)[0];
|
||||
}
|
||||
|
||||
contextStart.reverse().forEach(addOutput);
|
||||
if (doc) {
|
||||
output.unshift.apply(output, self.genForObject(doc, aContext));
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
|
@ -32,13 +32,13 @@
|
||||
// Simple traversal forward
|
||||
[ContentMessages.simpleMoveNext,
|
||||
new ExpectedCursorChange(
|
||||
['Phone status bar', 'Traversal Rule test document'],
|
||||
['Traversal Rule test document', 'Phone status bar'],
|
||||
{ focused: 'body' })],
|
||||
[ContentMessages.simpleMovePrevious, new ExpectedNoMove()],
|
||||
[ContentMessages.simpleMoveNext,
|
||||
new ExpectedCursorChange(["Back", {"string": "pushbutton"}])],
|
||||
[ContentMessages.simpleMoveNext, new ExpectedCursorChange(
|
||||
['wow', {'string': 'headingLevel', 'args': [1]} ,'such app'],
|
||||
['such app', 'wow', {'string': 'headingLevel', 'args': [1]}],
|
||||
{ focused: 'iframe' })],
|
||||
[ContentMessages.simpleMoveNext,
|
||||
new ExpectedCursorChange(['many option', {'string': 'stateNotChecked'},
|
||||
@ -79,7 +79,7 @@
|
||||
[ContentMessages.simpleMovePrevious,
|
||||
new ExpectedCursorChange(['Home', {'string': 'pushbutton'}])],
|
||||
[ContentMessages.simpleMovePrevious,
|
||||
new ExpectedCursorChange(['much range', '6', {'string': 'slider'}, 'such app'])],
|
||||
new ExpectedCursorChange(['such app', 'much range', '6', {'string': 'slider'}])],
|
||||
[ContentMessages.moveOrAdjustDown(), new ExpectedValueChange('5')],
|
||||
[ContentMessages.androidScrollForward(), new ExpectedValueChange('6')],
|
||||
[ContentMessages.androidScrollBackward(), new ExpectedValueChange('5')],
|
||||
@ -106,7 +106,7 @@
|
||||
// fails. Bug 972035.
|
||||
[ContentMessages.simpleMoveNext,
|
||||
new ExpectedCursorChange(
|
||||
['wow', {'string': 'headingLevel', 'args': [1]}, 'such app'])],
|
||||
['such app', 'wow', {'string': 'headingLevel', 'args': [1]}])],
|
||||
// Move from an inner frame to the last element in the parent doc
|
||||
[ContentMessages.simpleMoveLast,
|
||||
new ExpectedCursorChange(
|
||||
@ -115,13 +115,13 @@
|
||||
[ContentMessages.clearCursor, 'AccessFu:CursorCleared'],
|
||||
|
||||
[ContentMessages.simpleMoveNext,
|
||||
new ExpectedCursorChange(['Phone status bar', 'Traversal Rule test document'])],
|
||||
new ExpectedCursorChange(['Traversal Rule test document', 'Phone status bar'])],
|
||||
[ContentMessages.moveOrAdjustDown('FormElement'),
|
||||
new ExpectedCursorChange(['Back', {"string": "pushbutton"}])],
|
||||
[ContentMessages.moveOrAdjustDown('FormElement'),
|
||||
new ExpectedCursorChange(['many option', {'string': 'stateNotChecked'},
|
||||
new ExpectedCursorChange(['such app', 'many option', {'string': 'stateNotChecked'},
|
||||
{'string': 'checkbutton'}, {'string': 'listStart'},
|
||||
{'string': 'list'}, {'string': 'listItemsCount', 'count': 1}, 'such app'])],
|
||||
{'string': 'list'}, {'string': 'listItemsCount', 'count': 1}])],
|
||||
[ContentMessages.moveOrAdjustDown('FormElement'),
|
||||
new ExpectedCursorChange(['much range', '5', {'string': 'slider'}])],
|
||||
// Calling AdjustOrMove should adjust the range.
|
||||
@ -143,11 +143,11 @@
|
||||
// Moving to the absolute first item from an embedded document
|
||||
// fails. Bug 972035.
|
||||
[ContentMessages.simpleMoveNext,
|
||||
new ExpectedCursorChange(['Phone status bar', 'Traversal Rule test document'])],
|
||||
new ExpectedCursorChange(['Traversal Rule test document', 'Phone status bar'])],
|
||||
[ContentMessages.simpleMoveNext,
|
||||
new ExpectedCursorChange(["Back", {"string": "pushbutton"}])],
|
||||
[ContentMessages.simpleMoveNext,
|
||||
new ExpectedCursorChange(['wow', {'string': 'headingLevel', 'args': [1]}, 'such app'])],
|
||||
new ExpectedCursorChange(['such app', 'wow', {'string': 'headingLevel', 'args': [1]}])],
|
||||
[ContentMessages.simpleMoveNext, new ExpectedCursorChange(
|
||||
['many option', {'string': 'stateNotChecked'},
|
||||
{'string': 'checkbutton'}, {'string': 'listStart'},
|
||||
@ -160,7 +160,7 @@
|
||||
|
||||
// Current virtual cursor's position's name changes
|
||||
[ContentMessages.simpleMoveNext,
|
||||
new ExpectedCursorChange(['Phone status bar', 'Traversal Rule test document'])],
|
||||
new ExpectedCursorChange(['Traversal Rule test document', 'Phone status bar'])],
|
||||
[ContentMessages.focusSelector('button#fruit', false),
|
||||
new ExpectedCursorChange(['apple', {'string': 'pushbutton'}])],
|
||||
[doc.defaultView.renameFruit, new ExpectedNameChange('banana')],
|
||||
@ -177,7 +177,7 @@
|
||||
|
||||
// Move cursor with focus in outside document
|
||||
[ContentMessages.simpleMoveNext,
|
||||
new ExpectedCursorChange(['Phone status bar', 'Traversal Rule test document'])],
|
||||
new ExpectedCursorChange(['Traversal Rule test document', 'Phone status bar'])],
|
||||
[ContentMessages.focusSelector('button#home', false),
|
||||
new ExpectedCursorChange(['Home', {'string': 'pushbutton'}])],
|
||||
|
||||
@ -188,11 +188,11 @@
|
||||
// Set focus on element outside of embedded frame while
|
||||
// cursor is in frame
|
||||
[ContentMessages.simpleMoveNext,
|
||||
new ExpectedCursorChange(['Phone status bar', 'Traversal Rule test document'])],
|
||||
new ExpectedCursorChange(['Traversal Rule test document', 'Phone status bar'])],
|
||||
[ContentMessages.simpleMoveNext,
|
||||
new ExpectedCursorChange(["Back", {"string": "pushbutton"}])],
|
||||
[ContentMessages.simpleMoveNext,
|
||||
new ExpectedCursorChange(['wow', {'string': 'headingLevel', 'args': [1]}, 'such app'])],
|
||||
new ExpectedCursorChange(['such app', 'wow', {'string': 'headingLevel', 'args': [1]}])],
|
||||
[ContentMessages.focusSelector('button#home', false),
|
||||
new ExpectedCursorChange(['Home', {'string': 'pushbutton'}])],
|
||||
|
||||
@ -206,12 +206,12 @@
|
||||
|
||||
// aria-hidden element that the virtual cursor is positioned on
|
||||
[ContentMessages.simpleMoveNext,
|
||||
new ExpectedCursorChange(['Phone status bar', 'Traversal Rule test document'])],
|
||||
new ExpectedCursorChange(['Traversal Rule test document', 'Phone status bar'])],
|
||||
[ContentMessages.simpleMoveNext,
|
||||
new ExpectedCursorChange(["Back", {"string": "pushbutton"}])],
|
||||
[doc.defaultView.ariaHideBack,
|
||||
new ExpectedCursorChange(
|
||||
["wow", {"string": "headingLevel","args": [1]}, "such app"])],
|
||||
["such app", "wow", {"string": "headingLevel","args": [1]}])],
|
||||
// Changing aria-hidden attribute twice and making sure that the event
|
||||
// is fired only once when the actual change happens.
|
||||
[doc.defaultView.ariaHideBack],
|
||||
@ -222,11 +222,11 @@
|
||||
|
||||
// aria-hidden on the iframe that has the vc.
|
||||
[ContentMessages.simpleMoveNext,
|
||||
new ExpectedCursorChange(['Phone status bar', 'Traversal Rule test document'])],
|
||||
new ExpectedCursorChange(['Traversal Rule test document', 'Phone status bar'])],
|
||||
[ContentMessages.simpleMoveNext,
|
||||
new ExpectedCursorChange(["Back", {"string": "pushbutton"}])],
|
||||
[ContentMessages.simpleMoveNext,
|
||||
new ExpectedCursorChange(['wow', {'string': 'headingLevel', 'args': [1]}, 'such app'])],
|
||||
new ExpectedCursorChange(['such app', 'wow', {'string': 'headingLevel', 'args': [1]}])],
|
||||
[doc.defaultView.ariaHideIframe,
|
||||
new ExpectedCursorChange(['Home', {'string': 'pushbutton'}])],
|
||||
[doc.defaultView.ariaShowIframe],
|
||||
@ -234,37 +234,39 @@
|
||||
|
||||
// aria-hidden element and auto Move
|
||||
[ContentMessages.simpleMoveNext,
|
||||
new ExpectedCursorChange(['Phone status bar', 'Traversal Rule test document'])],
|
||||
new ExpectedCursorChange(['Traversal Rule test document', 'Phone status bar'])],
|
||||
[doc.defaultView.ariaHideBack],
|
||||
[ContentMessages.focusSelector('button#back', false),
|
||||
// Must not speak Back button as it is aria-hidden
|
||||
new ExpectedCursorChange(
|
||||
["wow", {"string": "headingLevel","args": [1]}, "such app"])],
|
||||
["such app", "wow", {"string": "headingLevel","args": [1]}])],
|
||||
[doc.defaultView.ariaShowBack],
|
||||
[ContentMessages.focusSelector('button#back', true), null],
|
||||
[ContentMessages.clearCursor, 'AccessFu:CursorCleared'],
|
||||
|
||||
// Open dialog in outer doc, while cursor is also in outer doc
|
||||
[ContentMessages.simpleMoveLast,
|
||||
new ExpectedCursorChange(['mover'])],
|
||||
new ExpectedCursorChange(['Traversal Rule test document', 'mover',
|
||||
'medium', {'string': 'slider'}])],
|
||||
[doc.defaultView.showAlert,
|
||||
new ExpectedCursorChange(['This is an alert!',
|
||||
{'string': 'headingLevel', 'args': [1]},
|
||||
{'string': 'dialog'}])],
|
||||
|
||||
[doc.defaultView.hideAlert,
|
||||
new ExpectedCursorChange(['mover'])],
|
||||
new ExpectedCursorChange(['Traversal Rule test document', 'mover',
|
||||
'medium', {'string': 'slider'}])],
|
||||
|
||||
[ContentMessages.clearCursor, 'AccessFu:CursorCleared'],
|
||||
|
||||
// Open dialog in outer doc, while cursor is in inner frame
|
||||
[ContentMessages.simpleMoveNext,
|
||||
new ExpectedCursorChange(['Phone status bar', 'Traversal Rule test document'])],
|
||||
new ExpectedCursorChange(['Traversal Rule test document', 'Phone status bar'])],
|
||||
[ContentMessages.simpleMoveNext,
|
||||
new ExpectedCursorChange(["Back", {"string": "pushbutton"}])],
|
||||
[ContentMessages.simpleMoveNext,
|
||||
new ExpectedCursorChange(
|
||||
['wow', {'string': 'headingLevel', 'args': [1]}, 'such app'])],
|
||||
['such app', 'wow', {'string': 'headingLevel', 'args': [1]}])],
|
||||
[doc.defaultView.showAlert, new ExpectedCursorChange(['This is an alert!',
|
||||
{'string': 'headingLevel', 'args': [1]},
|
||||
{'string': 'dialog'}])],
|
||||
@ -276,13 +278,13 @@
|
||||
[ContentMessages.activateCurrent(),
|
||||
new ExpectedClickAction(),
|
||||
new ExpectedCursorChange(
|
||||
['wow', {'string': 'headingLevel', 'args': [1]}, 'such app'])],
|
||||
['such app', 'wow', {'string': 'headingLevel', 'args': [1]}])],
|
||||
|
||||
[ContentMessages.clearCursor, 'AccessFu:CursorCleared'],
|
||||
|
||||
// Open dialog, then focus on something when closing
|
||||
[ContentMessages.simpleMoveNext,
|
||||
new ExpectedCursorChange(['Phone status bar', 'Traversal Rule test document'])],
|
||||
new ExpectedCursorChange(['Traversal Rule test document', 'Phone status bar'])],
|
||||
[doc.defaultView.showAlert,
|
||||
new ExpectedCursorChange(['This is an alert!',
|
||||
{'string': 'headingLevel', 'args': [1]}, {'string': 'dialog'}])],
|
||||
@ -290,8 +292,8 @@
|
||||
[function hideAlertAndFocusHomeButton() {
|
||||
doc.defaultView.hideAlert();
|
||||
doc.querySelector('button#home').focus();
|
||||
}, new ExpectedCursorChange(['Home', {'string': 'pushbutton'},
|
||||
'Traversal Rule test document'])],
|
||||
}, new ExpectedCursorChange(['Traversal Rule test document',
|
||||
'Home', {'string': 'pushbutton'}])],
|
||||
[ContentMessages.simpleMoveNext,
|
||||
new ExpectedCursorChange(['banana', {'string': 'pushbutton'}])]
|
||||
[ContentMessages.simpleMoveNext, new ExpectedNoMove()]
|
||||
|
@ -31,9 +31,9 @@
|
||||
// Read-only text tests
|
||||
[ContentMessages.simpleMoveFirst,
|
||||
new ExpectedCursorChange(
|
||||
['These are my awards, Mother. From Army. The seal is for ' +
|
||||
'marksmanship, and the gorilla is for sand racing.',
|
||||
'Text content test document'])],
|
||||
['Text content test document', 'These are my awards, Mother. ' +
|
||||
'From Army. The seal is for marksmanship, and the gorilla is ' +
|
||||
'for sand racing.'])],
|
||||
[ContentMessages.moveNextBy('word'),
|
||||
new ExpectedCursorTextChange('These', 0, 5)],
|
||||
[ContentMessages.moveNextBy('word'),
|
||||
|
@ -434,7 +434,8 @@ ia2AccessibleText::setCaretOffset(long aOffset)
|
||||
A11Y_TRYBLOCK_BEGIN
|
||||
|
||||
if (ProxyAccessible* proxy = HyperTextProxyFor(this)) {
|
||||
return proxy->SetCaretOffset(aOffset) ? S_OK : E_INVALIDARG;
|
||||
proxy->SetCaretOffset(aOffset);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
|
||||
|
@ -698,6 +698,10 @@ var settingsToObserve = {
|
||||
prefName: 'dom.sms.maxReadAheadEntries',
|
||||
defaultValue: 7
|
||||
},
|
||||
'services.sync.enabled': {
|
||||
defaultValue: false,
|
||||
notifyChange: true
|
||||
},
|
||||
'ui.touch.radius.leftmm': {
|
||||
resetToPref: true
|
||||
},
|
||||
@ -717,6 +721,18 @@ var settingsToObserve = {
|
||||
'wap.UAProf.url': ''
|
||||
};
|
||||
|
||||
function settingObserver(setPref, prefName, setting) {
|
||||
return value => {
|
||||
setPref(prefName, value);
|
||||
if (setting.notifyChange) {
|
||||
SystemAppProxy._sendCustomEvent('mozPrefChromeEvent', {
|
||||
prefName: prefName,
|
||||
value: value
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
for (let key in settingsToObserve) {
|
||||
let setting = settingsToObserve[key];
|
||||
|
||||
@ -766,7 +782,6 @@ for (let key in settingsToObserve) {
|
||||
break;
|
||||
}
|
||||
|
||||
SettingsListener.observe(key, defaultValue, function(value) {
|
||||
setPref(prefName, value);
|
||||
});
|
||||
SettingsListener.observe(key, defaultValue,
|
||||
settingObserver(setPref, prefName, setting));
|
||||
};
|
||||
|
@ -156,7 +156,8 @@ this.FxAccountsMgmtService = {
|
||||
case "signIn":
|
||||
case "signUp":
|
||||
case "refreshAuthentication":
|
||||
FxAccountsManager[data.method](data.email, data.password).then(
|
||||
FxAccountsManager[data.method](data.email, data.password,
|
||||
data.fetchKeys).then(
|
||||
user => {
|
||||
self._onFulfill(msg.id, user);
|
||||
},
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8ea9029190af2ffeb04dcd97b323738125e31a0e"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8999f0ba6326d815c8366e3c1155b7e4e9763b40"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7938df689aa87769fad3f2cf9097fb4ecb106a43"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8ea9029190af2ffeb04dcd97b323738125e31a0e"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8999f0ba6326d815c8366e3c1155b7e4e9763b40"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7938df689aa87769fad3f2cf9097fb4ecb106a43"/>
|
||||
|
@ -19,7 +19,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="8ea9029190af2ffeb04dcd97b323738125e31a0e"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="8999f0ba6326d815c8366e3c1155b7e4e9763b40"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7938df689aa87769fad3f2cf9097fb4ecb106a43"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="4ace9aaee0e048dfda11bb787646c59982a3dc80"/>
|
||||
|
@ -17,7 +17,7 @@
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8ea9029190af2ffeb04dcd97b323738125e31a0e"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8999f0ba6326d815c8366e3c1155b7e4e9763b40"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7938df689aa87769fad3f2cf9097fb4ecb106a43"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="31a7849fe9a8b743d6f5e5facc212f0ef9d57499"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0c28789b9957913be975eb002a22323f93585d4c"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8ea9029190af2ffeb04dcd97b323738125e31a0e"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8999f0ba6326d815c8366e3c1155b7e4e9763b40"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7938df689aa87769fad3f2cf9097fb4ecb106a43"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8ea9029190af2ffeb04dcd97b323738125e31a0e"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8999f0ba6326d815c8366e3c1155b7e4e9763b40"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7938df689aa87769fad3f2cf9097fb4ecb106a43"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -19,7 +19,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="8ea9029190af2ffeb04dcd97b323738125e31a0e"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="8999f0ba6326d815c8366e3c1155b7e4e9763b40"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7938df689aa87769fad3f2cf9097fb4ecb106a43"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="4ace9aaee0e048dfda11bb787646c59982a3dc80"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8ea9029190af2ffeb04dcd97b323738125e31a0e"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8999f0ba6326d815c8366e3c1155b7e4e9763b40"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7938df689aa87769fad3f2cf9097fb4ecb106a43"/>
|
||||
|
@ -1,9 +1,9 @@
|
||||
{
|
||||
"git": {
|
||||
"git_revision": "8ea9029190af2ffeb04dcd97b323738125e31a0e",
|
||||
"git_revision": "8999f0ba6326d815c8366e3c1155b7e4e9763b40",
|
||||
"remote": "https://git.mozilla.org/releases/gaia.git",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "25790d1036e01366a957eed0ade6c259f5442cbf",
|
||||
"revision": "983b7ecb17c67b9fb511f400bb5b28b9069eea00",
|
||||
"repo_path": "integration/gaia-central"
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8ea9029190af2ffeb04dcd97b323738125e31a0e"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8999f0ba6326d815c8366e3c1155b7e4e9763b40"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7938df689aa87769fad3f2cf9097fb4ecb106a43"/>
|
||||
|
@ -18,7 +18,7 @@
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8ea9029190af2ffeb04dcd97b323738125e31a0e"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8999f0ba6326d815c8366e3c1155b7e4e9763b40"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7938df689aa87769fad3f2cf9097fb4ecb106a43"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="31a7849fe9a8b743d6f5e5facc212f0ef9d57499"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0c28789b9957913be975eb002a22323f93585d4c"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8ea9029190af2ffeb04dcd97b323738125e31a0e"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8999f0ba6326d815c8366e3c1155b7e4e9763b40"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7938df689aa87769fad3f2cf9097fb4ecb106a43"/>
|
||||
|
@ -3,8 +3,8 @@
|
||||
"clang_version": "r247539"
|
||||
},
|
||||
{
|
||||
"size": 105219872,
|
||||
"digest": "aa8de2fa535d0667e079019c475c631ea008f1bb5228505510867255b4d9c30663e2c97e579220a575a5887aa3bcf250021b50f76b90c2fa8c65a7aa19270066",
|
||||
"size": 106877168,
|
||||
"digest": "1c50c6348eaf429ed59bb603cff63bcc1f870f59216dd3c234db5b1156cfd351d5ee7b820ec31be4d2661eb4213b2e0030e2ba2782b42905d1ec19c7f8bd322a",
|
||||
"algorithm": "sha512",
|
||||
"filename": "clang.tar.xz",
|
||||
"unpack": true,
|
||||
|
@ -3,8 +3,8 @@
|
||||
"clang_version": "r247539"
|
||||
},
|
||||
{
|
||||
"size": 105219872,
|
||||
"digest": "aa8de2fa535d0667e079019c475c631ea008f1bb5228505510867255b4d9c30663e2c97e579220a575a5887aa3bcf250021b50f76b90c2fa8c65a7aa19270066",
|
||||
"size": 106877168,
|
||||
"digest": "1c50c6348eaf429ed59bb603cff63bcc1f870f59216dd3c234db5b1156cfd351d5ee7b820ec31be4d2661eb4213b2e0030e2ba2782b42905d1ec19c7f8bd322a",
|
||||
"algorithm": "sha512",
|
||||
"filename": "clang.tar.xz",
|
||||
"unpack": true
|
||||
|
@ -3,8 +3,8 @@
|
||||
"clang_version": "r247539"
|
||||
},
|
||||
{
|
||||
"size": 105219872,
|
||||
"digest": "aa8de2fa535d0667e079019c475c631ea008f1bb5228505510867255b4d9c30663e2c97e579220a575a5887aa3bcf250021b50f76b90c2fa8c65a7aa19270066",
|
||||
"size": 106877168,
|
||||
"digest": "1c50c6348eaf429ed59bb603cff63bcc1f870f59216dd3c234db5b1156cfd351d5ee7b820ec31be4d2661eb4213b2e0030e2ba2782b42905d1ec19c7f8bd322a",
|
||||
"algorithm": "sha512",
|
||||
"filename": "clang.tar.xz",
|
||||
"unpack": true
|
||||
|
@ -3,8 +3,8 @@
|
||||
"clang_version": "r247539"
|
||||
},
|
||||
{
|
||||
"size": 121393888,
|
||||
"digest": "6ae4e651e545538e6de326a7fb8b44b6e6d0b3acdb6a969ecb2b6f63b9995bbad2111cabf044ba575464f17f1f948d78ec92ad3a6922a7bfdf3ad6b6b2cad050",
|
||||
"size": 121389802,
|
||||
"digest": "2be6b42cfa1e92de4b49a57123f54043fec2d3cf8385276516dc6aaed99c88768ac4aebd7ce2e007ab074163523da29223436a4d1aef82f0f750f08f1b14cd71",
|
||||
"algorithm": "sha512",
|
||||
"filename": "clang.tar.bz2",
|
||||
"unpack": true
|
||||
|
@ -3,8 +3,8 @@
|
||||
"clang_version": "r247539"
|
||||
},
|
||||
{
|
||||
"size": 105219872,
|
||||
"digest": "aa8de2fa535d0667e079019c475c631ea008f1bb5228505510867255b4d9c30663e2c97e579220a575a5887aa3bcf250021b50f76b90c2fa8c65a7aa19270066",
|
||||
"size": 106877168,
|
||||
"digest": "1c50c6348eaf429ed59bb603cff63bcc1f870f59216dd3c234db5b1156cfd351d5ee7b820ec31be4d2661eb4213b2e0030e2ba2782b42905d1ec19c7f8bd322a",
|
||||
"algorithm": "sha512",
|
||||
"filename": "clang.tar.xz",
|
||||
"unpack": true
|
||||
|
@ -1,12 +1,12 @@
|
||||
[
|
||||
{
|
||||
"clang_version": "r183744"
|
||||
"clang_version": "r247539"
|
||||
},
|
||||
{
|
||||
"size": 59602619,
|
||||
"digest": "86662ebc0ef650490559005948c4f0cb015dad72c7cac43732c2bf2995247081e30c139cf8008d19670a0009fc302c4eee2676981ee3f9ff4a15c01af22b783b",
|
||||
"algorithm": "sha512",
|
||||
"filename": "clang.tar.bz2",
|
||||
"size": 97314461,
|
||||
"digest": "9a74670fa917f760a4767923485d5166bbd258a8023c8aeb899b8c4d22f2847be76508ac5f26d7d2193318a2bb368a71bc62888d1bfe9d81eb45329a60451aa4",
|
||||
"algorithm": "sha512",
|
||||
"filename": "clang.tar.xz",
|
||||
"unpack": true
|
||||
},
|
||||
{
|
||||
|
@ -13,8 +13,20 @@
|
||||
"cc": "/home/worker/workspace/build/src/gcc/bin/gcc",
|
||||
"cxx": "/home/worker/workspace/build/src/gcc/bin/g++",
|
||||
"patches": {
|
||||
"macosx64": ["llvm-debug-frame.patch"],
|
||||
"linux64": ["llvm-debug-frame.patch"],
|
||||
"linux32": ["llvm-debug-frame.patch"]
|
||||
"macosx64": [
|
||||
"llvm-debug-frame.patch",
|
||||
"query-selector-visibility.patch",
|
||||
"return-empty-string-non-mangled.patch"
|
||||
],
|
||||
"linux64": [
|
||||
"llvm-debug-frame.patch",
|
||||
"query-selector-visibility.patch",
|
||||
"return-empty-string-non-mangled.patch"
|
||||
],
|
||||
"linux32": [
|
||||
"llvm-debug-frame.patch",
|
||||
"query-selector-visibility.patch",
|
||||
"return-empty-string-non-mangled.patch"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -13,8 +13,20 @@
|
||||
"cc": "/home/worker/workspace/build/src/gcc/bin/gcc",
|
||||
"cxx": "/home/worker/workspace/build/src/gcc/bin/g++",
|
||||
"patches": {
|
||||
"macosx64": ["llvm-debug-frame.patch"],
|
||||
"linux64": ["llvm-debug-frame.patch"],
|
||||
"linux32": ["llvm-debug-frame.patch"]
|
||||
"macosx64": [
|
||||
"llvm-debug-frame.patch",
|
||||
"query-selector-visibility.patch",
|
||||
"return-empty-string-non-mangled.patch"
|
||||
],
|
||||
"linux64": [
|
||||
"llvm-debug-frame.patch",
|
||||
"query-selector-visibility.patch",
|
||||
"return-empty-string-non-mangled.patch"
|
||||
],
|
||||
"linux32": [
|
||||
"llvm-debug-frame.patch",
|
||||
"query-selector-visibility.patch",
|
||||
"return-empty-string-non-mangled.patch"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -12,8 +12,20 @@
|
||||
"cc": "/usr/bin/clang",
|
||||
"cxx": "/usr/bin/clang++",
|
||||
"patches": {
|
||||
"macosx64": ["llvm-debug-frame.patch"],
|
||||
"linux64": ["llvm-debug-frame.patch"],
|
||||
"linux32": ["llvm-debug-frame.patch"]
|
||||
"macosx64": [
|
||||
"llvm-debug-frame.patch",
|
||||
"query-selector-visibility.patch",
|
||||
"return-empty-string-non-mangled.patch"
|
||||
],
|
||||
"linux64": [
|
||||
"llvm-debug-frame.patch",
|
||||
"query-selector-visibility.patch",
|
||||
"return-empty-string-non-mangled.patch"
|
||||
],
|
||||
"linux32": [
|
||||
"llvm-debug-frame.patch",
|
||||
"query-selector-visibility.patch",
|
||||
"return-empty-string-non-mangled.patch"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
79
build/unix/build-clang/query-selector-visibility.patch
Normal file
79
build/unix/build-clang/query-selector-visibility.patch
Normal file
@ -0,0 +1,79 @@
|
||||
commit 865b9340996f9f9d04b73b187248737dc6fd845e
|
||||
Author: Michael Wu <mwu@mozilla.com>
|
||||
Date: Mon Sep 14 17:47:21 2015 -0400
|
||||
|
||||
Add support for querying the visibility of a cursor
|
||||
|
||||
diff --git a/llvm/tools/clang/include/clang-c/Index.h b/llvm/tools/clang/include/clang-c/Index.h
|
||||
index fad9cfa..311bfcb 100644
|
||||
--- a/llvm/tools/clang/include/clang-c/Index.h
|
||||
+++ b/llvm/tools/clang/include/clang-c/Index.h
|
||||
@@ -2440,6 +2440,24 @@ enum CXLinkageKind {
|
||||
CINDEX_LINKAGE enum CXLinkageKind clang_getCursorLinkage(CXCursor cursor);
|
||||
|
||||
/**
|
||||
+ * \brief Describe the visibility of the entity referred to by a cursor.
|
||||
+ */
|
||||
+enum CXVisibilityKind {
|
||||
+ /** \brief This value indicates that no visibility information is available
|
||||
+ * for a provided CXCursor. */
|
||||
+ CXVisibility_Invalid,
|
||||
+
|
||||
+ /** \brief Symbol not seen by the linker. */
|
||||
+ CXVisibility_Hidden,
|
||||
+ /** \brief Symbol seen by the linker but resolves to a symbol inside this object. */
|
||||
+ CXVisibility_Protected,
|
||||
+ /** \brief Symbol seen by the linker and acts like a normal symbol. */
|
||||
+ CXVisibility_Default,
|
||||
+};
|
||||
+
|
||||
+CINDEX_LINKAGE enum CXVisibilityKind clang_getCursorVisibility(CXCursor cursor);
|
||||
+
|
||||
+/**
|
||||
* \brief Determine the availability of the entity that this cursor refers to,
|
||||
* taking the current target platform into account.
|
||||
*
|
||||
diff --git a/llvm/tools/clang/tools/libclang/CIndex.cpp b/llvm/tools/clang/tools/libclang/CIndex.cpp
|
||||
index 8225a6c..9fa18d3 100644
|
||||
--- a/llvm/tools/clang/tools/libclang/CIndex.cpp
|
||||
+++ b/llvm/tools/clang/tools/libclang/CIndex.cpp
|
||||
@@ -6361,6 +6361,27 @@ CXLinkageKind clang_getCursorLinkage(CXCursor cursor) {
|
||||
} // end: extern "C"
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
+// Operations for querying visibility of a cursor.
|
||||
+//===----------------------------------------------------------------------===//
|
||||
+
|
||||
+extern "C" {
|
||||
+CXVisibilityKind clang_getCursorVisibility(CXCursor cursor) {
|
||||
+ if (!clang_isDeclaration(cursor.kind))
|
||||
+ return CXVisibility_Invalid;
|
||||
+
|
||||
+ const Decl *D = cxcursor::getCursorDecl(cursor);
|
||||
+ if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(D))
|
||||
+ switch (ND->getVisibility()) {
|
||||
+ case HiddenVisibility: return CXVisibility_Hidden;
|
||||
+ case ProtectedVisibility: return CXVisibility_Protected;
|
||||
+ case DefaultVisibility: return CXVisibility_Default;
|
||||
+ };
|
||||
+
|
||||
+ return CXVisibility_Invalid;
|
||||
+}
|
||||
+} // end: extern "C"
|
||||
+
|
||||
+//===----------------------------------------------------------------------===//
|
||||
// Operations for querying language of a cursor.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
diff --git a/llvm/tools/clang/tools/libclang/libclang.exports b/llvm/tools/clang/tools/libclang/libclang.exports
|
||||
index f6a7175..a919a8e 100644
|
||||
--- a/llvm/tools/clang/tools/libclang/libclang.exports
|
||||
+++ b/llvm/tools/clang/tools/libclang/libclang.exports
|
||||
@@ -173,6 +173,7 @@ clang_getCursorSemanticParent
|
||||
clang_getCursorSpelling
|
||||
clang_getCursorType
|
||||
clang_getCursorUSR
|
||||
+clang_getCursorVisibility
|
||||
clang_getDeclObjCTypeEncoding
|
||||
clang_getDefinitionSpellingAndExtent
|
||||
clang_getDiagnostic
|
21
build/unix/build-clang/return-empty-string-non-mangled.patch
Normal file
21
build/unix/build-clang/return-empty-string-non-mangled.patch
Normal file
@ -0,0 +1,21 @@
|
||||
commit 009de5ea7a1913f0b4619cf514787bd52af38c28
|
||||
Author: Michael Wu <mwu@mozilla.com>
|
||||
Date: Thu Sep 24 11:36:08 2015 -0400
|
||||
|
||||
Return an empty string when a symbol isn't mangled
|
||||
|
||||
diff --git a/llvm/tools/clang/tools/libclang/CIndex.cpp b/llvm/tools/clang/tools/libclang/CIndex.cpp
|
||||
index 9fa18d3..1253832 100644
|
||||
--- a/llvm/tools/clang/tools/libclang/CIndex.cpp
|
||||
+++ b/llvm/tools/clang/tools/libclang/CIndex.cpp
|
||||
@@ -3891,6 +3891,10 @@ CXString clang_Cursor_getMangling(CXCursor C) {
|
||||
ASTContext &Ctx = ND->getASTContext();
|
||||
std::unique_ptr<MangleContext> MC(Ctx.createMangleContext());
|
||||
|
||||
+ // Don't mangle if we don't need to.
|
||||
+ if (!MC->shouldMangleCXXName(ND))
|
||||
+ return cxstring::createEmpty();
|
||||
+
|
||||
std::string FrontendBuf;
|
||||
llvm::raw_string_ostream FrontendBufOS(FrontendBuf);
|
||||
MC->mangleName(ND, FrontendBufOS);
|
@ -7,13 +7,14 @@ import subprocess
|
||||
|
||||
def get_all_toplevel_filenames():
|
||||
'''Get a list of all the files in the (Mercurial or Git) repository.'''
|
||||
failed_cmds = []
|
||||
try:
|
||||
cmd = ['hg', 'manifest', '-q']
|
||||
all_filenames = subprocess.check_output(cmd, universal_newlines=True,
|
||||
stderr=subprocess.PIPE).split('\n')
|
||||
return all_filenames
|
||||
except:
|
||||
pass
|
||||
failed_cmds.append(cmd)
|
||||
|
||||
try:
|
||||
# Get the relative path to the top-level directory.
|
||||
@ -25,6 +26,6 @@ def get_all_toplevel_filenames():
|
||||
stderr=subprocess.PIPE).split('\n')
|
||||
return all_filenames
|
||||
except:
|
||||
pass
|
||||
failed_cmds.append(cmd)
|
||||
|
||||
raise Exception('failed to run any of the repo manifest commands', cmds)
|
||||
raise Exception('failed to run any of the repo manifest commands', failed_cmds)
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "mozilla/dom/WindowBinding.h"
|
||||
#include "mozilla/dom/ElementBinding.h"
|
||||
#include "Units.h"
|
||||
#include "nsContentListDeclarations.h"
|
||||
|
||||
class nsIFrame;
|
||||
class nsIDOMMozNamedAttrMap;
|
||||
@ -61,11 +62,6 @@ namespace dom {
|
||||
} // namespace mozilla
|
||||
|
||||
|
||||
already_AddRefed<nsContentList>
|
||||
NS_GetContentList(nsINode* aRootNode,
|
||||
int32_t aMatchNameSpaceId,
|
||||
const nsAString& aTagname);
|
||||
|
||||
#define ELEMENT_FLAG_BIT(n_) NODE_FLAG_BIT(NODE_TYPE_SPECIFIC_BITS_OFFSET + (n_))
|
||||
|
||||
// Element-specific flags
|
||||
|
@ -198,7 +198,8 @@ NS_GetContentList(nsINode* aRootNode,
|
||||
NS_ASSERTION(aRootNode, "content list has to have a root");
|
||||
|
||||
nsRefPtr<nsContentList> list;
|
||||
nsContentListKey hashKey(aRootNode, aMatchNameSpaceId, aTagname);
|
||||
nsContentListKey hashKey(aRootNode, aMatchNameSpaceId, aTagname,
|
||||
aRootNode->OwnerDoc()->IsHTMLDocument());
|
||||
uint32_t recentlyUsedCacheIndex = RecentlyUsedCacheIndex(hashKey);
|
||||
nsContentList* cachedList = sRecentlyUsedContentLists[recentlyUsedCacheIndex];
|
||||
if (cachedList && cachedList->MatchesKey(hashKey)) {
|
||||
@ -398,7 +399,8 @@ nsContentList::nsContentList(nsINode* aRootNode,
|
||||
mData(nullptr),
|
||||
mState(LIST_DIRTY),
|
||||
mDeep(aDeep),
|
||||
mFuncMayDependOnAttr(false)
|
||||
mFuncMayDependOnAttr(false),
|
||||
mIsHTMLDocument(aRootNode->OwnerDoc()->IsHTMLDocument())
|
||||
{
|
||||
NS_ASSERTION(mRootNode, "Must have root");
|
||||
if (nsGkAtoms::_asterisk == mHTMLMatchAtom) {
|
||||
@ -438,7 +440,8 @@ nsContentList::nsContentList(nsINode* aRootNode,
|
||||
mState(LIST_DIRTY),
|
||||
mMatchAll(false),
|
||||
mDeep(aDeep),
|
||||
mFuncMayDependOnAttr(aFuncMayDependOnAttr)
|
||||
mFuncMayDependOnAttr(aFuncMayDependOnAttr),
|
||||
mIsHTMLDocument(false)
|
||||
{
|
||||
NS_ASSERTION(mRootNode, "Must have root");
|
||||
mRootNode->AddMutationObserver(this);
|
||||
@ -839,25 +842,20 @@ nsContentList::Match(Element *aElement)
|
||||
if (!mXMLMatchAtom)
|
||||
return false;
|
||||
|
||||
mozilla::dom::NodeInfo *ni = aElement->NodeInfo();
|
||||
|
||||
bool unknown = mMatchNameSpaceId == kNameSpaceID_Unknown;
|
||||
bool wildcard = mMatchNameSpaceId == kNameSpaceID_Wildcard;
|
||||
NodeInfo *ni = aElement->NodeInfo();
|
||||
|
||||
bool wildcard = mMatchNameSpaceId == kNameSpaceID_Wildcard ||
|
||||
mMatchNameSpaceId == kNameSpaceID_Unknown;
|
||||
bool toReturn = mMatchAll;
|
||||
if (!unknown && !wildcard)
|
||||
if (!wildcard)
|
||||
toReturn &= ni->NamespaceEquals(mMatchNameSpaceId);
|
||||
|
||||
if (toReturn)
|
||||
return toReturn;
|
||||
|
||||
bool matchHTML = aElement->GetNameSpaceID() == kNameSpaceID_XHTML &&
|
||||
aElement->OwnerDoc()->IsHTMLDocument();
|
||||
|
||||
if (unknown) {
|
||||
return matchHTML ? ni->QualifiedNameEquals(mHTMLMatchAtom) :
|
||||
ni->QualifiedNameEquals(mXMLMatchAtom);
|
||||
}
|
||||
|
||||
bool matchHTML =
|
||||
mIsHTMLDocument && aElement->GetNameSpaceID() == kNameSpaceID_XHTML;
|
||||
|
||||
if (wildcard) {
|
||||
return matchHTML ? ni->Equals(mHTMLMatchAtom) :
|
||||
ni->Equals(mXMLMatchAtom);
|
||||
@ -962,7 +960,7 @@ nsContentList::RemoveFromHashtable()
|
||||
}
|
||||
|
||||
nsDependentAtomString str(mXMLMatchAtom);
|
||||
nsContentListKey key(mRootNode, mMatchNameSpaceId, str);
|
||||
nsContentListKey key(mRootNode, mMatchNameSpaceId, str, mIsHTMLDocument);
|
||||
uint32_t recentlyUsedCacheIndex = RecentlyUsedCacheIndex(key);
|
||||
if (sRecentlyUsedContentLists[recentlyUsedCacheIndex] == this) {
|
||||
sRecentlyUsedContentLists[recentlyUsedCacheIndex] = nullptr;
|
||||
|
@ -142,14 +142,21 @@ private:
|
||||
*/
|
||||
struct nsContentListKey
|
||||
{
|
||||
// We have to take an aIsHTMLDocument arg for two reasons:
|
||||
// 1) We don't want to include nsIDocument.h in this header.
|
||||
// 2) We need to do that to make nsContentList::RemoveFromHashtable
|
||||
// work, because by the time it's called the document of the
|
||||
// list's root node might have changed.
|
||||
nsContentListKey(nsINode* aRootNode,
|
||||
int32_t aMatchNameSpaceId,
|
||||
const nsAString& aTagname)
|
||||
const nsAString& aTagname,
|
||||
bool aIsHTMLDocument)
|
||||
: mRootNode(aRootNode),
|
||||
mMatchNameSpaceId(aMatchNameSpaceId),
|
||||
mTagname(aTagname),
|
||||
mIsHTMLDocument(aIsHTMLDocument),
|
||||
mHash(mozilla::AddToHash(mozilla::HashString(aTagname), mRootNode,
|
||||
mMatchNameSpaceId))
|
||||
mMatchNameSpaceId, mIsHTMLDocument))
|
||||
{
|
||||
}
|
||||
|
||||
@ -157,6 +164,7 @@ struct nsContentListKey
|
||||
: mRootNode(aContentListKey.mRootNode),
|
||||
mMatchNameSpaceId(aContentListKey.mMatchNameSpaceId),
|
||||
mTagname(aContentListKey.mTagname),
|
||||
mIsHTMLDocument(aContentListKey.mIsHTMLDocument),
|
||||
mHash(aContentListKey.mHash)
|
||||
{
|
||||
}
|
||||
@ -169,6 +177,7 @@ struct nsContentListKey
|
||||
nsINode* const mRootNode; // Weak ref
|
||||
const int32_t mMatchNameSpaceId;
|
||||
const nsAString& mTagname;
|
||||
bool mIsHTMLDocument;
|
||||
const uint32_t mHash;
|
||||
};
|
||||
|
||||
@ -209,7 +218,7 @@ public:
|
||||
* The special value "*" always matches whatever aMatchAtom
|
||||
* is matched against.
|
||||
* @param aMatchNameSpaceId If kNameSpaceID_Unknown, then aMatchAtom is the
|
||||
* tagName to match.
|
||||
* localName to match.
|
||||
* If kNameSpaceID_Wildcard, then aMatchAtom is the
|
||||
* localName to match.
|
||||
* Otherwise we match nodes whose namespace is
|
||||
@ -237,7 +246,8 @@ public:
|
||||
* deeper. If true, then look at the whole subtree rooted at
|
||||
* our root.
|
||||
* @param aMatchAtom an atom to be passed back to aFunc
|
||||
* @param aMatchNameSpaceId a namespace id to be passed back to aFunc
|
||||
* @param aMatchNameSpaceId a namespace id to be passed back to aFunc. Is
|
||||
allowed to be kNameSpaceID_Unknown.
|
||||
* @param aFuncMayDependOnAttr a boolean that indicates whether this list is
|
||||
* sensitive to attribute changes.
|
||||
*/
|
||||
@ -318,13 +328,15 @@ public:
|
||||
{
|
||||
// The root node is most commonly the same: the document. And the
|
||||
// most common namespace id is kNameSpaceID_Unknown. So check the
|
||||
// string first.
|
||||
// string first. Cases in which whether our root's ownerDocument
|
||||
// is HTML changes are extremely rare, so check those last.
|
||||
NS_PRECONDITION(mXMLMatchAtom,
|
||||
"How did we get here with a null match atom on our list?");
|
||||
return
|
||||
mXMLMatchAtom->Equals(aKey.mTagname) &&
|
||||
mRootNode == aKey.mRootNode &&
|
||||
mMatchNameSpaceId == aKey.mMatchNameSpaceId;
|
||||
mMatchNameSpaceId == aKey.mMatchNameSpaceId &&
|
||||
mIsHTMLDocument == aKey.mIsHTMLDocument;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -445,6 +457,12 @@ protected:
|
||||
* Whether we actually need to flush to get our state correct.
|
||||
*/
|
||||
uint8_t mFlushesNeeded : 1;
|
||||
/**
|
||||
* Whether the ownerDocument of our root node at list creation time was an
|
||||
* HTML document. Only needed when we're doing a namespace/atom match, not
|
||||
* when doing function matching, always false otherwise.
|
||||
*/
|
||||
uint8_t mIsHTMLDocument : 1;
|
||||
|
||||
#ifdef DEBUG_CONTENT_LIST
|
||||
void AssertInSync();
|
||||
|
@ -9,12 +9,14 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsStringFwd.h"
|
||||
|
||||
class nsContentList;
|
||||
class nsIAtom;
|
||||
class nsIContent;
|
||||
class nsINode;
|
||||
// Can't use nsStringFwd.h because that's internal-API-only.
|
||||
class nsString;
|
||||
class nsAString;
|
||||
|
||||
// Magic namespace id that means "match all namespaces". This is
|
||||
// negative so it won't collide with actual namespace constants.
|
||||
@ -42,8 +44,9 @@ typedef void* (*nsFuncStringContentListDataAllocator)(nsINode* aRootNode,
|
||||
// If aMatchNameSpaceId is kNameSpaceID_Unknown, this will return a
|
||||
// content list which matches ASCIIToLower(aTagname) against HTML
|
||||
// elements in HTML documents and aTagname against everything else.
|
||||
// For any other value of aMatchNameSpaceId, the list will match
|
||||
// aTagname against all elements.
|
||||
// The comparison is done to the element's localName. For any
|
||||
// other value of aMatchNameSpaceId, the list will match aTagname
|
||||
// against all elements, again comparing to the localName.
|
||||
already_AddRefed<nsContentList>
|
||||
NS_GetContentList(nsINode* aRootNode,
|
||||
int32_t aMatchNameSpaceId,
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "mozilla/UseCounter.h"
|
||||
#include "mozilla/WeakPtr.h"
|
||||
#include "Units.h"
|
||||
#include "nsContentListDeclarations.h"
|
||||
#include "nsExpirationTracker.h"
|
||||
#include "nsClassHashtable.h"
|
||||
#include "prclist.h"
|
||||
@ -176,11 +177,6 @@ enum DocumentFlavor {
|
||||
// Some function forward-declarations
|
||||
class nsContentList;
|
||||
|
||||
already_AddRefed<nsContentList>
|
||||
NS_GetContentList(nsINode* aRootNode,
|
||||
int32_t aMatchNameSpaceId,
|
||||
const nsAString& aTagname);
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
// Document interface. This is implemented by all document objects in
|
||||
|
@ -32,7 +32,7 @@ function test_getElementsByTagName()
|
||||
do_check_eq(doc.getElementById("test2").getElementsByTagName("*").length,
|
||||
8);
|
||||
do_check_eq(doc.getElementById("test2").getElementsByTagName("test").length,
|
||||
3);
|
||||
7);
|
||||
|
||||
// Check that the first element of getElementsByTagName on the document is
|
||||
// the right thing.
|
||||
@ -40,7 +40,7 @@ function test_getElementsByTagName()
|
||||
|
||||
// Check that we get the right things in the right order
|
||||
var numTests = doc.getElementsByTagName("test").length;
|
||||
do_check_eq(numTests, 5);
|
||||
do_check_eq(numTests, 14);
|
||||
|
||||
for (var i = 1; i <= numTests; ++i) {
|
||||
do_check_true(doc.getElementById("test" + i) instanceof nsIDOMElement);
|
||||
@ -51,15 +51,15 @@ function test_getElementsByTagName()
|
||||
// Check that we handle tagnames containing ':' correctly
|
||||
do_check_true(doc.getElementsByTagName("foo:test")
|
||||
instanceof nsIDOMNodeList);
|
||||
do_check_eq(doc.getElementsByTagName("foo:test").length, 2);
|
||||
do_check_eq(doc.getElementsByTagName("foo:test").length, 0);
|
||||
|
||||
do_check_true(doc.getElementsByTagName("foo2:test")
|
||||
instanceof nsIDOMNodeList);
|
||||
do_check_eq(doc.getElementsByTagName("foo2:test").length, 3);
|
||||
do_check_eq(doc.getElementsByTagName("foo2:test").length, 0);
|
||||
|
||||
do_check_true(doc.getElementsByTagName("bar:test")
|
||||
instanceof nsIDOMNodeList);
|
||||
do_check_eq(doc.getElementsByTagName("bar:test").length, 4);
|
||||
do_check_eq(doc.getElementsByTagName("bar:test").length, 0);
|
||||
}
|
||||
|
||||
function test_getElementsByTagNameNS()
|
||||
|
@ -700,6 +700,10 @@ DOMInterfaces = {
|
||||
'notflattened': True
|
||||
},
|
||||
|
||||
'IterableIterator': {
|
||||
'skipGen': True
|
||||
},
|
||||
|
||||
'KeyEvent': {
|
||||
'concrete': False
|
||||
},
|
||||
|
@ -1121,7 +1121,10 @@ class CGHeaders(CGWrapper):
|
||||
# Now for non-callback descriptors make sure we include any
|
||||
# headers needed by Func declarations.
|
||||
for desc in descriptors:
|
||||
if desc.interface.isExternal():
|
||||
# If this is an iterator interface generated for a seperate
|
||||
# iterable interface, skip generating type includes, as we have
|
||||
# what we need in IterableIterator.h
|
||||
if desc.interface.isExternal() or desc.interface.isIteratorInterface():
|
||||
continue
|
||||
|
||||
def addHeaderForFunc(func):
|
||||
@ -1148,16 +1151,15 @@ class CGHeaders(CGWrapper):
|
||||
if funcList is not None:
|
||||
addHeaderForFunc(funcList[0])
|
||||
|
||||
for desc in descriptors:
|
||||
if desc.interface.maplikeOrSetlike:
|
||||
if desc.interface.maplikeOrSetlikeOrIterable:
|
||||
# We need ToJSValue.h for maplike/setlike type conversions
|
||||
bindingHeaders.add("mozilla/dom/ToJSValue.h")
|
||||
# Add headers for the key and value types of the maplike, since
|
||||
# they'll be needed for convenience functions
|
||||
addHeadersForType((desc.interface.maplikeOrSetlike.keyType,
|
||||
addHeadersForType((desc.interface.maplikeOrSetlikeOrIterable.keyType,
|
||||
desc, None))
|
||||
if desc.interface.maplikeOrSetlike.valueType:
|
||||
addHeadersForType((desc.interface.maplikeOrSetlike.valueType,
|
||||
if desc.interface.maplikeOrSetlikeOrIterable.valueType:
|
||||
addHeadersForType((desc.interface.maplikeOrSetlikeOrIterable.valueType,
|
||||
desc, None))
|
||||
|
||||
for d in dictionaries:
|
||||
@ -2197,13 +2199,18 @@ class MethodDefiner(PropertyDefiner):
|
||||
})
|
||||
continue
|
||||
|
||||
# Iterable methods should be enumerable, maplike/setlike methods
|
||||
# should not.
|
||||
isMaplikeOrSetlikeMethod = (m.isMaplikeOrSetlikeOrIterableMethod() and
|
||||
(m.maplikeOrSetlikeOrIterable.isMaplike() or
|
||||
m.maplikeOrSetlikeOrIterable.isSetlike()))
|
||||
method = {
|
||||
"name": m.identifier.name,
|
||||
"methodInfo": not m.isStatic(),
|
||||
"length": methodLength(m),
|
||||
# Methods generated for a maplike/setlike declaration are not
|
||||
# enumerable.
|
||||
"flags": "JSPROP_ENUMERATE" if not m.isMaplikeOrSetlikeMethod() else "0",
|
||||
"flags": "JSPROP_ENUMERATE" if not isMaplikeOrSetlikeMethod else "0",
|
||||
"condition": PropertyDefiner.getControllingCondition(m, descriptor),
|
||||
"allowCrossOriginThis": m.getExtendedAttribute("CrossOriginCallable"),
|
||||
"returnsPromise": m.returnsPromise(),
|
||||
@ -2247,19 +2254,23 @@ class MethodDefiner(PropertyDefiner):
|
||||
|
||||
# Generate the maplike/setlike iterator, if one wasn't already
|
||||
# generated by a method. If we already have an @@iterator symbol, fail.
|
||||
if descriptor.interface.maplikeOrSetlike:
|
||||
if descriptor.interface.maplikeOrSetlikeOrIterable:
|
||||
if hasIterator(methods, self.regular):
|
||||
raise TypeError("Cannot have maplike/setlike interface with "
|
||||
raise TypeError("Cannot have maplike/setlike/iterable interface with "
|
||||
"other members that generate @@iterator "
|
||||
"on interface %s, such as indexed getters "
|
||||
"or aliased functions." %
|
||||
self.descriptor.interface.identifier.name)
|
||||
for m in methods:
|
||||
if (m.isMaplikeOrSetlikeMethod() and
|
||||
((m.maplikeOrSetlike.isMaplike() and
|
||||
m.identifier.name == "entries") or
|
||||
(m.maplikeOrSetlike.isSetlike() and
|
||||
m.identifier.name == "values"))):
|
||||
if (m.isMaplikeOrSetlikeOrIterableMethod() and
|
||||
(((m.maplikeOrSetlikeOrIterable.isMaplike() or
|
||||
(m.maplikeOrSetlikeOrIterable.isIterable() and
|
||||
m.maplikeOrSetlikeOrIterable.hasValueType())) and
|
||||
m.identifier.name == "entries") or
|
||||
(((m.maplikeOrSetlikeOrIterable.isSetlike() or
|
||||
(m.maplikeOrSetlikeOrIterable.isIterable() and
|
||||
not m.maplikeOrSetlikeOrIterable.hasValueType()))) and
|
||||
m.identifier.name == "values"))):
|
||||
self.regular.append({
|
||||
"name": "@@iterator",
|
||||
"methodName": m.identifier.name,
|
||||
@ -5810,8 +5821,10 @@ class CGArgumentConverter(CGThing):
|
||||
# If we have a method generated by the maplike/setlike portion of an
|
||||
# interface, arguments can possibly be undefined, but will need to be
|
||||
# converted to the key/value type of the backing object. In this case,
|
||||
# use .get() instead of direct access to the argument.
|
||||
if member.isMethod() and member.isMaplikeOrSetlikeMethod():
|
||||
# use .get() instead of direct access to the argument. This won't
|
||||
# matter for iterable since generated functions for those interface
|
||||
# don't take arguments.
|
||||
if member.isMethod() and member.isMaplikeOrSetlikeOrIterableMethod():
|
||||
self.replacementVariables["val"] = string.Template(
|
||||
"args.get(${index})").substitute(replacer)
|
||||
else:
|
||||
@ -7111,10 +7124,16 @@ class CGPerSignatureCall(CGThing):
|
||||
# If this is a method that was generated by a maplike/setlike
|
||||
# interface, use the maplike/setlike generator to fill in the body.
|
||||
# Otherwise, use CGCallGenerator to call the native method.
|
||||
if idlNode.isMethod() and idlNode.isMaplikeOrSetlikeMethod():
|
||||
cgThings.append(CGMaplikeOrSetlikeMethodGenerator(descriptor,
|
||||
idlNode.maplikeOrSetlike,
|
||||
idlNode.identifier.name))
|
||||
if idlNode.isMethod() and idlNode.isMaplikeOrSetlikeOrIterableMethod():
|
||||
if (idlNode.maplikeOrSetlikeOrIterable.isMaplike() or
|
||||
idlNode.maplikeOrSetlikeOrIterable.isSetlike()):
|
||||
cgThings.append(CGMaplikeOrSetlikeMethodGenerator(descriptor,
|
||||
idlNode.maplikeOrSetlikeOrIterable,
|
||||
idlNode.identifier.name))
|
||||
else:
|
||||
cgThings.append(CGIterableMethodGenerator(descriptor,
|
||||
idlNode.maplikeOrSetlikeOrIterable,
|
||||
idlNode.identifier.name))
|
||||
else:
|
||||
cgThings.append(CGCallGenerator(
|
||||
self.getErrorReport() if self.isFallible() else None,
|
||||
@ -7349,7 +7368,7 @@ class CGMethodCall(CGThing):
|
||||
# Skip required arguments check for maplike/setlike interfaces, as
|
||||
# they can have arguments which are not passed, and are treated as
|
||||
# if undefined had been explicitly passed.
|
||||
if requiredArgs > 0 and not method.isMaplikeOrSetlikeMethod():
|
||||
if requiredArgs > 0 and not method.isMaplikeOrSetlikeOrIterableMethod():
|
||||
code = fill(
|
||||
"""
|
||||
if (MOZ_UNLIKELY(args.length() < ${requiredArgs})) {
|
||||
@ -12779,6 +12798,10 @@ class CGForwardDeclarations(CGWrapper):
|
||||
|
||||
# Needed for at least Wrap.
|
||||
for d in descriptors:
|
||||
# If this is a generated iterator interface, we only create these
|
||||
# in the generated bindings, and don't need to forward declare.
|
||||
if d.interface.isIteratorInterface():
|
||||
continue
|
||||
builder.add(d.nativeType)
|
||||
# If we're an interface and we have a maplike/setlike declaration,
|
||||
# we'll have helper functions exposed to the native side of our
|
||||
@ -12786,17 +12809,23 @@ class CGForwardDeclarations(CGWrapper):
|
||||
# our key/value types are interfaces, they'll be passed as
|
||||
# arguments to helper functions, and they'll need to be forward
|
||||
# declared in the header.
|
||||
if d.interface.maplikeOrSetlike:
|
||||
builder.forwardDeclareForType(d.interface.maplikeOrSetlike.keyType,
|
||||
config)
|
||||
builder.forwardDeclareForType(d.interface.maplikeOrSetlike.valueType,
|
||||
if d.interface.maplikeOrSetlikeOrIterable:
|
||||
builder.forwardDeclareForType(d.interface.maplikeOrSetlikeOrIterable.keyType,
|
||||
config)
|
||||
if d.interface.maplikeOrSetlikeOrIterable.hasValueType():
|
||||
builder.forwardDeclareForType(d.interface.maplikeOrSetlikeOrIterable.valueType,
|
||||
config)
|
||||
|
||||
# We just about always need NativePropertyHooks
|
||||
builder.addInMozillaDom("NativePropertyHooks", isStruct=True)
|
||||
builder.addInMozillaDom("ProtoAndIfaceCache")
|
||||
# Add the atoms cache type, even if we don't need it.
|
||||
for d in descriptors:
|
||||
# Iterators have native types that are template classes, so
|
||||
# creating an 'Atoms' cache type doesn't work for them, and is one
|
||||
# of the cases where we don't need it anyways.
|
||||
if d.interface.isIteratorInterface():
|
||||
continue
|
||||
builder.add(d.nativeType + "Atoms", isStruct=True)
|
||||
|
||||
for callback in mainCallbacks:
|
||||
@ -12859,6 +12888,8 @@ class CGBindingRoot(CGThing):
|
||||
|
||||
bindingDeclareHeaders["mozilla/dom/UnionMember.h"] = len(unionStructs) > 0
|
||||
bindingDeclareHeaders["mozilla/dom/BindingUtils.h"] = len(unionStructs) > 0
|
||||
bindingDeclareHeaders["mozilla/dom/IterableIterator.h"] = any(d.interface.isIteratorInterface() or
|
||||
d.interface.isIterable() for d in descriptors)
|
||||
|
||||
def descriptorHasCrossOriginProperties(desc):
|
||||
def hasCrossOriginProperty(m):
|
||||
@ -12922,14 +12953,6 @@ class CGBindingRoot(CGThing):
|
||||
bindingHeaders["nsIGlobalObject.h"] = jsImplemented
|
||||
bindingHeaders["AtomList.h"] = hasNonEmptyDictionaries or jsImplemented or callbackDescriptors
|
||||
|
||||
def addHeaderBasedOnTypes(header, typeChecker):
|
||||
bindingHeaders[header] = (
|
||||
bindingHeaders.get(header, False) or
|
||||
any(map(typeChecker,
|
||||
getAllTypes(descriptors + callbackDescriptors,
|
||||
dictionaries,
|
||||
mainCallbacks + workerCallbacks))))
|
||||
|
||||
# Only mainthread things can have hasXPConnectImpls
|
||||
provider = config.getDescriptorProvider(False)
|
||||
|
||||
@ -14966,7 +14989,7 @@ def getMaplikeOrSetlikeBackingObject(descriptor, maplikeOrSetlike, helperImpl=No
|
||||
Generate code to get/create a JS backing object for a maplike/setlike
|
||||
declaration from the declaration slot.
|
||||
"""
|
||||
func_prefix = maplikeOrSetlike.maplikeOrSetlikeType.title()
|
||||
func_prefix = maplikeOrSetlike.maplikeOrSetlikeOrIterableType.title()
|
||||
ret = fill(
|
||||
"""
|
||||
JS::Rooted<JSObject*> backingObj(cx);
|
||||
@ -15403,8 +15426,11 @@ class CGMaplikeOrSetlikeHelperGenerator(CGNamespace):
|
||||
"""
|
||||
def __init__(self, descriptor, maplikeOrSetlike):
|
||||
self.descriptor = descriptor
|
||||
# Since iterables are folded in with maplike/setlike, make sure we've
|
||||
# got the right type here.
|
||||
assert maplikeOrSetlike.isMaplike() or maplikeOrSetlike.isSetlike()
|
||||
self.maplikeOrSetlike = maplikeOrSetlike
|
||||
self.namespace = "%sHelpers" % (self.maplikeOrSetlike.maplikeOrSetlikeType.title())
|
||||
self.namespace = "%sHelpers" % (self.maplikeOrSetlike.maplikeOrSetlikeOrIterableType.title())
|
||||
self.helpers = [
|
||||
CGMaplikeOrSetlikeHelperFunctionGenerator(descriptor,
|
||||
maplikeOrSetlike,
|
||||
@ -15436,6 +15462,26 @@ class CGMaplikeOrSetlikeHelperGenerator(CGNamespace):
|
||||
CGNamespace.__init__(self, self.namespace, CGList(self.helpers))
|
||||
|
||||
|
||||
class CGIterableMethodGenerator(CGGeneric):
|
||||
"""
|
||||
Creates methods for iterable interfaces. Unwrapping/wrapping
|
||||
will be taken care of by the usual method generation machinery in
|
||||
CGMethodCall/CGPerSignatureCall. Functionality is filled in here instead of
|
||||
using CGCallGenerator.
|
||||
"""
|
||||
def __init__(self, descriptor, iterable, methodName):
|
||||
CGGeneric.__init__(self, fill(
|
||||
"""
|
||||
typedef IterableIterator<${nativeType}> itrType;
|
||||
nsRefPtr<itrType> result(new itrType(self,
|
||||
itrType::IterableIteratorType::${itrMethod},
|
||||
&${ifaceName}IteratorBinding::Wrap));
|
||||
""",
|
||||
nativeType=descriptor.nativeType,
|
||||
ifaceName=descriptor.interface.identifier.name,
|
||||
itrMethod=methodName.title()))
|
||||
|
||||
|
||||
class GlobalGenRoots():
|
||||
"""
|
||||
Roots for global codegen.
|
||||
|
@ -26,6 +26,7 @@ class Configuration:
|
||||
# |parseData|.
|
||||
self.descriptors = []
|
||||
self.interfaces = {}
|
||||
self.descriptorsByName = {}
|
||||
self.optimizedOutDescriptorNames = set()
|
||||
self.generatedEvents = generatedEvents
|
||||
self.maxProtoChainLength = 0
|
||||
@ -86,15 +87,18 @@ class Configuration:
|
||||
else:
|
||||
raise TypeError("Interface " + iface.identifier.name +
|
||||
" should have no more than two entries in Bindings.conf")
|
||||
self.descriptors.extend([Descriptor(self, iface, x) for x in entry])
|
||||
descs = [Descriptor(self, iface, x) for x in entry]
|
||||
self.descriptors.extend(descs)
|
||||
# Setting up descriptorsByName while iterating through interfaces
|
||||
# means we can get the nativeType of iterable interfaces without
|
||||
# having to do multiple loops.
|
||||
for d in descs:
|
||||
self.descriptorsByName.setdefault(d.interface.identifier.name,
|
||||
[]).append(d)
|
||||
|
||||
# Keep the descriptor list sorted for determinism.
|
||||
self.descriptors.sort(lambda x, y: cmp(x.name, y.name))
|
||||
|
||||
self.descriptorsByName = {}
|
||||
for d in self.descriptors:
|
||||
self.descriptorsByName.setdefault(d.interface.identifier.name,
|
||||
[]).append(d)
|
||||
|
||||
self.descriptorsByFile = {}
|
||||
for d in self.descriptors:
|
||||
@ -348,7 +352,18 @@ class Descriptor(DescriptorProvider):
|
||||
|
||||
# Read the desc, and fill in the relevant defaults.
|
||||
ifaceName = self.interface.identifier.name
|
||||
if self.interface.isExternal():
|
||||
# For generated iterator interfaces for other iterable interfaces, we
|
||||
# just use IterableIterator as the native type, templated on the
|
||||
# nativeType of the iterable interface. That way we can have a
|
||||
# templated implementation for all the duplicated iterator
|
||||
# functionality.
|
||||
if self.interface.isIteratorInterface():
|
||||
itrName = self.interface.iterableInterface.identifier.name
|
||||
itrDesc = self.getDescriptor(itrName)
|
||||
nativeTypeDefault = ("mozilla::dom::IterableIterator<%s>"
|
||||
% itrDesc.nativeType)
|
||||
|
||||
elif self.interface.isExternal():
|
||||
assert not self.workers
|
||||
nativeTypeDefault = "nsIDOM" + ifaceName
|
||||
elif self.interface.isCallback():
|
||||
@ -386,6 +401,8 @@ class Descriptor(DescriptorProvider):
|
||||
headerDefault = "mozilla/dom/workers/bindings/%s.h" % ifaceName
|
||||
elif not self.interface.isExternal() and self.interface.getExtendedAttribute("HeaderFile"):
|
||||
headerDefault = self.interface.getExtendedAttribute("HeaderFile")[0]
|
||||
elif self.interface.isIteratorInterface():
|
||||
headerDefault = "mozilla/dom/IterableIterator.h"
|
||||
else:
|
||||
headerDefault = self.nativeType
|
||||
headerDefault = headerDefault.replace("::", "/") + ".h"
|
||||
@ -514,6 +531,7 @@ class Descriptor(DescriptorProvider):
|
||||
if desc.get('wantsQI', None) is not None:
|
||||
self._wantsQI = desc.get('wantsQI', None)
|
||||
self.wrapperCache = (not self.interface.isCallback() and
|
||||
not self.interface.isIteratorInterface() and
|
||||
desc.get('wrapperCache', True))
|
||||
|
||||
def make_name(name):
|
||||
|
35
dom/bindings/IterableIterator.cpp
Normal file
35
dom/bindings/IterableIterator.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* 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 "mozilla/dom/IterableIterator.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
// Due to IterableIterator being a templated class, we implement the necessary
|
||||
// CC bits in a superclass that IterableIterator then inherits from. This allows
|
||||
// us to put the macros outside of the header. The base class has pure virtual
|
||||
// functions for Traverse/Unlink that the templated subclasses will override.
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(IterableIteratorBase)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(IterableIteratorBase)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(IterableIteratorBase)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IterableIteratorBase)
|
||||
tmp->TraverseHelper(cb);
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(IterableIteratorBase)
|
||||
tmp->UnlinkHelper();
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IterableIteratorBase)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
}
|
||||
}
|
192
dom/bindings/IterableIterator.h
Normal file
192
dom/bindings/IterableIterator.h
Normal file
@ -0,0 +1,192 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* 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/. */
|
||||
|
||||
/**
|
||||
* The IterableIterator class is used for WebIDL interfaces that have a
|
||||
* iterable<> member defined. It handles the ES6 Iterator-like functions that
|
||||
* are generated for the iterable interface.
|
||||
*
|
||||
* For iterable interfaces, the implementation class will need to contain three
|
||||
* functions:
|
||||
*
|
||||
* - size_t GetIterableLength()
|
||||
* - Returns the number of elements available to iterate over
|
||||
* - [type] GetKeyAtIndex(size_t index)
|
||||
* - Returns the key at the requested index
|
||||
* - [type] GetValueAtIndex(size_t index)
|
||||
* - Returns the value at the requested index, or the key again if this is
|
||||
* a single type iterator.
|
||||
*
|
||||
* Examples of iterable interface implementations can be found in the bindings
|
||||
* test directory.
|
||||
*/
|
||||
|
||||
#ifndef mozilla_dom_IterableIterator_h
|
||||
#define mozilla_dom_IterableIterator_h
|
||||
|
||||
#include "nsISupports.h"
|
||||
#include "nsWrapperCache.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "mozilla/dom/ToJSValue.h"
|
||||
#include "jswrapper.h"
|
||||
#include "mozilla/dom/IterableIteratorBinding.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class IterableIteratorBase : public nsISupports
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS(IterableIteratorBase)
|
||||
typedef enum {
|
||||
Keys = 0,
|
||||
Values,
|
||||
Entries
|
||||
} IterableIteratorType;
|
||||
|
||||
IterableIteratorBase() {}
|
||||
|
||||
protected:
|
||||
virtual ~IterableIteratorBase() {}
|
||||
virtual void UnlinkHelper() = 0;
|
||||
virtual void TraverseHelper(nsCycleCollectionTraversalCallback& cb) = 0;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class IterableIterator final : public IterableIteratorBase
|
||||
{
|
||||
public:
|
||||
|
||||
typedef bool (*WrapFunc)(JSContext* aCx,
|
||||
mozilla::dom::IterableIterator<T>* aObject,
|
||||
JS::Handle<JSObject*> aGivenProto,
|
||||
JS::MutableHandle<JSObject*> aReflector);
|
||||
IterableIterator(T* aIterableObj, IterableIteratorType aIteratorType, WrapFunc aWrapFunc)
|
||||
: mIteratorType(aIteratorType)
|
||||
, mIterableObj(aIterableObj)
|
||||
, mIndex(0)
|
||||
, mWrapFunc(aWrapFunc)
|
||||
{
|
||||
MOZ_ASSERT(mIterableObj);
|
||||
MOZ_ASSERT(mWrapFunc);
|
||||
}
|
||||
|
||||
void
|
||||
DictReturn(JSContext* aCx, JS::MutableHandle<JSObject*> aResult,
|
||||
bool aDone, JS::Handle<JS::Value> aValue, ErrorResult& aRv)
|
||||
{
|
||||
RootedDictionary<IterableKeyOrValueResult> dict(aCx);
|
||||
dict.mDone = aDone;
|
||||
dict.mValue = aValue;
|
||||
JS::Rooted<JS::Value> dictValue(aCx);
|
||||
if (!ToJSValue(aCx, dict, &dictValue)) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return;
|
||||
}
|
||||
aResult.set(&dictValue.toObject());
|
||||
}
|
||||
|
||||
void
|
||||
Next(JSContext* aCx, JS::MutableHandle<JSObject*> aResult, ErrorResult& aRv)
|
||||
{
|
||||
JS::Rooted<JS::Value> value(aCx, JS::UndefinedValue());
|
||||
if (mIndex >= mIterableObj->GetIterableLength()) {
|
||||
DictReturn(aCx, aResult, true, value, aRv);
|
||||
return;
|
||||
}
|
||||
switch (mIteratorType) {
|
||||
case IterableIteratorType::Keys:
|
||||
{
|
||||
if (!ToJSValue(aCx, mIterableObj->GetKeyAtIndex(mIndex), &value)) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return;
|
||||
}
|
||||
DictReturn(aCx, aResult, false, value, aRv);
|
||||
break;
|
||||
}
|
||||
case IterableIteratorType::Values:
|
||||
{
|
||||
if (!ToJSValue(aCx, mIterableObj->GetValueAtIndex(mIndex), &value)) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return;
|
||||
}
|
||||
DictReturn(aCx, aResult, false, value, aRv);
|
||||
break;
|
||||
}
|
||||
case IterableIteratorType::Entries:
|
||||
{
|
||||
JS::Rooted<JS::Value> key(aCx);
|
||||
if (!ToJSValue(aCx, mIterableObj->GetKeyAtIndex(mIndex), &key)) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return;
|
||||
}
|
||||
if (!ToJSValue(aCx, mIterableObj->GetValueAtIndex(mIndex), &value)) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return;
|
||||
}
|
||||
RootedDictionary<IterableKeyAndValueResult> dict(aCx);
|
||||
dict.mDone = false;
|
||||
// Dictionary values are a Sequence, which is a FallibleTArray, so we need
|
||||
// to check returns when appending.
|
||||
if (!dict.mValue.AppendElement(key, mozilla::fallible)) {
|
||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return;
|
||||
}
|
||||
if (!dict.mValue.AppendElement(value, mozilla::fallible)) {
|
||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return;
|
||||
}
|
||||
JS::Rooted<JS::Value> dictValue(aCx);
|
||||
if (!ToJSValue(aCx, dict, &dictValue)) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return;
|
||||
}
|
||||
aResult.set(&dictValue.toObject());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
MOZ_CRASH("Invalid iterator type!");
|
||||
}
|
||||
++mIndex;
|
||||
}
|
||||
virtual ~IterableIterator() {}
|
||||
|
||||
bool
|
||||
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aObj)
|
||||
{
|
||||
return (*mWrapFunc)(aCx, this, aGivenProto, aObj);
|
||||
}
|
||||
|
||||
protected:
|
||||
// Tells whether this is a key, value, or entries iterator.
|
||||
IterableIteratorType mIteratorType;
|
||||
// Binding Implementation Object that we're iterating over.
|
||||
nsRefPtr<T> mIterableObj;
|
||||
// Current index of iteration.
|
||||
uint32_t mIndex;
|
||||
// Function pointer to binding-type-specific Wrap() call for this iterator.
|
||||
WrapFunc mWrapFunc;
|
||||
|
||||
// Since we're templated on a binding, we need to possibly CC it, but can't do
|
||||
// that through macros. So it happens here.
|
||||
virtual void UnlinkHelper() final
|
||||
{
|
||||
mIterableObj = nullptr;
|
||||
}
|
||||
|
||||
virtual void TraverseHelper(nsCycleCollectionTraversalCallback& cb) override
|
||||
{
|
||||
IterableIterator<T>* tmp = this;
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIterableObj);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_IterableIterator_h
|
@ -27,6 +27,7 @@ EXPORTS.mozilla.dom += [
|
||||
'DOMString.h',
|
||||
'Errors.msg',
|
||||
'Exceptions.h',
|
||||
'IterableIterator.h',
|
||||
'JSSlots.h',
|
||||
'MozMap.h',
|
||||
'NonRefcountedDOMObject.h',
|
||||
@ -74,6 +75,7 @@ UNIFIED_SOURCES += [
|
||||
'Date.cpp',
|
||||
'DOMJSProxyHandler.cpp',
|
||||
'Exceptions.cpp',
|
||||
'IterableIterator.cpp',
|
||||
'ToJSValue.cpp',
|
||||
]
|
||||
|
||||
@ -88,12 +90,16 @@ SOURCES += [
|
||||
# them are only run in debug mode.
|
||||
if CONFIG['MOZ_DEBUG']:
|
||||
EXPORTS.mozilla.dom += [
|
||||
"test/TestInterfaceIterableDouble.h",
|
||||
"test/TestInterfaceIterableSingle.h",
|
||||
"test/TestInterfaceMaplike.h",
|
||||
"test/TestInterfaceMaplikeObject.h",
|
||||
"test/TestInterfaceSetlike.h",
|
||||
"test/TestInterfaceSetlikeNode.h"
|
||||
]
|
||||
UNIFIED_SOURCES += [
|
||||
"test/TestInterfaceIterableDouble.cpp",
|
||||
"test/TestInterfaceIterableSingle.cpp",
|
||||
"test/TestInterfaceMaplike.cpp",
|
||||
"test/TestInterfaceMaplikeObject.cpp",
|
||||
"test/TestInterfaceSetlike.cpp",
|
||||
|
@ -540,6 +540,9 @@ class IDLExternalInterface(IDLObjectWithIdentifier, IDLExposureMixins):
|
||||
def validate(self):
|
||||
pass
|
||||
|
||||
def isIteratorInterface(self):
|
||||
return False
|
||||
|
||||
def isExternal(self):
|
||||
return True
|
||||
|
||||
@ -640,7 +643,7 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
|
||||
self._callback = False
|
||||
self._finished = False
|
||||
self.members = []
|
||||
self.maplikeOrSetlike = None
|
||||
self.maplikeOrSetlikeOrIterable = None
|
||||
self._partialInterfaces = []
|
||||
self._extendedAttrDict = {}
|
||||
# namedConstructors needs deterministic ordering because bindings code
|
||||
@ -664,6 +667,9 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
|
||||
self.totalMembersInSlots = 0
|
||||
# Tracking of the number of own own members we have in slots
|
||||
self._ownMembersInSlots = 0
|
||||
# If this is an iterator interface, we need to know what iterable
|
||||
# interface we're iterating for in order to get its nativeType.
|
||||
self.iterableInterface = None
|
||||
|
||||
IDLObjectWithScope.__init__(self, location, parentScope, name)
|
||||
IDLExposureMixins.__init__(self, location)
|
||||
@ -682,6 +688,13 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
|
||||
except:
|
||||
return None
|
||||
|
||||
def isIterable(self):
|
||||
return (self.maplikeOrSetlikeOrIterable and
|
||||
self.maplikeOrSetlikeOrIterable.isIterable())
|
||||
|
||||
def isIteratorInterface(self):
|
||||
return self.iterableInterface is not None
|
||||
|
||||
def resolveIdentifierConflict(self, scope, identifier, originalObject, newObject):
|
||||
assert isinstance(scope, IDLScope)
|
||||
assert isinstance(originalObject, IDLInterfaceMember)
|
||||
@ -718,22 +731,22 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
|
||||
# need to be treated like regular interface members, do this before
|
||||
# things like exposure setting.
|
||||
for member in self.members:
|
||||
if member.isMaplikeOrSetlike():
|
||||
if member.isMaplikeOrSetlikeOrIterable():
|
||||
# Check that we only have one interface declaration (currently
|
||||
# there can only be one maplike/setlike declaration per
|
||||
# interface)
|
||||
if self.maplikeOrSetlike:
|
||||
if self.maplikeOrSetlikeOrIterable:
|
||||
raise WebIDLError("%s declaration used on "
|
||||
"interface that already has %s "
|
||||
"declaration" %
|
||||
(member.maplikeOrSetlikeType,
|
||||
self.maplikeOrSetlike.maplikeOrSetlikeType),
|
||||
[self.maplikeOrSetlike.location,
|
||||
(member.maplikeOrSetlikeOrIterableType,
|
||||
self.maplikeOrSetlike.maplikeOrSetlikeOrIterableType),
|
||||
[self.maplikeOrSetlikeOrIterable.location,
|
||||
member.location])
|
||||
self.maplikeOrSetlike = member
|
||||
self.maplikeOrSetlikeOrIterable = member
|
||||
# If we've got a maplike or setlike declaration, we'll be building all of
|
||||
# our required methods in Codegen. Generate members now.
|
||||
self.maplikeOrSetlike.expand(self.members, self.isJSImplemented())
|
||||
self.maplikeOrSetlikeOrIterable.expand(self.members, self.isJSImplemented())
|
||||
|
||||
# Now that we've merged in our partial interfaces, set the
|
||||
# _exposureGlobalNames on any members that don't have it set yet. Note
|
||||
@ -884,14 +897,14 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
|
||||
|
||||
# If we have a maplike or setlike, and the consequential interface
|
||||
# also does, throw an error.
|
||||
if iface.maplikeOrSetlike and self.maplikeOrSetlike:
|
||||
raise WebIDLError("Maplike/setlike interface %s cannot have "
|
||||
"maplike/setlike interface %s as a "
|
||||
if iface.maplikeOrSetlikeOrIterable and self.maplikeOrSetlikeOrIterable:
|
||||
raise WebIDLError("Maplike/setlike/iterable interface %s cannot have "
|
||||
"maplike/setlike/iterable interface %s as a "
|
||||
"consequential interface" %
|
||||
(self.identifier.name,
|
||||
iface.identifier.name),
|
||||
[self.maplikeOrSetlike.location,
|
||||
iface.maplikeOrSetlike.location])
|
||||
[self.maplikeOrSetlikeOrIterable.location,
|
||||
iface.maplikeOrSetlikeOrIterable.location])
|
||||
additionalMembers = iface.originalMembers
|
||||
for additionalMember in additionalMembers:
|
||||
for member in self.members:
|
||||
@ -905,15 +918,15 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
|
||||
|
||||
for ancestor in self.getInheritedInterfaces():
|
||||
ancestor.interfacesBasedOnSelf.add(self)
|
||||
if (ancestor.maplikeOrSetlike is not None and
|
||||
self.maplikeOrSetlike is not None):
|
||||
if (ancestor.maplikeOrSetlikeOrIterable is not None and
|
||||
self.maplikeOrSetlikeOrIterable is not None):
|
||||
raise WebIDLError("Cannot have maplike/setlike on %s that "
|
||||
"inherits %s, which is already "
|
||||
"maplike/setlike" %
|
||||
(self.identifier.name,
|
||||
ancestor.identifier.name),
|
||||
[self.maplikeOrSetlike.location,
|
||||
ancestor.maplikeOrSetlike.location])
|
||||
[self.maplikeOrSetlikeOrIterable.location,
|
||||
ancestor.maplikeOrSetlikeOrIterable.location])
|
||||
for ancestorConsequential in ancestor.getConsequentialInterfaces():
|
||||
ancestorConsequential.interfacesBasedOnSelf.add(self)
|
||||
|
||||
@ -997,12 +1010,12 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
|
||||
# At this point, we have all of our members. If the current interface
|
||||
# uses maplike/setlike, check for collisions anywhere in the current
|
||||
# interface or higher in the inheritance chain.
|
||||
if self.maplikeOrSetlike:
|
||||
if self.maplikeOrSetlikeOrIterable:
|
||||
testInterface = self
|
||||
isAncestor = False
|
||||
while testInterface:
|
||||
self.maplikeOrSetlike.checkCollisions(testInterface.members,
|
||||
isAncestor)
|
||||
self.maplikeOrSetlikeOrIterable.checkCollisions(testInterface.members,
|
||||
isAncestor)
|
||||
isAncestor = True
|
||||
testInterface = testInterface.parent
|
||||
|
||||
@ -3367,7 +3380,8 @@ class IDLInterfaceMember(IDLObjectWithIdentifier, IDLExposureMixins):
|
||||
'Const',
|
||||
'Attr',
|
||||
'Method',
|
||||
'MaplikeOrSetlike'
|
||||
'MaplikeOrSetlike',
|
||||
'Iterable'
|
||||
)
|
||||
|
||||
Special = enum(
|
||||
@ -3393,6 +3407,10 @@ class IDLInterfaceMember(IDLObjectWithIdentifier, IDLExposureMixins):
|
||||
def isConst(self):
|
||||
return self.tag == IDLInterfaceMember.Tags.Const
|
||||
|
||||
def isMaplikeOrSetlikeOrIterable(self):
|
||||
return (self.tag == IDLInterfaceMember.Tags.MaplikeOrSetlike or
|
||||
self.tag == IDLInterfaceMember.Tags.Iterable)
|
||||
|
||||
def isMaplikeOrSetlike(self):
|
||||
return self.tag == IDLInterfaceMember.Tags.MaplikeOrSetlike
|
||||
|
||||
@ -3470,58 +3488,42 @@ class IDLInterfaceMember(IDLObjectWithIdentifier, IDLExposureMixins):
|
||||
self.aliases.append(alias)
|
||||
|
||||
|
||||
# MaplikeOrSetlike adds a trait to an interface, like map or iteration
|
||||
# functions. To handle them while still getting all of the generated binding
|
||||
# code taken care of, we treat them as macros that are expanded into members
|
||||
# based on parsed values.
|
||||
class IDLMaplikeOrSetlike(IDLInterfaceMember):
|
||||
|
||||
MaplikeOrSetlikeTypes = enum(
|
||||
'maplike',
|
||||
'setlike'
|
||||
)
|
||||
|
||||
def __init__(self, location, identifier, maplikeOrSetlikeType,
|
||||
readonly, keyType, valueType):
|
||||
IDLInterfaceMember.__init__(self, location, identifier,
|
||||
IDLInterfaceMember.Tags.MaplikeOrSetlike)
|
||||
class IDLMaplikeOrSetlikeOrIterableBase(IDLInterfaceMember):
|
||||
|
||||
def __init__(self, location, identifier, ifaceType, keyType, valueType, ifaceKind):
|
||||
IDLInterfaceMember.__init__(self, location, identifier, ifaceKind)
|
||||
assert isinstance(keyType, IDLType)
|
||||
assert isinstance(valueType, IDLType)
|
||||
self.maplikeOrSetlikeType = maplikeOrSetlikeType
|
||||
self.readonly = readonly
|
||||
assert ifaceType in ['maplike', 'setlike', 'iterable']
|
||||
if valueType is not None:
|
||||
assert isinstance(valueType, IDLType)
|
||||
self.keyType = keyType
|
||||
self.valueType = valueType
|
||||
self.slotIndex = None
|
||||
self.maplikeOrSetlikeOrIterableType = ifaceType
|
||||
self.disallowedMemberNames = []
|
||||
self.disallowedNonMethodNames = []
|
||||
|
||||
# When generating JSAPI access code, we need to know the backing object
|
||||
# type prefix to create the correct function. Generate here for reuse.
|
||||
if self.isMaplike():
|
||||
self.prefix = 'Map'
|
||||
elif self.isSetlike():
|
||||
self.prefix = 'Set'
|
||||
|
||||
def __str__(self):
|
||||
return "declared '%s' with key '%s'" % (self.maplikeOrSetlikeType, self.keyType)
|
||||
|
||||
def isMaplike(self):
|
||||
return self.maplikeOrSetlikeType == "maplike"
|
||||
return self.maplikeOrSetlikeOrIterableType == "maplike"
|
||||
|
||||
def isSetlike(self):
|
||||
return self.maplikeOrSetlikeType == "setlike"
|
||||
return self.maplikeOrSetlikeOrIterableType == "setlike"
|
||||
|
||||
def isIterable(self):
|
||||
return self.maplikeOrSetlikeOrIterableType == "iterable"
|
||||
|
||||
def hasValueType(self):
|
||||
return self.valueType is not None
|
||||
|
||||
def checkCollisions(self, members, isAncestor):
|
||||
for member in members:
|
||||
# Check that there are no disallowed members
|
||||
if (member.identifier.name in self.disallowedMemberNames and
|
||||
not ((member.isMethod() and member.isMaplikeOrSetlikeMethod()) or
|
||||
not ((member.isMethod() and member.isMaplikeOrSetlikeOrIterableMethod()) or
|
||||
(member.isAttr() and member.isMaplikeOrSetlikeAttr()))):
|
||||
raise WebIDLError("Member '%s' conflicts "
|
||||
"with reserved %s name." %
|
||||
(member.identifier.name,
|
||||
self.maplikeOrSetlikeType),
|
||||
self.maplikeOrSetlikeOrIterableType),
|
||||
[self.location, member.location])
|
||||
# Check that there are no disallowed non-method members
|
||||
if (isAncestor or (member.isAttr() or member.isConst()) and
|
||||
@ -3529,168 +3531,76 @@ class IDLMaplikeOrSetlike(IDLInterfaceMember):
|
||||
raise WebIDLError("Member '%s' conflicts "
|
||||
"with reserved %s method." %
|
||||
(member.identifier.name,
|
||||
self.maplikeOrSetlikeType),
|
||||
self.maplikeOrSetlikeOrIterableType),
|
||||
[self.location, member.location])
|
||||
|
||||
def expand(self, members, isJSImplemented):
|
||||
def addMethod(self, name, members, allowExistingOperations, returnType, args=[],
|
||||
chromeOnly=False, isPure=False, affectsNothing=False, newObject=False):
|
||||
"""
|
||||
In order to take advantage of all of the method machinery in Codegen,
|
||||
we generate our functions as if they were part of the interface
|
||||
specification during parsing.
|
||||
Create an IDLMethod based on the parameters passed in.
|
||||
|
||||
- members is the member list to add this function to, since this is
|
||||
called during the member expansion portion of interface object
|
||||
building.
|
||||
|
||||
- chromeOnly is only True for read-only js implemented classes, to
|
||||
implement underscore prefixed convenience functions which would
|
||||
otherwise not be available, unlike the case of C++ bindings.
|
||||
|
||||
- isPure is only True for idempotent functions, so it is not valid for
|
||||
things like keys, values, etc. that return a new object every time.
|
||||
|
||||
- affectsNothing means that nothing changes due to this method, which
|
||||
affects JIT optimization behavior
|
||||
|
||||
- newObject means the method creates and returns a new object.
|
||||
|
||||
"""
|
||||
def addMethod(name, allowExistingOperations, returnType, args=[],
|
||||
chromeOnly=False, isPure=False, affectsNothing=False):
|
||||
"""
|
||||
Create an IDLMethod based on the parameters passed in. chromeOnly is only
|
||||
True for read-only js implemented classes, to implement underscore
|
||||
prefixed convenience functions would otherwise not be available,
|
||||
unlike the case of C++ bindings. isPure is only True for
|
||||
idempotent functions, so it is not valid for things like keys,
|
||||
values, etc. that return a new object every time.
|
||||
|
||||
"""
|
||||
|
||||
# Only add name to lists for collision checks if it's not chrome
|
||||
# only.
|
||||
if chromeOnly:
|
||||
name = "__" + name
|
||||
# Only add name to lists for collision checks if it's not chrome
|
||||
# only.
|
||||
if chromeOnly:
|
||||
name = "__" + name
|
||||
else:
|
||||
if not allowExistingOperations:
|
||||
self.disallowedMemberNames.append(name)
|
||||
else:
|
||||
if not allowExistingOperations:
|
||||
self.disallowedMemberNames.append(name)
|
||||
else:
|
||||
self.disallowedNonMethodNames.append(name)
|
||||
|
||||
# If allowExistingOperations is True, and another operation exists
|
||||
# with the same name as the one we're trying to add, don't add the
|
||||
# maplike/setlike operation. However, if the operation is static,
|
||||
# then fail by way of creating the function, which will cause a
|
||||
# naming conflict, per the spec.
|
||||
if allowExistingOperations:
|
||||
for m in members:
|
||||
if m.identifier.name == name and m.isMethod() and not m.isStatic():
|
||||
return
|
||||
|
||||
method = IDLMethod(self.location,
|
||||
IDLUnresolvedIdentifier(self.location, name, allowDoubleUnderscore=chromeOnly),
|
||||
returnType, args, maplikeOrSetlike=self)
|
||||
|
||||
# We need to be able to throw from declaration methods
|
||||
self.disallowedNonMethodNames.append(name)
|
||||
# If allowExistingOperations is True, and another operation exists
|
||||
# with the same name as the one we're trying to add, don't add the
|
||||
# maplike/setlike operation. However, if the operation is static,
|
||||
# then fail by way of creating the function, which will cause a
|
||||
# naming conflict, per the spec.
|
||||
if allowExistingOperations:
|
||||
for m in members:
|
||||
if m.identifier.name == name and m.isMethod() and not m.isStatic():
|
||||
return
|
||||
method = IDLMethod(self.location,
|
||||
IDLUnresolvedIdentifier(self.location, name, allowDoubleUnderscore=chromeOnly),
|
||||
returnType, args, maplikeOrSetlikeOrIterable=self)
|
||||
# We need to be able to throw from declaration methods
|
||||
method.addExtendedAttributes(
|
||||
[IDLExtendedAttribute(self.location, ("Throws",))])
|
||||
if chromeOnly:
|
||||
method.addExtendedAttributes(
|
||||
[IDLExtendedAttribute(self.location, ("Throws",))])
|
||||
if chromeOnly:
|
||||
method.addExtendedAttributes(
|
||||
[IDLExtendedAttribute(self.location, ("ChromeOnly",))])
|
||||
if isPure:
|
||||
method.addExtendedAttributes(
|
||||
[IDLExtendedAttribute(self.location, ("Pure",))])
|
||||
# Following attributes are used for keys/values/entries. Can't mark
|
||||
# them pure, since they return a new object each time they are run.
|
||||
if affectsNothing:
|
||||
method.addExtendedAttributes(
|
||||
[IDLExtendedAttribute(self.location, ("DependsOn", "Everything")),
|
||||
IDLExtendedAttribute(self.location, ("Affects", "Nothing"))])
|
||||
members.append(method)
|
||||
|
||||
# Both maplike and setlike have a size attribute
|
||||
members.append(IDLAttribute(self.location,
|
||||
IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"), "size"),
|
||||
BuiltinTypes[IDLBuiltinType.Types.unsigned_long],
|
||||
True,
|
||||
maplikeOrSetlike=self))
|
||||
self.reserved_ro_names = ["size"]
|
||||
|
||||
# object entries()
|
||||
addMethod("entries", False, BuiltinTypes[IDLBuiltinType.Types.object],
|
||||
affectsNothing=True)
|
||||
# object keys()
|
||||
addMethod("keys", False, BuiltinTypes[IDLBuiltinType.Types.object],
|
||||
affectsNothing=True)
|
||||
# object values()
|
||||
addMethod("values", False, BuiltinTypes[IDLBuiltinType.Types.object],
|
||||
affectsNothing=True)
|
||||
|
||||
# void forEach(callback(valueType, keyType), thisVal)
|
||||
foreachArguments = [IDLArgument(self.location,
|
||||
IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"),
|
||||
"callback"),
|
||||
BuiltinTypes[IDLBuiltinType.Types.object]),
|
||||
IDLArgument(self.location,
|
||||
IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"),
|
||||
"thisArg"),
|
||||
BuiltinTypes[IDLBuiltinType.Types.any],
|
||||
optional=True)]
|
||||
addMethod("forEach", False, BuiltinTypes[IDLBuiltinType.Types.void],
|
||||
foreachArguments)
|
||||
|
||||
def getKeyArg():
|
||||
return IDLArgument(self.location,
|
||||
IDLUnresolvedIdentifier(self.location, "key"),
|
||||
self.keyType)
|
||||
|
||||
# boolean has(keyType key)
|
||||
addMethod("has", False, BuiltinTypes[IDLBuiltinType.Types.boolean],
|
||||
[getKeyArg()], isPure=True)
|
||||
|
||||
if not self.readonly:
|
||||
# void clear()
|
||||
addMethod("clear", True, BuiltinTypes[IDLBuiltinType.Types.void],
|
||||
[])
|
||||
# boolean delete(keyType key)
|
||||
addMethod("delete", True,
|
||||
BuiltinTypes[IDLBuiltinType.Types.boolean], [getKeyArg()])
|
||||
|
||||
# Always generate underscored functions (e.g. __add, __clear) for js
|
||||
# implemented interfaces as convenience functions.
|
||||
if isJSImplemented:
|
||||
# void clear()
|
||||
addMethod("clear", True, BuiltinTypes[IDLBuiltinType.Types.void],
|
||||
[], chromeOnly=True)
|
||||
# boolean delete(keyType key)
|
||||
addMethod("delete", True,
|
||||
BuiltinTypes[IDLBuiltinType.Types.boolean], [getKeyArg()],
|
||||
chromeOnly=True)
|
||||
|
||||
if self.isSetlike():
|
||||
if not self.readonly:
|
||||
# Add returns the set object it just added to.
|
||||
# object add(keyType key)
|
||||
|
||||
addMethod("add", True,
|
||||
BuiltinTypes[IDLBuiltinType.Types.object], [getKeyArg()])
|
||||
if isJSImplemented:
|
||||
addMethod("add", True,
|
||||
BuiltinTypes[IDLBuiltinType.Types.object], [getKeyArg()],
|
||||
chromeOnly=True)
|
||||
return
|
||||
|
||||
# If we get this far, we're a maplike declaration.
|
||||
|
||||
# valueType get(keyType key)
|
||||
#
|
||||
# Note that instead of the value type, we're using any here. The
|
||||
# validity checks should happen as things are inserted into the map,
|
||||
# and using any as the return type makes code generation much simpler.
|
||||
#
|
||||
# TODO: Bug 1155340 may change this to use specific type to provide
|
||||
# more info to JIT.
|
||||
addMethod("get", False, BuiltinTypes[IDLBuiltinType.Types.any],
|
||||
[getKeyArg()], isPure=True)
|
||||
|
||||
def getValueArg():
|
||||
return IDLArgument(self.location,
|
||||
IDLUnresolvedIdentifier(self.location, "value"),
|
||||
self.valueType)
|
||||
|
||||
if not self.readonly:
|
||||
addMethod("set", True, BuiltinTypes[IDLBuiltinType.Types.object],
|
||||
[getKeyArg(), getValueArg()])
|
||||
if isJSImplemented:
|
||||
addMethod("set", True, BuiltinTypes[IDLBuiltinType.Types.object],
|
||||
[getKeyArg(), getValueArg()], chromeOnly=True)
|
||||
[IDLExtendedAttribute(self.location, ("ChromeOnly",))])
|
||||
if isPure:
|
||||
method.addExtendedAttributes(
|
||||
[IDLExtendedAttribute(self.location, ("Pure",))])
|
||||
# Following attributes are used for keys/values/entries. Can't mark
|
||||
# them pure, since they return a new object each time they are run.
|
||||
if affectsNothing:
|
||||
method.addExtendedAttributes(
|
||||
[IDLExtendedAttribute(self.location, ("DependsOn", "Everything")),
|
||||
IDLExtendedAttribute(self.location, ("Affects", "Nothing"))])
|
||||
if newObject:
|
||||
method.addExtendedAttributes(
|
||||
[IDLExtendedAttribute(self.location, ("NewObject",))])
|
||||
members.append(method)
|
||||
|
||||
def resolve(self, parentScope):
|
||||
self.keyType.resolveType(parentScope)
|
||||
self.valueType.resolveType(parentScope)
|
||||
if self.valueType:
|
||||
self.valueType.resolveType(parentScope)
|
||||
|
||||
def finish(self, scope):
|
||||
IDLInterfaceMember.finish(self, scope)
|
||||
@ -3701,7 +3611,7 @@ class IDLMaplikeOrSetlike(IDLInterfaceMember):
|
||||
assert not isinstance(t, IDLTypedefType)
|
||||
assert not isinstance(t.name, IDLUnresolvedIdentifier)
|
||||
self.keyType = t
|
||||
if not self.valueType.isComplete():
|
||||
if self.valueType and not self.valueType.isComplete():
|
||||
t = self.valueType.complete(scope)
|
||||
|
||||
assert not isinstance(t, IDLUnresolvedType)
|
||||
@ -3716,8 +3626,161 @@ class IDLMaplikeOrSetlike(IDLInterfaceMember):
|
||||
IDLInterfaceMember.handleExtendedAttribute(self, attr)
|
||||
|
||||
def _getDependentObjects(self):
|
||||
return set([self.keyType, self.valueType])
|
||||
if self.valueType:
|
||||
return set([self.keyType, self.valueType])
|
||||
return set([self.keyType])
|
||||
|
||||
# Iterable adds ES6 iterator style functions and traits
|
||||
# (keys/values/entries/@@iterator) to an interface.
|
||||
class IDLIterable(IDLMaplikeOrSetlikeOrIterableBase):
|
||||
|
||||
def __init__(self, location, identifier, keyType, valueType=None, scope=None):
|
||||
IDLMaplikeOrSetlikeOrIterableBase.__init__(self, location, identifier,
|
||||
"iterable", keyType, valueType,
|
||||
IDLInterfaceMember.Tags.Iterable)
|
||||
self.iteratorType = None
|
||||
|
||||
def __str__(self):
|
||||
return "declared iterable with key '%s' and value '%s'" % (self.keyType, self.valueType)
|
||||
|
||||
def expand(self, members, isJSImplemented):
|
||||
"""
|
||||
In order to take advantage of all of the method machinery in Codegen,
|
||||
we generate our functions as if they were part of the interface
|
||||
specification during parsing.
|
||||
"""
|
||||
# object entries()
|
||||
self.addMethod("entries", members, False, self.iteratorType,
|
||||
affectsNothing=True, newObject=True)
|
||||
# object keys()
|
||||
self.addMethod("keys", members, False, self.iteratorType,
|
||||
affectsNothing=True, newObject=True)
|
||||
# object values()
|
||||
self.addMethod("values", members, False, self.iteratorType,
|
||||
affectsNothing=True, newObject=True)
|
||||
|
||||
# MaplikeOrSetlike adds ES6 map-or-set-like traits to an interface.
|
||||
class IDLMaplikeOrSetlike(IDLMaplikeOrSetlikeOrIterableBase):
|
||||
|
||||
def __init__(self, location, identifier, maplikeOrSetlikeType,
|
||||
readonly, keyType, valueType):
|
||||
IDLMaplikeOrSetlikeOrIterableBase.__init__(self, location, identifier, maplikeOrSetlikeType,
|
||||
keyType, valueType, IDLInterfaceMember.Tags.MaplikeOrSetlike)
|
||||
self.readonly = readonly
|
||||
self.slotIndex = None
|
||||
|
||||
# When generating JSAPI access code, we need to know the backing object
|
||||
# type prefix to create the correct function. Generate here for reuse.
|
||||
if self.isMaplike():
|
||||
self.prefix = 'Map'
|
||||
elif self.isSetlike():
|
||||
self.prefix = 'Set'
|
||||
|
||||
def __str__(self):
|
||||
return "declared '%s' with key '%s'" % (self.maplikeOrSetlikeOrIterableType, self.keyType)
|
||||
|
||||
def expand(self, members, isJSImplemented):
|
||||
"""
|
||||
In order to take advantage of all of the method machinery in Codegen,
|
||||
we generate our functions as if they were part of the interface
|
||||
specification during parsing.
|
||||
"""
|
||||
# Both maplike and setlike have a size attribute
|
||||
members.append(IDLAttribute(self.location,
|
||||
IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"), "size"),
|
||||
BuiltinTypes[IDLBuiltinType.Types.unsigned_long],
|
||||
True,
|
||||
maplikeOrSetlike=self))
|
||||
self.reserved_ro_names = ["size"]
|
||||
|
||||
# object entries()
|
||||
self.addMethod("entries", members, False, BuiltinTypes[IDLBuiltinType.Types.object],
|
||||
affectsNothing=True)
|
||||
# object keys()
|
||||
self.addMethod("keys", members, False, BuiltinTypes[IDLBuiltinType.Types.object],
|
||||
affectsNothing=True)
|
||||
# object values()
|
||||
self.addMethod("values", members, False, BuiltinTypes[IDLBuiltinType.Types.object],
|
||||
affectsNothing=True)
|
||||
|
||||
# void forEach(callback(valueType, keyType), thisVal)
|
||||
foreachArguments = [IDLArgument(self.location,
|
||||
IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"),
|
||||
"callback"),
|
||||
BuiltinTypes[IDLBuiltinType.Types.object]),
|
||||
IDLArgument(self.location,
|
||||
IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"),
|
||||
"thisArg"),
|
||||
BuiltinTypes[IDLBuiltinType.Types.any],
|
||||
optional=True)]
|
||||
self.addMethod("forEach", members, False, BuiltinTypes[IDLBuiltinType.Types.void],
|
||||
foreachArguments)
|
||||
|
||||
def getKeyArg():
|
||||
return IDLArgument(self.location,
|
||||
IDLUnresolvedIdentifier(self.location, "key"),
|
||||
self.keyType)
|
||||
|
||||
# boolean has(keyType key)
|
||||
self.addMethod("has", members, False, BuiltinTypes[IDLBuiltinType.Types.boolean],
|
||||
[getKeyArg()], isPure=True)
|
||||
|
||||
if not self.readonly:
|
||||
# void clear()
|
||||
self.addMethod("clear", members, True, BuiltinTypes[IDLBuiltinType.Types.void],
|
||||
[])
|
||||
# boolean delete(keyType key)
|
||||
self.addMethod("delete", members, True,
|
||||
BuiltinTypes[IDLBuiltinType.Types.boolean], [getKeyArg()])
|
||||
|
||||
# Always generate underscored functions (e.g. __add, __clear) for js
|
||||
# implemented interfaces as convenience functions.
|
||||
if isJSImplemented:
|
||||
# void clear()
|
||||
self.addMethod("clear", members, True, BuiltinTypes[IDLBuiltinType.Types.void],
|
||||
[], chromeOnly=True)
|
||||
# boolean delete(keyType key)
|
||||
self.addMethod("delete", members, True,
|
||||
BuiltinTypes[IDLBuiltinType.Types.boolean], [getKeyArg()],
|
||||
chromeOnly=True)
|
||||
|
||||
if self.isSetlike():
|
||||
if not self.readonly:
|
||||
# Add returns the set object it just added to.
|
||||
# object add(keyType key)
|
||||
|
||||
self.addMethod("add", members, True,
|
||||
BuiltinTypes[IDLBuiltinType.Types.object], [getKeyArg()])
|
||||
if isJSImplemented:
|
||||
self.addMethod("add", members, True,
|
||||
BuiltinTypes[IDLBuiltinType.Types.object], [getKeyArg()],
|
||||
chromeOnly=True)
|
||||
return
|
||||
|
||||
# If we get this far, we're a maplike declaration.
|
||||
|
||||
# valueType get(keyType key)
|
||||
#
|
||||
# Note that instead of the value type, we're using any here. The
|
||||
# validity checks should happen as things are inserted into the map,
|
||||
# and using any as the return type makes code generation much simpler.
|
||||
#
|
||||
# TODO: Bug 1155340 may change this to use specific type to provide
|
||||
# more info to JIT.
|
||||
self.addMethod("get", members, False, BuiltinTypes[IDLBuiltinType.Types.any],
|
||||
[getKeyArg()], isPure=True)
|
||||
|
||||
def getValueArg():
|
||||
return IDLArgument(self.location,
|
||||
IDLUnresolvedIdentifier(self.location, "value"),
|
||||
self.valueType)
|
||||
|
||||
if not self.readonly:
|
||||
self.addMethod("set", members, True, BuiltinTypes[IDLBuiltinType.Types.object],
|
||||
[getKeyArg(), getValueArg()])
|
||||
if isJSImplemented:
|
||||
self.addMethod("set", members, True, BuiltinTypes[IDLBuiltinType.Types.object],
|
||||
[getKeyArg(), getValueArg()], chromeOnly=True)
|
||||
|
||||
class IDLConst(IDLInterfaceMember):
|
||||
def __init__(self, location, identifier, type, value):
|
||||
@ -4319,7 +4382,7 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
||||
static=False, getter=False, setter=False, creator=False,
|
||||
deleter=False, specialType=NamedOrIndexed.Neither,
|
||||
legacycaller=False, stringifier=False, jsonifier=False,
|
||||
maplikeOrSetlike=None):
|
||||
maplikeOrSetlikeOrIterable=None):
|
||||
# REVIEW: specialType is NamedOrIndexed -- wow, this is messed up.
|
||||
IDLInterfaceMember.__init__(self, location, identifier,
|
||||
IDLInterfaceMember.Tags.Method)
|
||||
@ -4347,8 +4410,8 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
||||
self._stringifier = stringifier
|
||||
assert isinstance(jsonifier, bool)
|
||||
self._jsonifier = jsonifier
|
||||
assert maplikeOrSetlike is None or isinstance(maplikeOrSetlike, IDLMaplikeOrSetlike)
|
||||
self.maplikeOrSetlike = maplikeOrSetlike
|
||||
assert maplikeOrSetlikeOrIterable is None or isinstance(maplikeOrSetlikeOrIterable, IDLMaplikeOrSetlikeOrIterableBase)
|
||||
self.maplikeOrSetlikeOrIterable = maplikeOrSetlikeOrIterable
|
||||
self._specialType = specialType
|
||||
self._unforgeable = False
|
||||
self.dependsOn = "Everything"
|
||||
@ -4430,12 +4493,12 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
||||
def isJsonifier(self):
|
||||
return self._jsonifier
|
||||
|
||||
def isMaplikeOrSetlikeMethod(self):
|
||||
def isMaplikeOrSetlikeOrIterableMethod(self):
|
||||
"""
|
||||
True if this method was generated as part of a
|
||||
maplike/setlike/etc interface (e.g. has/get methods)
|
||||
"""
|
||||
return self.maplikeOrSetlike is not None
|
||||
return self.maplikeOrSetlikeOrIterable is not None
|
||||
|
||||
def isSpecial(self):
|
||||
return (self.isGetter() or
|
||||
@ -4458,7 +4521,7 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
||||
an non-identifier name, they actually DO have an identifier.
|
||||
"""
|
||||
return (self.identifier.name[:2] == "__" and
|
||||
not self.isMaplikeOrSetlikeMethod())
|
||||
not self.isMaplikeOrSetlikeOrIterableMethod())
|
||||
|
||||
def resolve(self, parentScope):
|
||||
assert isinstance(parentScope, IDLScope)
|
||||
@ -4966,7 +5029,8 @@ class Tokenizer(object):
|
||||
"SharedArrayBuffer": "SHAREDARRAYBUFFER",
|
||||
"or": "OR",
|
||||
"maplike": "MAPLIKE",
|
||||
"setlike": "SETLIKE"
|
||||
"setlike": "SETLIKE",
|
||||
"iterable": "ITERABLE"
|
||||
}
|
||||
|
||||
tokens.extend(keywords.values())
|
||||
@ -5120,8 +5184,9 @@ class Parser(Tokenizer):
|
||||
raise ex
|
||||
pass
|
||||
|
||||
p[0] = IDLInterface(location, self.globalScope(), identifier, parent,
|
||||
iface = IDLInterface(location, self.globalScope(), identifier, parent,
|
||||
members, isKnownNonPartial=True)
|
||||
p[0] = iface
|
||||
|
||||
def p_InterfaceForwardDecl(self, p):
|
||||
"""
|
||||
@ -5207,7 +5272,7 @@ class Parser(Tokenizer):
|
||||
def p_InterfaceMember(self, p):
|
||||
"""
|
||||
InterfaceMember : Const
|
||||
| AttributeOrOperationOrMaplikeOrSetlike
|
||||
| AttributeOrOperationOrMaplikeOrSetlikeOrIterable
|
||||
"""
|
||||
p[0] = p[1]
|
||||
|
||||
@ -5422,15 +5487,30 @@ class Parser(Tokenizer):
|
||||
"""
|
||||
p[0] = False
|
||||
|
||||
def p_AttributeOrOperationOrMaplikeOrSetlike(self, p):
|
||||
def p_AttributeOrOperationOrMaplikeOrSetlikeOrIterable(self, p):
|
||||
"""
|
||||
AttributeOrOperationOrMaplikeOrSetlike : Attribute
|
||||
| Maplike
|
||||
| Setlike
|
||||
| Operation
|
||||
AttributeOrOperationOrMaplikeOrSetlikeOrIterable : Attribute
|
||||
| Maplike
|
||||
| Setlike
|
||||
| Iterable
|
||||
| Operation
|
||||
"""
|
||||
p[0] = p[1]
|
||||
|
||||
def p_Iterable(self, p):
|
||||
"""
|
||||
Iterable : ITERABLE LT Type GT SEMICOLON
|
||||
| ITERABLE LT Type COMMA Type GT SEMICOLON
|
||||
"""
|
||||
location = self.getLocation(p, 2)
|
||||
identifier = IDLUnresolvedIdentifier(location, "__iterable",
|
||||
allowDoubleUnderscore=True)
|
||||
keyType = p[3]
|
||||
valueType = None
|
||||
if (len(p) > 6):
|
||||
valueType = p[5]
|
||||
p[0] = IDLIterable(location, identifier, keyType, valueType, self.globalScope())
|
||||
|
||||
def p_Setlike(self, p):
|
||||
"""
|
||||
Setlike : ReadOnly SETLIKE LT Type GT SEMICOLON
|
||||
@ -5803,6 +5883,7 @@ class Parser(Tokenizer):
|
||||
| IMPLEMENTS
|
||||
| INHERIT
|
||||
| INTERFACE
|
||||
| ITERABLE
|
||||
| LEGACYCALLER
|
||||
| MAPLIKE
|
||||
| PARTIAL
|
||||
@ -6481,7 +6562,46 @@ class Parser(Tokenizer):
|
||||
self._filename = None
|
||||
|
||||
def finish(self):
|
||||
# First, finish all the IDLImplementsStatements. In particular, we
|
||||
# If we have interfaces that are iterable, create their
|
||||
# iterator interfaces and add them to the productions array.
|
||||
interfaceStatements = [p for p in self._productions if
|
||||
isinstance(p, IDLInterface)]
|
||||
|
||||
for iface in interfaceStatements:
|
||||
iterable = None
|
||||
# We haven't run finish() on the interface yet, so we don't know
|
||||
# whether our interface is maplike/setlike/iterable or not. This
|
||||
# means we have to loop through the members to see if we have an
|
||||
# iterable member.
|
||||
for m in iface.members:
|
||||
if isinstance(m, IDLIterable):
|
||||
iterable = m
|
||||
break
|
||||
if iterable:
|
||||
itr_ident = IDLUnresolvedIdentifier(iface.location,
|
||||
iface.identifier.name + "Iterator")
|
||||
itr_iface = IDLInterface(iface.location, self.globalScope(),
|
||||
itr_ident, None, [],
|
||||
isKnownNonPartial=True)
|
||||
itr_iface.addExtendedAttributes([IDLExtendedAttribute(iface.location,
|
||||
("NoInterfaceObject", ))])
|
||||
# Always append generated iterable interfaces and their
|
||||
# matching implements statements after the interface they're a
|
||||
# member of, otherwise nativeType generation won't work
|
||||
# correctly.
|
||||
itr_iface.iterableInterface = iface
|
||||
self._productions.append(itr_iface)
|
||||
iterable.iteratorType = IDLWrapperType(iface.location, itr_iface)
|
||||
itrPlaceholder = IDLIdentifierPlaceholder(iface.location,
|
||||
IDLUnresolvedIdentifier(iface.location,
|
||||
"IterableIterator"))
|
||||
implements = IDLImplementsStatement(iface.location,
|
||||
IDLIdentifierPlaceholder(iface.location,
|
||||
itr_ident),
|
||||
itrPlaceholder)
|
||||
self._productions.append(implements)
|
||||
|
||||
# Then, finish all the IDLImplementsStatements. In particular, we
|
||||
# have to make sure we do those before we do the IDLInterfaces.
|
||||
# XXX khuey hates this bit and wants to nuke it from orbit.
|
||||
implementsStatements = [p for p in self._productions if
|
||||
|
@ -41,11 +41,11 @@ def WebIDLTest(parser, harness):
|
||||
prefix + " - Interface failed but not as a WebIDLError exception")
|
||||
|
||||
iterableMembers = [(x, WebIDL.IDLMethod) for x in ["entries", "keys",
|
||||
"values", "forEach"]]
|
||||
iterableMembers.extend([("size", WebIDL.IDLAttribute)])
|
||||
setROMembers = ([(x, WebIDL.IDLMethod) for x in ["has"]] +
|
||||
"values"]]
|
||||
setROMembers = ([(x, WebIDL.IDLMethod) for x in ["has", "foreach"]] +
|
||||
[("__setlike", WebIDL.IDLMaplikeOrSetlike)] +
|
||||
iterableMembers)
|
||||
setROMembers.extend([("size", WebIDL.IDLAttribute)])
|
||||
setRWMembers = ([(x, WebIDL.IDLMethod) for x in ["add",
|
||||
"clear",
|
||||
"delete"]] +
|
||||
@ -58,9 +58,10 @@ def WebIDLTest(parser, harness):
|
||||
"__clear",
|
||||
"__delete"]] +
|
||||
setRWMembers)
|
||||
mapROMembers = ([(x, WebIDL.IDLMethod) for x in ["get", "has"]] +
|
||||
mapROMembers = ([(x, WebIDL.IDLMethod) for x in ["get", "has", "foreach"]] +
|
||||
[("__maplike", WebIDL.IDLMaplikeOrSetlike)] +
|
||||
iterableMembers)
|
||||
mapROMembers.extend([("size", WebIDL.IDLAttribute)])
|
||||
mapRWMembers = ([(x, WebIDL.IDLMethod) for x in ["set",
|
||||
"clear",
|
||||
"delete"]] + mapROMembers)
|
||||
@ -69,8 +70,8 @@ def WebIDLTest(parser, harness):
|
||||
"__delete"]] +
|
||||
mapRWMembers)
|
||||
|
||||
disallowedMemberNames = ["keys", "entries", "values", "forEach", "has",
|
||||
"size"]
|
||||
disallowedIterableNames = ["keys", "entries", "values"]
|
||||
disallowedMemberNames = ["forEach", "has", "size"] + disallowedIterableNames
|
||||
mapDisallowedMemberNames = ["get"] + disallowedMemberNames
|
||||
disallowedNonMethodNames = ["clear", "delete"]
|
||||
mapDisallowedNonMethodNames = ["set"] + disallowedNonMethodNames
|
||||
@ -80,6 +81,27 @@ def WebIDLTest(parser, harness):
|
||||
# Simple Usage Tests
|
||||
#
|
||||
|
||||
shouldPass("Iterable (key only)",
|
||||
"""
|
||||
interface Foo1 {
|
||||
iterable<long>;
|
||||
};
|
||||
""", iterableMembers)
|
||||
|
||||
shouldPass("Iterable (key and value)",
|
||||
"""
|
||||
interface Foo1 {
|
||||
iterable<long, long>;
|
||||
};
|
||||
""", iterableMembers)
|
||||
|
||||
shouldPass("Maplike (readwrite)",
|
||||
"""
|
||||
interface Foo1 {
|
||||
maplike<long, long>;
|
||||
};
|
||||
""", mapRWMembers)
|
||||
|
||||
shouldPass("Maplike (readwrite)",
|
||||
"""
|
||||
interface Foo1 {
|
||||
@ -157,6 +179,22 @@ def WebIDLTest(parser, harness):
|
||||
};
|
||||
""")
|
||||
|
||||
shouldFail("Two iterable/setlikes on same interface",
|
||||
"""
|
||||
interface Foo1 {
|
||||
iterable<long>;
|
||||
maplike<long, long>;
|
||||
};
|
||||
""")
|
||||
|
||||
shouldFail("Two iterables on same interface",
|
||||
"""
|
||||
interface Foo1 {
|
||||
iterable<long>;
|
||||
iterable<long, long>;
|
||||
};
|
||||
""")
|
||||
|
||||
shouldFail("Two maplike/setlikes in partials",
|
||||
"""
|
||||
interface Foo1 {
|
||||
@ -177,6 +215,16 @@ def WebIDLTest(parser, harness):
|
||||
};
|
||||
""")
|
||||
|
||||
shouldFail("Conflicting maplike/iterable across inheritance",
|
||||
"""
|
||||
interface Foo1 {
|
||||
maplike<long, long>;
|
||||
};
|
||||
interface Foo2 : Foo1 {
|
||||
iterable<long>;
|
||||
};
|
||||
""")
|
||||
|
||||
shouldFail("Conflicting maplike/setlikes across multistep inheritance",
|
||||
"""
|
||||
interface Foo1 {
|
||||
@ -283,6 +331,8 @@ def WebIDLTest(parser, harness):
|
||||
};
|
||||
""" % (likeMember, conflictName))
|
||||
|
||||
for member in disallowedIterableNames:
|
||||
testConflictingMembers("iterable<long, long>", member, iterableMembers, False)
|
||||
for member in mapDisallowedMemberNames:
|
||||
testConflictingMembers("maplike<long, long>", member, mapRWMembers, False)
|
||||
for member in disallowedMemberNames:
|
82
dom/bindings/test/TestInterfaceIterableDouble.cpp
Normal file
82
dom/bindings/test/TestInterfaceIterableDouble.cpp
Normal file
@ -0,0 +1,82 @@
|
||||
/* 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 "mozilla/dom/TestInterfaceIterableDouble.h"
|
||||
#include "mozilla/dom/TestInterfaceJSMaplikeSetlikeIterableBinding.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(TestInterfaceIterableDouble, mParent)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(TestInterfaceIterableDouble)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(TestInterfaceIterableDouble)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TestInterfaceIterableDouble)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
TestInterfaceIterableDouble::TestInterfaceIterableDouble(nsPIDOMWindow* aParent)
|
||||
: mParent(aParent)
|
||||
{
|
||||
mValues.AppendElement(std::pair<nsString, nsString>(NS_LITERAL_STRING("a"),
|
||||
NS_LITERAL_STRING("b")));
|
||||
mValues.AppendElement(std::pair<nsString, nsString>(NS_LITERAL_STRING("c"),
|
||||
NS_LITERAL_STRING("d")));
|
||||
mValues.AppendElement(std::pair<nsString, nsString>(NS_LITERAL_STRING("e"),
|
||||
NS_LITERAL_STRING("f")));
|
||||
}
|
||||
|
||||
//static
|
||||
already_AddRefed<TestInterfaceIterableDouble>
|
||||
TestInterfaceIterableDouble::Constructor(const GlobalObject& aGlobal,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal.GetAsSupports());
|
||||
if (!window) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<TestInterfaceIterableDouble> r = new TestInterfaceIterableDouble(window);
|
||||
return r.forget();
|
||||
}
|
||||
|
||||
JSObject*
|
||||
TestInterfaceIterableDouble::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
return TestInterfaceIterableDoubleBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
nsPIDOMWindow*
|
||||
TestInterfaceIterableDouble::GetParentObject() const
|
||||
{
|
||||
return mParent;
|
||||
}
|
||||
|
||||
size_t
|
||||
TestInterfaceIterableDouble::GetIterableLength()
|
||||
{
|
||||
return mValues.Length();
|
||||
}
|
||||
|
||||
nsAString&
|
||||
TestInterfaceIterableDouble::GetKeyAtIndex(uint32_t aIndex)
|
||||
{
|
||||
MOZ_ASSERT(aIndex < mValues.Length());
|
||||
return mValues.ElementAt(aIndex).first;
|
||||
}
|
||||
|
||||
nsAString&
|
||||
TestInterfaceIterableDouble::GetValueAtIndex(uint32_t aIndex)
|
||||
{
|
||||
MOZ_ASSERT(aIndex < mValues.Length());
|
||||
return mValues.ElementAt(aIndex).second;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
51
dom/bindings/test/TestInterfaceIterableDouble.h
Normal file
51
dom/bindings/test/TestInterfaceIterableDouble.h
Normal file
@ -0,0 +1,51 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_dom_TestInterfaceIterableDouble_h
|
||||
#define mozilla_dom_TestInterfaceIterableDouble_h
|
||||
|
||||
#include "nsWrapperCache.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
class nsPIDOMWindow;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class ErrorResult;
|
||||
|
||||
namespace dom {
|
||||
|
||||
class GlobalObject;
|
||||
|
||||
// Implementation of test binding for webidl iterable interfaces, using
|
||||
// primitives for value type
|
||||
class TestInterfaceIterableDouble final : public nsISupports,
|
||||
public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(TestInterfaceIterableDouble)
|
||||
|
||||
explicit TestInterfaceIterableDouble(nsPIDOMWindow* aParent);
|
||||
nsPIDOMWindow* GetParentObject() const;
|
||||
virtual JSObject* WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) override;
|
||||
static already_AddRefed<TestInterfaceIterableDouble>
|
||||
Constructor(const GlobalObject& aGlobal, ErrorResult& rv);
|
||||
|
||||
size_t GetIterableLength();
|
||||
nsAString& GetKeyAtIndex(uint32_t aIndex);
|
||||
nsAString& GetValueAtIndex(uint32_t aIndex);
|
||||
private:
|
||||
virtual ~TestInterfaceIterableDouble() {}
|
||||
nsCOMPtr<nsPIDOMWindow> mParent;
|
||||
nsTArray<std::pair<nsString, nsString>> mValues;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_TestInterfaceIterableDouble_h
|
78
dom/bindings/test/TestInterfaceIterableSingle.cpp
Normal file
78
dom/bindings/test/TestInterfaceIterableSingle.cpp
Normal file
@ -0,0 +1,78 @@
|
||||
/* 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 "mozilla/dom/TestInterfaceIterableSingle.h"
|
||||
#include "mozilla/dom/TestInterfaceJSMaplikeSetlikeIterableBinding.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(TestInterfaceIterableSingle, mParent)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(TestInterfaceIterableSingle)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(TestInterfaceIterableSingle)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TestInterfaceIterableSingle)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
TestInterfaceIterableSingle::TestInterfaceIterableSingle(nsPIDOMWindow* aParent)
|
||||
: mParent(aParent)
|
||||
{
|
||||
for(int i = 0; i < 3; ++i) {
|
||||
mValues.AppendElement(i);
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
already_AddRefed<TestInterfaceIterableSingle>
|
||||
TestInterfaceIterableSingle::Constructor(const GlobalObject& aGlobal,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal.GetAsSupports());
|
||||
if (!window) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<TestInterfaceIterableSingle> r = new TestInterfaceIterableSingle(window);
|
||||
return r.forget();
|
||||
}
|
||||
|
||||
JSObject*
|
||||
TestInterfaceIterableSingle::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
return TestInterfaceIterableSingleBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
nsPIDOMWindow*
|
||||
TestInterfaceIterableSingle::GetParentObject() const
|
||||
{
|
||||
return mParent;
|
||||
}
|
||||
|
||||
size_t
|
||||
TestInterfaceIterableSingle::GetIterableLength() const
|
||||
{
|
||||
return mValues.Length();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
TestInterfaceIterableSingle::GetKeyAtIndex(uint32_t index) const
|
||||
{
|
||||
MOZ_ASSERT(index < mValues.Length());
|
||||
return mValues.ElementAt(index);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
TestInterfaceIterableSingle::GetValueAtIndex(uint32_t index) const
|
||||
{
|
||||
return GetKeyAtIndex(index);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
51
dom/bindings/test/TestInterfaceIterableSingle.h
Normal file
51
dom/bindings/test/TestInterfaceIterableSingle.h
Normal file
@ -0,0 +1,51 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_dom_TestInterfaceIterableSingle_h
|
||||
#define mozilla_dom_TestInterfaceIterableSingle_h
|
||||
|
||||
#include "nsWrapperCache.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
class nsPIDOMWindow;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class ErrorResult;
|
||||
|
||||
namespace dom {
|
||||
|
||||
class GlobalObject;
|
||||
|
||||
// Implementation of test binding for webidl iterable interfaces, using
|
||||
// primitives for value type
|
||||
class TestInterfaceIterableSingle final : public nsISupports,
|
||||
public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(TestInterfaceIterableSingle)
|
||||
|
||||
explicit TestInterfaceIterableSingle(nsPIDOMWindow* aParent);
|
||||
nsPIDOMWindow* GetParentObject() const;
|
||||
virtual JSObject* WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) override;
|
||||
static already_AddRefed<TestInterfaceIterableSingle>
|
||||
Constructor(const GlobalObject& aGlobal, ErrorResult& rv);
|
||||
|
||||
size_t GetIterableLength() const;
|
||||
uint32_t GetKeyAtIndex(uint32_t aIndex) const;
|
||||
uint32_t GetValueAtIndex(uint32_t aIndex) const;
|
||||
private:
|
||||
virtual ~TestInterfaceIterableSingle() {}
|
||||
nsCOMPtr<nsPIDOMWindow> mParent;
|
||||
nsTArray<uint32_t> mValues;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_TestInterfaceIterableSingle_h
|
@ -3,7 +3,7 @@
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/dom/TestInterfaceMaplike.h"
|
||||
#include "mozilla/dom/TestInterfaceJSMaplikeSetlikeBinding.h"
|
||||
#include "mozilla/dom/TestInterfaceJSMaplikeSetlikeIterableBinding.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
#include "mozilla/dom/TestInterfaceMaplikeObject.h"
|
||||
#include "mozilla/dom/TestInterfaceMaplike.h"
|
||||
#include "mozilla/dom/TestInterfaceJSMaplikeSetlikeBinding.h"
|
||||
#include "mozilla/dom/TestInterfaceJSMaplikeSetlikeIterableBinding.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/dom/TestInterfaceSetlike.h"
|
||||
#include "mozilla/dom/TestInterfaceJSMaplikeSetlikeBinding.h"
|
||||
#include "mozilla/dom/TestInterfaceJSMaplikeSetlikeIterableBinding.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/dom/TestInterfaceSetlikeNode.h"
|
||||
#include "mozilla/dom/TestInterfaceJSMaplikeSetlikeBinding.h"
|
||||
#include "mozilla/dom/TestInterfaceJSMaplikeSetlikeIterableBinding.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
|
||||
|
@ -68,3 +68,5 @@ skip-if = debug == false
|
||||
skip-if = debug == false
|
||||
[test_jsimplemented_eventhandler.html]
|
||||
skip-if = debug == false
|
||||
[test_iterable.html]
|
||||
skip-if = debug == false
|
@ -57,7 +57,6 @@
|
||||
var m;
|
||||
var testSet;
|
||||
var testIndex;
|
||||
var iterable;
|
||||
// Simple map creation and functionality test
|
||||
info("SimpleMap: Testing simple map creation and functionality");
|
||||
m = new TestInterfaceMaplike();
|
||||
|
112
dom/bindings/test/test_iterable.html
Normal file
112
dom/bindings/test/test_iterable.html
Normal file
@ -0,0 +1,112 @@
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
- http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test Iterable Interface</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<script class="testbody" type="application/javascript">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({set: [['dom.expose_test_interfaces', true]]}, function() {
|
||||
|
||||
base_properties = [["entries", "function", 0],
|
||||
["keys", "function", 0],
|
||||
["values", "function", 0]]
|
||||
var testExistence = function testExistence(prefix, obj, properties) {
|
||||
for (var [name, type, args] of properties) {
|
||||
// Properties are somewhere up the proto chain, hasOwnProperty won't work
|
||||
isnot(obj[name], undefined,
|
||||
`${prefix} object has property ${name}`);
|
||||
|
||||
is(typeof obj[name], type,
|
||||
`${prefix} object property ${name} is a ${type}`);
|
||||
// Check function length
|
||||
if (type == "function") {
|
||||
is(obj[name].length, args,
|
||||
`${prefix} object property ${name} is length ${args}`);
|
||||
is(obj[name].name, name,
|
||||
`${prefix} object method name is ${name}`);
|
||||
}
|
||||
|
||||
// Find where property is on proto chain, check for enumerablility there.
|
||||
var owner = obj;
|
||||
while (owner) {
|
||||
var propDesc = Object.getOwnPropertyDescriptor(owner, name);
|
||||
if (propDesc) {
|
||||
ok(propDesc.enumerable,
|
||||
`${prefix} object property ${name} is enumerable`);
|
||||
break;
|
||||
}
|
||||
owner = Object.getPrototypeOf(owner);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var itr;
|
||||
// Simple single type iterable creation and functionality test
|
||||
info("IterableSingle: Testing simple iterable creation and functionality");
|
||||
itr = new TestInterfaceIterableSingle();
|
||||
testExistence("IterableSingle: ", itr, base_properties);
|
||||
var key_itr = itr.keys();
|
||||
var value_itr = itr.values();
|
||||
var entries_itr = itr.entries();
|
||||
for (var i = 0; i < 3; ++i) {
|
||||
var key = key_itr.next();
|
||||
var value = value_itr.next();
|
||||
var entry = entries_itr.next();
|
||||
is(key.value, i, "IterableSingle: Key iterator value should be " + i);
|
||||
is(value.value, key.value, "IterableSingle: Value iterator value should be " + key.value);
|
||||
is(entry.value[0], i, "IterableSingle: Entry iterator value 0 should be " + i);
|
||||
is(entry.value[1], i, "IterableSingle: Entry iterator value 1 should be " + i);
|
||||
}
|
||||
var key = key_itr.next();
|
||||
var value = value_itr.next();
|
||||
var entry = entries_itr.next();
|
||||
is(key.value, undefined, "IterableSingle: Key iterator value should be undefined");
|
||||
is(key.done, true, "IterableSingle: Key iterator done should be true");
|
||||
is(value.value, undefined, "IterableSingle: Value iterator value should be undefined");
|
||||
is(value.done, true, "IterableSingle: Value iterator done should be true");
|
||||
is(entry.value, undefined, "IterableDouble: Entry iterator value should be undefined");
|
||||
is(entry.done, true, "IterableSingle: Entry iterator done should be true");
|
||||
is(Object.prototype.toString.call(Object.getPrototypeOf(key_itr)),
|
||||
"[object TestInterfaceIterableSingleIteratorPrototype]",
|
||||
"iterator prototype should have the right brand");
|
||||
|
||||
// Simple dual type iterable creation and functionality test
|
||||
info("IterableDouble: Testing simple iterable creation and functionality");
|
||||
itr = new TestInterfaceIterableDouble();
|
||||
testExistence("IterableDouble: ", itr, base_properties);
|
||||
var elements = [["a", "b"], ["c", "d"], ["e", "f"]]
|
||||
var key_itr = itr.keys();
|
||||
var value_itr = itr.values();
|
||||
var entries_itr = itr.entries();
|
||||
for (var i = 0; i < 3; ++i) {
|
||||
var key = key_itr.next();
|
||||
var value = value_itr.next();
|
||||
var entry = entries_itr.next();
|
||||
is(key.value, elements[i][0], "IterableDouble: Key iterator value should be " + elements[i][0]);
|
||||
is(value.value, elements[i][1], "IterableDouble: Value iterator value should be " + elements[i][1]);
|
||||
is(entry.value[0], elements[i][0], "IterableDouble: Entry iterator value 0 should be " + elements[i][0]);
|
||||
is(entry.value[1], elements[i][1], "IterableDouble: Entry iterator value 1 should be " + elements[i][1]);
|
||||
}
|
||||
var key = key_itr.next();
|
||||
var value = value_itr.next();
|
||||
var entry = entries_itr.next()
|
||||
is(key.value, undefined, "IterableDouble: Key iterator value should be undefined");
|
||||
is(key.done, true, "IterableDouble: Key iterator done should be true");
|
||||
is(value.value, undefined, "IterableDouble: Value iterator value should be undefined");
|
||||
is(value.done, true, "IterableDouble: Value iterator done should be true");
|
||||
is(entry.value, undefined, "IterableDouble: Entry iterator value should be undefined");
|
||||
is(entry.done, true, "IterableDouble: Entry iterator done should be true");
|
||||
is(Object.prototype.toString.call(Object.getPrototypeOf(key_itr)),
|
||||
"[object TestInterfaceIterableDoubleIteratorPrototype]",
|
||||
"iterator prototype should have the right brand");
|
||||
|
||||
SimpleTest.finish();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
10
dom/cache/Context.cpp
vendored
10
dom/cache/Context.cpp
vendored
@ -1001,7 +1001,15 @@ Context::OnQuotaInit(nsresult aRv, const QuotaInfo& aQuotaInfo,
|
||||
MOZ_ASSERT(!mDirectoryLock);
|
||||
mDirectoryLock = aDirectoryLock;
|
||||
|
||||
if (mState == STATE_CONTEXT_CANCELED || NS_FAILED(aRv)) {
|
||||
// If we opening the context failed, but we were not explicitly canceled,
|
||||
// still treat the entire context as canceled. We don't want to allow
|
||||
// new actions to be dispatched. We also cannot leave the context in
|
||||
// the INIT state after failing to open.
|
||||
if (NS_FAILED(aRv)) {
|
||||
mState = STATE_CONTEXT_CANCELED;
|
||||
}
|
||||
|
||||
if (mState == STATE_CONTEXT_CANCELED) {
|
||||
for (uint32_t i = 0; i < mPendingActions.Length(); ++i) {
|
||||
mPendingActions[i].mAction->CompleteOnInitiatingThread(aRv);
|
||||
}
|
||||
|
2
dom/cache/TypeUtils.cpp
vendored
2
dom/cache/TypeUtils.cpp
vendored
@ -202,7 +202,7 @@ TypeUtils::ToCacheResponseWithoutBody(CacheResponse& aOut,
|
||||
{
|
||||
aOut.type() = aIn.Type();
|
||||
|
||||
aIn.GetUrl(aOut.url());
|
||||
aIn.GetUnfilteredUrl(aOut.url());
|
||||
|
||||
if (aOut.url() != EmptyCString()) {
|
||||
// Pass all Response URL schemes through... The spec only requires we take
|
||||
|
@ -400,7 +400,9 @@ HTMLCanvasElement::CreateContext(CanvasContextType aContextType)
|
||||
// Add Observer for webgl canvas.
|
||||
if (aContextType == CanvasContextType::WebGL1 ||
|
||||
aContextType == CanvasContextType::WebGL2) {
|
||||
mContextObserver = new HTMLCanvasElementObserver(this);
|
||||
if (!mContextObserver) {
|
||||
mContextObserver = new HTMLCanvasElementObserver(this);
|
||||
}
|
||||
}
|
||||
|
||||
ret->SetCanvasElement(this);
|
||||
@ -779,7 +781,9 @@ HTMLCanvasElement::TransferControlToOffscreen(ErrorResult& aRv)
|
||||
sz.height,
|
||||
GetCompositorBackendType(),
|
||||
renderer);
|
||||
mContextObserver = new HTMLCanvasElementObserver(this);
|
||||
if (!mContextObserver) {
|
||||
mContextObserver = new HTMLCanvasElementObserver(this);
|
||||
}
|
||||
} else {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
}
|
||||
|
@ -151,6 +151,7 @@ public:
|
||||
return nsRefPtr<ImportLoader>(mImportLoader).forget();
|
||||
}
|
||||
|
||||
virtual CORSMode GetCORSMode() const override;
|
||||
protected:
|
||||
virtual ~HTMLLinkElement();
|
||||
|
||||
@ -161,7 +162,6 @@ protected:
|
||||
nsAString& aMedia,
|
||||
bool* aIsScoped,
|
||||
bool* aIsAlternate) override;
|
||||
virtual CORSMode GetCORSMode() const override;
|
||||
protected:
|
||||
// nsGenericHTMLElement
|
||||
virtual void GetItemValueText(DOMString& text) override;
|
||||
|
@ -5,9 +5,7 @@ support-files =
|
||||
|
||||
[test_Document-createElement-namespace.html.json]
|
||||
[test_Document-createElementNS.html.json]
|
||||
[test_Document-getElementsByTagName.html.json]
|
||||
[test_Node-properties.html.json]
|
||||
[test_attributes.html.json]
|
||||
[test_case.html.json]
|
||||
[test_getElementsByClassName-10.xml.json]
|
||||
[test_getElementsByClassName-11.xml.json]
|
||||
|
@ -1,4 +0,0 @@
|
||||
{
|
||||
"Document.getElementsByTagName 1": true,
|
||||
"Document.getElementsByTagName 2": true
|
||||
}
|
@ -1,7 +1,5 @@
|
||||
{
|
||||
"getElementsByTagName abc": true,
|
||||
"getElementsByTagName Abc": true,
|
||||
"getElementsByTagName ABC": true,
|
||||
"getElementsByTagName \u00e4": true,
|
||||
"getElementsByTagName \u00c4": true
|
||||
"getElementsByTagName ABC": true
|
||||
}
|
||||
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"document.getElementsByClassName(): compound": true
|
||||
}
|
@ -36,7 +36,7 @@ public:
|
||||
nsresult Flush();
|
||||
|
||||
// Shutdown decoder and rejects the init promise.
|
||||
nsresult Shutdown();
|
||||
virtual nsresult Shutdown();
|
||||
|
||||
// True if sample is queued.
|
||||
bool HasQueuedSample();
|
||||
|
@ -59,16 +59,22 @@ GonkVideoDecoderManager::GonkVideoDecoderManager(
|
||||
nsIntSize frameSize(mVideoWidth, mVideoHeight);
|
||||
mPicture = pictureRect;
|
||||
mInitialFrame = frameSize;
|
||||
mVideoListener = new VideoResourceListener(this);
|
||||
mVideoListener = new VideoResourceListener();
|
||||
|
||||
}
|
||||
|
||||
GonkVideoDecoderManager::~GonkVideoDecoderManager()
|
||||
{
|
||||
mVideoListener->NotifyManagerRelease();
|
||||
MOZ_COUNT_DTOR(GonkVideoDecoderManager);
|
||||
}
|
||||
|
||||
nsresult
|
||||
GonkVideoDecoderManager::Shutdown()
|
||||
{
|
||||
mVideoCodecRequest.DisconnectIfExists();
|
||||
return GonkDecoderManager::Shutdown();
|
||||
}
|
||||
|
||||
nsRefPtr<MediaDataDecoder::InitPromise>
|
||||
GonkVideoDecoderManager::Init()
|
||||
{
|
||||
@ -107,6 +113,16 @@ GonkVideoDecoderManager::Init()
|
||||
}
|
||||
|
||||
nsRefPtr<InitPromise> p = mInitPromise.Ensure(__func__);
|
||||
android::sp<GonkVideoDecoderManager> self = this;
|
||||
mVideoCodecRequest.Begin(mVideoListener->Init()
|
||||
->Then(mReaderTaskQueue, __func__,
|
||||
[self] (bool) -> void {
|
||||
self->mVideoCodecRequest.Complete();
|
||||
self->codecReserved();
|
||||
}, [self] (bool) -> void {
|
||||
self->mVideoCodecRequest.Complete();
|
||||
self->codecCanceled();
|
||||
}));
|
||||
mDecoder = MediaCodecProxy::CreateByType(mDecodeLooper, mMimeType.get(), false, mVideoListener);
|
||||
mDecoder->AsyncAskMediaCodec();
|
||||
|
||||
@ -399,6 +415,9 @@ void GonkVideoDecoderManager::ReleaseVideoBuffer() {
|
||||
void
|
||||
GonkVideoDecoderManager::codecReserved()
|
||||
{
|
||||
if (mInitPromise.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
GVDM_LOG("codecReserved");
|
||||
sp<AMessage> format = new AMessage;
|
||||
sp<Surface> surface;
|
||||
@ -427,7 +446,7 @@ GonkVideoDecoderManager::codecReserved()
|
||||
return;
|
||||
}
|
||||
|
||||
mInitPromise.ResolveIfExists(TrackType::kVideoTrack, __func__);
|
||||
mInitPromise.Resolve(TrackType::kVideoTrack, __func__);
|
||||
}
|
||||
|
||||
void
|
||||
@ -456,66 +475,24 @@ GonkVideoDecoderManager::onMessageReceived(const sp<AMessage> &aMessage)
|
||||
}
|
||||
}
|
||||
|
||||
GonkVideoDecoderManager::VideoResourceListener::VideoResourceListener(GonkVideoDecoderManager *aManager)
|
||||
: mManager(aManager)
|
||||
GonkVideoDecoderManager::VideoResourceListener::VideoResourceListener()
|
||||
{
|
||||
}
|
||||
|
||||
GonkVideoDecoderManager::VideoResourceListener::~VideoResourceListener()
|
||||
{
|
||||
mManager = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
GonkVideoDecoderManager::VideoResourceListener::codecReserved()
|
||||
{
|
||||
// This class holds VideoResourceListener reference to prevent it's destroyed.
|
||||
class CodecListenerHolder : public nsRunnable {
|
||||
public:
|
||||
CodecListenerHolder(VideoResourceListener* aListener)
|
||||
: mVideoListener(aListener) {}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
mVideoListener->NotifyCodecReserved();
|
||||
mVideoListener = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
android::sp<VideoResourceListener> mVideoListener;
|
||||
};
|
||||
|
||||
if (mManager) {
|
||||
nsRefPtr<CodecListenerHolder> runner = new CodecListenerHolder(this);
|
||||
mManager->mReaderTaskQueue->Dispatch(runner.forget());
|
||||
}
|
||||
mVideoCodecPromise.Resolve(true, __func__);
|
||||
}
|
||||
|
||||
void
|
||||
GonkVideoDecoderManager::VideoResourceListener::codecCanceled()
|
||||
{
|
||||
if (mManager) {
|
||||
MOZ_ASSERT(mManager->mReaderTaskQueue->IsCurrentThreadIn());
|
||||
nsCOMPtr<nsIRunnable> r =
|
||||
NS_NewNonOwningRunnableMethod(mManager, &GonkVideoDecoderManager::codecCanceled);
|
||||
mManager->mReaderTaskQueue->Dispatch(r.forget());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GonkVideoDecoderManager::VideoResourceListener::NotifyManagerRelease()
|
||||
{
|
||||
MOZ_ASSERT_IF(mManager, mManager->mReaderTaskQueue->IsCurrentThreadIn());
|
||||
mManager = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
GonkVideoDecoderManager::VideoResourceListener::NotifyCodecReserved()
|
||||
{
|
||||
if (mManager) {
|
||||
MOZ_ASSERT(mManager->mReaderTaskQueue->IsCurrentThreadIn());
|
||||
mManager->codecReserved();
|
||||
}
|
||||
mVideoCodecPromise.Reject(true, __func__);
|
||||
}
|
||||
|
||||
uint8_t *
|
||||
|
@ -36,6 +36,8 @@ typedef android::MediaCodecProxy MediaCodecProxy;
|
||||
typedef mozilla::layers::TextureClient TextureClient;
|
||||
|
||||
public:
|
||||
typedef MozPromise<bool /* aIgnored */, bool /* aIgnored */, /* IsExclusive = */ true> MediaResourcePromise;
|
||||
|
||||
GonkVideoDecoderManager(mozilla::layers::ImageContainer* aImageContainer,
|
||||
const VideoInfo& aConfig);
|
||||
|
||||
@ -46,6 +48,8 @@ public:
|
||||
nsresult Output(int64_t aStreamOffset,
|
||||
nsRefPtr<MediaData>& aOutput) override;
|
||||
|
||||
nsresult Shutdown() override;
|
||||
|
||||
static void RecycleCallback(TextureClient* aClient, void* aClosure);
|
||||
|
||||
private:
|
||||
@ -67,24 +71,25 @@ private:
|
||||
class VideoResourceListener : public android::MediaCodecProxy::CodecResourceListener
|
||||
{
|
||||
public:
|
||||
VideoResourceListener(GonkVideoDecoderManager *aManager);
|
||||
VideoResourceListener();
|
||||
~VideoResourceListener();
|
||||
|
||||
nsRefPtr<MediaResourcePromise> Init()
|
||||
{
|
||||
nsRefPtr<MediaResourcePromise> p = mVideoCodecPromise.Ensure(__func__);
|
||||
return p.forget();
|
||||
}
|
||||
|
||||
void codecReserved() override;
|
||||
void codecCanceled() override;
|
||||
|
||||
void NotifyManagerRelease();
|
||||
void NotifyCodecReserved();
|
||||
|
||||
private:
|
||||
// Forbidden
|
||||
VideoResourceListener() = delete;
|
||||
VideoResourceListener(const VideoResourceListener &rhs) = delete;
|
||||
const VideoResourceListener &operator=(const VideoResourceListener &rhs) = delete;
|
||||
|
||||
GonkVideoDecoderManager *mManager;
|
||||
MozPromiseHolder<MediaResourcePromise> mVideoCodecPromise;
|
||||
};
|
||||
friend class VideoResourceListener;
|
||||
|
||||
bool SetVideoFormat();
|
||||
|
||||
@ -113,6 +118,7 @@ private:
|
||||
|
||||
MediaInfo mInfo;
|
||||
android::sp<VideoResourceListener> mVideoListener;
|
||||
MozPromiseRequestHolder<MediaResourcePromise> mVideoCodecRequest;
|
||||
FrameInfo mFrameInfo;
|
||||
|
||||
// color converter
|
||||
|
@ -1847,6 +1847,10 @@ nsPluginHost::SiteHasData(nsIPluginTag* plugin, const nsACString& domain,
|
||||
nsPluginHost::SpecialType
|
||||
nsPluginHost::GetSpecialType(const nsACString & aMIMEType)
|
||||
{
|
||||
if (aMIMEType.LowerCaseEqualsASCII("application/x-test")) {
|
||||
return eSpecialType_Test;
|
||||
}
|
||||
|
||||
if (aMIMEType.LowerCaseEqualsASCII("application/x-shockwave-flash") ||
|
||||
aMIMEType.LowerCaseEqualsASCII("application/futuresplash")) {
|
||||
return eSpecialType_Flash;
|
||||
@ -2446,6 +2450,7 @@ nsPluginHost::FindPluginsInContent(bool aCreatePluginList, bool* aPluginsChanged
|
||||
nsTArray<nsCString>(tag.extensions()),
|
||||
tag.isJavaPlugin(),
|
||||
tag.isFlashPlugin(),
|
||||
tag.supportsAsyncInit(),
|
||||
tag.lastModifiedTime(),
|
||||
tag.isFromExtension());
|
||||
AddPluginTag(pluginTag);
|
||||
@ -2682,6 +2687,7 @@ nsPluginHost::FindPluginsForContent(uint32_t aPluginEpoch,
|
||||
tag->Extensions(),
|
||||
tag->mIsJavaPlugin,
|
||||
tag->mIsFlashPlugin,
|
||||
tag->mSupportsAsyncInit,
|
||||
tag->FileName(),
|
||||
tag->Version(),
|
||||
tag->mLastModifiedTime,
|
||||
|
@ -191,6 +191,8 @@ public:
|
||||
|
||||
// checks whether aType is a type we recognize for potential special handling
|
||||
enum SpecialType { eSpecialType_None,
|
||||
// Needed to whitelist for async init support
|
||||
eSpecialType_Test,
|
||||
// Informs some decisions about OOP and quirks
|
||||
eSpecialType_Flash,
|
||||
// Binds to the <applet> tag, has various special
|
||||
|
@ -293,6 +293,7 @@ nsPluginTag::nsPluginTag(uint32_t aId,
|
||||
nsTArray<nsCString> aExtensions,
|
||||
bool aIsJavaPlugin,
|
||||
bool aIsFlashPlugin,
|
||||
bool aSupportsAsyncInit,
|
||||
int64_t aLastModifiedTime,
|
||||
bool aFromExtension)
|
||||
: nsIInternalPluginTag(aName, aDescription, aFileName, aVersion, aMimeTypes,
|
||||
@ -302,7 +303,7 @@ nsPluginTag::nsPluginTag(uint32_t aId,
|
||||
mLibrary(nullptr),
|
||||
mIsJavaPlugin(aIsJavaPlugin),
|
||||
mIsFlashPlugin(aIsFlashPlugin),
|
||||
mSupportsAsyncInit(false),
|
||||
mSupportsAsyncInit(aSupportsAsyncInit),
|
||||
mLastModifiedTime(aLastModifiedTime),
|
||||
mNiceFileName(),
|
||||
mCachedBlocklistState(nsIBlocklistService::STATE_NOT_BLOCKED),
|
||||
@ -354,6 +355,7 @@ void nsPluginTag::InitMime(const char* const* aMimeTypes,
|
||||
break;
|
||||
case nsPluginHost::eSpecialType_Silverlight:
|
||||
case nsPluginHost::eSpecialType_Unity:
|
||||
case nsPluginHost::eSpecialType_Test:
|
||||
mSupportsAsyncInit = true;
|
||||
break;
|
||||
case nsPluginHost::eSpecialType_None:
|
||||
|
@ -128,6 +128,7 @@ public:
|
||||
nsTArray<nsCString> aExtensions,
|
||||
bool aIsJavaPlugin,
|
||||
bool aIsFlashPlugin,
|
||||
bool aSupportsAsyncInit,
|
||||
int64_t aLastModifiedTime,
|
||||
bool aFromExtension);
|
||||
|
||||
|
@ -16,6 +16,7 @@ struct PluginTag
|
||||
nsCString[] extensions;
|
||||
bool isJavaPlugin;
|
||||
bool isFlashPlugin;
|
||||
bool supportsAsyncInit;
|
||||
nsCString filename;
|
||||
nsCString version;
|
||||
int64_t lastModifiedTime;
|
||||
|
@ -112,11 +112,33 @@ Volume::Dump(const char* aLabel) const
|
||||
: (IsUnmounting() ? "y" : "n"));
|
||||
}
|
||||
|
||||
void
|
||||
Volume::ResolveAndSetMountPoint(const nsCSubstring& aMountPoint)
|
||||
{
|
||||
nsCString mountPoint(aMountPoint);
|
||||
char realPathBuf[PATH_MAX];
|
||||
|
||||
// Call realpath so that we wind up with a path which is compatible with
|
||||
// functions like nsVolumeService::GetVolumeByPath.
|
||||
|
||||
if (realpath(mountPoint.get(), realPathBuf) < 0) {
|
||||
// The path we were handed doesn't exist. Warn about it, but use it
|
||||
// anyways assuming that the user knows what they're doing.
|
||||
|
||||
ERR("ResolveAndSetMountPoint: realpath on '%s' failed: %d",
|
||||
mountPoint.get(), errno);
|
||||
mMountPoint = mountPoint;
|
||||
} else {
|
||||
mMountPoint = realPathBuf;
|
||||
}
|
||||
DBG("Volume %s: Setting mountpoint to '%s'", NameStr(), mMountPoint.get());
|
||||
}
|
||||
|
||||
void Volume::SetFakeVolume(const nsACString& aMountPoint)
|
||||
{
|
||||
this->mMountLocked = false;
|
||||
this->mCanBeShared = false;
|
||||
this->mMountPoint = aMountPoint;
|
||||
ResolveAndSetMountPoint(aMountPoint);
|
||||
SetState(nsIVolume::STATE_MOUNTED);
|
||||
}
|
||||
|
||||
@ -386,8 +408,7 @@ Volume::SetMountPoint(const nsCSubstring& aMountPoint)
|
||||
if (mMountPoint.Equals(aMountPoint)) {
|
||||
return;
|
||||
}
|
||||
mMountPoint = aMountPoint;
|
||||
DBG("Volume %s: Setting mountpoint to '%s'", NameStr(), mMountPoint.get());
|
||||
ResolveAndSetMountPoint(aMountPoint);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -119,6 +119,8 @@ private:
|
||||
void SetMountPoint(const nsCSubstring& aMountPoint);
|
||||
void StartCommand(VolumeCommand* aCommand);
|
||||
|
||||
void ResolveAndSetMountPoint(const nsCSubstring& aMountPoint);
|
||||
|
||||
bool BoolConfigValue(const nsCString& aConfigValue, bool& aBoolValue);
|
||||
void SetConfig(const nsCString& aConfigName, const nsCString& aConfigValue);
|
||||
|
||||
|
@ -305,7 +305,7 @@ add_test(function test_is_cphs_service_available() {
|
||||
let context = worker.ContextPool._contexts[0];
|
||||
let ICCUtilsHelper = context.ICCUtilsHelper;
|
||||
let RIL = context.RIL;
|
||||
RIL.iccInfoPrivate.cphsSt = Uint8Array(2);
|
||||
RIL.iccInfoPrivate.cphsSt = new Uint8Array(2);
|
||||
|
||||
function test_table(cphsSt, geckoService) {
|
||||
RIL.iccInfoPrivate.cphsSt.set(cphsSt);
|
||||
|
@ -1312,7 +1312,7 @@ add_test(function test_read_cphs_info() {
|
||||
let recordHelper = context.SimRecordHelper;
|
||||
let buf = context.Buf;
|
||||
let io = context.ICCIOHelper;
|
||||
let cphsPDU = Uint8Array(3);
|
||||
let cphsPDU = new Uint8Array(3);
|
||||
|
||||
io.loadTransparentEF = function(options) {
|
||||
if (cphsPDU) {
|
||||
|
@ -100,7 +100,8 @@ function elementsetattributens03() {
|
||||
docRef = this.doc;
|
||||
}
|
||||
doc = load(docRef, "doc", "staffNS");
|
||||
elementList = doc.getElementsByTagName("emp:employee");
|
||||
// Changed for bug 492933.
|
||||
elementList = doc.getElementsByTagName("employee");
|
||||
element = elementList.item(0);
|
||||
assertNotNull("empEmployeeNotNull",element);
|
||||
element.setAttributeNS("http://www.w3.org/DOM/Test/1","defaultAttr","default1");
|
||||
|
@ -105,11 +105,13 @@ function getAttributeNS02() {
|
||||
}
|
||||
doc = load(docRef, "doc", "staffNS");
|
||||
newAttribute = doc.createAttributeNS(namespaceURI,qualifiedName);
|
||||
elementList = doc.getElementsByTagName("emp:address");
|
||||
// Changed for bug 492933.
|
||||
elementList = doc.getElementsByTagName("address");
|
||||
testAddr = elementList.item(0);
|
||||
assertNotNull("empAddrNotNull",testAddr);
|
||||
districtAttr = testAddr.setAttributeNodeNS(newAttribute);
|
||||
elementList = doc.getElementsByTagName("emp:address");
|
||||
// Changed for bug 492933.
|
||||
elementList = doc.getElementsByTagName("address");
|
||||
testAddr = elementList.item(0);
|
||||
attrValue = testAddr.getAttributeNS(namespaceURI,localName);
|
||||
assertEquals("throw_Equals","",attrValue);
|
||||
|
@ -100,7 +100,8 @@ function getAttributeNS03() {
|
||||
docRef = this.doc;
|
||||
}
|
||||
doc = load(docRef, "doc", "staffNS");
|
||||
elementList = doc.getElementsByTagName("emp:address");
|
||||
// Changed for bug 492933.
|
||||
elementList = doc.getElementsByTagName("address");
|
||||
testAddr = elementList.item(0);
|
||||
assertNotNull("empAddrNotNull",testAddr);
|
||||
testAddr.removeAttributeNS(namespaceURI,localName);
|
||||
|
@ -105,7 +105,8 @@ function getAttributeNS04() {
|
||||
}
|
||||
doc = load(docRef, "doc", "staffNS");
|
||||
newAttribute = doc.createAttributeNS(namespaceURI,qualifiedName);
|
||||
elementList = doc.getElementsByTagName("emp:address");
|
||||
// Changed for bug 492933.
|
||||
elementList = doc.getElementsByTagName("address");
|
||||
testAddr = elementList.item(0);
|
||||
assertNotNull("empAddrNotNull",testAddr);
|
||||
testAddr.setAttributeNS(namespaceURI,qualifiedName,"NewValue");
|
||||
|
@ -99,8 +99,9 @@ function getAttributeNS05() {
|
||||
docRef = this.doc;
|
||||
}
|
||||
doc = load(docRef, "doc", "staffNS");
|
||||
elementList = doc.getElementsByTagName("emp:address");
|
||||
testAddr = elementList.item(0);
|
||||
// Changed for bug 492933.
|
||||
elementList = doc.getElementsByTagName("address");
|
||||
testAddr = elementList.item(3);
|
||||
assertNotNull("empAddrNotNull",testAddr);
|
||||
attrValue = testAddr.getAttributeNS("http://www.nist.gov","domestic");
|
||||
assertEquals("attrValue","Yes",attrValue);
|
||||
|
@ -101,7 +101,8 @@ function getAttributeNodeNS01() {
|
||||
docRef = this.doc;
|
||||
}
|
||||
doc = load(docRef, "doc", "staffNS");
|
||||
elementList = doc.getElementsByTagName("emp:address");
|
||||
// Changed for bug 492933.
|
||||
elementList = doc.getElementsByTagName("address");
|
||||
testAddr = elementList.item(0);
|
||||
assertNotNull("empAddrNotNull",testAddr);
|
||||
attribute = testAddr.getAttributeNodeNS(namespaceURI,localName);
|
||||
|
@ -100,8 +100,9 @@ function getAttributeNodeNS02() {
|
||||
docRef = this.doc;
|
||||
}
|
||||
doc = load(docRef, "doc", "staffNS");
|
||||
elementList = doc.getElementsByTagName("emp:address");
|
||||
testAddr = elementList.item(0);
|
||||
// Changed for bug 492933.
|
||||
elementList = doc.getElementsByTagName("address");
|
||||
testAddr = elementList.item(3);
|
||||
assertNotNull("empAddrNotNull",testAddr);
|
||||
attribute = testAddr.getAttributeNodeNS("http://www.nist.gov","domestic");
|
||||
attrName = attribute.nodeName;
|
||||
|
@ -100,7 +100,8 @@ function hasAttributeNS03() {
|
||||
docRef = this.doc;
|
||||
}
|
||||
doc = load(docRef, "doc", "staffNS");
|
||||
elementList = doc.getElementsByTagName("emp:address");
|
||||
// Changed for bug 492933.
|
||||
elementList = doc.getElementsByTagName("address");
|
||||
testNode = elementList.item(0);
|
||||
assertNotNull("empAddrNotNull",testNode);
|
||||
state = testNode.hasAttributeNS(namespaceURI,localName);
|
||||
|
@ -102,7 +102,8 @@ function hasAttributeNS04() {
|
||||
docRef = this.doc;
|
||||
}
|
||||
doc = load(docRef, "doc", "staffNS");
|
||||
elementList = doc.getElementsByTagName("emp:address");
|
||||
// Changed for bug 492933.
|
||||
elementList = doc.getElementsByTagName("address");
|
||||
testNode = elementList.item(0);
|
||||
assertNotNull("empAddressNotNull",testNode);
|
||||
state = testNode.hasAttributeNS(namespaceURI,localName);
|
||||
|
@ -119,8 +119,9 @@ function importNode05() {
|
||||
aNewDocRef = this.aNewDoc;
|
||||
}
|
||||
aNewDoc = load(aNewDocRef, "aNewDoc", "staffNS");
|
||||
addresses = aNewDoc.getElementsByTagName("emp:address");
|
||||
element = addresses.item(0);
|
||||
// Changed for bug 492933.
|
||||
addresses = aNewDoc.getElementsByTagName("address");
|
||||
element = addresses.item(3);
|
||||
assertNotNull("empAddressNotNull",element);
|
||||
aNode = doc.importNode(element,false);
|
||||
hasChild = aNode.hasChildNodes();
|
||||
|
@ -117,8 +117,9 @@ function importNode06() {
|
||||
aNewDocRef = this.aNewDoc;
|
||||
}
|
||||
aNewDoc = load(aNewDocRef, "aNewDoc", "staffNS");
|
||||
addresses = aNewDoc.getElementsByTagName("emp:address");
|
||||
element = addresses.item(0);
|
||||
// Changed for bug 492933.
|
||||
addresses = aNewDoc.getElementsByTagName("address");
|
||||
element = addresses.item(3);
|
||||
assertNotNull("empAddressNotNull",element);
|
||||
aNode = doc.importNode(element,true);
|
||||
hasChild = aNode.hasChildNodes();
|
||||
|
@ -101,8 +101,9 @@ function localName01() {
|
||||
docRef = this.doc;
|
||||
}
|
||||
doc = load(docRef, "doc", "staffNS");
|
||||
elementList = doc.getElementsByTagName("emp:address");
|
||||
testAddr = elementList.item(0);
|
||||
// Changed for bug 492933.
|
||||
elementList = doc.getElementsByTagName("address");
|
||||
testAddr = elementList.item(3);
|
||||
assertNotNull("empAddrNotNull",testAddr);
|
||||
addrAttr = testAddr.getAttributeNode("emp:domestic");
|
||||
localName = addrAttr.localName;
|
||||
|
@ -99,8 +99,9 @@ function namespaceURI02() {
|
||||
docRef = this.doc;
|
||||
}
|
||||
doc = load(docRef, "doc", "staffNS");
|
||||
elementList = doc.getElementsByTagName("emp:address");
|
||||
testAddr = elementList.item(0);
|
||||
// Changed for bug 492933.
|
||||
elementList = doc.getElementsByTagName("address");
|
||||
testAddr = elementList.item(3);
|
||||
assertNotNull("empAddressNotNull",testAddr);
|
||||
addrAttr = testAddr.getAttributeNodeNS("http://www.nist.gov","domestic");
|
||||
attrNamespaceURI = addrAttr.namespaceURI;
|
||||
|
@ -94,7 +94,8 @@ function nodehasattributes03() {
|
||||
docRef = this.doc;
|
||||
}
|
||||
doc = load(docRef, "doc", "staffNS");
|
||||
elementList = doc.getElementsByTagName("emp:employee");
|
||||
// Changed for bug 492933.
|
||||
elementList = doc.getElementsByTagName("employee");
|
||||
element = elementList.item(0);
|
||||
assertNotNull("empEmployeeNotNull",element);
|
||||
hasAttributes = element.hasAttributes();
|
||||
|
@ -100,7 +100,8 @@ function prefix02() {
|
||||
docRef = this.doc;
|
||||
}
|
||||
doc = load(docRef, "doc", "staffNS");
|
||||
elementList = doc.getElementsByTagName("emp:employeeId");
|
||||
// Changed for bug 492933.
|
||||
elementList = doc.getElementsByTagName("employeeId");
|
||||
testEmployee = elementList.item(0);
|
||||
assertNotNull("empEmployeeNotNull",testEmployee);
|
||||
textNode = testEmployee.firstChild;
|
||||
|
@ -97,8 +97,9 @@ function prefix03() {
|
||||
docRef = this.doc;
|
||||
}
|
||||
doc = load(docRef, "doc", "staffNS");
|
||||
elementList = doc.getElementsByTagName("emp:employee");
|
||||
testEmployee = elementList.item(0);
|
||||
// Changed for bug 492933.
|
||||
elementList = doc.getElementsByTagName("employee");
|
||||
testEmployee = elementList.item(3);
|
||||
assertNotNull("empEmployeeNotNull",testEmployee);
|
||||
prefix = testEmployee.prefix;
|
||||
|
||||
|
@ -100,7 +100,8 @@ function setAttributeNS02() {
|
||||
docRef = this.doc;
|
||||
}
|
||||
doc = load(docRef, "doc", "staffNS");
|
||||
elementList = doc.getElementsByTagName("emp:employee");
|
||||
// Changed for bug 492933.
|
||||
elementList = doc.getElementsByTagName("employee");
|
||||
testAddr = elementList.item(0);
|
||||
|
||||
{
|
||||
|
@ -108,7 +108,8 @@ function setAttributeNS04() {
|
||||
docRef = this.doc;
|
||||
}
|
||||
doc = load(docRef, "doc", "staffNS");
|
||||
elementList = doc.getElementsByTagName("emp:address");
|
||||
// Changed for bug 492933.
|
||||
elementList = doc.getElementsByTagName("address");
|
||||
testAddr = elementList.item(0);
|
||||
assertNotNull("empAddrNotNull",testAddr);
|
||||
testAddr.setAttributeNS("http://www.nist.gov","newprefix:zone","newValue");
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user