Merge m-c to b-i

This commit is contained in:
Wes Kocher 2013-10-14 19:12:25 -07:00
commit 76de2fbfd9
162 changed files with 2588 additions and 1583 deletions

View File

@ -18,4 +18,4 @@
# Modifying this file will now automatically clobber the buildbot machines \o/
#
Bug 915002 - Clobber needed for webidl updates for AppNotificationServiceOptions. One more time.
Bug 872934 - Clobber needed for webidl updates for style sheet change events. Again and again.

View File

@ -243,5 +243,8 @@ ifdef MOZ_PSEUDO_DERECURSE
js/xpconnect/src/export: dom/bindings/export
accessible/src/xpcom/export: xpcom/xpidl/export
js/src/export: mfbt/export
ifdef ENABLE_CLANG_PLUGIN
js/src/export config/export: build/clang-plugin/export
endif
endif
endif

View File

@ -11,8 +11,9 @@ const Cr = Components.results;
const INCLUDE_DESC = 0x01;
const INCLUDE_NAME = 0x02;
const INCLUDE_CUSTOM = 0x04;
const NAME_FROM_SUBTREE_RULE = 0x08;
const INCLUDE_VALUE = 0x04;
const INCLUDE_CUSTOM = 0x08;
const NAME_FROM_SUBTREE_RULE = 0x10;
const OUTPUT_DESC_FIRST = 0;
const OUTPUT_DESC_LAST = 1;
@ -64,8 +65,9 @@ this.OutputGenerator = {
let nameRule = self.roleRuleMap[roleString] || 0;
// Ignore subtree if the name is explicit and the role's name rule is the
// NAME_FROM_SUBTREE_RULE.
return (nameRule & NAME_FROM_SUBTREE_RULE) &&
(Utils.getAttributes(aAccessible)['explicit-name'] === 'true');
return (((nameRule & INCLUDE_VALUE) && aAccessible.value) ||
((nameRule & NAME_FROM_SUBTREE_RULE) &&
Utils.getAttributes(aAccessible)['explicit-name'] === 'true'));
};
let contextStart = this._getContextStart(aContext);
@ -256,9 +258,9 @@ this.OutputGenerator = {
'buttondropdown': NAME_FROM_SUBTREE_RULE,
'combobox': INCLUDE_DESC,
'droplist': INCLUDE_DESC,
'progressbar': INCLUDE_DESC,
'slider': INCLUDE_DESC,
'spinbutton': INCLUDE_DESC,
'progressbar': INCLUDE_DESC | INCLUDE_VALUE,
'slider': INCLUDE_DESC | INCLUDE_VALUE,
'spinbutton': INCLUDE_DESC | INCLUDE_VALUE,
'diagram': INCLUDE_DESC,
'animation': INCLUDE_DESC,
'equation': INCLUDE_DESC,
@ -278,7 +280,7 @@ this.OutputGenerator = {
'parent menuitem': NAME_FROM_SUBTREE_RULE,
'header': INCLUDE_DESC,
'footer': INCLUDE_DESC,
'entry': INCLUDE_DESC | INCLUDE_NAME,
'entry': INCLUDE_DESC | INCLUDE_NAME | INCLUDE_VALUE,
'caption': INCLUDE_DESC,
'document frame': INCLUDE_DESC,
'heading': INCLUDE_DESC,
@ -309,25 +311,36 @@ this.OutputGenerator = {
output.push(desc.join(' '));
}
if (aFlags & INCLUDE_VALUE) {
let value = aAccessible.value;
if (value) {
output[this.outputOrder === OUTPUT_DESC_FIRST ?
'push' : 'unshift'](value);
}
}
this._addName(output, aAccessible, aFlags);
this._addLandmark(output, aAccessible);
return output;
},
label: function label(aAccessible, aRoleStr, aStates, aFlags, aContext) {
if (aContext.isNestedControl ||
aContext.accessible == Utils.getEmbeddedControl(aAccessible)) {
// If we are on a nested control, or a nesting label,
// we don't need the context.
return [];
}
return this.objectOutputFunctions.defaultFunc.apply(this, arguments);
},
entry: function entry(aAccessible, aRoleStr, aStates, aFlags) {
let output = [];
let desc = this._getLocalizedStates(aStates);
desc.push(this._getLocalizedRole(
(aStates.ext & Ci.nsIAccessibleStates.EXT_STATE_MULTI_LINE) ?
'textarea' : 'entry'));
output.push(desc.join(' '));
this._addName(output, aAccessible, aFlags);
this._addLandmark(output, aAccessible);
return output;
let rolestr = (aStates.ext & Ci.nsIAccessibleStates.EXT_STATE_MULTI_LINE) ?
'textarea' : 'entry';
return this.objectOutputFunctions.defaultFunc.apply(
this, [aAccessible, rolestr, aStates, aFlags]);
},
pagetab: function pagetab(aAccessible, aRoleStr, aStates, aFlags) {

View File

@ -163,20 +163,21 @@ VisualPresenter.prototype = {
pivotChanged: function VisualPresenter_pivotChanged(aContext, aReason) {
this._displayedAccessibles.set(aContext.accessible.document.window,
{ accessible: aContext.accessible,
{ accessible: aContext.accessibleForBounds,
startOffset: aContext.startOffset,
endOffset: aContext.endOffset });
if (!aContext.accessible)
if (!aContext.accessibleForBounds)
return {type: this.type, details: {method: 'hideBounds'}};
try {
aContext.accessible.scrollTo(
aContext.accessibleForBounds.scrollTo(
Ci.nsIAccessibleScrollType.SCROLL_TYPE_ANYWHERE);
let bounds = (aContext.startOffset === -1 && aContext.endOffset === -1) ?
aContext.bounds : Utils.getTextBounds(aContext.accessible,
aContext.startOffset, aContext.endOffset);
aContext.bounds : Utils.getTextBounds(aContext.accessibleForBounds,
aContext.startOffset,
aContext.endOffset);
return {
type: this.type,

View File

@ -48,6 +48,7 @@ const ROLE_TABLE = Ci.nsIAccessibleRole.ROLE_TABLE;
const ROLE_INTERNAL_FRAME = Ci.nsIAccessibleRole.ROLE_INTERNAL_FRAME;
const ROLE_PARAGRAPH = Ci.nsIAccessibleRole.ROLE_PARAGRAPH;
const ROLE_SECTION = Ci.nsIAccessibleRole.ROLE_SECTION;
const ROLE_LABEL = Ci.nsIAccessibleRole.ROLE_LABEL;
this.EXPORTED_SYMBOLS = ['TraversalRules'];
@ -57,8 +58,12 @@ Cu.import('resource://gre/modules/XPCOMUtils.jsm');
let gSkipEmptyImages = new PrefCache('accessibility.accessfu.skip_empty_images');
function BaseTraversalRule(aRoles, aMatchFunc) {
this._explicitMatchRoles = new Set(aRoles);
this._matchRoles = aRoles;
this._matchFunc = aMatchFunc;
if (aRoles.indexOf(ROLE_LABEL) < 0) {
this._matchRoles.push(ROLE_LABEL);
}
this._matchFunc = aMatchFunc || function (acc) { return FILTER_MATCH; };
}
BaseTraversalRule.prototype = {
@ -73,15 +78,25 @@ BaseTraversalRule.prototype = {
match: function BaseTraversalRule_match(aAccessible)
{
if (aAccessible.role == ROLE_INTERNAL_FRAME) {
let role = aAccessible.role;
if (role == ROLE_INTERNAL_FRAME) {
return (Utils.getMessageManager(aAccessible.DOMNode)) ?
FILTER_MATCH | FILTER_IGNORE_SUBTREE : FILTER_IGNORE;
}
if (this._matchFunc)
return this._matchFunc(aAccessible);
let matchResult = this._explicitMatchRoles.has(role) ?
this._matchFunc(aAccessible) : FILTER_IGNORE;
return FILTER_MATCH;
// If we are on a label that nests a checkbox/radio we should land on it.
// It is a bigger touch target, and it reduces clutter.
if (role == ROLE_LABEL && !(matchResult & FILTER_IGNORE_SUBTREE)) {
let control = Utils.getEmbeddedControl(aAccessible);
if (control && this._explicitMatchRoles.has(control.role)) {
matchResult = this._matchFunc(control) | FILTER_IGNORE_SUBTREE;
}
}
return matchResult;
},
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAccessibleTraversalRule])

View File

@ -14,6 +14,8 @@ const ROLE_CELL = Ci.nsIAccessibleRole.ROLE_CELL;
const ROLE_COLUMNHEADER = Ci.nsIAccessibleRole.ROLE_COLUMNHEADER;
const ROLE_ROWHEADER = Ci.nsIAccessibleRole.ROLE_ROWHEADER;
const RELATION_LABEL_FOR = Ci.nsIAccessibleRelation.RELATION_LABEL_FOR;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, 'Services',
'resource://gre/modules/Services.jsm');
@ -291,6 +293,20 @@ this.Utils = {
// Looking up a role that would match a landmark.
return this.matchAttributeValue(roles, landmarks);
},
getEmbeddedControl: function getEmbeddedControl(aLabel) {
if (aLabel) {
let relation = aLabel.getRelationByType(RELATION_LABEL_FOR);
for (let i = 0; i < relation.targetsCount; i++) {
let target = relation.getTarget(i);
if (target.parent === aLabel) {
return target;
}
}
}
return null;
}
};
@ -425,11 +441,18 @@ this.Logger = {
/**
* PivotContext: An object that generates and caches context information
* for a given accessible and its relationship with another accessible.
*
* If the given accessible is a label for a nested control, then this
* context will represent the nested control instead of the label.
* With the exception of bounds calculation, which will use the containing
* label. In this case the |accessible| field would be the embedded control,
* and the |accessibleForBounds| field would be the label.
*/
this.PivotContext = function PivotContext(aAccessible, aOldAccessible,
aStartOffset, aEndOffset, aIgnoreAncestry = false,
aIncludeInvisible = false) {
this._accessible = aAccessible;
this._nestedControl = Utils.getEmbeddedControl(aAccessible);
this._oldAccessible =
this._isDefunct(aOldAccessible) ? null : aOldAccessible;
this.startOffset = aStartOffset;
@ -440,13 +463,23 @@ this.PivotContext = function PivotContext(aAccessible, aOldAccessible,
PivotContext.prototype = {
get accessible() {
return this._accessible;
// If the current pivot accessible has a nested control,
// make this context use it publicly.
return this._nestedControl || this._accessible;
},
get oldAccessible() {
return this._oldAccessible;
},
get isNestedControl() {
return !!this._nestedControl;
},
get accessibleForBounds() {
return this._accessible;
},
get textAndAdjustedOffsets() {
if (this.startOffset === -1 && this.endOffset === -1) {
return null;
@ -521,7 +554,7 @@ PivotContext.prototype = {
get currentAncestry() {
if (!this._currentAncestry) {
this._currentAncestry = this._ignoreAncestry ? [] :
this._getAncestry(this._accessible);
this._getAncestry(this.accessible);
}
return this._currentAncestry;
},
@ -582,7 +615,7 @@ PivotContext.prototype = {
* traversal should stop.
*/
subtreeGenerator: function subtreeGenerator(aPreorder, aStop) {
return this._traverse(this._accessible, aPreorder, aStop);
return this._traverse(this.accessible, aPreorder, aStop);
},
getCellInfo: function getCellInfo(aAccessible) {
@ -677,7 +710,7 @@ PivotContext.prototype = {
get bounds() {
if (!this._bounds) {
this._bounds = Utils.getBounds(this._accessible);
this._bounds = Utils.getBounds(this.accessibleForBounds);
}
return this._bounds.clone();

View File

@ -173,6 +173,11 @@ function activateCurrent(aMessage) {
if (aAccessible.actionCount > 0) {
aAccessible.doAction(0);
} else {
let control = Utils.getEmbeddedControl(aAccessible);
if (control && control.actionCount > 0) {
control.doAction(0);
}
// XXX Some mobile widget sets do not expose actions properly
// (via ARIA roles, etc.), so we need to generate a click.
// Could possibly be made simpler in the future. Maybe core

View File

@ -25,7 +25,9 @@ function testContextOutput(expected, aAccOrElmOrID, aOldAccOrElmOrID, aGenerator
var output = aGenerator.genForContext(context).output;
isDeeply(output, expected,
"Context output is correct for " + aAccOrElmOrID);
"Context output is correct for " + aAccOrElmOrID +
" (output: " + output.join(", ") + ") ==" +
" (expected: " + expected.join(", ") + ")");
}
/**

View File

@ -56,6 +56,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=876475
},{
accOrElmOrID: "textarea",
expected: [["txtarea", "Here lies treasure."], ["Here lies treasure.", "txtarea"]]
},{
accOrElmOrID: "textentry",
expected: [["entry", "Mario", "First name:"], ["First name:", "Mario", "entry"]]
},{
accOrElmOrID: "range",
expected: [["slider", "3", "Points:"], ["Points:", "3", "slider"]]
}];
// Test all possible braille order preference values.
@ -109,6 +115,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=876475
<textarea id="textarea" cols="80" rows="5">
Here lies treasure.
</textarea>
<label>First name: <input id="textentry" value="Mario"></label>
<label>Points: <input id="range" type="range" name="points" min="1" max="10" value="3"></label>
</div>
</body>
</html>

View File

@ -28,7 +28,7 @@
expected: ["button", "Press me"]
}, {
accOrElmOrID: "textarea1",
expected: ["text area", "Test Text Area", "This is the text area text."]
expected: ["text area", "This is the text area text.", "Test Text Area"]
}, {
accOrElmOrID: "textarea2",
expected: ["text area", "This is the text area text."]

View File

@ -139,6 +139,56 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=753984
accOrElmOrID: 'tab2',
expected: [['tab list', 'tab 2 of 2', 'Advanced'],
['Advanced', 'tab 2 of 2', 'tab list']]
},
{
// Landing on this label should mimic landing on the checkbox.
accOrElmOrID: "label1",
expected: [['not checked check button', 'Orange'],
['Orange', 'not checked check button']]
},
{
// Here we get a top-level view of the form.
accOrElmOrID: "form1",
expected: [['label', 'not checked check button', 'Orange', 'Orange',
'not checked check button', 'Blue', 'label', 'Blue'],
['Orange', 'not checked check button', 'Orange', 'label',
'Blue', 'not checked check button', 'Blue', 'label']]
},
{
// This is a non-nesting label.
accOrElmOrID: "label2",
expected: [['label', 'Blue'], ['Blue', 'label']]
},
{
// This is a distinct control.
accOrElmOrID: "input2",
expected: [['not checked check button', 'Blue'],
['Blue', 'not checked check button']]
},
{
// This is a nested control.
accOrElmOrID: "input1",
expected: [['not checked check button', 'Orange'],
['Orange', 'not checked check button']]
},
{
// Landing on this label should mimic landing on the entry.
accOrElmOrID: "label3",
expected: [['entry', 'Joe', 'First name:'],
['First name:', 'Joe', 'entry']]
},
{
// This is a nested control with a value.
accOrElmOrID: "input3",
expected: [['entry', 'Joe', 'First name:'],
['First name:', 'Joe', 'entry']]
},
{
// This is a nested control with a value.
accOrElmOrID: "input4",
expected: [['slider', '3', 'Points:'],
['Points:', '3', 'slider']]
}];
// Test all possible utterance order preference values.
@ -218,6 +268,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=753984
<a id="tab1" href="#" role="tab" aria-selected="true">Account</a>
<a id="tab2" href="#" role="tab" aria-selected="false">Advanced</a>
</div>
<form id="form1">
<label id="label1"><input id="input1" type="checkbox">Orange</label>
<input id="input2" type="checkbox"><label id="label2" for="input2">Blue</label>
</form>
<label id="label3">First name: <input id="input3" value="Joe"></label>
<label id="label4">Points:
<input id="input4" type="range" name="points" min="1" max="10" value="3">
</label>
</div>
</body>
</html>

View File

@ -4,8 +4,6 @@
include $(topsrcdir)/config/config.mk
export PYMAKE = $(.PYMAKE)
libs::
$(PYTHON) $(srcdir)/copy_source.py $(topsrcdir) $(srcdir)/source/lib $(FINAL_TARGET)/modules/commonjs >copy_source.mk
$(MAKE) -f copy_source.mk libs

View File

@ -3,31 +3,14 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import os
import posixpath
import sys
def normpath(path):
"""Ensure UNIX style paths are used with GNU make on Windows.
This can be removed once we no longer support GNU make on Windows (bug
828317).
"""
if os.environ.get('PYMAKE') or os.name not in ('nt', 'ce'):
return path
if len(path) > 2 and path[1] == ':':
path = '/' + path[0] + path[2:]
return posixpath.normpath(path)
if len(sys.argv) != 4:
print >> sys.stderr, "Usage: copy_source.py " \
"<topsrcdir> <source directory> <target directory>"
sys.exit(1)
topsrcdir = normpath(sys.argv[1])
topsrcdir = sys.argv[1]
source_dir = sys.argv[2]
target_dir = sys.argv[3]

View File

@ -4137,7 +4137,7 @@
* close many tabs at once.
*/
let target = event.originalTarget;
if (target.className == 'tab-close-button') {
if (target.classList.contains('tab-close-button')) {
// We preemptively set this to allow the closing-multiple-tabs-
// in-a-row case.
if (this._blockDblClick) {

View File

@ -1143,7 +1143,7 @@ SourceScripts.prototype = {
if (item) {
DebuggerView.Sources.callMethod("checkItem", item.target, !isBlackBoxed);
}
DebuggerView.Sources.maybeShowBlackBoxMessage();
DebuggerView.maybeShowBlackBoxMessage();
},
/**
@ -1153,17 +1153,27 @@ SourceScripts.prototype = {
* The source form.
* @param bool aBlackBoxFlag
* True to black box the source, false to un-black box it.
* @returns Promise
* A promize that resolves to [aSource, isBlackBoxed] or rejects to
* [aSource, error].
*/
blackBox: function(aSource, aBlackBoxFlag) {
const sourceClient = this.activeThread.source(aSource);
sourceClient[aBlackBoxFlag ? "blackBox" : "unblackBox"](({ error, message }) => {
const deferred = promise.defer();
sourceClient[aBlackBoxFlag ? "blackBox" : "unblackBox"](aPacket => {
const { error, message } = aPacket;
if (error) {
let msg = "Couldn't toggle black boxing for " + aSource.url + ": " + message;
dumpn(msg);
Cu.reportError(msg);
return;
deferred.reject([aSource, msg]);
} else {
deferred.resolve([aSource, sourceClient.isBlackBoxed]);
}
});
return deferred.promise;
},
/**

View File

@ -50,7 +50,6 @@ SourcesView.prototype = Heritage.extend(WidgetMethods, {
this._cmPopup = document.getElementById("sourceEditorContextMenu");
this._cbPanel = document.getElementById("conditional-breakpoint-panel");
this._cbTextbox = document.getElementById("conditional-breakpoint-panel-textbox");
this._editorDeck = document.getElementById("editor-deck");
this._stopBlackBoxButton = document.getElementById("black-boxed-message-button");
this._prettyPrintButton = document.getElementById("pretty-print");
@ -383,6 +382,10 @@ SourcesView.prototype = Heritage.extend(WidgetMethods, {
* Pretty print the selected source.
*/
prettyPrint: function() {
if (this._prettyPrintButton.hasAttribute("disabled")) {
return;
}
const resetEditor = ([{ url }]) => {
// Only set the text when the source is still selected.
if (url == this.selectedValue) {
@ -397,9 +400,11 @@ SourcesView.prototype = Heritage.extend(WidgetMethods, {
return;
}
let { source } = this.selectedItem.attachment;
let prettyPrinted = DebuggerController.SourceScripts.prettyPrint(source);
prettyPrinted.then(resetEditor, printError);
DebuggerView.showProgressBar();
const { source } = this.selectedItem.attachment;
DebuggerController.SourceScripts.prettyPrint(source)
.then(resetEditor, printError)
.then(DebuggerView.showEditor);
},
/**
@ -690,17 +695,21 @@ SourcesView.prototype = Heritage.extend(WidgetMethods, {
let script = sourceItem.value.split(" -> ").pop();
document.title = L10N.getFormatStr("DebuggerWindowScriptTitle", script);
this.maybeShowBlackBoxMessage();
DebuggerView.maybeShowBlackBoxMessage();
this._updatePrettyPrintButtonState();
},
/**
* Show or hide the black box message vs. source editor depending on if the
* selected source is black boxed or not.
* Enable or disable the pretty print button depending on whether the selected
* source is black boxed or not.
*/
maybeShowBlackBoxMessage: function() {
let sourceForm = this.selectedItem.attachment.source;
let sourceClient = DebuggerController.activeThread.source(sourceForm);
this._editorDeck.selectedIndex = sourceClient.isBlackBoxed ? 1 : 0;
_updatePrettyPrintButtonState: function() {
const { source } = this.selectedItem.attachment;
if (gThreadClient.source(source).isBlackBoxed) {
this._prettyPrintButton.setAttribute("disabled", true);
} else {
this._prettyPrintButton.removeAttribute("disabled");
}
},
/**
@ -715,8 +724,23 @@ SourcesView.prototype = Heritage.extend(WidgetMethods, {
* The check listener for the sources container.
*/
_onSourceCheck: function({ detail: { checked }, target }) {
let item = this.getItemForElement(target);
DebuggerController.SourceScripts.blackBox(item.attachment.source, !checked);
const shouldBlackBox = !checked;
// Be optimistic that the (un-)black boxing will succeed and enable/disable
// the pretty print button immediately. Then, once we actually get the
// results from the server, make sure that it is in the correct state again
// by calling `_updatePrettyPrintButtonState`.
if (shouldBlackBox) {
this._prettyPrintButton.setAttribute("disabled", true);
} else {
this._prettyPrintButton.removeAttribute("disabled");
}
const { source } = this.getItemForElement(target).attachment;
DebuggerController.SourceScripts.blackBox(source, shouldBlackBox)
.then(this._updatePrettyPrintButtonState,
this._updatePrettyPrintButtonState);
},
/**

View File

@ -114,6 +114,12 @@ let DebuggerView = {
this._instrumentsPane = document.getElementById("instruments-pane");
this._instrumentsPaneToggleButton = document.getElementById("instruments-pane-toggle");
this.showEditor = this.showEditor.bind(this);
this.showBlackBoxMessage = this.showBlackBoxMessage.bind(this);
this.showProgressBar = this.showProgressBar.bind(this);
this.maybeShowBlackBoxMessage = this.maybeShowBlackBoxMessage.bind(this);
this._editorDeck = document.getElementById("editor-deck");
this._onTabSelect = this._onInstrumentsPaneTabSelect.bind(this);
this._instrumentsPane.tabpanels.addEventListener("select", this._onTabSelect);
@ -221,6 +227,40 @@ let DebuggerView = {
});
},
/**
* Display the source editor.
*/
showEditor: function() {
this._editorDeck.selectedIndex = 0;
},
/**
* Display the black box message.
*/
showBlackBoxMessage: function() {
this._editorDeck.selectedIndex = 1;
},
/**
* Display the progress bar.
*/
showProgressBar: function() {
this._editorDeck.selectedIndex = 2;
},
/**
* Show or hide the black box message vs. source editor depending on if the
* selected source is black boxed or not.
*/
maybeShowBlackBoxMessage: function() {
let { source } = DebuggerView.Sources.selectedItem.attachment;
if (gThreadClient.source(source).isBlackBoxed) {
this.showBlackBoxMessage();
} else {
this.showEditor();
}
},
/**
* Sets the currently displayed text contents in the source editor.
* This resets the mode and undo stack.
@ -522,6 +562,7 @@ let DebuggerView = {
_instrumentsPaneToggleButton: null,
_collapsePaneString: "",
_expandPaneString: "",
_editorDeck: null,
};
/**

View File

@ -345,6 +345,10 @@
image="chrome://browser/skin/devtools/blackBoxMessageEye.png"
command="unBlackBoxCommand"/>
</vbox>
<vbox id="source-progress-container" align="center" pack="center">
<progressmeter id="source-progress"
mode="undetermined"/>
</vbox>
</deck>
<splitter class="devtools-side-splitter"/>
<tabbox id="instruments-pane"

View File

@ -122,6 +122,7 @@ support-files =
[browser_dbg_pretty-print-07.js]
[browser_dbg_pretty-print-08.js]
[browser_dbg_pretty-print-09.js]
[browser_dbg_pretty-print-10.js]
[browser_dbg_progress-listener-bug.js]
[browser_dbg_reload-preferred-script-01.js]
[browser_dbg_reload-preferred-script-02.js]

View File

@ -24,9 +24,11 @@ function test() {
.then(() => {
const finished = waitForSourceShown(gPanel, "code_ugly.js");
clickPrettyPrintButton();
testProgressBarShown();
return finished;
})
.then(testSourceIsPretty)
.then(testEditorShown)
.then(testSourceIsStillPretty)
.then(() => closeDebuggerAndFinish(gPanel))
.then(null, aError => {
@ -46,11 +48,21 @@ function clickPrettyPrintButton() {
gDebugger);
}
function testProgressBarShown() {
const deck = gDebugger.document.getElementById("editor-deck");
is(deck.selectedIndex, 2, "The progress bar should be shown");
}
function testSourceIsPretty() {
ok(gEditor.getText().contains("\n "),
"The source should be pretty printed.")
}
function testEditorShown() {
const deck = gDebugger.document.getElementById("editor-deck");
is(deck.selectedIndex, 0, "The editor should be shown");
}
function testSourceIsStillPretty() {
const deferred = promise.defer();

View File

@ -0,0 +1,67 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Make sure that we disable the pretty print button for black boxed sources,
* and that clicking it doesn't do anything.
*/
const TAB_URL = EXAMPLE_URL + "doc_pretty-print.html";
let gTab, gDebuggee, gPanel, gDebugger;
let gEditor, gSources;
function test() {
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
gTab = aTab;
gDebuggee = aDebuggee;
gPanel = aPanel;
gDebugger = gPanel.panelWin;
gEditor = gDebugger.DebuggerView.editor;
gSources = gDebugger.DebuggerView.Sources;
waitForSourceShown(gPanel, "code_ugly.js")
.then(testSourceIsUgly)
.then(blackBoxSource)
.then(waitForThreadEvents.bind(null, gPanel, "blackboxchange"))
.then(clickPrettyPrintButton)
.then(testSourceIsStillUgly)
.then(() => closeDebuggerAndFinish(gPanel))
.then(null, aError => {
ok(false, "Got an error: " + DevToolsUtils.safeErrorString(aError));
});
});
}
function testSourceIsUgly() {
ok(!gEditor.getText().contains("\n "),
"The source shouldn't be pretty printed yet.");
}
function blackBoxSource() {
const checkbox = gDebugger.document.querySelector(
".selected .side-menu-widget-item-checkbox");
checkbox.click();
}
function clickPrettyPrintButton() {
EventUtils.sendMouseEvent({ type: "click" },
gDebugger.document.getElementById("pretty-print"),
gDebugger);
}
function testSourceIsStillUgly() {
const { source } = gSources.selectedItem.attachment;
return gDebugger.DebuggerController.SourceScripts.getText(source).then(([, text]) => {
ok(!text.contains("\n "));
});
}
registerCleanupFunction(function() {
gTab = null;
gDebuggee = null;
gPanel = null;
gDebugger = null;
gEditor = null;
gSources = null;
});

View File

@ -30,4 +30,5 @@ support-files =
[browser_bug731721_debugger_stepping.js]
[browser_bug744021_next_prev_bracket_jump.js]
[browser_codemirror.js]
skip-if = os == "linux"
[browser_sourceeditor_initialization.js]

View File

@ -26,6 +26,10 @@
<field name="controller">null</field>
<!-- collection of child items excluding empty tiles -->
<property name="items" readonly="true" onget="return this.querySelectorAll('richgriditem');"/>
<property name="itemCount" readonly="true" onget="return this.items.length;"/>
<!-- nsIDOMXULMultiSelectControlElement (not fully implemented) -->
<method name="clearSelection">
@ -158,8 +162,6 @@
<!-- nsIDOMXULSelectControlElement -->
<property name="itemCount" readonly="true" onget="return this.children.length;"/>
<field name="_selectedItem">null</field>
<property name="selectedItem" onget="return this._selectedItem;">
<setter>
@ -202,7 +204,7 @@
<parameter name="aSkipArrange"/>
<body>
<![CDATA[
let addition = this.createItemElement(aLabel, aValue);
let addition = this._createItemElement(aLabel, aValue);
this.appendChild(addition);
if (!aSkipArrange)
this.arrangeItems();
@ -232,7 +234,7 @@
<body>
<![CDATA[
let existing = this.getItemAtIndex(anIndex);
let addition = this.createItemElement(aLabel, aValue);
let addition = this._createItemElement(aLabel, aValue);
if (existing) {
this.insertBefore(addition, existing);
} else {
@ -250,7 +252,9 @@
<body>
<![CDATA[
let item = this.getItemAtIndex(anIndex);
return item ? this.removeItem(item, aSkipArrange) : null;
if (!item)
return null;
return this.removeItem(item, aSkipArrange);
]]>
</body>
</method>
@ -260,7 +264,9 @@
<parameter name="aSkipArrange"/>
<body>
<![CDATA[
let removal = aItem.parentNode == this && this.removeChild(aItem);
if (!aItem || Array.indexOf(this.items, aItem) < 0)
return null;
let removal = this.removeChild(aItem);
if (removal && !aSkipArrange)
this.arrangeItems();
@ -271,7 +277,6 @@
</body>
</method>
<method name="getIndexOfItem">
<parameter name="anItem"/>
<body>
@ -279,7 +284,7 @@
if (!anItem)
return -1;
return Array.indexOf(this.children, anItem);
return Array.indexOf(this.items, anItem);
]]>
</body>
</method>
@ -290,7 +295,7 @@
<![CDATA[
if (!this._isIndexInBounds(anIndex))
return null;
return this.children.item(anIndex);
return this.items.item(anIndex);
]]>
</body>
</method>
@ -609,16 +614,18 @@
</body>
</method>
<method name="createItemElement">
<method name="_createItemElement">
<parameter name="aLabel"/>
<parameter name="aValue"/>
<body>
<![CDATA[
let item = this.ownerDocument.createElement("richgriditem");
item.setAttribute("label", aLabel);
if (aValue) {
item.setAttribute("value", aValue);
}
if (aLabel) {
item.setAttribute("label", aLabel);
}
if(this.hasAttribute("tiletype")) {
item.setAttribute("tiletype", this.getAttribute("tiletype"));
}
@ -860,7 +867,7 @@
<property name="control">
<getter><![CDATA[
let parent = this.parentNode;
while (parent) {
while (parent && parent != this.ownerDocument.documentElement) {
if (parent instanceof Components.interfaces.nsIDOMXULSelectControlElement)
return parent;
parent = parent.parentNode;

View File

@ -100,7 +100,7 @@ TopSitesView.prototype = Util.extend(Object.create(View.prototype), {
case "pin":
let pinIndices = [];
Array.forEach(selectedTiles, function(aNode) {
pinIndices.push( Array.indexOf(aNode.control.children, aNode) );
pinIndices.push( Array.indexOf(aNode.control.items, aNode) );
aNode.contextActions.delete('pin');
aNode.contextActions.add('unpin');
});
@ -153,7 +153,6 @@ TopSitesView.prototype = Util.extend(Object.create(View.prototype), {
// flush, recreate all
this.isUpdating = true;
// destroy and recreate all item nodes, skip calling arrangeItems
grid.clearAll(true);
this.populateGrid();
}
},
@ -165,14 +164,18 @@ TopSitesView.prototype = Util.extend(Object.create(View.prototype), {
let filepath = PageThumbsStorage.getFilePathForURL(aSite.url);
if (yield OS.File.exists(filepath)) {
aSite.backgroundImage = 'url("'+PageThumbs.getThumbnailURL(aSite.url)+'")';
aTileNode.setAttribute("customImage", aSite.backgroundImage);
if (aTileNode.refresh) {
aTileNode.refresh()
if ('backgroundImage' in aTileNode) {
aTileNode.backgroundImage = aSite.backgroundImage;
} else {
aTileNode.setAttribute("customImage", aSite.backgroundImage);
}
}
});
aSite.applyToTileNode(aTileNode);
if (aTileNode.refresh) {
aTileNode.refresh();
}
if (aArrangeGrid) {
this._set.arrangeItems();
}
@ -182,24 +185,19 @@ TopSitesView.prototype = Util.extend(Object.create(View.prototype), {
this.isUpdating = true;
let sites = TopSites.getSites();
let length = Math.min(sites.length, this._topSitesMax || Infinity);
let tileset = this._set;
// if we're updating with a collection that is smaller than previous
// remove any extra tiles
while (tileset.children.length > length) {
tileset.removeChild(tileset.children[tileset.children.length -1]);
if (this._topSitesMax) {
sites = sites.slice(0, this._topSitesMax);
}
let tileset = this._set;
tileset.clearAll(true);
for (let idx=0; idx < length; idx++) {
let isNew = !tileset.children[idx],
site = sites[idx];
let item = isNew ? tileset.createItemElement(site.title, site.url) : tileset.children[idx];
for (let site of sites) {
// call to private _createItemElement is a temp measure
// we'll eventually just request the next slot
let item = tileset._createItemElement(site.title, site.url);
this.updateTile(item, site);
if (isNew) {
tileset.appendChild(item);
}
tileset.appendChild(item);
}
tileset.arrangeItems();
this.isUpdating = false;

View File

@ -18,8 +18,8 @@ gTests.push({
ok(grid, "#grid1 is found");
is(typeof grid.clearSelection, "function", "#grid1 has the binding applied");
is(grid.children.length, 2, "#grid1 has a 2 items");
is(grid.children[0].control, grid, "#grid1 item's control points back at #grid1'");
is(grid.items.length, 2, "#grid1 has a 2 items");
is(grid.items[0].control, grid, "#grid1 item's control points back at #grid1'");
}
});
@ -29,7 +29,7 @@ gTests.push({
let grid = doc.querySelector("#grid1");
is(typeof grid.handleItemClick, "function", "grid.handleItemClick is a function");
let handleStub = stubMethod(grid, 'handleItemClick');
let itemId = "grid1_item1"; // grid.children[0].getAttribute("id");
let itemId = "grid1_item1"; // grid.items[0].getAttribute("id");
// send click to item and wait for next tick;
EventUtils.sendMouseEvent({type: 'click'}, itemId, doc.defaultView);
@ -114,9 +114,8 @@ gTests.push({
grid.clearAll();
is(grid.itemCount, 0, "grid has 0 itemCount after clearAll");
is(grid.children.length, 0, "grid has 0 children after clearAll");
is(grid.rowCount, 0, "grid has 0 rows when empty");
is(grid.columnCount, 0, "grid has 0 cols when empty");
is(grid.items.length, 0, "grid has 0 items after clearAll");
// now that we use slots, an empty grid may still have non-zero rows & columns
is(arrangeSpy.callCount, 1, "arrangeItems is called once when we clearAll");
arrangeSpy.restore();
@ -150,13 +149,13 @@ gTests.push({
let grid = doc.querySelector("#emptygrid");
is(grid.itemCount, 0, "0 itemCount when empty");
is(grid.children.length, 0, "0 children when empty");
is(grid.items.length, 0, "0 items when empty");
is(typeof grid.appendItem, "function", "appendItem is a function on the grid");
let arrangeStub = stubMethod(grid, "arrangeItems");
let newItem = grid.appendItem("test title", "about:blank");
ok(newItem && grid.children[0]==newItem, "appendItem gives back the item");
ok(newItem && grid.items[0]==newItem, "appendItem gives back the item");
is(grid.itemCount, 1, "itemCount is incremented when we appendItem");
is(newItem.getAttribute("label"), "test title", "title ends up on label attribute");
is(newItem.getAttribute("value"), "about:blank", "url ends up on value attribute");
@ -193,7 +192,7 @@ gTests.push({
ok(removedItem, "removeItemAt gives back an item");
is(removedItem.getAttribute("id"), "grid2_item1", "removeItemAt gives back the correct item");
is(grid.children[0].getAttribute("id"), "grid2_item2", "2nd item becomes the first item");
is(grid.items[0].getAttribute("id"), "grid2_item2", "2nd item becomes the first item");
is(grid.itemCount, 1, "itemCount is decremented when we removeItemAt");
is(arrangeStub.callCount, 1, "arrangeItems is called when we removeItemAt");
@ -215,10 +214,10 @@ gTests.push({
let insertedItem = grid.insertItemAt(1, "inserted item", "http://example.com/inserted");
ok(insertedItem, "insertItemAt gives back an item");
is(grid.children[1], insertedItem, "item is inserted at the correct index");
is(grid.items[1], insertedItem, "item is inserted at the correct index");
is(insertedItem.getAttribute("label"), "inserted item", "insertItemAt creates item with the correct label");
is(insertedItem.getAttribute("value"), "http://example.com/inserted", "insertItemAt creates item with the correct url value");
is(grid.children[2].getAttribute("id"), "grid3_item2", "following item ends up at the correct index");
is(grid.items[2].getAttribute("id"), "grid3_item2", "following item ends up at the correct index");
is(grid.itemCount, 3, "itemCount is incremented when we insertItemAt");
is(arrangeStub.callCount, 1, "arrangeItems is called when we insertItemAt");
@ -275,11 +274,11 @@ gTests.push({
is(typeof grid.removeItem, "function", "removeItem is a function on the grid");
let arrangeStub = stubMethod(grid, "arrangeItems");
let removedFirst = grid.removeItem( grid.children[0] );
let removedFirst = grid.removeItem( grid.items[0] );
is(arrangeStub.callCount, 1, "arrangeItems is called when we removeItem");
let removed2nd = grid.removeItem( grid.children[0], true);
let removed2nd = grid.removeItem( grid.items[0], true);
is(removed2nd.getAttribute("label"), "2nd item", "the next item was returned");
is(grid.itemCount, 2, "2 items remain");
@ -316,23 +315,23 @@ gTests.push({
is(grid.itemCount, 2, "2 items initially");
is(grid.selectedItems.length, 0, "nothing selected initially");
grid.toggleItemSelection(grid.children[1]);
ok(grid.children[1].selected, "toggleItemSelection sets truthy selected prop on previously-unselected item");
grid.toggleItemSelection(grid.items[1]);
ok(grid.items[1].selected, "toggleItemSelection sets truthy selected prop on previously-unselected item");
is(grid.selectedIndex, 1, "selectedIndex is correct");
grid.toggleItemSelection(grid.children[1]);
ok(!grid.children[1].selected, "toggleItemSelection sets falsy selected prop on previously-selected item");
grid.toggleItemSelection(grid.items[1]);
ok(!grid.items[1].selected, "toggleItemSelection sets falsy selected prop on previously-selected item");
is(grid.selectedIndex, -1, "selectedIndex reports correctly with nothing selected");
// item selection
grid.selectItem(grid.children[1]);
ok(grid.children[1].selected, "Item selected property is truthy after grid.selectItem");
ok(grid.children[1].getAttribute("selected"), "Item selected attribute is truthy after grid.selectItem");
grid.selectItem(grid.items[1]);
ok(grid.items[1].selected, "Item selected property is truthy after grid.selectItem");
ok(grid.items[1].getAttribute("selected"), "Item selected attribute is truthy after grid.selectItem");
ok(grid.selectedItems.length, "There are selectedItems after grid.selectItem");
// clearSelection
grid.selectItem(grid.children[0]);
grid.selectItem(grid.children[1]);
grid.selectItem(grid.items[0]);
grid.selectItem(grid.items[1]);
grid.clearSelection();
is(grid.selectedItems.length, 0, "Nothing selected when we clearSelection");
is(grid.selectedIndex, -1, "selectedIndex resets after clearSelection");
@ -347,10 +346,10 @@ gTests.push({
doc.defaultView.addEventListener("select", handler, false);
info("select listener added");
info("calling selectItem, currently it is:" + grid.children[0].selected);
info("calling selectItem, currently it is:" + grid.items[0].selected);
// Note: A richgrid in seltype=single mode fires "select" events from selectItem
grid.selectItem(grid.children[0]);
info("calling selectItem, now it is:" + grid.children[0].selected);
grid.selectItem(grid.items[0]);
info("calling selectItem, now it is:" + grid.items[0].selected);
yield waitForMs(0);
is(handlerStub.callCount, 1, "select event handler was called when we selected an item");
@ -378,22 +377,22 @@ gTests.push({
is(grid.itemCount, 2, "2 items initially");
is(grid.selectedItems.length, 0, "nothing selected initially");
grid.toggleItemSelection(grid.children[1]);
ok(grid.children[1].selected, "toggleItemSelection sets truthy selected prop on previously-unselected item");
grid.toggleItemSelection(grid.items[1]);
ok(grid.items[1].selected, "toggleItemSelection sets truthy selected prop on previously-unselected item");
is(grid.selectedItems.length, 1, "1 item selected when we first toggleItemSelection");
is(grid.selectedItems[0], grid.children[1], "the right item is selected");
is(grid.selectedItems[0], grid.items[1], "the right item is selected");
is(grid.selectedIndex, 1, "selectedIndex is correct");
grid.toggleItemSelection(grid.children[1]);
grid.toggleItemSelection(grid.items[1]);
is(grid.selectedItems.length, 0, "Nothing selected when we toggleItemSelection again");
// clearSelection
grid.children[0].selected=true;
grid.children[1].selected=true;
grid.items[0].selected=true;
grid.items[1].selected=true;
is(grid.selectedItems.length, 2, "Both items are selected before calling clearSelection");
grid.clearSelection();
is(grid.selectedItems.length, 0, "Nothing selected when we clearSelection");
ok(!(grid.children[0].selected || grid.children[1].selected), "selected properties all falsy when we clearSelection");
ok(!(grid.items[0].selected || grid.items[1].selected), "selected properties all falsy when we clearSelection");
// selectionchange events
// in seltype=multiple mode, we track selected state on all items
@ -405,10 +404,10 @@ gTests.push({
doc.defaultView.addEventListener("selectionchange", handler, false);
info("selectionchange listener added");
info("calling toggleItemSelection, currently it is:" + grid.children[0].selected);
info("calling toggleItemSelection, currently it is:" + grid.items[0].selected);
// Note: A richgrid in seltype=single mode fires "select" events from selectItem
grid.toggleItemSelection(grid.children[0]);
info("/calling toggleItemSelection, now it is:" + grid.children[0].selected);
grid.toggleItemSelection(grid.items[0]);
info("/calling toggleItemSelection, now it is:" + grid.items[0].selected);
yield waitForMs(0);
is(handlerStub.callCount, 1, "selectionchange event handler was called when we selected an item");
@ -418,6 +417,3 @@ gTests.push({
doc.defaultView.removeEventListener("selectionchange", handler, false);
}
});
// implements a getItemAtIndex method (or grid.children[idx] ?)

View File

@ -194,7 +194,7 @@ gTests.push({
},
run: function() {
let grid = TopSitesTestHelper.grid;
let items = grid.children;
let items = grid.items;
is(items.length, 8, "should be 8 topsites"); // i.e. not 10
if(items.length) {
let firstitem = items[0];
@ -230,7 +230,7 @@ gTests.push({
run: function() {
// test that pinned state of each site as rendered matches our expectations
let pins = this.pins.split(",");
let items = TopSitesTestHelper.grid.children;
let items = TopSitesTestHelper.grid.items;
is(items.length, 8, "should be 8 topsites in the grid");
is(TopSitesTestHelper.document.querySelectorAll("#start-topsites-grid > [pinned]").length, 3, "should be 3 children with 'pinned' attribute");
@ -273,10 +273,10 @@ gTests.push({
// test that site is pinned as expected
// and that sites fill positions around it
let grid = TopSitesTestHelper.grid,
items = grid.children;
items = grid.items;
is(items.length, 4, this.desc + ": should be 4 topsites");
let tile = grid.children[2],
let tile = grid.items[2],
url = tile.getAttribute("value"),
title = tile.getAttribute("label");
@ -291,7 +291,7 @@ gTests.push({
return !grid.controller.isUpdating;
});
let thirdTile = grid.children[2];
let thirdTile = grid.items[2];
ok( thirdTile.hasAttribute("pinned"), thirdTile.getAttribute("value")+ " should look pinned" );
// visit some more sites
@ -329,7 +329,7 @@ gTests.push({
// unpin a pinned site
// test that sites are unpinned as expected
let grid = TopSitesTestHelper.grid,
items = grid.children;
items = grid.items;
is(items.length, 8, this.desc + ": should be 8 topsites");
let site = {
url: items[1].getAttribute("value"),
@ -346,7 +346,7 @@ gTests.push({
return !grid.controller.isUpdating;
});
let secondTile = grid.children[1];
let secondTile = grid.items[1];
ok( !secondTile.hasAttribute("pinned"), "2nd item should no longer be marked as pinned" );
ok( !NewTabUtils.pinnedLinks.isPinned(site), "2nd item should no longer be pinned" );
}
@ -371,7 +371,7 @@ gTests.push({
// block a site
// test that sites are removed from the grid as expected
let grid = TopSitesTestHelper.grid,
items = grid.children;
items = grid.items;
is(items.length, 8, this.desc + ": should be 8 topsites");
let brianSite = TopSitesTestHelper.siteFromNode(items[0]);
@ -426,7 +426,7 @@ gTests.push({
is( grid.querySelectorAll("[value='"+dougalSite.url+"']").length, 1, "Unblocked site is back in the grid");
// ..and that a previously pinned site is re-pinned after being blocked, then restored
ok( NewTabUtils.pinnedLinks.isPinned(dougalSite), "Restoring previously pinned site makes it pinned again" );
is( grid.children[1].getAttribute("value"), dougalSite.url, "Blocked Site restored to pinned index" );
is( grid.items[1].getAttribute("value"), dougalSite.url, "Blocked Site restored to pinned index" );
ok( !NewTabUtils.blockedLinks.isBlocked(dylanSite), "site was unblocked" );
is( grid.querySelectorAll("[value='"+dylanSite.url+"']").length, 1, "Unblocked site is back in the grid");
@ -458,7 +458,7 @@ gTests.push({
// delete a both pinned and unpinned sites
// test that sites are removed from the grid
let grid = TopSitesTestHelper.grid,
items = grid.children;
items = grid.items;
is(items.length, 4, this.desc + ": should be 4 topsites");
let brianTile = grid.querySelector('richgriditem[value$="brian"]');

View File

@ -66,9 +66,10 @@
display: none;
}
/* Black box message */
/* Black box message and source progress meter */
#black-boxed-message {
#black-boxed-message,
#source-progress-container {
background: url(background-noise-toolbar.png) rgb(61,69,76);
/* Prevent the container deck from aquiring the height from this message. */
min-height: 1px;
@ -76,6 +77,11 @@
color: white;
}
#source-progress {
min-height: 2em;
min-width: 40em;
}
#black-boxed-message-label,
#black-boxed-message-button {
text-align: center;

View File

@ -64,9 +64,10 @@
display: none;
}
/* Black box message */
/* Black box message and source progress meter */
#black-boxed-message {
#black-boxed-message,
#source-progress-container {
background: url(background-noise-toolbar.png) rgb(61,69,76);
/* Prevent the container deck from aquiring the height from this message. */
min-height: 1px;
@ -74,6 +75,11 @@
color: white;
}
#source-progress {
min-height: 2em;
min-width: 40em;
}
#black-boxed-message-label,
#black-boxed-message-button {
text-align: center;

View File

@ -64,9 +64,10 @@
display: none;
}
/* Black box message */
/* Black box message and source progress meter */
#black-boxed-message {
#black-boxed-message,
#source-progress-container {
background: url(background-noise-toolbar.png) rgb(61,69,76);
/* Prevent the container deck from aquiring the height from this message. */
min-height: 1px;
@ -74,6 +75,11 @@
color: white;
}
#source-progress {
min-height: 2em;
min-width: 40em;
}
#black-boxed-message-label,
#black-boxed-message-button {
text-align: center;

View File

@ -171,10 +171,10 @@ AC_DEFUN([MOZ_COMPILER_OPTS],
AC_SUBST(DEVELOPER_OPTIONS)
if test -n "$DEVELOPER_OPTIONS" -a "${MOZ_PSEUDO_DERECURSE-unset}" = unset; then
if test "${MOZ_PSEUDO_DERECURSE-unset}" = unset; then
dnl Don't enable on pymake, because of bug 918652. Bug 912979 is an annoyance
dnl with pymake, too.
MOZ_PSEUDO_DERECURSE=no-parallel-export,no-pymake,no-skip
MOZ_PSEUDO_DERECURSE=no-pymake,no-skip
fi
MOZ_DEBUGGING_OPTS

View File

@ -41,11 +41,16 @@ TESTFLAGS := -fsyntax-only -Xclang -verify \
$(TESTS): test-%: tests/%.cpp $(PLUGIN)
$(CXX) $(TESTFLAGS) $<
compile binaries libs export tools: all
compile libs export tools: all
distclean clean:
rm -f $(OBJS) $(TESTS) $(PLUGIN)
check:
.PHONY: compile binaries libs export tools distclean clean check
libs: binaries
binaries: all
@touch $@
.PHONY: compile libs export tools distclean clean check

View File

@ -353,14 +353,17 @@ const kEventConstructors = {
StyleRuleChangeEvent: { create: function (aName, aProps) {
return new StyleRuleChangeEvent(aName, aProps);
},
chromeOnly: true,
},
StyleSheetApplicableStateChangeEvent: { create: function (aName, aProps) {
return new StyleSheetApplicableStateChangeEvent(aName, aProps);
},
chromeOnly: true,
},
StyleSheetChangeEvent: { create: function (aName, aProps) {
return new StyleSheetChangeEvent(aName, aProps);
},
chromeOnly: true,
},
SVGZoomEvent: { create: function (aName, aProps) {
var e = document.createEvent("svgzoomevent");
@ -410,6 +413,16 @@ const kEventConstructors = {
},
};
for (var name of Object.keys(kEventConstructors)) {
if (!kEventConstructors[name].chromeOnly) {
continue;
}
if (window[name]) {
ok(false, name + " should be chrome only.");
}
window[name] = SpecialPowers.unwrap(SpecialPowers.wrap(window)[name]);
}
var props = Object.getOwnPropertyNames(window);
for (var i = 0; i < props.length; i++) {
// Assume that event object must be named as "FooBarEvent".

View File

@ -870,6 +870,12 @@ DOMInterfaces = {
'resultNotAddRefed': [ 'coneGain', 'distanceGain' ],
}],
'PeerConnectionImpl': {
'nativeType': 'sipcc::PeerConnectionImpl',
'headerFile': 'PeerConnectionImpl.h',
'wrapperCache': False
},
'Performance': {
'nativeType': 'nsPerformance',
'resultNotAddRefed': [ 'timing', 'navigation' ]

View File

@ -76,6 +76,8 @@ LOCAL_INCLUDES += -I$(topsrcdir)/js/xpconnect/src \
-I$(topsrcdir)/content/canvas/src \
-I$(topsrcdir)/content/html/content/src \
-I$(topsrcdir)/media/webrtc/signaling/src/peerconnection \
-I$(topsrcdir)/media/webrtc/signaling/src/common/time_profiling \
-I$(topsrcdir)/media/mtransport \
-I$(topsrcdir)/dom/base \
-I$(topsrcdir)/dom/battery \
-I$(topsrcdir)/dom/indexedDB \

View File

@ -10,11 +10,13 @@ Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
const PC_CONTRACT = "@mozilla.org/dom/peerconnection;1";
const PC_OBS_CONTRACT = "@mozilla.org/dom/peerconnectionobserver;1";
const PC_ICE_CONTRACT = "@mozilla.org/dom/rtcicecandidate;1";
const PC_SESSION_CONTRACT = "@mozilla.org/dom/rtcsessiondescription;1";
const PC_MANAGER_CONTRACT = "@mozilla.org/dom/peerconnectionmanager;1";
const PC_CID = Components.ID("{9878b414-afaa-4176-a887-1e02b3b047c2}");
const PC_OBS_CID = Components.ID("{1d44a18e-4545-4ff3-863d-6dbd6234a583}");
const PC_ICE_CID = Components.ID("{02b9970c-433d-4cc2-923d-f7028ac66073}");
const PC_SESSION_CID = Components.ID("{1775081b-b62d-4954-8ffe-a067bbf508a7}");
const PC_MANAGER_CID = Components.ID("{7293e901-2be3-4c02-b4bd-cbef6fc24f78}");
@ -189,8 +191,7 @@ RTCPeerConnection.prototype = {
classID: PC_CID,
contractID: PC_CONTRACT,
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
Ci.nsIDOMGlobalPropertyInitializer,
Ci.nsISupportsWeakReference]),
Ci.nsIDOMGlobalPropertyInitializer]),
init: function(win) { this._win = win; },
__init: function(rtcConfig) {
@ -217,9 +218,8 @@ RTCPeerConnection.prototype = {
this.makeGetterSetterEH("onclosedconnection");
this.makeGetterSetterEH("oniceconnectionstatechange");
this._pc = Cc["@mozilla.org/peerconnection;1"].
createInstance(Ci.IPeerConnection);
this._observer = new PeerConnectionObserver(this);
this._pc = new this._win.PeerConnectionImpl();
this._observer = new this._win.PeerConnectionObserver(this);
this._winID = this._win.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils).currentInnerWindowID;
@ -227,13 +227,18 @@ RTCPeerConnection.prototype = {
_globalPCList.addPC(this);
this._queueOrRun({
func: this._getPC().initialize,
args: [this._observer, this._win, rtcConfig, Services.tm.currentThread],
func: this._initialize,
args: [rtcConfig],
// If not trickling, suppress start.
wait: !this._trickleIce
});
},
_initialize: function(rtcConfig) {
this._getPC().initialize(this._observer, this._win, rtcConfig,
Services.tm.currentThread);
},
_getPC: function() {
if (!this._pc) {
throw new this._win.DOMError("",
@ -301,6 +306,9 @@ RTCPeerConnection.prototype = {
}
}
function mustValidateServer(server) {
if (!server.url) {
throw new errorCtor("", errorMsg + " - missing url");
}
let url = nicerNewURI(server.url, errorMsg);
if (url.scheme in { turn:1, turns:1 }) {
if (!server.username) {
@ -324,75 +332,44 @@ RTCPeerConnection.prototype = {
},
/**
* Constraints look like this:
* MediaConstraints look like this:
*
* {
* mandatory: {"OfferToReceiveAudio": true, "OfferToReceiveVideo": true },
* optional: [{"VoiceActivityDetection": true}, {"FooBar": 10}]
* }
*
* We check for basic structure of constraints and the validity of
* mandatory constraints against those we support (fail if we don't).
* Unknown optional constraints may be of any type.
* WebIDL normalizes the top structure for us, but the mandatory constraints
* member comes in as a raw object so we can detect unknown constraints.
* We compare its members against ones we support, and fail if not found.
*/
_mustValidateConstraints: function(constraints, errorMsg) {
function isObject(obj) {
return obj && (typeof obj === "object");
}
function isArraylike(obj) {
return isObject(obj) && ("length" in obj);
}
const SUPPORTED_CONSTRAINTS = {
OfferToReceiveAudio:1,
OfferToReceiveVideo:1,
MozDontOfferDataChannel:1
};
const OTHER_KNOWN_CONSTRAINTS = {
VoiceActivityDetection:1,
IceTransports:1,
RequestIdentity:1
};
// Parse-aid: Testing for pilot error of missing outer block avoids
// otherwise silent no-op since both mandatory and optional are optional
if (!isObject(constraints) || Array.isArray(constraints)) {
throw new this._win.DOMError("", errorMsg);
}
if (constraints.mandatory) {
// Testing for pilot error of using [] on mandatory here throws nicer msg
// (arrays would throw in loop below regardless but with more cryptic msg)
if (!isObject(constraints.mandatory) || Array.isArray(constraints.mandatory)) {
throw new this._win.DOMError("",
errorMsg + " - malformed mandatory constraints");
let supported;
try {
// Passing the raw constraints.mandatory here validates its structure
supported = this._observer.getSupportedConstraints(constraints.mandatory);
} catch (e) {
throw new this._win.DOMError("", errorMsg + " - " + e.message);
}
for (let constraint in constraints.mandatory) {
if (!(constraint in SUPPORTED_CONSTRAINTS) &&
constraints.mandatory.hasOwnProperty(constraint)) {
throw new this._win.DOMError("", errorMsg + " - " +
((constraint in OTHER_KNOWN_CONSTRAINTS)? "unsupported" : "unknown") +
" mandatory constraint: " + constraint);
for (let constraint of Object.keys(constraints.mandatory)) {
if (!(constraint in supported)) {
throw new this._win.DOMError("",
errorMsg + " - unknown mandatory constraint: " + constraint);
}
}
}
if (constraints.optional) {
if (!isArraylike(constraints.optional)) {
throw new this._win.DOMError("",
errorMsg + " - malformed optional constraint array");
}
let len = constraints.optional.length;
for (let i = 0; i < len; i += 1) {
if (!isObject(constraints.optional[i])) {
throw new this._win.DOMError("", errorMsg +
" - malformed optional constraint: " + constraints.optional[i]);
}
for (let i = 0; i < len; i++) {
let constraints_per_entry = 0;
for (let constraint in constraints.optional[i]) {
if (constraints.optional[i].hasOwnProperty(constraint)) {
if (constraints_per_entry) {
throw new this._win.DOMError("", errorMsg +
" - optional constraint must be single key/value pair");
}
constraints_per_entry += 1;
for (let constraint in Object.keys(constraints.optional[i])) {
if (constraints_per_entry) {
throw new this._win.DOMError("", errorMsg +
" - optional constraint must be single key/value pair");
}
constraints_per_entry += 1;
}
}
}
@ -493,11 +470,11 @@ RTCPeerConnection.prototype = {
this._onCreateOfferSuccess = onSuccess;
this._onCreateOfferFailure = onError;
this._queueOrRun({
func: this._getPC().createOffer,
args: [constraints],
wait: true
});
this._queueOrRun({ func: this._createOffer, args: [constraints], wait: true });
},
_createOffer: function(constraints) {
this._getPC().createOffer(constraints);
},
_createAnswer: function(onSuccess, onError, constraints, provisional) {
@ -567,13 +544,17 @@ RTCPeerConnection.prototype = {
}
this._queueOrRun({
func: this._getPC().setLocalDescription,
func: this._setLocalDescription,
args: [type, desc.sdp],
wait: true,
type: desc.type
});
},
_setLocalDescription: function(type, sdp) {
this._getPC().setLocalDescription(type, sdp);
},
setRemoteDescription: function(desc, onSuccess, onError) {
// TODO -- if we have two setRemoteDescriptions in the
// queue, this code overwrites the callbacks for the first
@ -597,13 +578,17 @@ RTCPeerConnection.prototype = {
}
this._queueOrRun({
func: this._getPC().setRemoteDescription,
func: this._setRemoteDescription,
args: [type, desc.sdp],
wait: true,
type: desc.type
});
},
_setRemoteDescription: function(type, sdp) {
this._getPC().setRemoteDescription(type, sdp);
},
updateIce: function(config, constraints) {
throw new this._win.DOMError("", "updateIce not yet implemented");
},
@ -616,12 +601,13 @@ RTCPeerConnection.prototype = {
this._onAddIceCandidateSuccess = onSuccess || null;
this._onAddIceCandidateError = onError || null;
this._queueOrRun({
func: this._getPC().addIceCandidate,
args: [cand.candidate, cand.sdpMid || "",
(cand.sdpMLineIndex === null)? 0 : cand.sdpMLineIndex + 1],
wait: true
});
this._queueOrRun({ func: this._addIceCandidate, args: [cand], wait: true });
},
_addIceCandidate: function(cand) {
this._getPC().addIceCandidate(cand.candidate, cand.sdpMid || "",
(cand.sdpMLineIndex === null)? 0 :
cand.sdpMLineIndex + 1);
},
addStream: function(stream, constraints) {
@ -629,11 +615,11 @@ RTCPeerConnection.prototype = {
throw new this._win.DOMError("", "Invalid stream passed to addStream!");
}
// TODO: Implement constraints.
this._queueOrRun({
func: this._getPC().addStream,
args: [stream],
wait: false
});
this._queueOrRun({ func: this._addStream, args: [stream], wait: false });
},
_addStream: function(stream) {
this._getPC().addStream(stream);
},
removeStream: function(stream) {
@ -646,23 +632,23 @@ RTCPeerConnection.prototype = {
},
close: function() {
this._queueOrRun({
func: this._getPC().close,
args: [false],
wait: false
});
this._queueOrRun({ func: this._close, args: [false], wait: false });
this._closed = true;
this.changeIceConnectionState("closed");
},
_close: function() {
this._getPC().close();
},
getLocalStreams: function() {
this._checkClosed();
return this._getPC().localStreams;
return this._getPC().getLocalStreams();
},
getRemoteStreams: function() {
this._checkClosed();
return this._getPC().remoteStreams;
return this._getPC().getRemoteStreams();
},
// Backwards-compatible attributes
@ -698,24 +684,21 @@ RTCPeerConnection.prototype = {
get iceGatheringState() { return this._iceGatheringState; },
get iceConnectionState() { return this._iceConnectionState; },
// Corresponds to constants in IPeerConnection.idl
_signalingStateMap: [
'invalid',
'stable',
'have-local-offer',
'have-remote-offer',
'have-local-pranswer',
'have-remote-pranswer',
'closed'
],
get signalingState() {
// checking for our local pc closed indication
// before invoking the pc methods.
if(this._closed) {
return "closed";
}
return this._signalingStateMap[this._getPC().signalingState];
return {
"SignalingInvalid": "",
"SignalingStable": "stable",
"SignalingHaveLocalOffer": "have-local-offer",
"SignalingHaveRemoteOffer": "have-remote-offer",
"SignalingHaveLocalPranswer": "have-local-pranswer",
"SignalingHaveRemotePranswer": "have-remote-pranswer",
"SignalingClosed": "closed"
}[this._getPC().signalingState];
},
changeIceGatheringState: function(state) {
@ -814,10 +797,14 @@ RTCPeerConnection.prototype = {
numstreams = 16;
}
this._queueOrRun({
func: this._getPC().connectDataConnection,
func: this._connectDataConnection,
args: [localport, remoteport, numstreams],
wait: false
});
},
_connectDataConnection: function(localport, remoteport, numstreams) {
this._getPC().connectDataConnection(localport, remoteport, numstreams);
}
};
@ -843,12 +830,20 @@ RTCError.prototype = {
};
// This is a separate object because we don't want to expose it to DOM.
function PeerConnectionObserver(dompc) {
this._dompc = dompc;
function PeerConnectionObserver() {
this._dompc = null;
}
PeerConnectionObserver.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.IPeerConnectionObserver,
Ci.nsISupportsWeakReference]),
classDescription: "PeerConnectionObserver",
classID: PC_OBS_CID,
contractID: PC_OBS_CONTRACT,
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
Ci.nsIDOMGlobalPropertyInitializer]),
init: function(win) { this._win = win; },
__init: function(dompc) {
this._dompc = dompc;
},
dispatchEvent: function(event) {
this._dompc.dispatchEvent(event);
@ -1000,23 +995,19 @@ PeerConnectionObserver.prototype = {
handleIceStateChanges: function(iceState) {
var histogram = Services.telemetry.getHistogramById("WEBRTC_ICE_SUCCESS_RATE");
const STATE_MAP = [
// Ci.IPeerConnection.kIceGathering:
const STATE_MAP = {
IceGathering:
{ gathering: "gathering" },
// Ci.IPeerConnection.kIceWaiting:
IceWaiting:
{ connection: "new", gathering: "complete", legacy: "starting" },
// Ci.IPeerConnection.kIceChecking:
IceChecking:
{ connection: "checking", legacy: "checking" },
// Ci.IPeerConnection.kIceConnected:
IceConnected:
{ connection: "connected", legacy: "connected", success: true },
// Ci.IPeerConnection.kIceFailed:
IceFailed:
{ connection: "failed", legacy: "failed", success: false }
];
if (iceState < 0 || iceState > STATE_MAP.length) {
this._dompc.reportWarning("Unhandled ice state: " + iceState, null, 0);
return;
}
};
// These are all the allowed inputs.
let transitions = STATE_MAP[iceState];
@ -1036,7 +1027,7 @@ PeerConnectionObserver.prototype = {
histogram.add(transitions.success);
}
if (iceState == Ci.IPeerConnection.kIceWaiting) {
if (iceState == "IceWaiting") {
if (!this._dompc._trickleIce) {
// If we are not trickling, then the queue is in a pending state
// waiting for ICE gathering and executeNext frees it
@ -1053,24 +1044,24 @@ PeerConnectionObserver.prototype = {
onStateChange: function(state) {
switch (state) {
case Ci.IPeerConnectionObserver.kSignalingState:
case "SignalingState":
this.callCB(this._dompc.onsignalingstatechange,
this._dompc.signalingState);
break;
case Ci.IPeerConnectionObserver.kIceState:
case "IceState":
this.handleIceStateChanges(this._dompc._pc.iceState);
break;
case Ci.IPeerConnectionObserver.kSdpState:
case "SdpState":
// No-op
break;
case Ci.IPeerConnectionObserver.kReadyState:
case "ReadyState":
// No-op
break;
case Ci.IPeerConnectionObserver.kSipccState:
case "SipccState":
// No-op
break;
@ -1106,9 +1097,14 @@ PeerConnectionObserver.prototype = {
notifyClosedConnection: function() {
this.dispatchEvent(new this._dompc._win.Event("closedconnection"));
},
getSupportedConstraints: function(dict) {
return dict;
}
};
this.NSGetFactory = XPCOMUtils.generateNSGetFactory(
[GlobalPCList, RTCIceCandidate, RTCSessionDescription, RTCPeerConnection]
[GlobalPCList, RTCIceCandidate, RTCSessionDescription, RTCPeerConnection,
PeerConnectionObserver]
);

View File

@ -1,9 +1,11 @@
component {9878b414-afaa-4176-a887-1e02b3b047c2} PeerConnection.js
component {1d44a18e-4545-4ff3-863d-6dbd6234a583} PeerConnection.js
component {02b9970c-433d-4cc2-923d-f7028ac66073} PeerConnection.js
component {1775081b-b62d-4954-8ffe-a067bbf508a7} PeerConnection.js
component {7293e901-2be3-4c02-b4bd-cbef6fc24f78} PeerConnection.js
contract @mozilla.org/dom/peerconnection;1 {9878b414-afaa-4176-a887-1e02b3b047c2}
contract @mozilla.org/dom/peerconnectionobserver;1 {1d44a18e-4545-4ff3-863d-6dbd6234a583}
contract @mozilla.org/dom/rtcicecandidate;1 {02b9970c-433d-4cc2-923d-f7028ac66073}
contract @mozilla.org/dom/rtcsessiondescription;1 {1775081b-b62d-4954-8ffe-a067bbf508a7}
contract @mozilla.org/dom/peerconnectionmanager;1 {7293e901-2be3-4c02-b4bd-cbef6fc24f78}

View File

@ -24,45 +24,12 @@ interface IPeerConnectionManager : nsISupports
*
* See media/webrtc/signaling/include/PeerConnectionImpl.h
*/
[scriptable, uuid(896dc16a-05d6-45e4-bdbf-aba57123ed3e)]
[scriptable, uuid(d7dfe148-0416-446b-a128-66a7c71ae8d3)]
interface IPeerConnectionObserver : nsISupports
{
/* Constants */
const long kReadyState = 0x1;
const long kIceState = 0x2;
const long kSdpState = 0x3;
const long kSipccState = 0x4;
const long kSignalingState = 0x5;
/* JSEP callbacks */
void onCreateOfferSuccess(in string offer);
void onCreateOfferError(in unsigned long name, in string message);
void onCreateAnswerSuccess(in string answer);
void onCreateAnswerError(in unsigned long name, in string message);
void onSetLocalDescriptionSuccess();
void onSetRemoteDescriptionSuccess();
void onSetLocalDescriptionError(in unsigned long name, in string message);
void onSetRemoteDescriptionError(in unsigned long name, in string message);
void onAddIceCandidateSuccess();
void onAddIceCandidateError(in unsigned long name, in string message);
void onIceCandidate(in unsigned short level, in string mid, in string candidate);
/* Data channel callbacks */
void notifyDataChannel(in nsIDOMDataChannel channel);
void notifyConnection();
void notifyClosedConnection();
/* Notification of one of several types of state changed */
void onStateChange(in unsigned long state);
/* Changes to MediaStreams */
void onAddStream(in nsIDOMMediaStream stream);
void onRemoveStream();
void onAddTrack();
void onRemoveTrack();
};
[scriptable, uuid(930dce8b-7c5e-4393-b8c0-cb3a928f68bd)]
[scriptable, uuid(c9c31639-1a49-4533-8429-f6a348c4d8c3)]
interface IPeerConnection : nsISupports
{
const unsigned long kHintAudio = 0x00000001;
@ -86,15 +53,6 @@ interface IPeerConnection : nsISupports
const long kClosing = 3;
const long kClosed = 4;
/* RTCSignalingState from WebRTC spec */
const long kSignalingInvalid = 0;
const long kSignalingStable = 1;
const long kSignalingHaveLocalOffer = 2;
const long kSignalingHaveRemoteOffer = 3;
const long kSignalingHaveLocalPranswer = 4;
const long kSignalingHaveRemotePranswer = 5;
const long kSignalingClosed = 6;
/* for 'type' in DataChannelInit dictionary */
const unsigned short kDataChannelReliable = 0;
const unsigned short kDataChannelPartialReliableRexmit = 1;
@ -112,50 +70,4 @@ interface IPeerConnection : nsISupports
const unsigned long kIncompatibleMediaStreamTrack = 8;
const unsigned long kInternalError = 9;
const unsigned long kMaxErrorType = 9; // Same as final error
/* Must be called first. Observer events will be dispatched on the thread provided */
[implicit_jscontext] void initialize(in IPeerConnectionObserver observer, in nsIDOMWindow window,
[optional] in jsval iceServers,
[optional] in nsIThread thread);
/* JSEP calls */
[implicit_jscontext] void createOffer(in jsval constraints);
[implicit_jscontext] void createAnswer(in jsval constraints);
void setLocalDescription(in long action, in string sdp);
void setRemoteDescription(in long action, in string sdp);
/* Adds the stream created by GetUserMedia */
void addStream(in nsIDOMMediaStream stream);
void removeStream(in nsIDOMMediaStream stream);
void closeStreams();
[implicit_jscontext] readonly attribute jsval localStreams; // MediaStream[]
[implicit_jscontext] readonly attribute jsval remoteStreams; // MediaStream[]
/* As the ICE candidates roll in this one should be called each time
* in order to keep the candidate list up-to-date for the next SDP-related
* call PeerConnectionImpl does not parse ICE candidates, just sticks them
* into the SDP.
*/
void addIceCandidate(in string candidate, in string mid, in unsigned short level);
/* Puts the SIPCC engine back to 'kIdle', shuts down threads, deletes state */
void close();
/* Attributes */
readonly attribute string localDescription;
readonly attribute string remoteDescription;
readonly attribute unsigned long iceState;
readonly attribute unsigned long readyState;
readonly attribute unsigned long signalingState;
readonly attribute unsigned long sipccState;
/* Data channels */
nsIDOMDataChannel createDataChannel(in ACString label, in ACString protocol,
in unsigned short type, in boolean outOfOrderAllowed,
in unsigned short maxTime, in unsigned short maxNum,
in boolean externalNegotiated, in unsigned short stream);
void connectDataConnection(in unsigned short localport,
in unsigned short remoteport, in unsigned short numstreams);
};

View File

@ -27,15 +27,9 @@
try { pconnect.createOffer(step1, failed, 1); } catch (e) { exception = e; }
ok(exception, "createOffer(step1, failed, 1) throws");
exception = null;
try { pconnect.createOffer(step1, failed, []); } catch (e) { exception = e; }
ok(exception, "createOffer(step1, failed, []) throws");
exception = null;
try { pconnects.createOffer(step1, failed, {}); } catch (e) { exception = e; }
ok(!exception, "createOffer(step1, failed, {}) succeeds");
exception = null;
try { pconnect.createOffer(step1, failed, { mandatory: [] }); } catch (e) { exception = e; }
ok(exception, "createOffer(step1, failed, { mandatory: [] }) throws");
exception = null;
try {
pconnect.createOffer(step1, failed, { mandatory: { FooBar: true } });
} catch (e) {
@ -44,9 +38,6 @@
}
ok(exception, "createOffer(step1, failed, { mandatory: { FooBar: true } }) throws");
exception = null;
try { pconnect.createOffer(step1, failed, { optional: {} }); } catch (e) { exception = e; }
ok(exception, "createOffer(step1, failed, { optional: {} }) throws");
exception = null;
try { pconnects.createOffer(step1, failed, { optional: [] }); } catch (e) { exception = e; }
ok(!exception, "createOffer(step1, failed, { optional: [] }) succeeds");
exception = null;

View File

@ -411,10 +411,7 @@ var interfaceNamesInGlobalScope =
{name: "SpecialPowers", xbl: false},
"Storage",
"StorageEvent",
"StyleRuleChangeEvent",
"StyleSheet",
"StyleSheetApplicableStateChangeEvent",
"StyleSheetChangeEvent",
"StyleSheetList",
"SVGAElement",
"SVGAltGlyphElement",

View File

@ -4,7 +4,7 @@
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
[NoInterfaceObject]
[ChromeOnly]
interface MediaStreamList {
getter MediaStream? (unsigned long index);
readonly attribute unsigned long length;

View File

@ -0,0 +1,77 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*
* PeerConnection.js' interface to the C++ PeerConnectionImpl.
*
* Do not confuse with mozRTCPeerConnection. This interface is purely for
* communication between the PeerConnection JS DOM binding and the C++
* implementation in SIPCC.
*
* See media/webrtc/signaling/include/PeerConnectionImpl.h
*
*/
interface Window;
interface nsISupports;
/* Must be created first. Observer events will be dispatched on the thread provided */
[ChromeOnly, Constructor]
interface PeerConnectionImpl {
/* Must be called first. Observer events dispatched on the thread provided */
[Throws]
void initialize(PeerConnectionObserver observer, Window window,
RTCConfiguration iceServers,
nsISupports thread);
/* JSEP calls */
[Throws]
void createOffer(optional MediaConstraintsInternal constraints);
[Throws]
void createAnswer(optional MediaConstraintsInternal constraints);
[Throws]
void setLocalDescription(long action, DOMString sdp);
[Throws]
void setRemoteDescription(long action, DOMString sdp);
/* Adds the stream created by GetUserMedia */
[Throws]
void addStream(MediaStream stream);
[Throws]
void removeStream(MediaStream stream);
[Throws]
void closeStreams();
sequence<MediaStream> getLocalStreams();
sequence<MediaStream> getRemoteStreams();
/* As the ICE candidates roll in this one should be called each time
* in order to keep the candidate list up-to-date for the next SDP-related
* call PeerConnectionImpl does not parse ICE candidates, just sticks them
* into the SDP.
*/
[Throws]
void addIceCandidate(DOMString candidate, DOMString mid, unsigned short level);
/* Puts the SIPCC engine back to 'kIdle', shuts down threads, deletes state */
void close();
/* Attributes */
readonly attribute DOMString localDescription;
readonly attribute DOMString remoteDescription;
readonly attribute PCImplIceState iceState;
readonly attribute PCImplReadyState readyState;
readonly attribute PCImplSignalingState signalingState;
readonly attribute PCImplSipccState sipccState;
/* Data channels */
[Throws]
DataChannel createDataChannel(DOMString label, DOMString protocol,
unsigned short type, boolean outOfOrderAllowed,
unsigned short maxTime, unsigned short maxNum,
boolean externalNegotiated, unsigned short stream);
[Throws]
void connectDataConnection(unsigned short localport,
unsigned short remoteport, unsigned short numstreams);
};

View File

@ -0,0 +1,41 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This is in a separate file so it can be shared with unittests.
*/
enum PCImplReadyState {
"New",
"Negotiating",
"Active",
"Closing",
"Closed"
};
/* Must be in the same order as comparable fsmdef_states_t in fsmdef_states.h */
enum PCImplSignalingState {
"SignalingInvalid",
"SignalingStable",
"SignalingHaveLocalOffer",
"SignalingHaveRemoteOffer",
"SignalingHaveLocalPranswer",
"SignalingHaveRemotePranswer",
"SignalingClosed",
};
enum PCImplSipccState {
"Idle",
"Starting",
"Started"
};
// TODO(ekr@rtfm.com): make this conform to the specifications
enum PCImplIceState {
"IceGathering",
"IceWaiting",
"IceChecking",
"IceConnected",
"IceFailed"
};

View File

@ -0,0 +1,46 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
[ChromeOnly,
JSImplementation="@mozilla.org/dom/peerconnectionobserver;1",
Constructor (object domPC)]
interface PeerConnectionObserver
{
/* JSEP callbacks */
void onCreateOfferSuccess(DOMString offer);
void onCreateOfferError(unsigned long name, DOMString message);
void onCreateAnswerSuccess(DOMString answer);
void onCreateAnswerError(unsigned long name, DOMString message);
void onSetLocalDescriptionSuccess();
void onSetRemoteDescriptionSuccess();
void onSetLocalDescriptionError(unsigned long name, DOMString message);
void onSetRemoteDescriptionError(unsigned long name, DOMString message);
void onAddIceCandidateSuccess();
void onAddIceCandidateError(unsigned long name, DOMString message);
void onIceCandidate(unsigned short level, DOMString mid, DOMString candidate);
/* Data channel callbacks */
void notifyDataChannel(DataChannel channel);
void notifyConnection();
void notifyClosedConnection();
/* Notification of one of several types of state changed */
void onStateChange(PCObserverStateType state);
/* Changes to MediaStreams */
void onAddStream(MediaStream stream);
void onRemoveStream();
void onAddTrack();
void onRemoveTrack();
/* Helper function to access supported constraints defined in webidl. Needs to
* be in a separate webidl object we hold, so putting it here was convenient.
*/
// TODO: Bug 863949
// MediaConstraintSet getSupportedConstraints(optional
object getSupportedConstraints(optional
MediaConstraintSet constraints);
};

View File

@ -0,0 +1,16 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This is in a separate file so it can be shared with unittests.
*/
enum PCObserverStateType {
"None",
"ReadyState",
"IceState",
"SdpState",
"SipccState",
"SignalingState"
};

View File

@ -51,6 +51,32 @@ dictionary RTCDataChannelInit {
unsigned short stream; // now id
};
// Misnomer dictionaries housing PeerConnection-specific constraints.
//
// Important! Do not ever add members that might need tracing (e.g. object)
// to MediaConstraintSet or any dictionary marked XxxInternal here
dictionary MediaConstraintSet {
boolean OfferToReceiveAudio;
boolean OfferToReceiveVideo;
boolean MozDontOfferDataChannel;
};
// MediaConstraint = single-property-subset of MediaConstraintSet
// Implemented as full set. Test Object.keys(pair).length == 1
// typedef MediaConstraintSet MediaConstraint; // TODO: Bug 913053
dictionary MediaConstraints {
object mandatory; // so we can see unknown + unsupported constraints
sequence<MediaConstraintSet> _optional; // a.k.a. MediaConstraint
};
dictionary MediaConstraintsInternal {
MediaConstraintSet mandatory; // holds only supported constraints
sequence<MediaConstraintSet> _optional; // a.k.a. MediaConstraint
};
interface RTCDataChannel;
[Pref="media.peerconnection.enabled",
@ -61,10 +87,10 @@ interface RTCDataChannel;
interface mozRTCPeerConnection : EventTarget {
void createOffer (RTCSessionDescriptionCallback successCallback,
RTCPeerConnectionErrorCallback? failureCallback, // for apprtc
optional object? constraints);
optional MediaConstraints constraints);
void createAnswer (RTCSessionDescriptionCallback successCallback,
RTCPeerConnectionErrorCallback? failureCallback, // for apprtc
optional object? constraints);
optional MediaConstraints constraints);
void setLocalDescription (mozRTCSessionDescription description,
optional VoidFunction successCallback,
optional RTCPeerConnectionErrorCallback failureCallback);
@ -75,7 +101,7 @@ interface mozRTCPeerConnection : EventTarget {
readonly attribute mozRTCSessionDescription? remoteDescription;
readonly attribute RTCSignalingState signalingState;
void updateIce (optional RTCConfiguration configuration,
optional object? constraints);
optional MediaConstraints constraints);
void addIceCandidate (mozRTCIceCandidate candidate,
optional VoidFunction successCallback,
optional RTCPeerConnectionErrorCallback failureCallback);
@ -84,7 +110,7 @@ interface mozRTCPeerConnection : EventTarget {
sequence<MediaStream> getLocalStreams ();
sequence<MediaStream> getRemoteStreams ();
MediaStream? getStreamById (DOMString streamId);
void addStream (MediaStream stream, optional object? constraints);
void addStream (MediaStream stream, optional MediaConstraints constraints);
void removeStream (MediaStream stream);
void close ();
attribute EventHandler onnegotiationneeded;

View File

@ -5,7 +5,7 @@
*/
interface CSSRule;
[Constructor(DOMString type, optional StyleRuleChangeEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"]
[ChromeOnly, Constructor(DOMString type, optional StyleRuleChangeEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"]
interface StyleRuleChangeEvent : Event
{
readonly attribute CSSStyleSheet? stylesheet;

View File

@ -4,7 +4,7 @@
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
[Constructor(DOMString type, optional StyleSheetApplicableStateChangeEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"]
[ChromeOnly, Constructor(DOMString type, optional StyleSheetApplicableStateChangeEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"]
interface StyleSheetApplicableStateChangeEvent : Event
{
readonly attribute CSSStyleSheet? stylesheet;

View File

@ -4,7 +4,7 @@
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
[Constructor(DOMString type, optional StyleSheetChangeEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"]
[ChromeOnly, Constructor(DOMString type, optional StyleSheetChangeEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"]
interface StyleSheetChangeEvent : Event
{
readonly attribute CSSStyleSheet? stylesheet;

View File

@ -242,6 +242,10 @@ WEBIDL_FILES = [
'PaintRequestList.webidl',
'PannerNode.webidl',
'ParentNode.webidl',
'PeerConnectionImpl.webidl',
'PeerConnectionImplEnums.webidl',
'PeerConnectionObserver.webidl',
'PeerConnectionObserverEnums.webidl',
'Performance.webidl',
'PerformanceNavigation.webidl',
'PerformanceTiming.webidl',

View File

@ -99,10 +99,10 @@ CanvasClient2D::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
}
TemporaryRef<BufferTextureClient>
CanvasClient2D::CreateBufferTextureClient(gfx::SurfaceFormat aFormat)
CanvasClient2D::CreateBufferTextureClient(gfx::SurfaceFormat aFormat, TextureFlags aFlags)
{
return CompositableClient::CreateBufferTextureClient(aFormat,
mTextureInfo.mTextureFlags);
mTextureInfo.mTextureFlags | aFlags);
}
void

View File

@ -83,7 +83,8 @@ public:
}
virtual TemporaryRef<BufferTextureClient>
CreateBufferTextureClient(gfx::SurfaceFormat aFormat) MOZ_OVERRIDE;
CreateBufferTextureClient(gfx::SurfaceFormat aFormat,
TextureFlags aFlags = TEXTURE_FLAGS_DEFAULT) MOZ_OVERRIDE;
virtual void OnDetach() MOZ_OVERRIDE
{

View File

@ -207,12 +207,6 @@ CompositableClient::CreateBufferTextureClient(gfx::SurfaceFormat aFormat,
return result.forget();
}
TemporaryRef<BufferTextureClient>
CompositableClient::CreateBufferTextureClient(gfx::SurfaceFormat aFormat)
{
return CreateBufferTextureClient(aFormat, TEXTURE_FLAGS_DEFAULT);
}
bool
CompositableClient::AddTextureClient(TextureClient* aClient)
{

View File

@ -85,10 +85,8 @@ public:
gfxContentType aContentType = GFX_CONTENT_SENTINEL);
virtual TemporaryRef<BufferTextureClient>
CreateBufferTextureClient(gfx::SurfaceFormat aFormat, TextureFlags aFlags);
virtual TemporaryRef<BufferTextureClient>
CreateBufferTextureClient(gfx::SurfaceFormat aFormat);
CreateBufferTextureClient(gfx::SurfaceFormat aFormat,
TextureFlags aFlags = TEXTURE_FLAGS_DEFAULT);
virtual void SetDescriptorFromReply(TextureIdentifier aTextureId,
const SurfaceDescriptor& aDescriptor)

View File

@ -293,13 +293,6 @@ ImageClientSingle::CreateBufferTextureClient(gfx::SurfaceFormat aFormat, Texture
return CompositableClient::CreateBufferTextureClient(aFormat, mTextureFlags | aFlags);
}
TemporaryRef<BufferTextureClient>
ImageClientSingle::CreateBufferTextureClient(gfx::SurfaceFormat aFormat)
{
return CompositableClient::CreateBufferTextureClient(aFormat,
mTextureFlags | TEXTURE_FLAGS_DEFAULT);
}
void
ImageClientSingle::OnDetach()
{

View File

@ -92,10 +92,8 @@ public:
virtual bool AddTextureClient(TextureClient* aTexture) MOZ_OVERRIDE;
virtual TemporaryRef<BufferTextureClient>
CreateBufferTextureClient(gfx::SurfaceFormat aFormat, TextureFlags aFlags) MOZ_OVERRIDE;
virtual TemporaryRef<BufferTextureClient>
CreateBufferTextureClient(gfx::SurfaceFormat aFormat) MOZ_OVERRIDE;
CreateBufferTextureClient(gfx::SurfaceFormat aFormat,
TextureFlags aFlags = TEXTURE_FLAGS_DEFAULT) MOZ_OVERRIDE;
virtual TextureInfo GetTextureInfo() const MOZ_OVERRIDE;

View File

@ -714,7 +714,7 @@ nsEventStatus AsyncPanZoomController::OnLongPress(const TapGestureInput& aEvent)
nsEventStatus AsyncPanZoomController::OnSingleTapUp(const TapGestureInput& aEvent) {
APZC_LOG("%p got a single-tap-up in state %d\n", this, mState);
nsRefPtr<GeckoContentController> controller = GetGeckoContentController();
if (controller && mAllowZoom) {
if (controller && !mAllowZoom) {
ReentrantMonitorAutoEnter lock(mMonitor);
CSSPoint point = WidgetSpaceToCompensatedViewportSpace(aEvent.mPoint, mFrameMetrics.mZoom);

View File

@ -0,0 +1,38 @@
# HG changeset patch
# User Nomis101
# Date 1380136873 -7200
# Wed Sep 25 21:21:13 2013 +0200
# Node ID 2921e2256ba8a8ac1ca8b5b0e48eb04511545d41
# Parent 39f30376058cf20823534f2d510430eaa31844bf
Bug 901348 - [10.9] Duplicate symbol errors building --with-intl-api
diff --git a/intl/icu/source/common/umutex.h b/intl/icu/source/common/umutex.h
--- a/intl/icu/source/common/umutex.h
+++ b/intl/icu/source/common/umutex.h
@@ -43,26 +43,18 @@
# define NOIME
# define NOMCX
# include <windows.h>
#endif /* 0 */
#define U_WINDOWS_CRIT_SEC_SIZE 64
#endif /* win32 */
#if U_PLATFORM_IS_DARWIN_BASED
-#if defined(__STRICT_ANSI__)
-#define UPRV_REMAP_INLINE
-#define inline
-#endif
#include <libkern/OSAtomic.h>
#define USE_MAC_OS_ATOMIC_INCREMENT 1
-#if defined(UPRV_REMAP_INLINE)
-#undef inline
-#undef UPRV_REMAP_INLINE
-#endif
#endif
/*
* If we do not compile with dynamic_annotations.h then define
* empty annotation macros.
* See http://code.google.com/p/data-race-test/wiki/DynamicAnnotations
*/
#ifndef ANNOTATE_HAPPENS_BEFORE

View File

@ -48,16 +48,8 @@
#endif /* win32 */
#if U_PLATFORM_IS_DARWIN_BASED
#if defined(__STRICT_ANSI__)
#define UPRV_REMAP_INLINE
#define inline
#endif
#include <libkern/OSAtomic.h>
#define USE_MAC_OS_ATOMIC_INCREMENT 1
#if defined(UPRV_REMAP_INLINE)
#undef inline
#undef UPRV_REMAP_INLINE
#endif
#endif
/*

View File

@ -558,9 +558,9 @@ struct JSClass {
//
// Implementing this efficiently requires that global objects have classes
// with the following flags. Failure to use JSCLASS_GLOBAL_FLAGS was
// prevously allowed, but is now an ES5 violation and thus unsupported.
// previously allowed, but is now an ES5 violation and thus unsupported.
//
#define JSCLASS_GLOBAL_SLOT_COUNT (JSProto_LIMIT * 3 + 26)
#define JSCLASS_GLOBAL_SLOT_COUNT (3 + JSProto_LIMIT * 3 + 26)
#define JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(n) \
(JSCLASS_IS_GLOBAL | JSCLASS_HAS_RESERVED_SLOTS(JSCLASS_GLOBAL_SLOT_COUNT + (n)))
#define JSCLASS_GLOBAL_FLAGS \

View File

@ -171,10 +171,10 @@ AC_DEFUN([MOZ_COMPILER_OPTS],
AC_SUBST(DEVELOPER_OPTIONS)
if test -n "$DEVELOPER_OPTIONS" -a "${MOZ_PSEUDO_DERECURSE-unset}" = unset; then
if test "${MOZ_PSEUDO_DERECURSE-unset}" = unset; then
dnl Don't enable on pymake, because of bug 918652. Bug 912979 is an annoyance
dnl with pymake, too.
MOZ_PSEUDO_DERECURSE=no-parallel-export,no-pymake,no-skip
MOZ_PSEUDO_DERECURSE=no-pymake,no-skip
fi
MOZ_DEBUGGING_OPTS

View File

@ -2038,7 +2038,7 @@ js_InitIntlClass(JSContext *cx, HandleObject obj)
return nullptr;
}
MarkStandardClassInitializedNoProto(global, &IntlClass);
global->markStandardClassInitializedNoProto(&IntlClass);
return Intl;
}
@ -2052,6 +2052,6 @@ GlobalObject::initIntlObject(JSContext *cx, Handle<GlobalObject*> global)
if (!Intl)
return false;
global->setReservedSlot(JSProto_Intl, ObjectValue(*Intl));
global->setConstructor(JSProto_Intl, ObjectValue(*Intl));
return true;
}

View File

@ -122,7 +122,7 @@ ControlProfilers(bool toState)
{
bool ok = true;
if (! Probes::ProfilingActive && toState) {
if (! probes::ProfilingActive && toState) {
#ifdef __APPLE__
#if defined(MOZ_SHARK) || defined(MOZ_INSTRUMENTS)
const char* profiler;
@ -145,7 +145,7 @@ ControlProfilers(bool toState)
ok = false;
}
#endif
} else if (Probes::ProfilingActive && ! toState) {
} else if (probes::ProfilingActive && ! toState) {
#ifdef __APPLE__
#ifdef MOZ_SHARK
Shark::Stop();
@ -162,7 +162,7 @@ ControlProfilers(bool toState)
#endif
}
Probes::ProfilingActive = toState;
probes::ProfilingActive = toState;
return ok;
}

View File

@ -486,7 +486,7 @@ SetupAndGetPrototypeObjectForComplexTypeInstance(JSContext *cx,
RootedValue complexTypePrototypePrototypeVal(cx);
if (!JSObject::getProperty(cx, complexTypeGlobal, complexTypeGlobal,
cx->names().classPrototype, &complexTypePrototypeVal))
cx->names().prototype, &complexTypePrototypeVal))
return nullptr;
JS_ASSERT(complexTypePrototypeVal.isObject()); // immutable binding
@ -495,7 +495,7 @@ SetupAndGetPrototypeObjectForComplexTypeInstance(JSContext *cx,
if (!JSObject::getProperty(cx, complexTypePrototypeObj,
complexTypePrototypeObj,
cx->names().classPrototype,
cx->names().prototype,
&complexTypePrototypePrototypeVal))
return nullptr;
@ -1333,7 +1333,7 @@ GlobalObject::initDataObject(JSContext *cx, Handle<GlobalObject *> global)
DataCtor, DataProto))
return false;
global->setReservedSlot(JSProto_Data, ObjectValue(*DataCtor));
global->setConstructor(JSProto_Data, ObjectValue(*DataCtor));
return true;
}
@ -1358,7 +1358,7 @@ GlobalObject::initTypeObject(JSContext *cx, Handle<GlobalObject *> global)
TypeCtor, TypeProto))
return false;
global->setReservedSlot(JSProto_Type, ObjectValue(*TypeCtor));
global->setConstructor(JSProto_Type, ObjectValue(*TypeCtor));
return true;
}
@ -1369,7 +1369,7 @@ GlobalObject::initArrayTypeObject(JSContext *cx, Handle<GlobalObject *> global)
global->createConstructor(cx, ArrayType::construct,
cx->names().ArrayType, 2));
global->setReservedSlot(JSProto_ArrayTypeObject, ObjectValue(*ctor));
global->setConstructor(JSProto_ArrayTypeObject, ObjectValue(*ctor));
return true;
}
@ -1393,7 +1393,7 @@ SetupComplexHeirarchy(JSContext *cx, Handle<GlobalObject*> global, JSProtoKey pr
RootedValue DataProtoVal(cx);
if (!JSObject::getProperty(cx, DataObject, DataObject,
cx->names().classPrototype, &DataProtoVal))
cx->names().prototype, &DataProtoVal))
return nullptr;
RootedObject DataProto(cx, &DataProtoVal.toObject());
@ -1443,7 +1443,7 @@ InitType(JSContext *cx, HandleObject globalObj)
RootedValue protoVal(cx);
if (!JSObject::getProperty(cx, ctor, ctor,
cx->names().classPrototype, &protoVal))
cx->names().prototype, &protoVal))
return false;
JS_ASSERT(protoVal.isObject());
@ -1686,7 +1686,7 @@ BinaryBlock::createNull(JSContext *cx, HandleObject type, HandleValue owner)
RootedValue protoVal(cx);
if (!JSObject::getProperty(cx, type, type,
cx->names().classPrototype, &protoVal))
cx->names().prototype, &protoVal))
return nullptr;
RootedObject obj(cx,

View File

@ -1368,9 +1368,6 @@ ICUpdatedStub::addUpdateStubForValue(JSContext *cx, HandleScript script, HandleO
return true;
}
if (!obj->getType(cx))
return false;
types::EnsureTrackPropertyTypes(cx, obj, id);
if (val.isPrimitive()) {
@ -5326,6 +5323,10 @@ TryAttachGlobalNameStub(JSContext *cx, HandleScript script, ICGetName_Fallback *
RootedId id(cx, NameToId(name));
// Instantiate this global property, for use during Ion compilation.
if (IsIonEnabled(cx))
types::EnsureTrackPropertyTypes(cx, global, NameToId(name));
// The property must be found, and it must be found as a normal data property.
RootedShape shape(cx, global->nativeLookup(cx, id));
if (!shape || !shape->hasDefaultGetter() || !shape->hasSlot())
@ -5383,6 +5384,10 @@ TryAttachScopeNameStub(JSContext *cx, HandleScript script, ICGetName_Fallback *s
if (!IsCacheableGetPropReadSlot(scopeChain, scopeChain, shape))
return true;
// Instantiate properties on singleton scope chain objects, for use during Ion compilation.
if (scopeChain->hasSingletonType() && IsIonEnabled(cx))
types::EnsureTrackPropertyTypes(cx, scopeChain, NameToId(name));
bool isFixedSlot;
uint32_t offset;
GetFixedOrDynamicSlotOffset(scopeChain, shape->slot(), &isFixedSlot, &offset);
@ -5810,6 +5815,10 @@ TryAttachNativeGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc,
uint32_t offset;
GetFixedOrDynamicSlotOffset(holder, shape->slot(), &isFixedSlot, &offset);
// Instantiate this property for singleton holders, for use during Ion compilation.
if (IsIonEnabled(cx))
types::EnsureTrackPropertyTypes(cx, holder, NameToId(name));
ICStub::Kind kind = (obj == holder) ? ICStub::GetProp_Native
: ICStub::GetProp_NativePrototype;
@ -5919,6 +5928,10 @@ TryAttachStringGetPropStub(JSContext *cx, HandleScript script, ICGetProp_Fallbac
if (!stringProto)
return false;
// Instantiate this property, for use during Ion compilation.
if (IsIonEnabled(cx))
types::EnsureTrackPropertyTypes(cx, stringProto, NameToId(name));
// For now, only look for properties directly set on String.prototype
RootedId propId(cx, NameToId(name));
RootedShape shape(cx, stringProto->nativeLookup(cx, propId));
@ -7465,6 +7478,11 @@ TryAttachCallStub(JSContext *cx, ICCall_Fallback *stub, HandleScript script, jsb
return true;
}
// Keep track of the function's |prototype| property in type
// information, for use during Ion compilation.
if (IsIonEnabled(cx))
types::EnsureTrackPropertyTypes(cx, fun, NameToId(cx->names().prototype));
IonSpew(IonSpew_BaselineIC,
" Generating Call_Scripted stub (fun=%p, %s:%d, cons=%s)",
fun.get(), fun->nonLazyScript()->filename(), fun->nonLazyScript()->lineno,

View File

@ -2151,7 +2151,7 @@ CodeGenerator::visitApplyArgsGeneric(LApplyArgsGeneric *apply)
ExecutionMode executionMode = gen->info().executionMode();
if (apply->hasSingleTarget()) {
JSFunction *target = apply->getSingleTarget();
if (!CanIonCompile(target, executionMode)) {
if (target->isNative()) {
if (!emitCallInvokeFunction(apply, copyreg))
return false;
emitPopArguments(apply, copyreg);

View File

@ -73,12 +73,6 @@ CanIonCompile(JSScript *script, ExecutionMode cmode)
return false;
}
static inline bool
CanIonCompile(JSFunction *fun, ExecutionMode cmode)
{
return fun->isInterpreted() && CanIonCompile(fun->nonLazyScript(), cmode);
}
static inline bool
CompilingOffThread(JSScript *script, ExecutionMode cmode)
{

View File

@ -1922,7 +1922,7 @@ AnalyzePoppedThis(JSContext *cx, types::TypeObject *type,
// Don't use GetAtomId here, we need to watch for SETPROP on
// integer properties and bail out. We can't mark the aggregate
// JSID_VOID type property as being in a definite slot.
if (setprop->name() == cx->names().classPrototype ||
if (setprop->name() == cx->names().prototype ||
setprop->name() == cx->names().proto ||
setprop->name() == cx->names().constructor)
{

View File

@ -271,6 +271,13 @@ IonBuilder::canInlineTarget(JSFunction *target, bool constructing)
return false;
}
// Allow constructing lazy scripts when performing the definite properties
// analysis, as baseline has not been used to warm the caller up yet.
if (target->isInterpretedLazy() && info().executionMode() == DefinitePropertiesAnalysis) {
if (!target->getOrCreateScript(cx))
return false;
}
if (!target->hasScript()) {
IonSpew(IonSpew_Inlining, "Cannot inline due to lack of Non-Lazy script");
return false;
@ -4584,11 +4591,11 @@ IonBuilder::createThisScripted(MDefinition *callee)
// and thus invalidation.
MInstruction *getProto;
if (!invalidatedIdempotentCache()) {
MGetPropertyCache *getPropCache = MGetPropertyCache::New(callee, cx->names().classPrototype);
MGetPropertyCache *getPropCache = MGetPropertyCache::New(callee, cx->names().prototype);
getPropCache->setIdempotent();
getProto = getPropCache;
} else {
MCallGetProperty *callGetProp = MCallGetProperty::New(callee, cx->names().classPrototype);
MCallGetProperty *callGetProp = MCallGetProperty::New(callee, cx->names().prototype);
callGetProp->setIdempotent();
getProto = callGetProp;
}
@ -4610,7 +4617,7 @@ IonBuilder::getSingletonPrototype(JSFunction *target)
if (targetType->unknownProperties())
return nullptr;
jsid protoid = NameToId(cx->names().classPrototype);
jsid protoid = NameToId(cx->names().prototype);
types::HeapTypeSetKey protoProperty = targetType->property(protoid);
return protoProperty.singleton(constraints());
@ -5447,7 +5454,7 @@ IonBuilder::jsop_initelem_array()
needStub = true;
} else if (!initializer->unknownProperties()) {
types::HeapTypeSetKey elemTypes = initializer->property(JSID_VOID);
if (!TypeSetIncludes(elemTypes.actualTypes, value->type(), value->resultTypeSet())) {
if (!TypeSetIncludes(elemTypes.maybeTypes(), value->type(), value->resultTypeSet())) {
elemTypes.freeze(constraints());
needStub = true;
}
@ -5994,7 +6001,7 @@ IonBuilder::testSingletonProperty(JSObject *obj, JSObject *singleton,
if (objType->unknownProperties())
return true;
types::HeapTypeSetKey property = objType->property(idRoot);
types::HeapTypeSetKey property = objType->property(NameToId(name), context());
if (obj != holder) {
if (property.notEmpty(constraints()))
return true;
@ -6076,7 +6083,7 @@ IonBuilder::testSingletonPropertyTypes(MDefinition *obj, JSObject *singleton,
if (object->unknownProperties())
return true;
types::HeapTypeSetKey property = object->property(NameToId(name));
types::HeapTypeSetKey property = object->property(NameToId(name), context());
if (property.notEmpty(constraints()))
return true;
@ -6213,7 +6220,7 @@ IonBuilder::getStaticName(JSObject *staticObject, PropertyName *name, bool *psuc
types::TypeObjectKey *staticType = types::TypeObjectKey::get(staticObject);
Maybe<types::HeapTypeSetKey> propertyTypes;
if (!staticType->unknownProperties()) {
propertyTypes.construct(staticType->property(id));
propertyTypes.construct(staticType->property(id, context()));
if (propertyTypes.ref().configured(constraints(), staticType)) {
// The property has been reconfigured as non-configurable, non-enumerable
// or non-writable.
@ -6223,7 +6230,7 @@ IonBuilder::getStaticName(JSObject *staticObject, PropertyName *name, bool *psuc
}
types::StackTypeSet *baseTypes = types::TypeScript::BytecodeTypes(script(), pc);
bool barrier = PropertyReadNeedsTypeBarrier(cx, constraints(), staticType,
bool barrier = PropertyReadNeedsTypeBarrier(cx, context(), constraints(), staticType,
name, baseTypes, /* updateObserved = */ true);
types::TemporaryTypeSet *types = cloneTypeSet(baseTypes);
@ -6266,6 +6273,9 @@ IonBuilder::getStaticName(JSObject *staticObject, PropertyName *name, bool *psuc
bool
jit::TypeSetIncludes(types::TypeSet *types, MIRType input, types::TypeSet *inputTypes)
{
if (!types)
return inputTypes && inputTypes->empty();
switch (input) {
case MIRType_Undefined:
case MIRType_Null:
@ -6324,7 +6334,7 @@ IonBuilder::setStaticName(JSObject *staticObject, PropertyName *name)
return jsop_setprop(name);
}
if (!TypeSetIncludes(propertyTypes.actualTypes, value->type(), value->resultTypeSet()))
if (!TypeSetIncludes(propertyTypes.maybeTypes(), value->type(), value->resultTypeSet()))
return jsop_setprop(name);
current->pop();
@ -6733,7 +6743,7 @@ IonBuilder::getElemTryCache(bool *emitted, MDefinition *obj, MDefinition *index)
// Emit GetElementCache.
types::StackTypeSet *baseTypes = types::TypeScript::BytecodeTypes(script(), pc);
bool barrier = PropertyReadNeedsTypeBarrier(cx, constraints(), obj, nullptr, baseTypes);
bool barrier = PropertyReadNeedsTypeBarrier(cx, context(), constraints(), obj, nullptr, baseTypes);
types::TemporaryTypeSet *types = cloneTypeSet(baseTypes);
// Always add a barrier if the index might be a string, so that the cache
@ -6782,7 +6792,7 @@ IonBuilder::jsop_getelem_dense(MDefinition *obj, MDefinition *index)
return false;
}
bool barrier = PropertyReadNeedsTypeBarrier(cx, constraints(), obj, nullptr, baseTypes);
bool barrier = PropertyReadNeedsTypeBarrier(cx, context(), constraints(), obj, nullptr, baseTypes);
types::TemporaryTypeSet *types = cloneTypeSet(baseTypes);
bool needsHoleCheck = !ElementAccessIsPacked(constraints(), obj);
@ -7576,7 +7586,8 @@ IonBuilder::getDefiniteSlot(types::TemporaryTypeSet *types, PropertyName *name,
jsid id = NameToId(name);
*property = type->property(id);
return property->actualTypes->definiteProperty() &&
return property->maybeTypes() &&
property->maybeTypes()->definiteProperty() &&
!property->configured(constraints(), type);
}
@ -7615,7 +7626,7 @@ TestTypeHasOwnProperty(types::TypeObjectKey *typeObj, PropertyName *name, bool &
{
cont = true;
types::HeapTypeSetKey propSet = typeObj->property(NameToId(name));
if (!propSet.actualTypes->empty())
if (propSet.maybeTypes() && !propSet.maybeTypes()->empty())
cont = false;
// Note: Callers must explicitly freeze the property type set later on if optimizing.
return true;
@ -8032,7 +8043,7 @@ IonBuilder::jsop_getprop(PropertyName *name)
return emitted;
types::StackTypeSet *baseTypes = types::TypeScript::BytecodeTypes(script(), pc);
bool barrier = PropertyReadNeedsTypeBarrier(cx, constraints(),
bool barrier = PropertyReadNeedsTypeBarrier(cx, context(), constraints(),
current->peek(-1), name, baseTypes);
types::TemporaryTypeSet *types = cloneTypeSet(baseTypes);
@ -8042,13 +8053,14 @@ IonBuilder::jsop_getprop(PropertyName *name)
// Except when loading constants above, always use a call if we are doing
// the definite properties analysis and not actually emitting code, to
// simplify later analysis.
if (info().executionMode() == DefinitePropertiesAnalysis) {
// simplify later analysis. Also skip deeper analysis if there are no known
// types for this operation, as it will always invalidate when executing.
if (info().executionMode() == DefinitePropertiesAnalysis || baseTypes->empty()) {
MDefinition *obj = current->pop();
MCallGetProperty *call = MCallGetProperty::New(obj, name);
current->add(call);
current->push(call);
return resumeAfter(call);
return resumeAfter(call) && pushTypeBarrier(call, types, true);
}
// Try to emit loads from known binary data blocks
@ -8268,7 +8280,7 @@ IonBuilder::getPropTryDefiniteSlot(bool *emitted, PropertyName *name,
useObj = guard;
}
MLoadFixedSlot *fixed = MLoadFixedSlot::New(useObj, property.actualTypes->definiteSlot());
MLoadFixedSlot *fixed = MLoadFixedSlot::New(useObj, property.maybeTypes()->definiteSlot());
if (!barrier)
fixed->setResultType(MIRTypeFromValueType(types->getKnownTypeTag()));
@ -8748,7 +8760,7 @@ IonBuilder::setPropTryDefiniteSlot(bool *emitted, MDefinition *obj,
if (!getDefiniteSlot(obj->resultTypeSet(), name, &property))
return true;
MStoreFixedSlot *fixed = MStoreFixedSlot::New(obj, property.actualTypes->definiteSlot(), value);
MStoreFixedSlot *fixed = MStoreFixedSlot::New(obj, property.maybeTypes()->definiteSlot(), value);
current->add(fixed);
current->push(value);
@ -9395,7 +9407,7 @@ IonBuilder::jsop_instanceof()
break;
types::HeapTypeSetKey protoProperty =
rhsType->property(NameToId(cx->names().classPrototype));
rhsType->property(NameToId(cx->names().prototype));
JSObject *protoObject = protoProperty.singleton(constraints());
if (!protoObject)
break;

View File

@ -690,6 +690,16 @@ class IonBuilder : public MIRGenerator
return callerBuilder_ != nullptr;
}
JSContext *context() {
// JSContexts are only available to IonBuilder when running on the main
// thread, which after bug 785905 will only occur when doing eager
// analyses with no available baseline information. Until this bug is
// completed, both the |cx| member and |context()| may be used.
if (info().executionMode() == DefinitePropertiesAnalysis)
return cx;
return NULL;
}
private:
bool init();

View File

@ -554,7 +554,7 @@ HandleException(ResumeFromException *rfe)
// the function has exited, so invoke the probe that a function
// is exiting.
JSScript *script = frames.script();
Probes::exitScript(cx, script, script->function(), nullptr);
probes::ExitScript(cx, script, script->function(), nullptr);
if (!frames.more())
break;
++frames;
@ -574,7 +574,7 @@ HandleException(ResumeFromException *rfe)
// Unwind profiler pseudo-stack
JSScript *script = iter.script();
Probes::exitScript(cx, script, script->function(), iter.baselineFrame());
probes::ExitScript(cx, script, script->function(), iter.baselineFrame());
// After this point, any pushed SPS frame would have been popped if it needed
// to be. Unset the flag here so that if we call DebugEpilogue below,
// it doesn't try to pop the SPS frame again.

View File

@ -1064,7 +1064,7 @@ class MacroAssembler : public MacroAssemblerSpecific
storePtr(ImmPtr(nullptr), Address(temp, ProfileEntry::offsetOfStackAddress()));
// Store 0 for PCIdx because that's what interpreter does.
// (See Probes::enterScript, which calls spsProfiler.enter, which pushes an entry
// (See probes::EnterScript, which calls spsProfiler.enter, which pushes an entry
// with 0 pcIdx).
store32(Imm32(0), Address(temp, ProfileEntry::offsetOfPCIdx()));

View File

@ -221,7 +221,7 @@ IonBuilder::inlineArray(CallInfo &callInfo)
for (uint32_t i = 0; i < initLength; i++) {
MDefinition *value = callInfo.getArg(i);
if (!TypeSetIncludes(elemTypes.actualTypes, value->type(), value->resultTypeSet())) {
if (!TypeSetIncludes(elemTypes.maybeTypes(), value->type(), value->resultTypeSet())) {
elemTypes.freeze(constraints());
return InliningStatus_NotInlined;
}
@ -332,7 +332,7 @@ IonBuilder::inlineArrayPopShift(CallInfo &callInfo, MArrayPopShift::Mode mode)
bool needsHoleCheck = thisTypes->hasObjectFlags(constraints(), types::OBJECT_FLAG_NON_PACKED);
bool maybeUndefined = returnTypes->hasType(types::Type::UndefinedType());
bool barrier = PropertyReadNeedsTypeBarrier(cx, constraints(),
bool barrier = PropertyReadNeedsTypeBarrier(cx, context(), constraints(),
callInfo.thisArg(), nullptr, returnTypes);
if (barrier)
returnType = MIRType_Value;

View File

@ -2780,12 +2780,12 @@ PropertyReadNeedsTypeBarrier(JSContext *cx, types::CompilerConstraintList *const
// which are accounted for by type information, i.e. native data properties
// and elements.
if (object->unknownProperties())
if (object->unknownProperties() || observed->empty())
return true;
jsid id = name ? NameToId(name) : JSID_VOID;
types::HeapTypeSetKey property = object->property(id);
if (!TypeSetIncludes(observed, MIRType_Value, property.actualTypes))
if (property.maybeTypes() && !TypeSetIncludes(observed, MIRType_Value, property.maybeTypes()))
return true;
// Type information for singleton objects is not required to reflect the
@ -2807,7 +2807,8 @@ PropertyReadNeedsTypeBarrier(JSContext *cx, types::CompilerConstraintList *const
}
bool
jit::PropertyReadNeedsTypeBarrier(JSContext *cx, types::CompilerConstraintList *constraints,
jit::PropertyReadNeedsTypeBarrier(JSContext *cx, JSContext *propertycx,
types::CompilerConstraintList *constraints,
types::TypeObjectKey *object, PropertyName *name,
types::StackTypeSet *observed, bool updateObserved)
{
@ -2820,11 +2821,18 @@ jit::PropertyReadNeedsTypeBarrier(JSContext *cx, types::CompilerConstraintList *
if (!obj->isNative())
break;
Value v;
if (HasDataProperty(cx, obj, NameToId(name), &v)) {
if (v.isUndefined())
break;
observed->addType(cx, types::GetValueType(v));
types::TypeObjectKey *typeObj = types::TypeObjectKey::get(obj);
if (!typeObj->unknownProperties()) {
types::HeapTypeSetKey property = typeObj->property(NameToId(name), propertycx);
if (property.maybeTypes()) {
types::TypeSet::TypeList types;
if (!property.maybeTypes()->enumerateTypes(&types))
return false;
if (types.length()) {
observed->addType(cx, types[0]);
break;
}
}
}
obj = obj->getProto();
@ -2835,7 +2843,8 @@ jit::PropertyReadNeedsTypeBarrier(JSContext *cx, types::CompilerConstraintList *
}
bool
jit::PropertyReadNeedsTypeBarrier(JSContext *cx, types::CompilerConstraintList *constraints,
jit::PropertyReadNeedsTypeBarrier(JSContext *cx, JSContext *propertycx,
types::CompilerConstraintList *constraints,
MDefinition *obj, PropertyName *name,
types::StackTypeSet *observed)
{
@ -2850,7 +2859,7 @@ jit::PropertyReadNeedsTypeBarrier(JSContext *cx, types::CompilerConstraintList *
for (size_t i = 0; i < types->getObjectCount(); i++) {
types::TypeObjectKey *object = types->getObject(i);
if (object) {
if (PropertyReadNeedsTypeBarrier(cx, constraints, object, name,
if (PropertyReadNeedsTypeBarrier(cx, propertycx, constraints, object, name,
observed, updateObserved))
{
return true;
@ -2983,7 +2992,10 @@ TryAddTypeBarrierForWrite(types::CompilerConstraintList *constraints,
jsid id = name ? NameToId(name) : JSID_VOID;
types::HeapTypeSetKey property = object->property(id);
if (TypeSetIncludes(property.actualTypes, (*pvalue)->type(), (*pvalue)->resultTypeSet()))
if (!property.maybeTypes())
return false;
if (TypeSetIncludes(property.maybeTypes(), (*pvalue)->type(), (*pvalue)->resultTypeSet()))
return false;
// This freeze is not required for correctness, but ensures that we
@ -2994,8 +3006,8 @@ TryAddTypeBarrierForWrite(types::CompilerConstraintList *constraints,
if (aggregateProperty.empty()) {
aggregateProperty.construct(property);
} else {
if (!aggregateProperty.ref().actualTypes->isSubset(property.actualTypes) ||
!property.actualTypes->isSubset(aggregateProperty.ref().actualTypes))
if (!aggregateProperty.ref().maybeTypes()->isSubset(property.maybeTypes()) ||
!property.maybeTypes()->isSubset(aggregateProperty.ref().maybeTypes()))
{
return false;
}
@ -3030,7 +3042,7 @@ TryAddTypeBarrierForWrite(types::CompilerConstraintList *constraints,
return false;
types::TemporaryTypeSet *types =
aggregateProperty.ref().actualTypes->clone(GetIonContext()->temp->lifoAlloc());
aggregateProperty.ref().maybeTypes()->clone(GetIonContext()->temp->lifoAlloc());
if (!types)
return false;
@ -3085,7 +3097,7 @@ jit::PropertyWriteNeedsTypeBarrier(types::CompilerConstraintList *constraints,
jsid id = name ? NameToId(name) : JSID_VOID;
types::HeapTypeSetKey property = object->property(id);
if (!TypeSetIncludes(property.actualTypes, (*pvalue)->type(), (*pvalue)->resultTypeSet())) {
if (!TypeSetIncludes(property.maybeTypes(), (*pvalue)->type(), (*pvalue)->resultTypeSet())) {
// Either pobj or pvalue needs to be modified to filter out the
// types which the value could have but are not in the property,
// or a VM call is required. A VM call is always required if pobj
@ -3117,10 +3129,10 @@ jit::PropertyWriteNeedsTypeBarrier(types::CompilerConstraintList *constraints,
jsid id = name ? NameToId(name) : JSID_VOID;
types::HeapTypeSetKey property = object->property(id);
if (TypeSetIncludes(property.actualTypes, (*pvalue)->type(), (*pvalue)->resultTypeSet()))
if (TypeSetIncludes(property.maybeTypes(), (*pvalue)->type(), (*pvalue)->resultTypeSet()))
continue;
if (!property.actualTypes->empty() || excluded)
if ((property.maybeTypes() && !property.maybeTypes()->empty()) || excluded)
return true;
excluded = object->isTypeObject() ? object->asTypeObject() : object->asSingleObject()->getType(GetIonContext()->cx);
}

View File

@ -8993,10 +8993,12 @@ bool ElementAccessIsPacked(types::CompilerConstraintList *constraints, MDefiniti
bool ElementAccessHasExtraIndexedProperty(types::CompilerConstraintList *constraints,
MDefinition *obj);
MIRType DenseNativeElementType(types::CompilerConstraintList *constraints, MDefinition *obj);
bool PropertyReadNeedsTypeBarrier(JSContext *cx, types::CompilerConstraintList *constraints,
bool PropertyReadNeedsTypeBarrier(JSContext *cx, JSContext *propertycx,
types::CompilerConstraintList *constraints,
types::TypeObjectKey *object, PropertyName *name,
types::StackTypeSet *observed, bool updateObserved);
bool PropertyReadNeedsTypeBarrier(JSContext *cx, types::CompilerConstraintList *constraints,
bool PropertyReadNeedsTypeBarrier(JSContext *cx, JSContext *propertycx,
types::CompilerConstraintList *constraints,
MDefinition *obj, PropertyName *name,
types::StackTypeSet *observed);
bool PropertyReadOnPrototypeNeedsTypeBarrier(JSContext *cx, types::CompilerConstraintList *constraints,

View File

@ -716,7 +716,7 @@ DebugEpilogue(JSContext *cx, BaselineFrame *frame, bool ok)
if (frame->hasPushedSPSFrame()) {
cx->runtime()->spsProfiler.exit(cx, frame->script(), frame->maybeFun());
// Unset the pushedSPSFrame flag because DebugEpilogue may get called before
// Probes::exitScript in baseline during exception handling, and we don't
// probes::ExitScript in baseline during exception handling, and we don't
// want to double-pop SPS frames.
frame->unsetPushedSPSFrame();
}

View File

@ -1553,6 +1553,7 @@ JS_ResolveStandardClass(JSContext *cx, HandleObject obj, HandleId id, bool *reso
AssertHeapIsIdle(cx);
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj, id);
JS_ASSERT(obj->is<GlobalObject>());
*resolved = false;
rt = cx->runtime();
@ -1622,11 +1623,10 @@ JS_ResolveStandardClass(JSContext *cx, HandleObject obj, HandleId id, bool *reso
* If this standard class is anonymous, then we don't want to resolve
* by name.
*/
JS_ASSERT(obj->is<GlobalObject>());
if (stdnm->clasp->flags & JSCLASS_IS_ANONYMOUS)
return true;
if (IsStandardClassResolved(obj, stdnm->clasp))
if (obj->as<GlobalObject>().isStandardClassResolved(stdnm->clasp))
return true;
if (!stdnm->init(cx, obj))
@ -1642,6 +1642,7 @@ JS_EnumerateStandardClasses(JSContext *cx, HandleObject obj)
AssertHeapIsIdle(cx);
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj);
MOZ_ASSERT(obj->is<GlobalObject>());
/*
* Check whether we need to bind 'undefined' and define it if so.
@ -1659,7 +1660,7 @@ JS_EnumerateStandardClasses(JSContext *cx, HandleObject obj)
/* Initialize any classes that have not been initialized yet. */
for (unsigned i = 0; standard_class_atoms[i].init; i++) {
const JSStdName &stdnm = standard_class_atoms[i];
if (!js::IsStandardClassResolved(obj, stdnm.clasp)) {
if (!obj->as<GlobalObject>().isStandardClassResolved(stdnm.clasp)) {
if (!stdnm.init(cx, obj))
return false;
}

View File

@ -3192,7 +3192,7 @@ NewArray(ExclusiveContext *cxArg, uint32_t length,
if (allocateCapacity && !EnsureNewArrayElements(cxArg, arr, length))
return nullptr;
Probes::createObject(cxArg, arr);
probes::CreateObject(cxArg, arr);
return arr;
}

View File

@ -537,7 +537,7 @@ Exception(JSContext *cx, unsigned argc, Value *vp)
*/
RootedObject callee(cx, &args.callee());
RootedValue protov(cx);
if (!JSObject::getProperty(cx, callee, callee, cx->names().classPrototype, &protov))
if (!JSObject::getProperty(cx, callee, callee, cx->names().prototype, &protov))
return false;
if (!protov.isObject()) {

View File

@ -165,7 +165,7 @@ fun_enumerate(JSContext *cx, HandleObject obj)
bool found;
if (!obj->isBoundFunction()) {
id = NameToId(cx->names().classPrototype);
id = NameToId(cx->names().prototype);
if (!JSObject::hasProperty(cx, obj, id, &found, 0))
return false;
}
@ -224,7 +224,7 @@ ResolveInterpretedFunctionPrototype(JSContext *cx, HandleObject obj)
// Per ES5 15.3.5.2 a user-defined function's .prototype property is
// initially non-configurable, non-enumerable, and writable.
RootedValue protoVal(cx, ObjectValue(*proto));
if (!JSObject::defineProperty(cx, obj, cx->names().classPrototype,
if (!JSObject::defineProperty(cx, obj, cx->names().prototype,
protoVal, JS_PropertyStub, JS_StrictPropertyStub,
JSPROP_PERMANENT))
{
@ -256,7 +256,7 @@ js::fun_resolve(JSContext *cx, HandleObject obj, HandleId id, unsigned flags,
RootedFunction fun(cx, &obj->as<JSFunction>());
if (JSID_IS_ATOM(id, cx->names().classPrototype)) {
if (JSID_IS_ATOM(id, cx->names().prototype)) {
/*
* Built-in functions do not have a .prototype property per ECMA-262,
* or (Object.prototype, Function.prototype, etc.) have that property
@ -474,7 +474,7 @@ fun_hasInstance(JSContext *cx, HandleObject objArg, MutableHandleValue v, bool *
obj = obj->as<JSFunction>().getBoundFunctionTarget();
RootedValue pval(cx);
if (!JSObject::getProperty(cx, obj, obj, cx->names().classPrototype, &pval))
if (!JSObject::getProperty(cx, obj, obj, cx->names().prototype, &pval))
return false;
if (pval.isPrimitive()) {

View File

@ -49,7 +49,7 @@ using mozilla::PodZero;
static inline jsid
id_prototype(JSContext *cx) {
return NameToId(cx->names().classPrototype);
return NameToId(cx->names().prototype);
}
static inline jsid
@ -336,6 +336,39 @@ TypeSet::isSubset(TypeSet *other)
return true;
}
bool
TypeSet::enumerateTypes(TypeList *list)
{
/* If any type is possible, there's no need to worry about specifics. */
if (flags & TYPE_FLAG_UNKNOWN)
return list->append(Type::UnknownType());
/* Enqueue type set members stored as bits. */
for (TypeFlags flag = 1; flag < TYPE_FLAG_ANYOBJECT; flag <<= 1) {
if (flags & flag) {
Type type = Type::PrimitiveType(TypeFlagPrimitive(flag));
if (!list->append(type))
return false;
}
}
/* If any object is possible, skip specifics. */
if (flags & TYPE_FLAG_ANYOBJECT)
return list->append(Type::AnyObjectType());
/* Enqueue specific object types. */
unsigned count = getObjectCount();
for (unsigned i = 0; i < count; i++) {
TypeObjectKey *object = getObject(i);
if (object) {
if (!list->append(Type::ObjectType(object)))
return false;
}
}
return true;
}
inline void
TypeSet::addTypesToConstraint(JSContext *cx, TypeConstraint *constraint)
{
@ -343,38 +376,9 @@ TypeSet::addTypesToConstraint(JSContext *cx, TypeConstraint *constraint)
* Build all types in the set into a vector before triggering the
* constraint, as doing so may modify this type set.
*/
Vector<Type> types(cx);
/* If any type is possible, there's no need to worry about specifics. */
if (flags & TYPE_FLAG_UNKNOWN) {
if (!types.append(Type::UnknownType()))
cx->compartment()->types.setPendingNukeTypes(cx);
} else {
/* Enqueue type set members stored as bits. */
for (TypeFlags flag = 1; flag < TYPE_FLAG_ANYOBJECT; flag <<= 1) {
if (flags & flag) {
Type type = Type::PrimitiveType(TypeFlagPrimitive(flag));
if (!types.append(type))
cx->compartment()->types.setPendingNukeTypes(cx);
}
}
/* If any object is possible, skip specifics. */
if (flags & TYPE_FLAG_ANYOBJECT) {
if (!types.append(Type::AnyObjectType()))
cx->compartment()->types.setPendingNukeTypes(cx);
} else {
/* Enqueue specific object types. */
unsigned count = getObjectCount();
for (unsigned i = 0; i < count; i++) {
TypeObjectKey *object = getObject(i);
if (object) {
if (!types.append(Type::ObjectType(object)))
cx->compartment()->types.setPendingNukeTypes(cx);
}
}
}
}
TypeList types;
if (!enumerateTypes(&types))
cx->compartment()->types.setPendingNukeTypes(cx);
for (unsigned i = 0; i < types.length(); i++)
constraint->newType(cx, this, types[i]);
@ -566,10 +570,8 @@ class types::CompilerConstraint
CompilerConstraint(const HeapTypeSetKey &property)
: property(property),
expected(property.actualTypes->clone(IonAlloc()))
{
// Note: CompilerConstraintList::add watches for OOM under clone().
}
expected(property.maybeTypes() ? property.maybeTypes()->clone(IonAlloc()) : NULL)
{}
// Generate the type constraint recording the assumption made by this
// compilation. Returns true if the assumption originally made still holds.
@ -580,7 +582,7 @@ void
CompilerConstraintList::add(CompilerConstraint *constraint)
{
#ifdef JS_ION
if (!constraint || !constraint->expected || !constraints.append(constraint))
if (!constraint || !constraints.append(constraint))
setFailed();
#else
MOZ_CRASH();
@ -641,14 +643,17 @@ template <typename T>
bool
CompilerConstraintInstance<T>::generateTypeConstraint(JSContext *cx, RecompileInfo recompileInfo)
{
if (property.actualObject->unknownProperties())
if (property.object()->unknownProperties())
return false;
if (!property.instantiate(cx))
return false;
if (!data.constraintHolds(cx, property, expected))
return false;
property.actualTypes->add(cx, cx->typeLifoAlloc().new_<TypeCompilerConstraint<T> >(recompileInfo, data),
/* callExisting = */ false);
property.maybeTypes()->add(cx, cx->typeLifoAlloc().new_<TypeCompilerConstraint<T> >(recompileInfo, data),
/* callExisting = */ false);
return true;
}
@ -683,37 +688,62 @@ TypeObjectKey::newScript()
return nullptr;
}
TypeObject *
TypeObjectKey::maybeType()
{
if (isTypeObject())
return asTypeObject();
if (asSingleObject()->hasLazyType())
return NULL;
return asSingleObject()->type();
}
bool
TypeObjectKey::unknownProperties()
{
#ifdef JS_ION
JSContext *cx = jit::GetIonContext()->cx;
TypeObject *type = isSingleObject() ? asSingleObject()->getType(cx) : asTypeObject();
if (!type)
MOZ_CRASH();
return type->unknownProperties();
#else
MOZ_CRASH();
#endif
if (TypeObject *type = maybeType())
return type->unknownProperties();
return false;
}
HeapTypeSetKey
TypeObjectKey::property(jsid id)
TypeObjectKey::property(jsid id, JSContext *maybecx /* = NULL */)
{
#ifdef JS_ION
JSContext *cx = jit::GetIonContext()->cx;
TypeObject *type = isSingleObject() ? asSingleObject()->getType(cx) : asTypeObject();
if (!type)
MOZ_CRASH();
JS_ASSERT(!unknownProperties());
HeapTypeSetKey property;
property.actualObject = type;
property.actualTypes = type->getProperty(cx, id);
if (!property.actualTypes)
MOZ_CRASH();
property.object_ = this;
property.id_ = id;
if (TypeObject *type = maybeType())
property.maybeTypes_ = type->maybeGetProperty(id);
#ifdef JS_ION
// If we are accessing a lazily defined property which actually exists in
// the VM and has not been instantiated yet, instantiate it now if we are
// on the main thread and able to do so.
if (maybecx && !property.maybeTypes() && !JSID_IS_VOID(id) && !JSID_IS_EMPTY(id)) {
JS_ASSERT(CurrentThreadCanAccessRuntime(maybecx->runtime()));
JSObject *singleton = isSingleObject() ? asSingleObject() : asTypeObject()->singleton;
if (singleton && singleton->isNative() && singleton->nativeLookupPure(id)) {
EnsureTrackPropertyTypes(maybecx, singleton, id);
if (TypeObject *type = maybeType())
property.maybeTypes_ = type->maybeGetProperty(id);
}
}
#endif // JS_ION
return property;
#else
MOZ_CRASH();
#endif
}
bool
HeapTypeSetKey::instantiate(JSContext *cx)
{
if (maybeTypes())
return true;
if (object()->isSingleObject() && !object()->asSingleObject()->getType(cx))
return false;
maybeTypes_ = object()->maybeType()->getProperty(cx, id());
return maybeTypes_ != NULL;
}
bool
@ -738,12 +768,17 @@ types::FinishCompilation(JSContext *cx, JSScript *script, ExecutionMode executio
*precompileInfo = RecompileInfo(index);
bool succeeded = true;
for (size_t i = 0; i < constraints->length(); i++) {
CompilerConstraint *constraint = constraints->get(i);
if (!constraint->generateTypeConstraint(cx, *precompileInfo)) {
types.constrainedOutputs->back().invalidate();
return false;
}
if (!constraint->generateTypeConstraint(cx, *precompileInfo))
succeeded = false;
}
if (!succeeded) {
types.constrainedOutputs->back().invalidate();
return false;
}
return true;
@ -766,7 +801,9 @@ class ConstraintDataFreeze
bool constraintHolds(JSContext *cx,
const HeapTypeSetKey &property, TemporaryTypeSet *expected)
{
return property.actualTypes->isSubset(expected);
return expected
? property.maybeTypes()->isSubset(expected)
: property.maybeTypes()->empty();
}
};
@ -842,13 +879,15 @@ TemporaryTypeSet::mightBeType(JSValueType type)
JSValueType
HeapTypeSetKey::knownTypeTag(CompilerConstraintList *constraints)
{
if (actualTypes->unknown())
TypeSet *types = maybeTypes();
if (!types || types->unknown())
return JSVAL_TYPE_UNKNOWN;
TypeFlags flags = actualTypes->baseFlags() & ~TYPE_FLAG_ANYOBJECT;
TypeFlags flags = types->baseFlags() & ~TYPE_FLAG_ANYOBJECT;
JSValueType type;
if (actualTypes->unknownObject() || actualTypes->getObjectCount())
if (types->unknownObject() || types->getObjectCount())
type = flags ? JSVAL_TYPE_UNKNOWN : JSVAL_TYPE_OBJECT;
else
type = GetValueTypeFromTypeFlags(flags);
@ -863,7 +902,7 @@ HeapTypeSetKey::knownTypeTag(CompilerConstraintList *constraints)
* that the exact tag is unknown, as it will stay unknown as more types are
* added to the set.
*/
JS_ASSERT_IF(actualTypes->empty(), type == JSVAL_TYPE_UNKNOWN);
JS_ASSERT_IF(types->empty(), type == JSVAL_TYPE_UNKNOWN);
return type;
}
@ -871,7 +910,7 @@ HeapTypeSetKey::knownTypeTag(CompilerConstraintList *constraints)
bool
HeapTypeSetKey::notEmpty(CompilerConstraintList *constraints)
{
if (!actualTypes->empty())
if (maybeTypes() && !maybeTypes()->empty())
return true;
freeze(constraints);
return false;
@ -880,7 +919,11 @@ HeapTypeSetKey::notEmpty(CompilerConstraintList *constraints)
bool
HeapTypeSetKey::knownSubset(CompilerConstraintList *constraints, const HeapTypeSetKey &other)
{
if (!actualTypes->isSubset(other.actualTypes))
if (!maybeTypes() || maybeTypes()->empty()) {
freeze(constraints);
return true;
}
if (!other.maybeTypes() || !maybeTypes()->isSubset(other.maybeTypes()))
return false;
freeze(constraints);
return true;
@ -898,10 +941,12 @@ TemporaryTypeSet::getSingleton()
JSObject *
HeapTypeSetKey::singleton(CompilerConstraintList *constraints)
{
if (actualTypes->baseFlags() != 0 || actualTypes->getObjectCount() != 1)
TypeSet *types = maybeTypes();
if (!types || types->baseFlags() != 0 || types->getObjectCount() != 1)
return nullptr;
JSObject *obj = actualTypes->getSingleObject(0);
JSObject *obj = types->getSingleObject(0);
if (obj)
freeze(constraints);
@ -912,9 +957,12 @@ HeapTypeSetKey::singleton(CompilerConstraintList *constraints)
bool
HeapTypeSetKey::needsBarrier(CompilerConstraintList *constraints)
{
bool result = actualTypes->unknownObject()
|| actualTypes->getObjectCount() > 0
|| actualTypes->hasAnyFlag(TYPE_FLAG_STRING);
TypeSet *types = maybeTypes();
if (!types)
return false;
bool result = types->unknownObject()
|| types->getObjectCount() > 0
|| types->hasAnyFlag(TYPE_FLAG_STRING);
if (!result)
freeze(constraints);
return result;
@ -946,7 +994,7 @@ class ConstraintDataFreezeObjectFlags
bool constraintHolds(JSContext *cx,
const HeapTypeSetKey &property, TemporaryTypeSet *expected)
{
return !invalidateOnNewObjectState(property.actualObject);
return !invalidateOnNewObjectState(property.object()->maybeType());
}
};
@ -955,22 +1003,16 @@ class ConstraintDataFreezeObjectFlags
bool
TypeObjectKey::hasFlags(CompilerConstraintList *constraints, TypeObjectFlags flags)
{
#ifdef JS_ION
JS_ASSERT(flags);
JSContext *cx = jit::GetIonContext()->cx;
TypeObject *type = isSingleObject() ? asSingleObject()->getType(cx) : asTypeObject();
if (!type)
MOZ_CRASH();
if (type->hasAnyFlags(flags))
return true;
if (TypeObject *type = maybeType()) {
if (type->hasAnyFlags(flags))
return true;
}
HeapTypeSetKey objectProperty = property(JSID_EMPTY);
constraints->add(IonAlloc()->new_<CompilerConstraintInstance<ConstraintDataFreezeObjectFlags> >(objectProperty, ConstraintDataFreezeObjectFlags(flags)));
return false;
#else
MOZ_CRASH();
#endif
}
bool
@ -1047,7 +1089,7 @@ class ConstraintDataFreezeObjectForNewScriptTemplate
bool constraintHolds(JSContext *cx,
const HeapTypeSetKey &property, TemporaryTypeSet *expected)
{
return !invalidateOnNewObjectState(property.actualObject);
return !invalidateOnNewObjectState(property.object()->maybeType());
}
};
@ -1073,7 +1115,7 @@ class ConstraintDataFreezeObjectForTypedArrayBuffer
bool constraintHolds(JSContext *cx,
const HeapTypeSetKey &property, TemporaryTypeSet *expected)
{
return !invalidateOnNewObjectState(property.actualObject);
return !invalidateOnNewObjectState(property.object()->maybeType());
}
};
@ -1170,7 +1212,7 @@ class ConstraintDataFreezeConfiguredProperty
}
}
return !property.actualTypes->configuredProperty();
return !property.maybeTypes()->configuredProperty();
}
};
@ -1179,7 +1221,7 @@ class ConstraintDataFreezeConfiguredProperty
bool
HeapTypeSetKey::configured(CompilerConstraintList *constraints, TypeObjectKey *type)
{
if (actualTypes->configuredProperty())
if (maybeTypes() && maybeTypes()->configuredProperty())
return true;
constraints->add(IonAlloc()->new_<CompilerConstraintInstance<ConstraintDataFreezeConfiguredProperty> >(*this, ConstraintDataFreezeConfiguredProperty(type)));
@ -1255,7 +1297,8 @@ TemporaryTypeSet::convertDoubleElements(CompilerConstraintList *constraints)
// double in their element types (as the conversion may render the type
// information incorrect), nor for non-array objects (as their elements
// may point to emptyObjectElements, which cannot be converted).
if (!property.actualTypes->hasType(Type::DoubleType()) ||
if (!property.maybeTypes() ||
!property.maybeTypes()->hasType(Type::DoubleType()) ||
type->clasp() != &ArrayObject::class_)
{
dontConvert = true;
@ -1763,15 +1806,9 @@ bool
types::ArrayPrototypeHasIndexedProperty(CompilerConstraintList *constraints,
HandleScript script)
{
#ifdef JS_ION
JSObject *proto = script->global().getOrCreateArrayPrototype(jit::GetIonContext()->cx);
if (!proto)
return true;
return PrototypeHasIndexedProperty(constraints, proto);
#else
MOZ_CRASH();
#endif
if (JSObject *proto = script->global().maybeGetArrayPrototype())
return PrototypeHasIndexedProperty(constraints, proto);
return true;
}
bool

View File

@ -177,8 +177,7 @@ namespace types {
class TypeCompartment;
class TypeSet;
struct TypeObjectKey;
class TypeObjectKey;
/*
* Information about a single concrete type. We pack this into a single word,
@ -543,6 +542,10 @@ class TypeSet
/* Mark this type set as representing a configured property. */
inline void setConfiguredProperty(ExclusiveContext *cx);
/* Get a list of all types in this set. */
typedef Vector<Type, 1, SystemAllocPolicy> TypeList;
bool enumerateTypes(TypeList *list);
/*
* Iterate through the objects in this set. getObjectCount overapproximates
* in the hash case (see SET_ARRAY_SIZE in jsinferinlines.h), and getObject
@ -1219,8 +1222,9 @@ typedef HashMap<AllocationSiteKey,ReadBarriered<TypeObject>,AllocationSiteKey,Sy
class HeapTypeSetKey;
/* Type set entry for either a JSObject with singleton type or a non-singleton TypeObject. */
struct TypeObjectKey {
// Type set entry for either a JSObject with singleton type or a non-singleton TypeObject.
struct TypeObjectKey
{
static intptr_t keyBits(TypeObjectKey *obj) { return (intptr_t) obj; }
static TypeObjectKey *getKey(TypeObjectKey *obj) { return obj; }
@ -1259,14 +1263,40 @@ struct TypeObjectKey {
void watchStateChangeForInlinedCall(CompilerConstraintList *constraints);
void watchStateChangeForNewScriptTemplate(CompilerConstraintList *constraints);
void watchStateChangeForTypedArrayBuffer(CompilerConstraintList *constraints);
HeapTypeSetKey property(jsid id);
HeapTypeSetKey property(jsid id, JSContext *maybecx = NULL);
TypeObject *maybeType();
};
// Representation of a heap type property which may or may not be instantiated.
// Heap properties for singleton types are instantiated lazily as they are used
// by the compiler, but this is only done on the main thread. If we are
// compiling off thread and use a property which has not yet been instantiated,
// it will be treated as empty and non-configured and will be instantiated when
// rejoining to the main thread. If it is in fact not empty, the compilation
// will fail; to avoid this, we try to instantiate singleton property types
// during generation of baseline caches.
class HeapTypeSetKey
{
friend class TypeObjectKey;
// Object and property being accessed.
TypeObjectKey *object_;
jsid id_;
// If instantiated, the underlying heap type set.
HeapTypeSet *maybeTypes_;
public:
TypeObject *actualObject;
HeapTypeSet *actualTypes;
HeapTypeSetKey()
: object_(NULL), id_(JSID_EMPTY), maybeTypes_(NULL)
{}
TypeObjectKey *object() const { return object_; }
jsid id() const { return id_; }
HeapTypeSet *maybeTypes() const { return maybeTypes_; }
bool instantiate(JSContext *cx);
void freeze(CompilerConstraintList *constraints);
JSValueType knownTypeTag(CompilerConstraintList *constraints);

View File

@ -422,16 +422,19 @@ TrackPropertyTypes(ExclusiveContext *cx, JSObject *obj, jsid id)
inline void
EnsureTrackPropertyTypes(JSContext *cx, JSObject *obj, jsid id)
{
JS_ASSERT(!obj->hasLazyType());
if (!cx->typeInferenceEnabled() || obj->type()->unknownProperties())
if (!cx->typeInferenceEnabled())
return;
id = IdToTypeId(id);
if (obj->hasSingletonType()) {
AutoEnterAnalysis enter(cx);
obj->type()->getProperty(cx, id);
if (obj->hasLazyType() && !obj->getType(cx)) {
cx->compartment()->types.setPendingNukeTypes(cx);
return;
}
if (!obj->type()->unknownProperties())
obj->type()->getProperty(cx, id);
}
JS_ASSERT(obj->type()->unknownProperties() || TrackPropertyTypes(cx, obj, id));

View File

@ -1557,7 +1557,7 @@ js_NewGenerator(JSContext *cx, const FrameRegs &stackRegs)
RootedObject fun(cx, stackfp->fun());
// FIXME: This would be faster if we could avoid doing a lookup to get
// the prototype for the instance. Bug 906600.
if (!JSObject::getProperty(cx, fun, fun, cx->names().classPrototype, &pval))
if (!JSObject::getProperty(cx, fun, fun, cx->names().prototype, &pval))
return nullptr;
JSObject *proto = pval.isObject() ? &pval.toObject() : nullptr;
if (!proto) {
@ -1949,8 +1949,8 @@ GlobalObject::initIteratorClasses(JSContext *cx, Handle<GlobalObject *> global)
return false;
global->setSlot(STAR_GENERATOR_OBJECT_PROTO, ObjectValue(*genObjectProto));
global->setSlot(JSProto_GeneratorFunction, ObjectValue(*genFunction));
global->setSlot(JSProto_GeneratorFunction + JSProto_LIMIT, ObjectValue(*genFunctionProto));
global->setConstructor(JSProto_GeneratorFunction, ObjectValue(*genFunction));
global->setPrototype(JSProto_GeneratorFunction, ObjectValue(*genFunctionProto));
}
if (global->getPrototype(JSProto_StopIteration).isUndefined()) {
@ -1962,7 +1962,7 @@ GlobalObject::initIteratorClasses(JSContext *cx, Handle<GlobalObject *> global)
if (!DefineConstructorAndPrototype(cx, global, JSProto_StopIteration, proto, proto))
return false;
MarkStandardClassInitializedNoProto(global, &StopIterationObject::class_);
global->markStandardClassInitializedNoProto(&StopIterationObject::class_);
}
return true;

View File

@ -1495,7 +1495,7 @@ js_InitMathClass(JSContext *cx, HandleObject obj)
if (!JS_DefineConstDoubles(cx, Math, math_constants))
return nullptr;
MarkStandardClassInitializedNoProto(obj, &MathClass);
obj->as<GlobalObject>().markStandardClassInitializedNoProto(&MathClass);
return Math;
}

View File

@ -1309,7 +1309,7 @@ NewObject(ExclusiveContext *cx, const Class *clasp, types::TypeObject *type_, JS
#endif
}
Probes::createObject(cx, obj);
probes::CreateObject(cx, obj);
return obj;
}
@ -1543,7 +1543,7 @@ JSObject*
js::CreateThis(JSContext *cx, const Class *newclasp, HandleObject callee)
{
RootedValue protov(cx);
if (!JSObject::getProperty(cx, callee, callee, cx->names().classPrototype, &protov))
if (!JSObject::getProperty(cx, callee, callee, cx->names().prototype, &protov))
return nullptr;
JSObject *proto = protov.isObjectOrNull() ? protov.toObjectOrNull() : nullptr;
@ -1608,7 +1608,7 @@ JSObject *
js::CreateThisForFunction(JSContext *cx, HandleObject callee, bool newType)
{
RootedValue protov(cx);
if (!JSObject::getProperty(cx, callee, callee, cx->names().classPrototype, &protov))
if (!JSObject::getProperty(cx, callee, callee, cx->names().prototype, &protov))
return nullptr;
JSObject *proto;
if (protov.isObject())
@ -2186,8 +2186,9 @@ DefineStandardSlot(JSContext *cx, HandleObject obj, JSProtoKey key, JSAtom *atom
JS_ASSERT(obj->isNative());
if (!obj->nativeLookup(cx, id)) {
uint32_t slot = 2 * JSProto_LIMIT + key;
obj->setReservedSlot(slot, v);
obj->as<GlobalObject>().setConstructorPropertySlot(key, v);
uint32_t slot = GlobalObject::constructorPropertySlot(key);
if (!JSObject::addProperty(cx, obj, id, JS_PropertyStub, JS_StrictPropertyStub, slot, attrs, 0, 0))
return false;
AddTypePropertyId(cx, obj, id, v);
@ -2209,8 +2210,8 @@ SetClassObject(JSObject *obj, JSProtoKey key, JSObject *cobj, JSObject *proto)
if (!obj->is<GlobalObject>())
return;
obj->setReservedSlot(key, ObjectOrNullValue(cobj));
obj->setReservedSlot(JSProto_LIMIT + key, ObjectOrNullValue(proto));
obj->as<GlobalObject>().setConstructor(key, ObjectOrNullValue(cobj));
obj->as<GlobalObject>().setPrototype(key, ObjectOrNullValue(proto));
}
static void
@ -2220,8 +2221,8 @@ ClearClassObject(JSObject *obj, JSProtoKey key)
if (!obj->is<GlobalObject>())
return;
obj->setSlot(key, UndefinedValue());
obj->setSlot(JSProto_LIMIT + key, UndefinedValue());
obj->as<GlobalObject>().setConstructor(key, UndefinedValue());
obj->as<GlobalObject>().setPrototype(key, UndefinedValue());
}
JSObject *
@ -2361,37 +2362,6 @@ bad:
return nullptr;
}
/*
* Lazy standard classes need a way to indicate if they have been initialized.
* Otherwise, when we delete them, we might accidentally recreate them via a
* lazy initialization. We use the presence of a ctor or proto in the
* global object's slot to indicate that they've been constructed, but this only
* works for classes which have a proto and ctor. Classes which don't have one
* can call MarkStandardClassInitializedNoProto(), and we can always check
* whether a class is initialized by calling IsStandardClassResolved().
*/
bool
js::IsStandardClassResolved(JSObject *obj, const js::Class *clasp)
{
JSProtoKey key = JSCLASS_CACHED_PROTO_KEY(clasp);
/* If the constructor is undefined, then it hasn't been initialized. */
return (obj->getReservedSlot(key) != UndefinedValue());
}
void
js::MarkStandardClassInitializedNoProto(JSObject *obj, const js::Class *clasp)
{
JSProtoKey key = JSCLASS_CACHED_PROTO_KEY(clasp);
/*
* We use True so that it's obvious what we're doing (instead of, say,
* Null, which might be miscontrued as an error in setting Undefined).
*/
if (obj->getReservedSlot(key) == UndefinedValue())
obj->setSlot(key, BooleanValue(true));
}
JSObject *
js_InitClass(JSContext *cx, HandleObject obj, JSObject *protoProto_,
const Class *clasp, Native constructor, unsigned nargs,
@ -3044,13 +3014,9 @@ js::SetClassAndProto(JSContext *cx, HandleObject obj,
bool
js_GetClassObject(ExclusiveContext *cxArg, JSObject *obj, JSProtoKey key, MutableHandleObject objp)
{
RootedObject global(cxArg, &obj->global());
if (!global->is<GlobalObject>()) {
objp.set(nullptr);
return true;
}
Rooted<GlobalObject*> global(cxArg, &obj->global());
Value v = global->getReservedSlot(key);
Value v = global->getConstructor(key);
if (v.isObject()) {
objp.set(&v.toObject());
return true;
@ -3074,7 +3040,7 @@ js_GetClassObject(ExclusiveContext *cxArg, JSObject *obj, JSProtoKey key, Mutabl
if (ClassInitializerOp init = lazy_prototype_init[key]) {
if (!init(cx, global))
return false;
v = global->getReservedSlot(key);
v = global->getConstructor(key);
if (v.isObject())
cobj = &v.toObject();
}
@ -3097,8 +3063,8 @@ js_IdentifyClassPrototype(JSObject *obj)
//
// Note that standard class objects are cached in the range [0, JSProto_LIMIT),
// and the prototypes are cached in [JSProto_LIMIT, 2*JSProto_LIMIT).
JSObject &global = obj->global();
Value v = global.getReservedSlot(JSProto_LIMIT + key);
GlobalObject &global = obj->global();
Value v = global.getPrototype(key);
if (v.isObject() && obj == &v.toObject())
return key;
@ -5239,7 +5205,7 @@ js::GetClassPrototypePure(GlobalObject *global, JSProtoKey protoKey)
JS_ASSERT(protoKey < JSProto_LIMIT);
if (protoKey != JSProto_Null) {
const Value &v = global->getReservedSlot(JSProto_LIMIT + protoKey);
const Value &v = global->getPrototype(protoKey);
if (v.isObject())
return &v.toObject();
}
@ -5268,12 +5234,12 @@ js_GetClassPrototype(ExclusiveContext *cx, JSProtoKey protoKey,
RootedObject ctor(cx, &v.get().toObject());
if (cx->isJSContext()) {
if (!JSObject::getProperty(cx->asJSContext(),
ctor, ctor, cx->names().classPrototype, &v))
ctor, ctor, cx->names().prototype, &v))
{
return false;
}
} else {
Shape *shape = ctor->nativeLookup(cx, cx->names().classPrototype);
Shape *shape = ctor->nativeLookup(cx, cx->names().prototype);
if (!shape || !NativeGetPureInline(ctor, shape, v.address()))
return false;
}

View File

@ -1251,12 +1251,6 @@ HasOwnProperty(JSContext *cx, LookupGenericOp lookup,
typename MaybeRooted<JSObject*, allowGC>::MutableHandleType objp,
typename MaybeRooted<Shape*, allowGC>::MutableHandleType propp);
bool
IsStandardClassResolved(JSObject *obj, const js::Class *clasp);
void
MarkStandardClassInitializedNoProto(JSObject *obj, const js::Class *clasp);
typedef JSObject *(*ClassInitializerOp)(JSContext *cx, JS::HandleObject obj);
} /* namespace js */

View File

@ -75,7 +75,7 @@ JSObject::deleteSpecial(JSContext *cx, js::HandleObject obj, js::HandleSpecialId
inline void
JSObject::finalize(js::FreeOp *fop)
{
js::Probes::finalizeObject(this);
js::probes::FinalizeObject(this);
#ifdef DEBUG
JS_ASSERT(isTenured());
@ -936,15 +936,15 @@ DefineConstructorAndPrototype(JSContext *cx, Handle<GlobalObject*> global,
JS_ASSERT(!global->nativeLookup(cx, id));
/* Set these first in case AddTypePropertyId looks for this class. */
global->setSlot(key, ObjectValue(*ctor));
global->setSlot(key + JSProto_LIMIT, ObjectValue(*proto));
global->setSlot(key + JSProto_LIMIT * 2, ObjectValue(*ctor));
global->setConstructor(key, ObjectValue(*ctor));
global->setPrototype(key, ObjectValue(*proto));
global->setConstructorPropertySlot(key, ObjectValue(*ctor));
types::AddTypePropertyId(cx, global, id, ObjectValue(*ctor));
if (!global->addDataProperty(cx, id, key + JSProto_LIMIT * 2, 0)) {
global->setSlot(key, UndefinedValue());
global->setSlot(key + JSProto_LIMIT, UndefinedValue());
global->setSlot(key + JSProto_LIMIT * 2, UndefinedValue());
if (!global->addDataProperty(cx, id, GlobalObject::constructorPropertySlot(key), 0)) {
global->setConstructor(key, UndefinedValue());
global->setPrototype(key, UndefinedValue());
global->setConstructorPropertySlot(key, UndefinedValue());
return false;
}

View File

@ -886,7 +886,7 @@ js_InitJSONClass(JSContext *cx, HandleObject obj)
if (!JS_DefineFunctions(cx, JSON, json_static_methods))
return nullptr;
MarkStandardClassInitializedNoProto(global, &JSONClass);
global->markStandardClassInitializedNoProto(&JSONClass);
return JSON;
}

View File

@ -3293,7 +3293,7 @@ static const JSFunctionSpec static_methods[] = {
JS_FRIEND_API(JSObject *)
js_InitProxyClass(JSContext *cx, HandleObject obj)
{
Rooted<GlobalObject*> global(cx);
Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
RootedFunction ctor(cx);
ctor = global->createConstructor(cx, proxy, cx->names().Proxy, 2);
if (!ctor)
@ -3306,6 +3306,6 @@ js_InitProxyClass(JSContext *cx, HandleObject obj)
return nullptr;
}
MarkStandardClassInitializedNoProto(obj, &ProxyObject::uncallableClass_);
global->markStandardClassInitializedNoProto(&ProxyObject::uncallableClass_);
return ctor;
}

View File

@ -4870,7 +4870,7 @@ dom_constructor(JSContext* cx, unsigned argc, JS::Value *vp)
RootedObject callee(cx, &args.callee());
RootedValue protov(cx);
if (!JSObject::getProperty(cx, callee, callee, cx->names().classPrototype, &protov))
if (!JSObject::getProperty(cx, callee, callee, cx->names().prototype, &protov))
return false;
if (!protov.isObject()) {

View File

@ -27,7 +27,6 @@
macro(caller, caller, "caller") \
macro(callFunction, callFunction, "callFunction") \
macro(caseFirst, caseFirst, "caseFirst") \
macro(classPrototype, classPrototype, "prototype") \
macro(Collator, Collator, "Collator") \
macro(CollatorCompareGet, CollatorCompareGet, "Intl_Collator_compare_get") \
macro(columnNumber, columnNumber, "columnNumber") \
@ -124,6 +123,7 @@
macro(preventExtensions, preventExtensions, "preventExtensions") \
macro(propertyIsEnumerable, propertyIsEnumerable, "propertyIsEnumerable") \
macro(proto, proto, "__proto__") \
macro(prototype, prototype, "prototype") \
macro(return, return_, "return") \
macro(sensitivity, sensitivity, "sensitivity") \
macro(set, set, "set") \

View File

@ -2087,7 +2087,7 @@ Debugger::construct(JSContext *cx, unsigned argc, Value *vp)
/* Get Debugger.prototype. */
RootedValue v(cx);
RootedObject callee(cx, &args.callee());
if (!JSObject::getProperty(cx, callee, callee, cx->names().classPrototype, &v))
if (!JSObject::getProperty(cx, callee, callee, cx->names().prototype, &v))
return false;
RootedObject proto(cx, &v.toObject());
JS_ASSERT(proto->getClass() == &Debugger::jsclass);

View File

@ -361,9 +361,9 @@ GlobalObject::initFunctionAndObjectClasses(JSContext *cx)
}
/* Add the global Function and Object properties now. */
if (!self->addDataProperty(cx, cx->names().Object, JSProto_Object + JSProto_LIMIT * 2, 0))
if (!self->addDataProperty(cx, cx->names().Object, constructorPropertySlot(JSProto_Object), 0))
return nullptr;
if (!self->addDataProperty(cx, cx->names().Function, JSProto_Function + JSProto_LIMIT * 2, 0))
if (!self->addDataProperty(cx, cx->names().Function, constructorPropertySlot(JSProto_Function), 0))
return nullptr;
/* Heavy lifting done, but lingering tasks remain. */
@ -551,7 +551,7 @@ js::LinkConstructorAndPrototype(JSContext *cx, JSObject *ctor_, JSObject *proto_
RootedValue protoVal(cx, ObjectValue(*proto));
RootedValue ctorVal(cx, ObjectValue(*ctor));
return JSObject::defineProperty(cx, ctor, cx->names().classPrototype,
return JSObject::defineProperty(cx, ctor, cx->names().prototype,
protoVal, JS_PropertyStub, JS_StrictPropertyStub,
JSPROP_PERMANENT | JSPROP_READONLY) &&
JSObject::defineProperty(cx, proto, cx->names().constructor,

View File

@ -35,31 +35,39 @@ class Debugger;
/*
* Global object slots are reserved as follows:
*
* [0, JSProto_LIMIT)
* [0, APPLICATION_SLOTS)
* Pre-reserved slots in all global objects set aside for the embedding's
* use. As with all reserved slots these start out as UndefinedValue() and
* are traced for GC purposes. Apart from that the engine never touches
* these slots, so the embedding can do whatever it wants with them.
* [APPLICATION_SLOTS, APPLICATION_SLOTS + JSProto_LIMIT)
* Stores the original value of the constructor for the corresponding
* JSProtoKey.
* [JSProto_LIMIT, 2 * JSProto_LIMIT)
* [APPLICATION_SLOTS + JSProto_LIMIT, APPLICATION_SLOTS + 2 * JSProto_LIMIT)
* Stores the prototype, if any, for the constructor for the corresponding
* JSProtoKey offset from JSProto_LIMIT.
* [2 * JSProto_LIMIT, 3 * JSProto_LIMIT)
* [APPLICATION_SLOTS + 2 * JSProto_LIMIT, APPLICATION_SLOTS + 3 * JSProto_LIMIT)
* Stores the current value of the global property named for the JSProtoKey
* for the corresponding JSProtoKey offset from 2 * JSProto_LIMIT.
* [3 * JSProto_LIMIT, RESERVED_SLOTS)
* [APPLICATION_SLOTS + 3 * JSProto_LIMIT, RESERVED_SLOTS)
* Various one-off values: ES5 13.2.3's [[ThrowTypeError]], RegExp statics,
* the original eval for this global object (implementing |var eval =
* otherWindow.eval; eval(...)| as an indirect eval), a bit indicating
* whether this object has been cleared (see JS_ClearScope), and a cache for
* whether eval is allowed (per the global's Content Security Policy).
*
* The first two ranges are necessary to implement js::FindClassObject,
* and spec language speaking in terms of "the original Array prototype
* object", or "as if by the expression new Array()" referring to the original
* Array constructor. The third range stores the (writable and even deletable)
* Object, Array, &c. properties (although a slot won't be used again if its
* property is deleted and readded).
* The first two JSProto_LIMIT-sized ranges are necessary to implement
* js::FindClassObject, and spec language speaking in terms of "the original
* Array prototype object", or "as if by the expression new Array()" referring
* to the original Array constructor. The third range stores the (writable and
* even deletable) Object, Array, &c. properties (although a slot won't be used
* again if its property is deleted and readded).
*/
class GlobalObject : public JSObject
{
/* Count of slots set aside for application use. */
static const unsigned APPLICATION_SLOTS = 3;
/*
* Count of slots to store built-in constructors, prototypes, and initial
* visible properties for the constructors.
@ -67,7 +75,7 @@ class GlobalObject : public JSObject
static const unsigned STANDARD_CLASS_SLOTS = JSProto_LIMIT * 3;
/* Various function values needed by the engine. */
static const unsigned EVAL = STANDARD_CLASS_SLOTS;
static const unsigned EVAL = APPLICATION_SLOTS + STANDARD_CLASS_SLOTS;
static const unsigned CREATE_DATAVIEW_FOR_THIS = EVAL + 1;
static const unsigned THROWTYPEERROR = CREATE_DATAVIEW_FOR_THIS + 1;
static const unsigned PROTO_GETTER = THROWTYPEERROR + 1;
@ -122,23 +130,6 @@ class GlobalObject : public JSObject
JSObject *
initFunctionAndObjectClasses(JSContext *cx);
void setDetailsForKey(JSProtoKey key, JSObject *ctor, JSObject *proto) {
JS_ASSERT(getSlotRef(key).isUndefined());
JS_ASSERT(getSlotRef(JSProto_LIMIT + key).isUndefined());
JS_ASSERT(getSlotRef(2 * JSProto_LIMIT + key).isUndefined());
setSlot(key, ObjectValue(*ctor));
setSlot(JSProto_LIMIT + key, ObjectValue(*proto));
setSlot(2 * JSProto_LIMIT + key, ObjectValue(*ctor));
}
void setObjectClassDetails(JSFunction *ctor, JSObject *proto) {
setDetailsForKey(JSProto_Object, ctor, proto);
}
void setFunctionClassDetails(JSFunction *ctor, JSObject *proto) {
setDetailsForKey(JSProto_Function, ctor, proto);
}
void setThrowTypeError(JSFunction *fun) {
JS_ASSERT(getSlotRef(THROWTYPEERROR).isUndefined());
setSlot(THROWTYPEERROR, ObjectValue(*fun));
@ -159,14 +150,38 @@ class GlobalObject : public JSObject
setSlot(INTRINSICS, ObjectValue(*obj));
}
public:
Value getConstructor(JSProtoKey key) const {
JS_ASSERT(key <= JSProto_LIMIT);
return getSlot(key);
return getSlot(APPLICATION_SLOTS + key);
}
void setConstructor(JSProtoKey key, const Value &v) {
JS_ASSERT(key <= JSProto_LIMIT);
setSlot(APPLICATION_SLOTS + key, v);
}
Value getPrototype(JSProtoKey key) const {
JS_ASSERT(key <= JSProto_LIMIT);
return getSlot(JSProto_LIMIT + key);
return getSlot(APPLICATION_SLOTS + JSProto_LIMIT + key);
}
void setPrototype(JSProtoKey key, const Value &value) {
JS_ASSERT(key <= JSProto_LIMIT);
setSlot(APPLICATION_SLOTS + JSProto_LIMIT + key, value);
}
static uint32_t constructorPropertySlot(JSProtoKey key) {
JS_ASSERT(key <= JSProto_LIMIT);
return APPLICATION_SLOTS + JSProto_LIMIT * 2 + key;
}
Value getConstructorPropertySlot(JSProtoKey key) {
return getSlot(constructorPropertySlot(key));
}
void setConstructorPropertySlot(JSProtoKey key, const Value &ctor) {
setSlot(constructorPropertySlot(key), ctor);
}
bool classIsInitialized(JSProtoKey key) const {
@ -181,6 +196,50 @@ class GlobalObject : public JSObject
return inited;
}
/*
* Lazy standard classes need a way to indicate they have been initialized.
* Otherwise, when we delete them, we might accidentally recreate them via
* a lazy initialization. We use the presence of a ctor or proto in the
* global object's slot to indicate that they've been constructed, but this
* only works for classes which have a proto and ctor. Classes which don't
* have one can call markStandardClassInitializedNoProto(), and we can
* always check whether a class is initialized by calling
* isStandardClassResolved().
*/
bool isStandardClassResolved(const js::Class *clasp) const {
JSProtoKey key = JSCLASS_CACHED_PROTO_KEY(clasp);
// If the constructor is undefined, then it hasn't been initialized.
return !getConstructor(key).isUndefined();
}
void markStandardClassInitializedNoProto(const js::Class *clasp) {
JSProtoKey key = JSCLASS_CACHED_PROTO_KEY(clasp);
// We use true so that it's obvious what we're doing (instead of, say,
// null, which might be miscontrued as an error in setting Undefined).
if (getConstructor(key).isUndefined())
setConstructor(key, BooleanValue(true));
}
private:
void setDetailsForKey(JSProtoKey key, JSObject *ctor, JSObject *proto) {
JS_ASSERT(getConstructor(key).isUndefined());
JS_ASSERT(getPrototype(key).isUndefined());
JS_ASSERT(getConstructorPropertySlot(key).isUndefined());
setConstructor(key, ObjectValue(*ctor));
setPrototype(key, ObjectValue(*proto));
setConstructorPropertySlot(key, ObjectValue(*ctor));
}
void setObjectClassDetails(JSFunction *ctor, JSObject *proto) {
setDetailsForKey(JSProto_Object, ctor, proto);
}
void setFunctionClassDetails(JSFunction *ctor, JSObject *proto) {
setDetailsForKey(JSProto_Function, ctor, proto);
}
bool arrayClassInitialized() const {
return classIsInitialized(JSProto_Array);
}
@ -287,6 +346,12 @@ class GlobalObject : public JSObject
return &self->getPrototype(JSProto_Array).toObject();
}
JSObject *maybeGetArrayPrototype() {
if (arrayClassInitialized())
return &getPrototype(JSProto_Array).toObject();
return NULL;
}
JSObject *getOrCreateBooleanPrototype(JSContext *cx) {
if (booleanClassInitialized())
return &getPrototype(JSProto_Boolean).toObject();
@ -343,7 +408,24 @@ class GlobalObject : public JSObject
}
JSObject *getOrCreateIntlObject(JSContext *cx) {
return getOrCreateObject(cx, JSProto_Intl, initIntlObject);
return getOrCreateObject(cx, APPLICATION_SLOTS + JSProto_Intl, initIntlObject);
}
JSObject *getIteratorPrototype() {
return &getPrototype(JSProto_Iterator).toObject();
}
JSObject *getOrCreateDataObject(JSContext *cx) {
return getOrCreateObject(cx, APPLICATION_SLOTS + JSProto_Data, initDataObject);
}
JSObject *getOrCreateTypeObject(JSContext *cx) {
return getOrCreateObject(cx, APPLICATION_SLOTS + JSProto_Type, initTypeObject);
}
JSObject *getOrCreateArrayTypeObject(JSContext *cx) {
return getOrCreateObject(cx, APPLICATION_SLOTS + JSProto_ArrayTypeObject,
initArrayTypeObject);
}
JSObject *getOrCreateCollatorPrototype(JSContext *cx) {
@ -358,22 +440,6 @@ class GlobalObject : public JSObject
return getOrCreateObject(cx, DATE_TIME_FORMAT_PROTO, initDateTimeFormatProto);
}
JSObject *getIteratorPrototype() {
return &getPrototype(JSProto_Iterator).toObject();
}
JSObject *getOrCreateDataObject(JSContext *cx) {
return getOrCreateObject(cx, JSProto_Data, initDataObject);
}
JSObject *getOrCreateTypeObject(JSContext *cx) {
return getOrCreateObject(cx, JSProto_Type, initTypeObject);
}
JSObject *getOrCreateArrayTypeObject(JSContext *cx) {
return getOrCreateObject(cx, JSProto_ArrayTypeObject, initArrayTypeObject);
}
private:
typedef bool (*ObjectInitOp)(JSContext *cx, Handle<GlobalObject*> global);
@ -389,7 +455,8 @@ class GlobalObject : public JSObject
public:
JSObject *getOrCreateIteratorPrototype(JSContext *cx) {
return getOrCreateObject(cx, JSProto_LIMIT + JSProto_Iterator, initIteratorClasses);
return getOrCreateObject(cx, APPLICATION_SLOTS + JSProto_LIMIT + JSProto_Iterator,
initIteratorClasses);
}
JSObject *getOrCreateElementIteratorPrototype(JSContext *cx) {
@ -405,12 +472,13 @@ class GlobalObject : public JSObject
}
JSObject *getOrCreateStarGeneratorFunctionPrototype(JSContext *cx) {
return getOrCreateObject(cx, JSProto_LIMIT + JSProto_GeneratorFunction,
return getOrCreateObject(cx, APPLICATION_SLOTS + JSProto_LIMIT + JSProto_GeneratorFunction,
initIteratorClasses);
}
JSObject *getOrCreateStarGeneratorFunction(JSContext *cx) {
return getOrCreateObject(cx, JSProto_GeneratorFunction, initIteratorClasses);
return getOrCreateObject(cx, APPLICATION_SLOTS + JSProto_GeneratorFunction,
initIteratorClasses);
}
JSObject *getOrCreateMapIteratorPrototype(JSContext *cx) {

View File

@ -606,10 +606,10 @@ js::ExecuteKernel(JSContext *cx, HandleScript script, JSObject &scopeChainArg, c
TypeScript::SetThis(cx, script, thisv);
Probes::startExecution(script);
probes::StartExecution(script);
ExecuteState state(cx, script, thisv, scopeChainArg, type, evalInFrame, result);
bool ok = RunScript(cx, state);
Probes::stopExecution(script);
probes::StopExecution(script);
return ok;
}
@ -1335,7 +1335,7 @@ Interpret(JSContext *cx, RunState &state)
* fail if cx->isExceptionPending() is true.
*/
if (cx->isExceptionPending()) {
Probes::enterScript(cx, script, script->function(), regs.fp());
probes::EnterScript(cx, script, script->function(), regs.fp());
goto error;
}
}
@ -1347,7 +1347,7 @@ Interpret(JSContext *cx, RunState &state)
if (!entryFrame->prologue(cx))
goto error;
} else {
Probes::enterScript(cx, script, script->function(), entryFrame);
probes::EnterScript(cx, script, script->function(), entryFrame);
}
if (cx->compartment()->debugMode()) {
JSTrapStatus status = ScriptDebugPrologue(cx, entryFrame);
@ -1623,7 +1623,7 @@ BEGIN_CASE(JSOP_STOP)
if (!regs.fp()->isYielding())
regs.fp()->epilogue(cx);
else
Probes::exitScript(cx, script, script->function(), regs.fp());
probes::ExitScript(cx, script, script->function(), regs.fp());
#if defined(JS_ION)
jit_return_pop_frame:
@ -3401,7 +3401,7 @@ default:
if (!regs.fp()->isYielding())
regs.fp()->epilogue(cx);
else
Probes::exitScript(cx, script, script->function(), regs.fp());
probes::ExitScript(cx, script, script->function(), regs.fp());
gc::MaybeVerifyBarriers(cx, true);

View File

@ -19,7 +19,7 @@ namespace js {
*/
inline bool
Probes::callTrackingActive(JSContext *cx)
probes::CallTrackingActive(JSContext *cx)
{
#ifdef INCLUDE_MOZILLA_DTRACE
if (JAVASCRIPT_FUNCTION_ENTRY_ENABLED() || JAVASCRIPT_FUNCTION_RETURN_ENABLED())
@ -33,14 +33,14 @@ Probes::callTrackingActive(JSContext *cx)
}
inline bool
Probes::wantNativeAddressInfo(JSContext *cx)
probes::WantNativeAddressInfo(JSContext *cx)
{
return (cx->reportGranularity >= JITREPORT_GRANULARITY_FUNCTION &&
JITGranularityRequested(cx) >= JITREPORT_GRANULARITY_FUNCTION);
}
inline bool
Probes::enterScript(JSContext *cx, JSScript *script, JSFunction *maybeFun,
probes::EnterScript(JSContext *cx, JSScript *script, JSFunction *maybeFun,
StackFrame *fp)
{
bool ok = true;
@ -63,7 +63,7 @@ Probes::enterScript(JSContext *cx, JSScript *script, JSFunction *maybeFun,
}
inline bool
Probes::exitScript(JSContext *cx, JSScript *script, JSFunction *maybeFun,
probes::ExitScript(JSContext *cx, JSScript *script, JSFunction *maybeFun,
AbstractFramePtr fp)
{
bool ok = true;
@ -88,14 +88,14 @@ Probes::exitScript(JSContext *cx, JSScript *script, JSFunction *maybeFun,
}
inline bool
Probes::exitScript(JSContext *cx, JSScript *script, JSFunction *maybeFun,
probes::ExitScript(JSContext *cx, JSScript *script, JSFunction *maybeFun,
StackFrame *fp)
{
return Probes::exitScript(cx, script, maybeFun, fp ? AbstractFramePtr(fp) : AbstractFramePtr());
return probes::ExitScript(cx, script, maybeFun, fp ? AbstractFramePtr(fp) : AbstractFramePtr());
}
inline bool
Probes::startExecution(JSScript *script)
probes::StartExecution(JSScript *script)
{
bool ok = true;
@ -109,7 +109,7 @@ Probes::startExecution(JSScript *script)
}
inline bool
Probes::stopExecution(JSScript *script)
probes::StopExecution(JSScript *script)
{
bool ok = true;

View File

@ -16,13 +16,13 @@
using namespace js;
const char Probes::nullName[] = "(null)";
const char Probes::anonymousName[] = "(anonymous)";
const char probes::nullName[] = "(null)";
const char probes::anonymousName[] = "(anonymous)";
bool Probes::ProfilingActive = true;
bool probes::ProfilingActive = true;
Probes::JITReportGranularity
Probes::JITGranularityRequested(JSContext *cx)
probes::JITReportGranularity
probes::JITGranularityRequested(JSContext *cx)
{
if (cx->runtime()->spsProfiler.enabled())
return JITREPORT_GRANULARITY_LINE;
@ -31,7 +31,7 @@ Probes::JITGranularityRequested(JSContext *cx)
/* ICs are unregistered in a batch */
void
Probes::discardExecutableRegion(void *start, size_t size)
probes::DiscardExecutableRegion(void *start, size_t size)
{
/*
* Not needed for SPS because ICs are disposed of when the normal JITChunk
@ -44,9 +44,9 @@ static const char *
ScriptFilename(const JSScript *script)
{
if (!script)
return Probes::nullName;
return probes::nullName;
if (!script->filename())
return Probes::anonymousName;
return probes::anonymousName;
return script->filename();
}
@ -54,10 +54,10 @@ static const char *
FunctionName(JSContext *cx, JSFunction *fun, JSAutoByteString* bytes)
{
if (!fun)
return Probes::nullName;
return probes::nullName;
if (!fun->displayAtom())
return Probes::anonymousName;
return bytes->encodeLatin1(cx, fun->displayAtom()) ? bytes->ptr() : Probes::nullName;
return probes::anonymousName;
return bytes->encodeLatin1(cx, fun->displayAtom()) ? bytes->ptr() : probes::nullName;
}
/*
@ -68,18 +68,18 @@ FunctionName(JSContext *cx, JSFunction *fun, JSAutoByteString* bytes)
* a number of usually unused lines of code would cause.
*/
void
Probes::DTraceEnterJSFun(JSContext *cx, JSFunction *fun, JSScript *script)
probes::DTraceEnterJSFun(JSContext *cx, JSFunction *fun, JSScript *script)
{
JSAutoByteString funNameBytes;
JAVASCRIPT_FUNCTION_ENTRY(ScriptFilename(script), Probes::nullName,
JAVASCRIPT_FUNCTION_ENTRY(ScriptFilename(script), probes::nullName,
FunctionName(cx, fun, &funNameBytes));
}
void
Probes::DTraceExitJSFun(JSContext *cx, JSFunction *fun, JSScript *script)
probes::DTraceExitJSFun(JSContext *cx, JSFunction *fun, JSScript *script)
{
JSAutoByteString funNameBytes;
JAVASCRIPT_FUNCTION_RETURN(ScriptFilename(script), Probes::nullName,
JAVASCRIPT_FUNCTION_RETURN(ScriptFilename(script), probes::nullName,
FunctionName(cx, fun, &funNameBytes));
}
#endif

View File

@ -15,13 +15,13 @@
namespace js {
namespace Probes {
namespace probes {
/*
* Static probes
*
* The probe points defined in this file are scattered around the SpiderMonkey
* source tree. The presence of Probes::someEvent() means that someEvent is
* source tree. The presence of probes::SomeEvent() means that someEvent is
* about to happen or has happened. To the extent possible, probes should be
* inserted in all paths associated with a given event, regardless of the
* active runmode (interpreter/traceJIT/methodJIT/ionJIT).
@ -57,37 +57,37 @@ extern const char anonymousName[];
* to decide whether they can optimize in a way that would prevent probes from
* firing.
*/
bool callTrackingActive(JSContext *);
bool CallTrackingActive(JSContext *);
/*
* Test whether anything is looking for JIT native code registration events.
* This information will not be collected otherwise.
*/
bool wantNativeAddressInfo(JSContext *);
bool WantNativeAddressInfo(JSContext *);
/* Entering a JS function */
bool enterScript(JSContext *, JSScript *, JSFunction *, StackFrame *);
bool EnterScript(JSContext *, JSScript *, JSFunction *, StackFrame *);
/* About to leave a JS function */
bool exitScript(JSContext *, JSScript *, JSFunction *, AbstractFramePtr);
bool exitScript(JSContext *, JSScript *, JSFunction *, StackFrame *);
bool ExitScript(JSContext *, JSScript *, JSFunction *, AbstractFramePtr);
bool ExitScript(JSContext *, JSScript *, JSFunction *, StackFrame *);
/* Executing a script */
bool startExecution(JSScript *script);
bool StartExecution(JSScript *script);
/* Script has completed execution */
bool stopExecution(JSScript *script);
bool StopExecution(JSScript *script);
/*
* Object has been created. |obj| must exist (its class and size are read)
*/
bool createObject(ExclusiveContext *cx, JSObject *obj);
bool CreateObject(ExclusiveContext *cx, JSObject *obj);
/*
* Object is about to be finalized. |obj| must still exist (its class is
* read)
*/
bool finalizeObject(JSObject *obj);
bool FinalizeObject(JSObject *obj);
/* JIT code observation */
@ -109,11 +109,11 @@ JITGranularityRequested(JSContext *cx);
* (ICs are unregistered in a batch, so individual ICs are not registered.)
*/
void
discardExecutableRegion(void *start, size_t size);
DiscardExecutableRegion(void *start, size_t size);
/*
* Internal: DTrace-specific functions to be called during Probes::enterScript
* and Probes::exitScript. These will not be inlined, but the argument
* Internal: DTrace-specific functions to be called during probes::EnterScript
* and probes::ExitScript. These will not be inlined, but the argument
* marshalling required for these probe points is expensive enough that it
* shouldn't really matter.
*/
@ -137,7 +137,7 @@ static const char *ObjectClassname(JSObject *obj) {
#endif
inline bool
Probes::createObject(ExclusiveContext *cx, JSObject *obj)
probes::CreateObject(ExclusiveContext *cx, JSObject *obj)
{
bool ok = true;
@ -150,7 +150,7 @@ Probes::createObject(ExclusiveContext *cx, JSObject *obj)
}
inline bool
Probes::finalizeObject(JSObject *obj)
probes::FinalizeObject(JSObject *obj)
{
bool ok = true;

View File

@ -53,7 +53,7 @@ NewObjectCache::newObjectFromHit(JSContext *cx, EntryIndex entry_, js::gc::Initi
JSObject *obj = js_NewGCObject<NoGC>(cx, entry->kind, heap);
if (obj) {
copyCachedToObject(obj, templateObj, entry->kind);
Probes::createObject(cx, obj);
probes::CreateObject(cx, obj);
return obj;
}

View File

@ -142,7 +142,7 @@ intrinsic_MakeConstructible(JSContext *cx, unsigned argc, Value *vp)
// Normal .prototype properties aren't enumerable. But for this to clone
// correctly, it must be enumerable.
RootedObject ctor(cx, &args[0].toObject());
if (!JSObject::defineProperty(cx, ctor, cx->names().classPrototype, args[1],
if (!JSObject::defineProperty(cx, ctor, cx->names().prototype, args[1],
JS_PropertyStub, JS_StrictPropertyStub,
JSPROP_READONLY | JSPROP_ENUMERATE | JSPROP_PERMANENT))
{

Some files were not shown because too many files have changed in this diff Show More