mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge m-c to b2g-inbound.
This commit is contained in:
commit
c6e97adff4
2
CLOBBER
2
CLOBBER
@ -18,4 +18,4 @@
|
|||||||
# Modifying this file will now automatically clobber the buildbot machines \o/
|
# Modifying this file will now automatically clobber the buildbot machines \o/
|
||||||
#
|
#
|
||||||
|
|
||||||
Bug 909870 - xpidl header generation is somehow busted so we need to clobber on windows
|
Bug 627487 - random test failures caused by bookmark JSON changes
|
||||||
|
@ -492,6 +492,119 @@ var Output = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
speechHelper: {
|
||||||
|
EARCONS: ['chrome://global/content/accessibility/tick.wav'],
|
||||||
|
|
||||||
|
delayedActions: [],
|
||||||
|
|
||||||
|
earconsToLoad: -1, // -1: not inited, 1 or more: initing, 0: inited
|
||||||
|
|
||||||
|
earconBuffers: {},
|
||||||
|
|
||||||
|
webaudioEnabled: false,
|
||||||
|
|
||||||
|
webspeechEnabled: false,
|
||||||
|
|
||||||
|
doDelayedActionsIfLoaded: function doDelayedActionsIfLoaded(aToLoadCount) {
|
||||||
|
if (aToLoadCount === 0) {
|
||||||
|
this.outputActions(this.delayedActions);
|
||||||
|
this.delayedActions = [];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
init: function init() {
|
||||||
|
if (this.earconsToLoad === 0) {
|
||||||
|
// Already inited.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let window = Utils.win;
|
||||||
|
this.webaudioEnabled = !!window.AudioContext;
|
||||||
|
this.webspeechEnabled = !!window.speechSynthesis;
|
||||||
|
|
||||||
|
this.earconsToLoad = this.webaudioEnabled ? this.EARCONS.length : 0;
|
||||||
|
|
||||||
|
if (this.doDelayedActionsIfLoaded(this.earconsToLoad)) {
|
||||||
|
// Nothing to load
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.audioContext = new window.AudioContext();
|
||||||
|
|
||||||
|
for (let earcon of this.EARCONS) {
|
||||||
|
let xhr = new window.XMLHttpRequest();
|
||||||
|
xhr.open('GET', earcon);
|
||||||
|
xhr.responseType = 'arraybuffer';
|
||||||
|
xhr.onerror = () => {
|
||||||
|
Logger.error('Error getting earcon:', xhr.statusText);
|
||||||
|
this.doDelayedActionsIfLoaded(--this.earconsToLoad);
|
||||||
|
};
|
||||||
|
xhr.onload = () => {
|
||||||
|
this.audioContext.decodeAudioData(
|
||||||
|
xhr.response,
|
||||||
|
(audioBuffer) => {
|
||||||
|
try {
|
||||||
|
let earconName = /.*\/(.*)\..*$/.exec(earcon)[1];
|
||||||
|
this.earconBuffers[earconName] = new WeakMap();
|
||||||
|
this.earconBuffers[earconName].set(window, audioBuffer);
|
||||||
|
this.doDelayedActionsIfLoaded(--this.earconsToLoad);
|
||||||
|
} catch (x) {
|
||||||
|
Logger.logException(x);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
this.doDelayedActionsIfLoaded(--this.earconsToLoad);
|
||||||
|
Logger.error('Error decoding earcon');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
xhr.send();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
output: function output(aActions) {
|
||||||
|
if (this.earconsToLoad !== 0) {
|
||||||
|
// We did not load the earcons yet.
|
||||||
|
this.delayedActions.push.apply(this.delayedActions, aActions);
|
||||||
|
if (this.earconsToLoad < 0) {
|
||||||
|
// Loading did not start yet, start it.
|
||||||
|
this.init();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.outputActions(aActions);
|
||||||
|
},
|
||||||
|
|
||||||
|
outputActions: function outputActions(aActions) {
|
||||||
|
for (let action of aActions) {
|
||||||
|
let window = Utils.win;
|
||||||
|
Logger.info('tts.' + action.method,
|
||||||
|
'"' + action.data + '"',
|
||||||
|
JSON.stringify(action.options));
|
||||||
|
|
||||||
|
if (!action.options.enqueue && this.webspeechEnabled) {
|
||||||
|
window.speechSynthesis.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action.method === 'speak' && this.webspeechEnabled) {
|
||||||
|
window.speechSynthesis.speak(
|
||||||
|
new window.SpeechSynthesisUtterance(action.data));
|
||||||
|
} else if (action.method === 'playEarcon' && this.webaudioEnabled) {
|
||||||
|
let audioBufferWeakMap = this.earconBuffers[action.data];
|
||||||
|
if (audioBufferWeakMap) {
|
||||||
|
let node = this.audioContext.createBufferSource();
|
||||||
|
node.connect(this.audioContext.destination);
|
||||||
|
node.buffer = audioBufferWeakMap.get(window);
|
||||||
|
node.start(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
start: function start() {
|
start: function start() {
|
||||||
Cu.import('resource://gre/modules/Geometry.jsm');
|
Cu.import('resource://gre/modules/Geometry.jsm');
|
||||||
},
|
},
|
||||||
@ -509,8 +622,7 @@ var Output = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
Speech: function Speech(aDetails, aBrowser) {
|
Speech: function Speech(aDetails, aBrowser) {
|
||||||
for each (let action in aDetails.actions)
|
this.speechHelper.output(aDetails.actions);
|
||||||
Logger.info('tts.' + action.method, '"' + action.data + '"', JSON.stringify(action.options));
|
|
||||||
},
|
},
|
||||||
|
|
||||||
Visual: function Visual(aDetails, aBrowser) {
|
Visual: function Visual(aDetails, aBrowser) {
|
||||||
|
@ -5,3 +5,4 @@
|
|||||||
toolkit.jar:
|
toolkit.jar:
|
||||||
content/global/accessibility/AccessFu.css (AccessFu.css)
|
content/global/accessibility/AccessFu.css (AccessFu.css)
|
||||||
content/global/accessibility/content-script.js (content-script.js)
|
content/global/accessibility/content-script.js (content-script.js)
|
||||||
|
content/global/accessibility/tick.wav (tick.wav)
|
||||||
|
BIN
accessible/src/jsat/tick.wav
Normal file
BIN
accessible/src/jsat/tick.wav
Normal file
Binary file not shown.
@ -240,6 +240,7 @@
|
|||||||
@BINPATH@/components/intl.xpt
|
@BINPATH@/components/intl.xpt
|
||||||
@BINPATH@/components/jar.xpt
|
@BINPATH@/components/jar.xpt
|
||||||
@BINPATH@/components/jsdebugger.xpt
|
@BINPATH@/components/jsdebugger.xpt
|
||||||
|
@BINPATH@/components/jsdownloads.xpt
|
||||||
@BINPATH@/components/jsdservice.xpt
|
@BINPATH@/components/jsdservice.xpt
|
||||||
@BINPATH@/components/jsinspector.xpt
|
@BINPATH@/components/jsinspector.xpt
|
||||||
@BINPATH@/components/layout_base.xpt
|
@BINPATH@/components/layout_base.xpt
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
This is the pdf.js project output, https://github.com/mozilla/pdf.js
|
This is the pdf.js project output, https://github.com/mozilla/pdf.js
|
||||||
|
|
||||||
Current extension version is: 0.8.423
|
Current extension version is: 0.8.478
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
/* jshint esnext:true */
|
/* jshint esnext:true */
|
||||||
/* globals Components, Services, XPCOMUtils, NetUtil, PrivateBrowsingUtils,
|
/* globals Components, Services, XPCOMUtils, NetUtil, PrivateBrowsingUtils,
|
||||||
dump, NetworkManager */
|
dump, NetworkManager, PdfJsTelemetry */
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
@ -42,6 +42,9 @@ Cu.import('resource://pdf.js/network.js');
|
|||||||
XPCOMUtils.defineLazyModuleGetter(this, 'PrivateBrowsingUtils',
|
XPCOMUtils.defineLazyModuleGetter(this, 'PrivateBrowsingUtils',
|
||||||
'resource://gre/modules/PrivateBrowsingUtils.jsm');
|
'resource://gre/modules/PrivateBrowsingUtils.jsm');
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyModuleGetter(this, 'PdfJsTelemetry',
|
||||||
|
'resource://pdf.js/PdfJsTelemetry.jsm');
|
||||||
|
|
||||||
var Svc = {};
|
var Svc = {};
|
||||||
XPCOMUtils.defineLazyServiceGetter(Svc, 'mime',
|
XPCOMUtils.defineLazyServiceGetter(Svc, 'mime',
|
||||||
'@mozilla.org/mime;1',
|
'@mozilla.org/mime;1',
|
||||||
@ -194,6 +197,12 @@ PdfDataListener.prototype = {
|
|||||||
function ChromeActions(domWindow, contentDispositionFilename) {
|
function ChromeActions(domWindow, contentDispositionFilename) {
|
||||||
this.domWindow = domWindow;
|
this.domWindow = domWindow;
|
||||||
this.contentDispositionFilename = contentDispositionFilename;
|
this.contentDispositionFilename = contentDispositionFilename;
|
||||||
|
this.telemetryState = {
|
||||||
|
documentInfo: false,
|
||||||
|
firstPageInfo: false,
|
||||||
|
streamTypesUsed: [],
|
||||||
|
startAt: Date.now()
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
ChromeActions.prototype = {
|
ChromeActions.prototype = {
|
||||||
@ -321,12 +330,49 @@ ChromeActions.prototype = {
|
|||||||
supportsDocumentColors: function() {
|
supportsDocumentColors: function() {
|
||||||
return getBoolPref('browser.display.use_document_colors', true);
|
return getBoolPref('browser.display.use_document_colors', true);
|
||||||
},
|
},
|
||||||
|
reportTelemetry: function (data) {
|
||||||
|
var probeInfo = JSON.parse(data);
|
||||||
|
switch (probeInfo.type) {
|
||||||
|
case 'documentInfo':
|
||||||
|
if (!this.telemetryState.documentInfo) {
|
||||||
|
PdfJsTelemetry.onDocumentVersion(probeInfo.version | 0);
|
||||||
|
PdfJsTelemetry.onDocumentGenerator(probeInfo.generator | 0);
|
||||||
|
if (probeInfo.formType) {
|
||||||
|
PdfJsTelemetry.onForm(probeInfo.formType === 'acroform');
|
||||||
|
}
|
||||||
|
this.telemetryState.documentInfo = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'pageInfo':
|
||||||
|
if (!this.telemetryState.firstPageInfo) {
|
||||||
|
var duration = Date.now() - this.telemetryState.startAt;
|
||||||
|
PdfJsTelemetry.onTimeToView(duration);
|
||||||
|
this.telemetryState.firstPageInfo = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'streamInfo':
|
||||||
|
if (!Array.isArray(probeInfo.streamTypes)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for (var i = 0; i < probeInfo.streamTypes.length; i++) {
|
||||||
|
var streamTypeId = probeInfo.streamTypes[i] | 0;
|
||||||
|
if (streamTypeId >= 0 && streamTypeId < 10 &&
|
||||||
|
!this.telemetryState.streamTypesUsed[streamTypeId]) {
|
||||||
|
PdfJsTelemetry.onStreamType(streamTypeId);
|
||||||
|
this.telemetryState.streamTypesUsed[streamTypeId] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
fallback: function(url, sendResponse) {
|
fallback: function(url, sendResponse) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var domWindow = this.domWindow;
|
var domWindow = this.domWindow;
|
||||||
var strings = getLocalizedStrings('chrome.properties');
|
var strings = getLocalizedStrings('chrome.properties');
|
||||||
var message = getLocalizedString(strings, 'unsupported_feature');
|
var message = getLocalizedString(strings, 'unsupported_feature');
|
||||||
|
|
||||||
|
PdfJsTelemetry.onFallback();
|
||||||
|
|
||||||
var notificationBox = null;
|
var notificationBox = null;
|
||||||
try {
|
try {
|
||||||
// Based on MDN's "Working with windows in chrome code"
|
// Based on MDN's "Working with windows in chrome code"
|
||||||
@ -730,6 +776,9 @@ PdfStreamConverter.prototype = {
|
|||||||
false);
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PdfJsTelemetry.onViewerIsUsed();
|
||||||
|
PdfJsTelemetry.onDocumentSize(aRequest.contentLength);
|
||||||
|
|
||||||
if (!rangeRequest) {
|
if (!rangeRequest) {
|
||||||
// Creating storage for PDF data
|
// Creating storage for PDF data
|
||||||
var contentLength = aRequest.contentLength;
|
var contentLength = aRequest.contentLength;
|
||||||
|
@ -254,7 +254,7 @@ let PdfJs = {
|
|||||||
this._pdfStreamConverterFactory.unregister();
|
this._pdfStreamConverterFactory.unregister();
|
||||||
delete this._pdfStreamConverterFactory;
|
delete this._pdfStreamConverterFactory;
|
||||||
|
|
||||||
this._pdfRedirectorFactory.unregister;
|
this._pdfRedirectorFactory.unregister();
|
||||||
delete this._pdfRedirectorFactory;
|
delete this._pdfRedirectorFactory;
|
||||||
Svc.pluginHost.unregisterPlayPreviewMimeType(PDF_CONTENT_TYPE);
|
Svc.pluginHost.unregisterPlayPreviewMimeType(PDF_CONTENT_TYPE);
|
||||||
|
|
||||||
|
59
browser/extensions/pdfjs/content/PdfJsTelemetry.jsm
Normal file
59
browser/extensions/pdfjs/content/PdfJsTelemetry.jsm
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
||||||
|
/* Copyright 2013 Mozilla Foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
/* jshint esnext:true */
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
this.EXPORTED_SYMBOLS = ['PdfJsTelemetry'];
|
||||||
|
|
||||||
|
const Cu = Components.utils;
|
||||||
|
Cu.import('resource://gre/modules/Services.jsm');
|
||||||
|
|
||||||
|
this.PdfJsTelemetry = {
|
||||||
|
onViewerIsUsed: function () {
|
||||||
|
let histogram = Services.telemetry.getHistogramById("PDF_VIEWER_USED");
|
||||||
|
histogram.add(true);
|
||||||
|
},
|
||||||
|
onFallback: function () {
|
||||||
|
let histogram = Services.telemetry.getHistogramById("PDF_VIEWER_FALLBACK_SHOWN");
|
||||||
|
histogram.add(true);
|
||||||
|
},
|
||||||
|
onDocumentSize: function (size) {
|
||||||
|
let histogram = Services.telemetry.getHistogramById("PDF_VIEWER_DOCUMENT_SIZE_KB");
|
||||||
|
histogram.add(size / 1024);
|
||||||
|
},
|
||||||
|
onDocumentVersion: function (versionId) {
|
||||||
|
let histogram = Services.telemetry.getHistogramById("PDF_VIEWER_DOCUMENT_VERSION");
|
||||||
|
histogram.add(versionId);
|
||||||
|
},
|
||||||
|
onDocumentGenerator: function (generatorId) {
|
||||||
|
let histogram = Services.telemetry.getHistogramById("PDF_VIEWER_DOCUMENT_GENERATOR");
|
||||||
|
histogram.add(generatorId);
|
||||||
|
},
|
||||||
|
onForm: function (isAcroform) {
|
||||||
|
let histogram = Services.telemetry.getHistogramById("PDF_VIEWER_FORM");
|
||||||
|
histogram.add(isAcroform);
|
||||||
|
},
|
||||||
|
onStreamType: function (streamTypeId) {
|
||||||
|
let histogram = Services.telemetry.getHistogramById("PDF_VIEWER_STREAM_TYPES");
|
||||||
|
histogram.add(streamTypeId);
|
||||||
|
},
|
||||||
|
onTimeToView: function (ms) {
|
||||||
|
let histogram = Services.telemetry.getHistogramById("PDF_VIEWER_TIME_TO_VIEW_MS");
|
||||||
|
histogram.add(ms);
|
||||||
|
}
|
||||||
|
};
|
File diff suppressed because it is too large
Load Diff
38469
browser/extensions/pdfjs/content/build/pdf.worker.js
vendored
Normal file
38469
browser/extensions/pdfjs/content/build/pdf.worker.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@ -228,6 +228,25 @@ var Stepper = (function StepperClosure() {
|
|||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function glyphsToString(glyphs) {
|
||||||
|
var out = '';
|
||||||
|
for (var i = 0; i < glyphs.length; i++) {
|
||||||
|
if (glyphs[i] === null) {
|
||||||
|
out += ' ';
|
||||||
|
} else {
|
||||||
|
out += glyphs[i].fontChar;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
var glyphCommands = {
|
||||||
|
'showText': 0,
|
||||||
|
'showSpacedText': 0,
|
||||||
|
'nextLineShowText': 0,
|
||||||
|
'nextLineSetSpacingShowText': 2
|
||||||
|
};
|
||||||
|
|
||||||
function Stepper(panel, pageIndex, initialBreakPoints) {
|
function Stepper(panel, pageIndex, initialBreakPoints) {
|
||||||
this.panel = panel;
|
this.panel = panel;
|
||||||
this.breakPoint = 0;
|
this.breakPoint = 0;
|
||||||
@ -281,8 +300,29 @@ var Stepper = (function StepperClosure() {
|
|||||||
breakCell.appendChild(cbox);
|
breakCell.appendChild(cbox);
|
||||||
line.appendChild(breakCell);
|
line.appendChild(breakCell);
|
||||||
line.appendChild(c('td', i.toString()));
|
line.appendChild(c('td', i.toString()));
|
||||||
line.appendChild(c('td', operatorList.fnArray[i]));
|
var fn = operatorList.fnArray[i];
|
||||||
line.appendChild(c('td', args.join(', ')));
|
var decArgs = args;
|
||||||
|
if (fn in glyphCommands) {
|
||||||
|
var glyphIndex = glyphCommands[fn];
|
||||||
|
var glyphs = args[glyphIndex];
|
||||||
|
var decArgs = args.slice();
|
||||||
|
var newArg;
|
||||||
|
if (fn === 'showSpacedText') {
|
||||||
|
newArg = [];
|
||||||
|
for (var j = 0; j < glyphs.length; j++) {
|
||||||
|
if (typeof glyphs[j] === 'number') {
|
||||||
|
newArg.push(glyphs[j]);
|
||||||
|
} else {
|
||||||
|
newArg.push(glyphsToString(glyphs[j]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
newArg = glyphsToString(glyphs);
|
||||||
|
}
|
||||||
|
decArgs[glyphIndex] = newArg;
|
||||||
|
}
|
||||||
|
line.appendChild(c('td', fn));
|
||||||
|
line.appendChild(c('td', JSON.stringify(decArgs)));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getNextBreakPoint: function getNextBreakPoint() {
|
getNextBreakPoint: function getNextBreakPoint() {
|
||||||
|
@ -982,7 +982,7 @@ html[dir='rtl'] .outlineItem > a {
|
|||||||
}
|
}
|
||||||
|
|
||||||
canvas {
|
canvas {
|
||||||
margin: auto;
|
margin: 0;
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1105,6 +1105,9 @@ canvas {
|
|||||||
padding: 3px;
|
padding: 3px;
|
||||||
font-size: 0.8em;
|
font-size: 0.8em;
|
||||||
}
|
}
|
||||||
|
.loadingInProgress #errorWrapper {
|
||||||
|
top: 39px;
|
||||||
|
}
|
||||||
|
|
||||||
#errorMessageLeft {
|
#errorMessageLeft {
|
||||||
float: left;
|
float: left;
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
/* globals PDFJS, PDFBug, FirefoxCom, Stats, Cache, PDFFindBar, CustomStyle,
|
/* globals PDFJS, PDFBug, FirefoxCom, Stats, Cache, PDFFindBar, CustomStyle,
|
||||||
PDFFindController, ProgressBar, TextLayerBuilder, DownloadManager,
|
PDFFindController, ProgressBar, TextLayerBuilder, DownloadManager,
|
||||||
getFileName, getOutputScale, scrollIntoView, getPDFFileNameFromURL,
|
getFileName, getOutputScale, scrollIntoView, getPDFFileNameFromURL,
|
||||||
PDFHistory, noContextMenuHandler */
|
PDFHistory, ThumbnailView, noContextMenuHandler */
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ var FindStates = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
PDFJS.imageResourcesPath = './images/';
|
PDFJS.imageResourcesPath = './images/';
|
||||||
PDFJS.workerSrc = '../build/pdf.js';
|
PDFJS.workerSrc = '../build/pdf.worker.js';
|
||||||
|
|
||||||
var mozL10n = document.mozL10n || document.webL10n;
|
var mozL10n = document.mozL10n || document.webL10n;
|
||||||
|
|
||||||
@ -662,6 +662,12 @@ var PDFFindController = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
reset: function pdfFindControllerReset() {
|
||||||
|
this.startedTextExtraction = false;
|
||||||
|
this.extractTextPromises = [];
|
||||||
|
this.active = false;
|
||||||
|
},
|
||||||
|
|
||||||
calcFindMatch: function(pageIndex) {
|
calcFindMatch: function(pageIndex) {
|
||||||
var pageContent = this.pageContents[pageIndex];
|
var pageContent = this.pageContents[pageIndex];
|
||||||
var query = this.state.query;
|
var query = this.state.query;
|
||||||
@ -969,7 +975,7 @@ var PDFHistory = {
|
|||||||
// is opened in the web viewer.
|
// is opened in the web viewer.
|
||||||
this.reInitialized = true;
|
this.reInitialized = true;
|
||||||
}
|
}
|
||||||
window.history.replaceState({ fingerprint: this.fingerprint }, '', '');
|
window.history.replaceState({ fingerprint: this.fingerprint }, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
@ -1174,9 +1180,9 @@ var PDFHistory = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (overwrite || this.uid === 0) {
|
if (overwrite || this.uid === 0) {
|
||||||
window.history.replaceState(this._stateObj(params), '', '');
|
window.history.replaceState(this._stateObj(params), '');
|
||||||
} else {
|
} else {
|
||||||
window.history.pushState(this._stateObj(params), '', '');
|
window.history.pushState(this._stateObj(params), '');
|
||||||
}
|
}
|
||||||
this.currentUid = this.uid++;
|
this.currentUid = this.uid++;
|
||||||
this.current = params;
|
this.current = params;
|
||||||
@ -1248,8 +1254,6 @@ var PDFView = {
|
|||||||
currentScale: UNKNOWN_SCALE,
|
currentScale: UNKNOWN_SCALE,
|
||||||
currentScaleValue: null,
|
currentScaleValue: null,
|
||||||
initialBookmark: document.location.hash.substring(1),
|
initialBookmark: document.location.hash.substring(1),
|
||||||
startedTextExtraction: false,
|
|
||||||
pageText: [],
|
|
||||||
container: null,
|
container: null,
|
||||||
thumbnailContainer: null,
|
thumbnailContainer: null,
|
||||||
initialized: false,
|
initialized: false,
|
||||||
@ -1839,6 +1843,8 @@ var PDFView = {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PDFFindController.reset();
|
||||||
|
|
||||||
this.pdfDocument = pdfDocument;
|
this.pdfDocument = pdfDocument;
|
||||||
|
|
||||||
var errorWrapper = document.getElementById('errorWrapper');
|
var errorWrapper = document.getElementById('errorWrapper');
|
||||||
@ -1876,8 +1882,6 @@ var PDFView = {
|
|||||||
this.pageRotation = 0;
|
this.pageRotation = 0;
|
||||||
|
|
||||||
var pages = this.pages = [];
|
var pages = this.pages = [];
|
||||||
this.pageText = [];
|
|
||||||
this.startedTextExtraction = false;
|
|
||||||
var pagesRefMap = this.pagesRefMap = {};
|
var pagesRefMap = this.pagesRefMap = {};
|
||||||
var thumbnails = this.thumbnails = [];
|
var thumbnails = this.thumbnails = [];
|
||||||
|
|
||||||
@ -2030,6 +2034,32 @@ var PDFView = {
|
|||||||
console.warn('Warning: AcroForm/XFA is not supported');
|
console.warn('Warning: AcroForm/XFA is not supported');
|
||||||
PDFView.fallback();
|
PDFView.fallback();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var versionId = String(info.PDFFormatVersion).slice(-1) | 0;
|
||||||
|
var generatorId = 0;
|
||||||
|
var KNOWN_GENERATORS = ["acrobat distiller", "acrobat pdfwritter",
|
||||||
|
"adobe livecycle", "adobe pdf library", "adobe photoshop", "ghostscript",
|
||||||
|
"tcpdf", "cairo", "dvipdfm", "dvips", "pdftex", "pdfkit", "itext",
|
||||||
|
"prince", "quarkxpress", "mac os x", "microsoft", "openoffice", "oracle",
|
||||||
|
"luradocument", "pdf-xchange", "antenna house", "aspose.cells", "fpdf"];
|
||||||
|
var generatorId = 0;
|
||||||
|
if (info.Producer) {
|
||||||
|
KNOWN_GENERATORS.some(function (generator, s, i) {
|
||||||
|
if (generator.indexOf(s) < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
generatorId = i + 1;
|
||||||
|
return true;
|
||||||
|
}.bind(null, info.Producer.toLowerCase()));
|
||||||
|
}
|
||||||
|
var formType = !info.IsAcroFormPresent ? null : info.IsXFAPresent ?
|
||||||
|
'xfa' : 'acroform';
|
||||||
|
FirefoxCom.request('reportTelemetry', JSON.stringify({
|
||||||
|
type: 'documentInfo',
|
||||||
|
version: versionId,
|
||||||
|
generator: generatorId,
|
||||||
|
formType: formType
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -2624,6 +2654,52 @@ var PageView = function pageView(container, id, scale,
|
|||||||
link.className = 'internalLink';
|
link.className = 'internalLink';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function bindNamedAction(link, action) {
|
||||||
|
link.onclick = function pageViewSetupNamedActionOnClick() {
|
||||||
|
// See PDF reference, table 8.45 - Named action
|
||||||
|
switch (action) {
|
||||||
|
case 'GoToPage':
|
||||||
|
document.getElementById('pageNumber').focus();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'GoBack':
|
||||||
|
PDFHistory.back();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'GoForward':
|
||||||
|
PDFHistory.forward();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'Find':
|
||||||
|
if (!PDFView.supportsIntegratedFind) {
|
||||||
|
PDFFindBar.toggle();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'NextPage':
|
||||||
|
PDFView.page++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'PrevPage':
|
||||||
|
PDFView.page--;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'LastPage':
|
||||||
|
PDFView.page = PDFView.pages.length;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'FirstPage':
|
||||||
|
PDFView.page = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break; // No action according to spec
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
link.className = 'internalLink';
|
||||||
|
}
|
||||||
|
|
||||||
pdfPage.getAnnotations().then(function(annotationsData) {
|
pdfPage.getAnnotations().then(function(annotationsData) {
|
||||||
viewport = viewport.clone({ dontFlip: true });
|
viewport = viewport.clone({ dontFlip: true });
|
||||||
for (var i = 0; i < annotationsData.length; i++) {
|
for (var i = 0; i < annotationsData.length; i++) {
|
||||||
@ -2656,7 +2732,11 @@ var PageView = function pageView(container, id, scale,
|
|||||||
CustomStyle.setProp('transformOrigin', element, transformOriginStr);
|
CustomStyle.setProp('transformOrigin', element, transformOriginStr);
|
||||||
|
|
||||||
if (data.subtype === 'Link' && !data.url) {
|
if (data.subtype === 'Link' && !data.url) {
|
||||||
bindLink(element, ('dest' in data) ? data.dest : null);
|
if (data.action) {
|
||||||
|
bindNamedAction(element, data.action);
|
||||||
|
} else {
|
||||||
|
bindLink(element, ('dest' in data) ? data.dest : null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
annotationsDiv.appendChild(element);
|
annotationsDiv.appendChild(element);
|
||||||
@ -2884,6 +2964,10 @@ var PageView = function pageView(container, id, scale,
|
|||||||
});
|
});
|
||||||
div.dispatchEvent(event);
|
div.dispatchEvent(event);
|
||||||
|
|
||||||
|
FirefoxCom.request('reportTelemetry', JSON.stringify({
|
||||||
|
type: 'pageInfo'
|
||||||
|
}));
|
||||||
|
// TODO add stream types report here
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2990,6 +3074,7 @@ var PageView = function pageView(container, id, scale,
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
var ThumbnailView = function thumbnailView(container, id, defaultViewport) {
|
var ThumbnailView = function thumbnailView(container, id, defaultViewport) {
|
||||||
var anchor = document.createElement('a');
|
var anchor = document.createElement('a');
|
||||||
anchor.href = PDFView.getAnchorUrl('#page=' + id);
|
anchor.href = PDFView.getAnchorUrl('#page=' + id);
|
||||||
@ -2999,7 +3084,6 @@ var ThumbnailView = function thumbnailView(container, id, defaultViewport) {
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
this.pdfPage = undefined;
|
this.pdfPage = undefined;
|
||||||
this.viewport = defaultViewport;
|
this.viewport = defaultViewport;
|
||||||
this.pdfPageRotate = defaultViewport.rotate;
|
this.pdfPageRotate = defaultViewport.rotate;
|
||||||
@ -3574,6 +3658,7 @@ document.addEventListener('DOMContentLoaded', function webViewerLoad(evt) {
|
|||||||
|
|
||||||
var file = window.location.href.split('#')[0];
|
var file = window.location.href.split('#')[0];
|
||||||
|
|
||||||
|
|
||||||
document.getElementById('openFile').setAttribute('hidden', 'true');
|
document.getElementById('openFile').setAttribute('hidden', 'true');
|
||||||
|
|
||||||
// Special debugging flags in the hash section of the URL.
|
// Special debugging flags in the hash section of the URL.
|
||||||
@ -4034,8 +4119,12 @@ window.addEventListener('keydown', function keydown(evt) {
|
|||||||
break;
|
break;
|
||||||
case 48: // '0'
|
case 48: // '0'
|
||||||
case 96: // '0' on Numpad of Swedish keyboard
|
case 96: // '0' on Numpad of Swedish keyboard
|
||||||
PDFView.parseScale(DEFAULT_SCALE, true);
|
// keeping it unhandled (to restore page zoom to 100%)
|
||||||
handled = false; // keeping it unhandled (to restore page zoom to 100%)
|
setTimeout(function () {
|
||||||
|
// ... and resetting the scale after browser adjusts its scale
|
||||||
|
PDFView.parseScale(DEFAULT_SCALE, true);
|
||||||
|
});
|
||||||
|
handled = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,10 @@ chrome.manifest
|
|||||||
components/PdfRedirector.js
|
components/PdfRedirector.js
|
||||||
components/PdfStreamConverter.js
|
components/PdfStreamConverter.js
|
||||||
content/build/pdf.js
|
content/build/pdf.js
|
||||||
|
content/build/pdf.worker.js
|
||||||
content/network.js
|
content/network.js
|
||||||
content/PdfJs.jsm
|
content/PdfJs.jsm
|
||||||
|
content/PdfJsTelemetry.jsm
|
||||||
content/web/debugger.js
|
content/web/debugger.js
|
||||||
content/web/images/annotation-check.svg
|
content/web/images/annotation-check.svg
|
||||||
content/web/images/annotation-comment.svg
|
content/web/images/annotation-comment.svg
|
||||||
|
@ -248,6 +248,7 @@
|
|||||||
@BINPATH@/components/jsdservice.xpt
|
@BINPATH@/components/jsdservice.xpt
|
||||||
#endif
|
#endif
|
||||||
@BINPATH@/components/jsdebugger.xpt
|
@BINPATH@/components/jsdebugger.xpt
|
||||||
|
@BINPATH@/components/jsdownloads.xpt
|
||||||
@BINPATH@/components/jsinspector.xpt
|
@BINPATH@/components/jsinspector.xpt
|
||||||
@BINPATH@/components/layout_base.xpt
|
@BINPATH@/components/layout_base.xpt
|
||||||
#ifdef NS_PRINTING
|
#ifdef NS_PRINTING
|
||||||
|
@ -10,6 +10,9 @@ Cu.import("resource://gre/modules/Services.jsm");
|
|||||||
* JS modules
|
* JS modules
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyModuleGetter(this , "FormHistory",
|
||||||
|
"resource://gre/modules/FormHistory.jsm");
|
||||||
|
|
||||||
XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
|
XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
|
||||||
"resource://gre/modules/PluralForm.jsm");
|
"resource://gre/modules/PluralForm.jsm");
|
||||||
|
|
||||||
|
@ -143,8 +143,6 @@ var BrowserUI = {
|
|||||||
|
|
||||||
// Login Manager and Form History initialization
|
// Login Manager and Form History initialization
|
||||||
Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager);
|
Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager);
|
||||||
Cc["@mozilla.org/satchel/form-history;1"].getService(Ci.nsIFormHistory2);
|
|
||||||
|
|
||||||
messageManager.addMessageListener("Browser:MozApplicationManifest", OfflineApps);
|
messageManager.addMessageListener("Browser:MozApplicationManifest", OfflineApps);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -3,10 +3,6 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
|
||||||
XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
|
|
||||||
"resource://gre/modules/PlacesUtils.jsm");
|
|
||||||
|
|
||||||
function Sanitizer() {}
|
function Sanitizer() {}
|
||||||
|
|
||||||
Sanitizer.prototype = {
|
Sanitizer.prototype = {
|
||||||
@ -17,17 +13,22 @@ Sanitizer.prototype = {
|
|||||||
this.items[aItemName].clear();
|
this.items[aItemName].clear();
|
||||||
},
|
},
|
||||||
|
|
||||||
canClearItem: function (aItemName)
|
canClearItem: function (aItemName, aCallback, aArg)
|
||||||
{
|
{
|
||||||
return this.items[aItemName].canClear;
|
let canClear = this.items[aItemName].canClear;
|
||||||
|
if (typeof canClear == "function"){
|
||||||
|
canClear(aCallback, aArg);
|
||||||
|
} else {
|
||||||
|
aCallback(aItemName, canClear, aArg);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_prefDomain: "privacy.item.",
|
_prefDomain: "privacy.item.",
|
||||||
getNameFromPreference: function (aPreferenceName)
|
getNameFromPreference: function (aPreferenceName)
|
||||||
{
|
{
|
||||||
return aPreferenceName.substr(this._prefDomain.length);
|
return aPreferenceName.substr(this._prefDomain.length);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes privacy sensitive data in a batch, according to user preferences
|
* Deletes privacy sensitive data in a batch, according to user preferences
|
||||||
*
|
*
|
||||||
@ -39,26 +40,32 @@ Sanitizer.prototype = {
|
|||||||
var branch = Services.prefs.getBranch(this._prefDomain);
|
var branch = Services.prefs.getBranch(this._prefDomain);
|
||||||
var errors = null;
|
var errors = null;
|
||||||
for (var itemName in this.items) {
|
for (var itemName in this.items) {
|
||||||
var item = this.items[itemName];
|
if ("clear" in item && branch.getBoolPref(itemName)) {
|
||||||
if ("clear" in item && item.canClear && branch.getBoolPref(itemName)) {
|
|
||||||
// Some of these clear() may raise exceptions (see bug #265028)
|
// Some of these clear() may raise exceptions (see bug #265028)
|
||||||
// to sanitize as much as possible, we catch and store them,
|
// to sanitize as much as possible, we catch and store them,
|
||||||
// rather than fail fast.
|
// rather than fail fast.
|
||||||
// Callers should check returned errors and give user feedback
|
// Callers should check returned errors and give user feedback
|
||||||
// about items that could not be sanitized
|
// about items that could not be sanitized
|
||||||
try {
|
let clearCallback = (itemName, aCanClear) => {
|
||||||
item.clear();
|
let item = this.items[itemName];
|
||||||
} catch(er) {
|
try{
|
||||||
if (!errors)
|
if (aCanClear){
|
||||||
errors = {};
|
item.clear();
|
||||||
errors[itemName] = er;
|
}
|
||||||
dump("Error sanitizing " + itemName + ": " + er + "\n");
|
} catch(er){
|
||||||
|
if (!errors){
|
||||||
|
errors = {};
|
||||||
|
}
|
||||||
|
errors[itemName] = er;
|
||||||
|
dump("Error sanitizing " + itemName + ":" + er + "\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
this.canClearItem(itemName, clearCallback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return errors;
|
return errors;
|
||||||
},
|
},
|
||||||
|
|
||||||
items: {
|
items: {
|
||||||
// Clear Sync account before passwords so that Sync still has access to the
|
// Clear Sync account before passwords so that Sync still has access to the
|
||||||
// credentials to clean up device-specific records on the server. Also
|
// credentials to clean up device-specific records on the server. Also
|
||||||
@ -88,20 +95,20 @@ Sanitizer.prototype = {
|
|||||||
imageCache.clearCache(false); // true=chrome, false=content
|
imageCache.clearCache(false); // true=chrome, false=content
|
||||||
} catch(er) {}
|
} catch(er) {}
|
||||||
},
|
},
|
||||||
|
|
||||||
get canClear()
|
get canClear()
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
cookies: {
|
cookies: {
|
||||||
clear: function ()
|
clear: function ()
|
||||||
{
|
{
|
||||||
var cookieMgr = Cc["@mozilla.org/cookiemanager;1"].getService(Ci.nsICookieManager);
|
var cookieMgr = Cc["@mozilla.org/cookiemanager;1"].getService(Ci.nsICookieManager);
|
||||||
cookieMgr.removeAll();
|
cookieMgr.removeAll();
|
||||||
},
|
},
|
||||||
|
|
||||||
get canClear()
|
get canClear()
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
@ -185,18 +192,21 @@ Sanitizer.prototype = {
|
|||||||
searchBar.textbox.editor.transactionManager.clear();
|
searchBar.textbox.editor.transactionManager.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
FormHistory.update({op : "remove"});
|
||||||
var formHistory = Cc["@mozilla.org/satchel/form-history;1"].getService(Ci.nsIFormHistory2);
|
|
||||||
formHistory.removeAllEntries();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
get canClear()
|
canClear : function(aCallback, aArg)
|
||||||
{
|
{
|
||||||
var formHistory = Cc["@mozilla.org/satchel/form-history;1"].getService(Ci.nsIFormHistory2);
|
let count = 0;
|
||||||
return formHistory.hasEntries;
|
let countDone = {
|
||||||
|
handleResult : function(aResult) { count = aResult; },
|
||||||
|
handleError : function(aError) { Components.utils.reportError(aError); },
|
||||||
|
handleCompletion : function(aReason) { aCallback("formdata", aReason == 0 && count > 0, aArg); }
|
||||||
|
};
|
||||||
|
FormHistory.count({}, countDone);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
downloads: {
|
downloads: {
|
||||||
clear: function ()
|
clear: function ()
|
||||||
{
|
{
|
||||||
@ -210,14 +220,14 @@ Sanitizer.prototype = {
|
|||||||
return dlMgr.canCleanUp;
|
return dlMgr.canCleanUp;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
passwords: {
|
passwords: {
|
||||||
clear: function ()
|
clear: function ()
|
||||||
{
|
{
|
||||||
var pwmgr = Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager);
|
var pwmgr = Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager);
|
||||||
pwmgr.removeAllLogins();
|
pwmgr.removeAllLogins();
|
||||||
},
|
},
|
||||||
|
|
||||||
get canClear()
|
get canClear()
|
||||||
{
|
{
|
||||||
var pwmgr = Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager);
|
var pwmgr = Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager);
|
||||||
@ -225,7 +235,7 @@ Sanitizer.prototype = {
|
|||||||
return (count > 0);
|
return (count > 0);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
sessions: {
|
sessions: {
|
||||||
clear: function ()
|
clear: function ()
|
||||||
{
|
{
|
||||||
@ -237,7 +247,7 @@ Sanitizer.prototype = {
|
|||||||
var authMgr = Cc['@mozilla.org/network/http-auth-manager;1'].getService(Ci.nsIHttpAuthManager);
|
var authMgr = Cc['@mozilla.org/network/http-auth-manager;1'].getService(Ci.nsIHttpAuthManager);
|
||||||
authMgr.clearAll();
|
authMgr.clearAll();
|
||||||
},
|
},
|
||||||
|
|
||||||
get canClear()
|
get canClear()
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
@ -6,8 +6,7 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
function clearFormHistory() {
|
function clearFormHistory() {
|
||||||
var formHistory = Cc["@mozilla.org/satchel/form-history;1"].getService(Ci.nsIFormHistory2);
|
FormHistory.update({ op : "remove" });
|
||||||
formHistory.removeAllEntries();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function test() {
|
function test() {
|
||||||
|
@ -82,13 +82,6 @@ public interface Actions {
|
|||||||
|
|
||||||
void drag(int startingX, int endingX, int startingY, int endingY);
|
void drag(int startingX, int endingX, int startingY, int endingY);
|
||||||
|
|
||||||
/**
|
|
||||||
* This is the implementation of clickLongOnScreen from Robotium 4.0 since this sometimes fails for Robotium 3.6
|
|
||||||
* TODO : Remove this when Robotium is updated
|
|
||||||
*/
|
|
||||||
|
|
||||||
void clickLongOnScreen(float x, float y);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Run a sql query on the specified database
|
* Run a sql query on the specified database
|
||||||
*/
|
*/
|
||||||
|
@ -460,41 +460,6 @@ public class FennecNativeActions implements Actions {
|
|||||||
mSolo.drag(startingX, endingX, startingY, endingY, 10);
|
mSolo.drag(startingX, endingX, startingY, endingY, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This is the implementation of clickLongOnScreen from Robotium 4.0 since this sometimes fails for Robotium 3.6
|
|
||||||
* TODO : Remove this when Robotium is updated
|
|
||||||
*/
|
|
||||||
|
|
||||||
public void clickLongOnScreen(float x, float y) {
|
|
||||||
boolean successfull = false;
|
|
||||||
int retry = 0;
|
|
||||||
long downTime = SystemClock.uptimeMillis();
|
|
||||||
long eventTime = SystemClock.uptimeMillis();
|
|
||||||
MotionEvent event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_DOWN, x, y, 0);
|
|
||||||
|
|
||||||
while(!successfull && retry < 10) {
|
|
||||||
try{
|
|
||||||
mInstr.sendPointerSync(event);
|
|
||||||
successfull = true;
|
|
||||||
}catch(SecurityException e){
|
|
||||||
FennecNativeDriver.log(LogLevel.ERROR, e);
|
|
||||||
retry++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mAsserter.ok(successfull, "Trying to click on long on screen at (" + x + "," + y + ")", "Was able to click long on screen");
|
|
||||||
|
|
||||||
eventTime = SystemClock.uptimeMillis();
|
|
||||||
event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE, x + 1.0f, y + 1.0f, 0);
|
|
||||||
mInstr.sendPointerSync(event);
|
|
||||||
mSolo.sleep(((int)(ViewConfiguration.getLongPressTimeout() * 2.5f)));
|
|
||||||
|
|
||||||
eventTime = SystemClock.uptimeMillis();
|
|
||||||
event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_UP, x, y, 0);
|
|
||||||
mInstr.sendPointerSync(event);
|
|
||||||
mSolo.sleep(500);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Cursor querySql(String dbPath, String sql) {
|
public Cursor querySql(String dbPath, String sql) {
|
||||||
try {
|
try {
|
||||||
return (Cursor)mQuerySql.invoke(mRobocopApi, dbPath, sql);
|
return (Cursor)mQuerySql.invoke(mRobocopApi, dbPath, sql);
|
||||||
|
@ -15,7 +15,7 @@ include $(DEPTH)/config/autoconf.mk
|
|||||||
|
|
||||||
ANDROID_APK_NAME := robocop-debug
|
ANDROID_APK_NAME := robocop-debug
|
||||||
|
|
||||||
ROBOTIUM_PATH = $(srcdir)/robotium-solo-3.6.jar
|
ROBOTIUM_PATH = $(srcdir)/robotium-solo-4.2.jar
|
||||||
|
|
||||||
JAVAFILES = \
|
JAVAFILES = \
|
||||||
R.java \
|
R.java \
|
||||||
|
@ -4,7 +4,7 @@ Robotium is an open source tool licensed under the Apache 2.0 license and the or
|
|||||||
source can be found here:
|
source can be found here:
|
||||||
http://code.google.com/p/robotium/
|
http://code.google.com/p/robotium/
|
||||||
|
|
||||||
We are including robotium-solo-3.6.jar as a binary and are not modifying it in any way
|
We are including robotium-solo-4.2.jar as a binary and are not modifying it in any way
|
||||||
from the original download found at:
|
from the original download found at:
|
||||||
http://code.google.com/p/robotium/
|
http://code.google.com/p/robotium/
|
||||||
|
|
||||||
|
Binary file not shown.
BIN
build/mobile/robocop/robotium-solo-4.2.jar
Normal file
BIN
build/mobile/robocop/robotium-solo-4.2.jar
Normal file
Binary file not shown.
10
configure.in
10
configure.in
@ -1733,6 +1733,16 @@ case "$host" in
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
dnl Check for using a custom <inttypes.h> implementation
|
||||||
|
dnl ========================================================
|
||||||
|
AC_MSG_CHECKING(for custom <inttypes.h> implementation)
|
||||||
|
if test "$MOZ_CUSTOM_INTTYPES_H"; then
|
||||||
|
AC_DEFINE_UNQUOTED(MOZ_CUSTOM_INTTYPES_H, "$MOZ_CUSTOM_INTTYPES_H")
|
||||||
|
AC_MSG_RESULT(using $MOZ_CUSTOM_INTTYPES_H)
|
||||||
|
else
|
||||||
|
AC_MSG_RESULT(none specified)
|
||||||
|
fi
|
||||||
|
|
||||||
dnl Get mozilla version from central milestone file
|
dnl Get mozilla version from central milestone file
|
||||||
MOZILLA_VERSION=`$PERL $srcdir/config/milestone.pl -topsrcdir $srcdir`
|
MOZILLA_VERSION=`$PERL $srcdir/config/milestone.pl -topsrcdir $srcdir`
|
||||||
MOZILLA_UAVERSION=`$PERL $srcdir/config/milestone.pl -topsrcdir $srcdir -uaversion`
|
MOZILLA_UAVERSION=`$PERL $srcdir/config/milestone.pl -topsrcdir $srcdir -uaversion`
|
||||||
|
@ -61,7 +61,6 @@ EXPORTS += [
|
|||||||
'nsINodeList.h',
|
'nsINodeList.h',
|
||||||
'nsIScriptElement.h',
|
'nsIScriptElement.h',
|
||||||
'nsIStyleSheetLinkingElement.h',
|
'nsIStyleSheetLinkingElement.h',
|
||||||
'nsIXPathEvaluatorInternal.h',
|
|
||||||
'nsLineBreaker.h',
|
'nsLineBreaker.h',
|
||||||
'nsReferencedElement.h',
|
'nsReferencedElement.h',
|
||||||
'nsTreeSanitizer.h',
|
'nsTreeSanitizer.h',
|
||||||
|
@ -109,6 +109,7 @@ class ProcessingInstruction;
|
|||||||
class Touch;
|
class Touch;
|
||||||
class TreeWalker;
|
class TreeWalker;
|
||||||
class UndoManager;
|
class UndoManager;
|
||||||
|
class XPathEvaluator;
|
||||||
template<typename> class OwningNonNull;
|
template<typename> class OwningNonNull;
|
||||||
template<typename> class Sequence;
|
template<typename> class Sequence;
|
||||||
|
|
||||||
@ -2171,6 +2172,8 @@ protected:
|
|||||||
return mContentType;
|
return mContentType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mozilla::dom::XPathEvaluator* XPathEvaluator();
|
||||||
|
|
||||||
nsCString mReferrer;
|
nsCString mReferrer;
|
||||||
nsString mLastModified;
|
nsString mLastModified;
|
||||||
|
|
||||||
@ -2426,6 +2429,8 @@ protected:
|
|||||||
uint8_t mDefaultElementType;
|
uint8_t mDefaultElementType;
|
||||||
|
|
||||||
uint32_t mInSyncOperationCount;
|
uint32_t mInSyncOperationCount;
|
||||||
|
|
||||||
|
nsRefPtr<mozilla::dom::XPathEvaluator> mXPathEvaluator;
|
||||||
};
|
};
|
||||||
|
|
||||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocument, NS_IDOCUMENT_IID)
|
NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocument, NS_IDOCUMENT_IID)
|
||||||
|
@ -1,43 +0,0 @@
|
|||||||
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
||||||
|
|
||||||
#ifndef nsIXPathEvaluatorInternal_h__
|
|
||||||
#define nsIXPathEvaluatorInternal_h__
|
|
||||||
|
|
||||||
#include "nsCOMArray.h"
|
|
||||||
#include "nsTArray.h"
|
|
||||||
#include "nsStringGlue.h"
|
|
||||||
|
|
||||||
class nsIDOMDocument;
|
|
||||||
class nsIDOMXPathExpression;
|
|
||||||
class nsIDOMXPathNSResolver;
|
|
||||||
|
|
||||||
#define NS_IXPATHEVALUATORINTERNAL_IID \
|
|
||||||
{0xb4b72daa, 0x65d6, 0x440f, \
|
|
||||||
{ 0xb6, 0x08, 0xe2, 0xee, 0x9a, 0x82, 0xf3, 0x13 }}
|
|
||||||
|
|
||||||
class nsIXPathEvaluatorInternal : public nsISupports
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IXPATHEVALUATORINTERNAL_IID)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the document this evaluator corresponds to
|
|
||||||
*/
|
|
||||||
NS_IMETHOD SetDocument(nsIDOMDocument* aDocument) = 0;
|
|
||||||
|
|
||||||
NS_IMETHOD CreateExpression(const nsAString &aExpression,
|
|
||||||
nsIDOMXPathNSResolver *aResolver,
|
|
||||||
nsTArray<nsString> *aNamespaceURIs,
|
|
||||||
nsTArray<nsCString> *aContractIDs,
|
|
||||||
nsCOMArray<nsISupports> *aState,
|
|
||||||
nsIDOMXPathExpression **aResult) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIXPathEvaluatorInternal,
|
|
||||||
NS_IXPATHEVALUATORINTERNAL_IID)
|
|
||||||
|
|
||||||
#endif //nsIXPathEvaluatorInternal_h__
|
|
@ -27,6 +27,7 @@ LOCAL_INCLUDES += \
|
|||||||
-I$(topsrcdir)/content/xbl/src \
|
-I$(topsrcdir)/content/xbl/src \
|
||||||
-I$(topsrcdir)/content/xml/content/src \
|
-I$(topsrcdir)/content/xml/content/src \
|
||||||
-I$(topsrcdir)/content/xml/document/src \
|
-I$(topsrcdir)/content/xml/document/src \
|
||||||
|
-I$(topsrcdir)/content/xslt/src/xpath \
|
||||||
-I$(topsrcdir)/content/xul/content/src \
|
-I$(topsrcdir)/content/xul/content/src \
|
||||||
-I$(topsrcdir)/content/xul/document/src \
|
-I$(topsrcdir)/content/xul/document/src \
|
||||||
-I$(topsrcdir)/dom/base \
|
-I$(topsrcdir)/dom/base \
|
||||||
|
@ -99,10 +99,8 @@
|
|||||||
#include "nsBidiUtils.h"
|
#include "nsBidiUtils.h"
|
||||||
|
|
||||||
#include "nsIDOMUserDataHandler.h"
|
#include "nsIDOMUserDataHandler.h"
|
||||||
#include "nsIDOMXPathEvaluator.h"
|
|
||||||
#include "nsIDOMXPathExpression.h"
|
#include "nsIDOMXPathExpression.h"
|
||||||
#include "nsIDOMXPathNSResolver.h"
|
#include "nsIDOMXPathNSResolver.h"
|
||||||
#include "nsIXPathEvaluatorInternal.h"
|
|
||||||
#include "nsIParserService.h"
|
#include "nsIParserService.h"
|
||||||
#include "nsContentCreatorFunctions.h"
|
#include "nsContentCreatorFunctions.h"
|
||||||
|
|
||||||
@ -213,6 +211,7 @@
|
|||||||
#include "nsIHttpChannelInternal.h"
|
#include "nsIHttpChannelInternal.h"
|
||||||
#include "nsISecurityConsoleMessage.h"
|
#include "nsISecurityConsoleMessage.h"
|
||||||
#include "nsCharSeparatedTokenizer.h"
|
#include "nsCharSeparatedTokenizer.h"
|
||||||
|
#include "mozilla/dom/XPathEvaluator.h"
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
using namespace mozilla::dom;
|
using namespace mozilla::dom;
|
||||||
@ -1582,23 +1581,11 @@ NS_INTERFACE_TABLE_HEAD(nsDocument)
|
|||||||
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIMutationObserver)
|
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIMutationObserver)
|
||||||
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIApplicationCacheContainer)
|
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIApplicationCacheContainer)
|
||||||
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIObserver)
|
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIObserver)
|
||||||
|
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDOMXPathEvaluator)
|
||||||
NS_INTERFACE_TABLE_END
|
NS_INTERFACE_TABLE_END
|
||||||
NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(nsDocument)
|
NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(nsDocument)
|
||||||
NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOMXPathNSResolver,
|
NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOMXPathNSResolver,
|
||||||
new nsNode3Tearoff(this))
|
new nsNode3Tearoff(this))
|
||||||
if (aIID.Equals(NS_GET_IID(nsIDOMXPathEvaluator)) ||
|
|
||||||
aIID.Equals(NS_GET_IID(nsIXPathEvaluatorInternal))) {
|
|
||||||
if (!mXPathEvaluatorTearoff) {
|
|
||||||
nsresult rv;
|
|
||||||
mXPathEvaluatorTearoff =
|
|
||||||
do_CreateInstance(NS_XPATH_EVALUATOR_CONTRACTID,
|
|
||||||
static_cast<nsIDocument *>(this), &rv);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
}
|
|
||||||
|
|
||||||
return mXPathEvaluatorTearoff->QueryInterface(aIID, aInstancePtr);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
NS_INTERFACE_MAP_END
|
NS_INTERFACE_MAP_END
|
||||||
|
|
||||||
|
|
||||||
@ -1784,7 +1771,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsDocument)
|
|||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChannel)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChannel)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStyleAttrStyleSheet)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStyleAttrStyleSheet)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mXPathEvaluatorTearoff)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mXPathEvaluator)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLayoutHistoryState)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLayoutHistoryState)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOnloadBlocker)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOnloadBlocker)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFirstBaseNodeWithHref)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFirstBaseNodeWithHref)
|
||||||
@ -1871,7 +1858,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDocument)
|
|||||||
}
|
}
|
||||||
tmp->mFirstChild = nullptr;
|
tmp->mFirstChild = nullptr;
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mXPathEvaluatorTearoff)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mXPathEvaluator)
|
||||||
tmp->mCachedRootElement = nullptr; // Avoid a dangling pointer
|
tmp->mCachedRootElement = nullptr; // Avoid a dangling pointer
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDisplayDocument)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDisplayDocument)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mFirstBaseNodeWithHref)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mFirstBaseNodeWithHref)
|
||||||
@ -11285,31 +11272,14 @@ nsIDocument::CreateExpression(const nsAString& aExpression,
|
|||||||
nsIDOMXPathNSResolver* aResolver,
|
nsIDOMXPathNSResolver* aResolver,
|
||||||
ErrorResult& rv)
|
ErrorResult& rv)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIDOMXPathEvaluator> evaluator = do_QueryInterface(this);
|
return XPathEvaluator()->CreateExpression(aExpression, aResolver, rv);
|
||||||
if (!evaluator) {
|
|
||||||
rv.Throw(NS_ERROR_FAILURE);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMXPathExpression> expr;
|
|
||||||
rv = evaluator->CreateExpression(aExpression, aResolver, getter_AddRefs(expr));
|
|
||||||
return expr.forget();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<nsIDOMXPathNSResolver>
|
already_AddRefed<nsIDOMXPathNSResolver>
|
||||||
nsIDocument::CreateNSResolver(nsINode* aNodeResolver,
|
nsIDocument::CreateNSResolver(nsINode* aNodeResolver,
|
||||||
ErrorResult& rv)
|
ErrorResult& rv)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIDOMXPathEvaluator> evaluator = do_QueryInterface(this);
|
return XPathEvaluator()->CreateNSResolver(aNodeResolver, rv);
|
||||||
if (!evaluator) {
|
|
||||||
rv.Throw(NS_ERROR_FAILURE);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMNode> nodeResolver = do_QueryInterface(aNodeResolver);
|
|
||||||
nsCOMPtr<nsIDOMXPathNSResolver> res;
|
|
||||||
rv = evaluator->CreateNSResolver(nodeResolver, getter_AddRefs(res));
|
|
||||||
return res.forget();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<nsISupports>
|
already_AddRefed<nsISupports>
|
||||||
@ -11317,19 +11287,34 @@ nsIDocument::Evaluate(const nsAString& aExpression, nsINode* aContextNode,
|
|||||||
nsIDOMXPathNSResolver* aResolver, uint16_t aType,
|
nsIDOMXPathNSResolver* aResolver, uint16_t aType,
|
||||||
nsISupports* aResult, ErrorResult& rv)
|
nsISupports* aResult, ErrorResult& rv)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIDOMXPathEvaluator> evaluator = do_QueryInterface(this);
|
return XPathEvaluator()->Evaluate(aExpression, aContextNode, aResolver, aType,
|
||||||
if (!evaluator) {
|
aResult, rv);
|
||||||
rv.Throw(NS_ERROR_FAILURE);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMNode> contextNode = do_QueryInterface(aContextNode);
|
|
||||||
nsCOMPtr<nsISupports> res;
|
|
||||||
rv = evaluator->Evaluate(aExpression, contextNode, aResolver, aType,
|
|
||||||
aResult, getter_AddRefs(res));
|
|
||||||
return res.forget();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsDocument::CreateExpression(const nsAString& aExpression,
|
||||||
|
nsIDOMXPathNSResolver* aResolver,
|
||||||
|
nsIDOMXPathExpression** aResult)
|
||||||
|
{
|
||||||
|
return XPathEvaluator()->CreateExpression(aExpression, aResolver, aResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsDocument::CreateNSResolver(nsIDOMNode* aNodeResolver,
|
||||||
|
nsIDOMXPathNSResolver** aResult)
|
||||||
|
{
|
||||||
|
return XPathEvaluator()->CreateNSResolver(aNodeResolver, aResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsDocument::Evaluate(const nsAString& aExpression, nsIDOMNode* aContextNode,
|
||||||
|
nsIDOMXPathNSResolver* aResolver, uint16_t aType,
|
||||||
|
nsISupports* aInResult, nsISupports** aResult)
|
||||||
|
{
|
||||||
|
return XPathEvaluator()->Evaluate(aExpression, aContextNode, aResolver, aType,
|
||||||
|
aInResult, aResult);
|
||||||
|
}
|
||||||
|
|
||||||
// This is just a hack around the fact that window.document is not
|
// This is just a hack around the fact that window.document is not
|
||||||
// [Unforgeable] yet.
|
// [Unforgeable] yet.
|
||||||
JSObject*
|
JSObject*
|
||||||
@ -11381,6 +11366,15 @@ nsIDocument::WrapObject(JSContext *aCx, JS::Handle<JSObject*> aScope)
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XPathEvaluator*
|
||||||
|
nsIDocument::XPathEvaluator()
|
||||||
|
{
|
||||||
|
if (!mXPathEvaluator) {
|
||||||
|
mXPathEvaluator = new dom::XPathEvaluator(this);
|
||||||
|
}
|
||||||
|
return mXPathEvaluator;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
MarkDocumentTreeToBeInSyncOperation(nsIDocument* aDoc, void* aData)
|
MarkDocumentTreeToBeInSyncOperation(nsIDocument* aDoc, void* aData)
|
||||||
{
|
{
|
||||||
|
@ -68,6 +68,7 @@
|
|||||||
#include "nsDataHashtable.h"
|
#include "nsDataHashtable.h"
|
||||||
#include "mozilla/TimeStamp.h"
|
#include "mozilla/TimeStamp.h"
|
||||||
#include "mozilla/Attributes.h"
|
#include "mozilla/Attributes.h"
|
||||||
|
#include "nsIDOMXPathEvaluator.h"
|
||||||
|
|
||||||
#define XML_DECLARATION_BITS_DECLARATION_EXISTS (1 << 0)
|
#define XML_DECLARATION_BITS_DECLARATION_EXISTS (1 << 0)
|
||||||
#define XML_DECLARATION_BITS_ENCODING_EXISTS (1 << 1)
|
#define XML_DECLARATION_BITS_ENCODING_EXISTS (1 << 1)
|
||||||
@ -504,7 +505,8 @@ class nsDocument : public nsIDocument,
|
|||||||
public nsIRadioGroupContainer,
|
public nsIRadioGroupContainer,
|
||||||
public nsIApplicationCacheContainer,
|
public nsIApplicationCacheContainer,
|
||||||
public nsStubMutationObserver,
|
public nsStubMutationObserver,
|
||||||
public nsIObserver
|
public nsIObserver,
|
||||||
|
public nsIDOMXPathEvaluator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef mozilla::dom::Element Element;
|
typedef mozilla::dom::Element Element;
|
||||||
@ -784,6 +786,8 @@ public:
|
|||||||
// nsIObserver
|
// nsIObserver
|
||||||
NS_DECL_NSIOBSERVER
|
NS_DECL_NSIOBSERVER
|
||||||
|
|
||||||
|
NS_DECL_NSIDOMXPATHEVALUATOR
|
||||||
|
|
||||||
virtual nsresult Init();
|
virtual nsresult Init();
|
||||||
|
|
||||||
virtual nsresult CreateElem(const nsAString& aName, nsIAtom *aPrefix,
|
virtual nsresult CreateElem(const nsAString& aName, nsIAtom *aPrefix,
|
||||||
@ -1343,8 +1347,6 @@ private:
|
|||||||
nsDocument(const nsDocument& aOther);
|
nsDocument(const nsDocument& aOther);
|
||||||
nsDocument& operator=(const nsDocument& aOther);
|
nsDocument& operator=(const nsDocument& aOther);
|
||||||
|
|
||||||
nsCOMPtr<nsISupports> mXPathEvaluatorTearoff;
|
|
||||||
|
|
||||||
// The layout history state that should be used by nodes in this
|
// The layout history state that should be used by nodes in this
|
||||||
// document. We only actually store a pointer to it when:
|
// document. We only actually store a pointer to it when:
|
||||||
// 1) We have no script global object.
|
// 1) We have no script global object.
|
||||||
|
@ -25,6 +25,17 @@ public:
|
|||||||
nsCOMPtr<nsIAtom> mPrevAttrValue;
|
nsCOMPtr<nsIAtom> mPrevAttrValue;
|
||||||
nsCOMPtr<nsIAtom> mNewAttrValue;
|
nsCOMPtr<nsIAtom> mNewAttrValue;
|
||||||
unsigned short mAttrChange;
|
unsigned short mAttrChange;
|
||||||
|
|
||||||
|
void AssignMutationEventData(const nsMutationEvent& aEvent, bool aCopyTargets)
|
||||||
|
{
|
||||||
|
AssignEventData(aEvent, aCopyTargets);
|
||||||
|
|
||||||
|
mRelatedNode = aEvent.mRelatedNode;
|
||||||
|
mAttrName = aEvent.mAttrName;
|
||||||
|
mPrevAttrValue = aEvent.mPrevAttrValue;
|
||||||
|
mNewAttrValue = aEvent.mNewAttrValue;
|
||||||
|
mAttrChange = aEvent.mAttrChange;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NS_MUTATION_START 1800
|
#define NS_MUTATION_START 1800
|
||||||
|
@ -520,17 +520,6 @@ nsDOMEvent::DuplicatePrivateData()
|
|||||||
newEvent = guiEvent;
|
newEvent = guiEvent;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NS_SCROLLBAR_EVENT:
|
|
||||||
{
|
|
||||||
nsScrollbarEvent* oldScrollbarEvent =
|
|
||||||
static_cast<nsScrollbarEvent*>(mEvent);
|
|
||||||
nsScrollbarEvent* scrollbarEvent =
|
|
||||||
new nsScrollbarEvent(false, msg, nullptr);
|
|
||||||
scrollbarEvent->AssignGUIEventData(*scrollbarEvent, true);
|
|
||||||
scrollbarEvent->position = oldScrollbarEvent->position;
|
|
||||||
newEvent = scrollbarEvent;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case NS_INPUT_EVENT:
|
case NS_INPUT_EVENT:
|
||||||
{
|
{
|
||||||
nsInputEvent* oldInputEvent = static_cast<nsInputEvent*>(mEvent);
|
nsInputEvent* oldInputEvent = static_cast<nsInputEvent*>(mEvent);
|
||||||
@ -561,15 +550,7 @@ nsDOMEvent::DuplicatePrivateData()
|
|||||||
nsDragEvent* oldDragEvent = static_cast<nsDragEvent*>(mEvent);
|
nsDragEvent* oldDragEvent = static_cast<nsDragEvent*>(mEvent);
|
||||||
nsDragEvent* dragEvent =
|
nsDragEvent* dragEvent =
|
||||||
new nsDragEvent(false, msg, nullptr);
|
new nsDragEvent(false, msg, nullptr);
|
||||||
dragEvent->AssignInputEventData(*oldDragEvent, true);
|
dragEvent->AssignDragEventData(*oldDragEvent, true);
|
||||||
dragEvent->dataTransfer = oldDragEvent->dataTransfer;
|
|
||||||
dragEvent->clickCount = oldDragEvent->clickCount;
|
|
||||||
dragEvent->acceptActivation = oldDragEvent->acceptActivation;
|
|
||||||
dragEvent->relatedTarget = oldDragEvent->relatedTarget;
|
|
||||||
dragEvent->button = oldDragEvent->button;
|
|
||||||
dragEvent->buttons = oldDragEvent->buttons;
|
|
||||||
static_cast<nsMouseEvent*>(dragEvent)->inputSource =
|
|
||||||
static_cast<nsMouseEvent*>(oldDragEvent)->inputSource;
|
|
||||||
newEvent = dragEvent;
|
newEvent = dragEvent;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -577,8 +558,7 @@ nsDOMEvent::DuplicatePrivateData()
|
|||||||
{
|
{
|
||||||
nsClipboardEvent* oldClipboardEvent = static_cast<nsClipboardEvent*>(mEvent);
|
nsClipboardEvent* oldClipboardEvent = static_cast<nsClipboardEvent*>(mEvent);
|
||||||
nsClipboardEvent* clipboardEvent = new nsClipboardEvent(false, msg);
|
nsClipboardEvent* clipboardEvent = new nsClipboardEvent(false, msg);
|
||||||
clipboardEvent->AssignEventData(*oldClipboardEvent, true);
|
clipboardEvent->AssignClipboardEventData(*oldClipboardEvent, true);
|
||||||
clipboardEvent->clipboardData = oldClipboardEvent->clipboardData;
|
|
||||||
newEvent = clipboardEvent;
|
newEvent = clipboardEvent;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -587,8 +567,7 @@ nsDOMEvent::DuplicatePrivateData()
|
|||||||
nsScriptErrorEvent* oldScriptErrorEvent =
|
nsScriptErrorEvent* oldScriptErrorEvent =
|
||||||
static_cast<nsScriptErrorEvent*>(mEvent);
|
static_cast<nsScriptErrorEvent*>(mEvent);
|
||||||
nsScriptErrorEvent* scriptErrorEvent = new nsScriptErrorEvent(false, msg);
|
nsScriptErrorEvent* scriptErrorEvent = new nsScriptErrorEvent(false, msg);
|
||||||
scriptErrorEvent->AssignEventData(*oldScriptErrorEvent, true);
|
scriptErrorEvent->AssignScriptErrorEventData(*oldScriptErrorEvent, true);
|
||||||
scriptErrorEvent->lineNr = oldScriptErrorEvent->lineNr;
|
|
||||||
newEvent = scriptErrorEvent;
|
newEvent = scriptErrorEvent;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -596,7 +575,7 @@ nsDOMEvent::DuplicatePrivateData()
|
|||||||
{
|
{
|
||||||
nsTextEvent* oldTextEvent = static_cast<nsTextEvent*>(mEvent);
|
nsTextEvent* oldTextEvent = static_cast<nsTextEvent*>(mEvent);
|
||||||
nsTextEvent* textEvent = new nsTextEvent(false, msg, nullptr);
|
nsTextEvent* textEvent = new nsTextEvent(false, msg, nullptr);
|
||||||
textEvent->AssignGUIEventData(*oldTextEvent, true);
|
textEvent->AssignTextEventData(*oldTextEvent, true);
|
||||||
newEvent = textEvent;
|
newEvent = textEvent;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -606,8 +585,7 @@ nsDOMEvent::DuplicatePrivateData()
|
|||||||
new nsCompositionEvent(false, msg, nullptr);
|
new nsCompositionEvent(false, msg, nullptr);
|
||||||
nsCompositionEvent* oldCompositionEvent =
|
nsCompositionEvent* oldCompositionEvent =
|
||||||
static_cast<nsCompositionEvent*>(mEvent);
|
static_cast<nsCompositionEvent*>(mEvent);
|
||||||
compositionEvent->AssignGUIEventData(*oldCompositionEvent, true);
|
compositionEvent->AssignCompositionEventData(*oldCompositionEvent, true);
|
||||||
compositionEvent->data = oldCompositionEvent->data;
|
|
||||||
newEvent = compositionEvent;
|
newEvent = compositionEvent;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -617,14 +595,7 @@ nsDOMEvent::DuplicatePrivateData()
|
|||||||
static_cast<nsMouseScrollEvent*>(mEvent);
|
static_cast<nsMouseScrollEvent*>(mEvent);
|
||||||
nsMouseScrollEvent* mouseScrollEvent =
|
nsMouseScrollEvent* mouseScrollEvent =
|
||||||
new nsMouseScrollEvent(false, msg, nullptr);
|
new nsMouseScrollEvent(false, msg, nullptr);
|
||||||
mouseScrollEvent->AssignInputEventData(*oldMouseScrollEvent, true);
|
mouseScrollEvent->AssignMouseScrollEventData(*oldMouseScrollEvent, true);
|
||||||
mouseScrollEvent->isHorizontal = oldMouseScrollEvent->isHorizontal;
|
|
||||||
mouseScrollEvent->delta = oldMouseScrollEvent->delta;
|
|
||||||
mouseScrollEvent->relatedTarget = oldMouseScrollEvent->relatedTarget;
|
|
||||||
mouseScrollEvent->button = oldMouseScrollEvent->button;
|
|
||||||
mouseScrollEvent->buttons = oldMouseScrollEvent->buttons;
|
|
||||||
static_cast<nsMouseEvent_base*>(mouseScrollEvent)->inputSource =
|
|
||||||
static_cast<nsMouseEvent_base*>(oldMouseScrollEvent)->inputSource;
|
|
||||||
newEvent = mouseScrollEvent;
|
newEvent = mouseScrollEvent;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -634,24 +605,7 @@ nsDOMEvent::DuplicatePrivateData()
|
|||||||
static_cast<widget::WheelEvent*>(mEvent);
|
static_cast<widget::WheelEvent*>(mEvent);
|
||||||
widget::WheelEvent* wheelEvent =
|
widget::WheelEvent* wheelEvent =
|
||||||
new widget::WheelEvent(false, msg, nullptr);
|
new widget::WheelEvent(false, msg, nullptr);
|
||||||
wheelEvent->AssignInputEventData(*oldWheelEvent, true);
|
wheelEvent->AssignWheelEventData(*oldWheelEvent, true);
|
||||||
wheelEvent->deltaX = oldWheelEvent->deltaX;
|
|
||||||
wheelEvent->deltaY = oldWheelEvent->deltaY;
|
|
||||||
wheelEvent->deltaZ = oldWheelEvent->deltaZ;
|
|
||||||
wheelEvent->deltaMode = oldWheelEvent->deltaMode;
|
|
||||||
wheelEvent->relatedTarget = oldWheelEvent->relatedTarget;
|
|
||||||
wheelEvent->button = oldWheelEvent->button;
|
|
||||||
wheelEvent->buttons = oldWheelEvent->buttons;
|
|
||||||
wheelEvent->modifiers = oldWheelEvent->modifiers;
|
|
||||||
wheelEvent->inputSource = oldWheelEvent->inputSource;
|
|
||||||
wheelEvent->customizedByUserPrefs = oldWheelEvent->customizedByUserPrefs;
|
|
||||||
wheelEvent->isMomentum = oldWheelEvent->isMomentum;
|
|
||||||
wheelEvent->isPixelOnlyDevice = oldWheelEvent->isPixelOnlyDevice;
|
|
||||||
wheelEvent->lineOrPageDeltaX = oldWheelEvent->lineOrPageDeltaX;
|
|
||||||
wheelEvent->lineOrPageDeltaY = oldWheelEvent->lineOrPageDeltaY;
|
|
||||||
wheelEvent->scrollType = oldWheelEvent->scrollType;
|
|
||||||
wheelEvent->overflowDeltaX = oldWheelEvent->overflowDeltaX;
|
|
||||||
wheelEvent->overflowDeltaY = oldWheelEvent->overflowDeltaY;
|
|
||||||
newEvent = wheelEvent;
|
newEvent = wheelEvent;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -661,8 +615,7 @@ nsDOMEvent::DuplicatePrivateData()
|
|||||||
static_cast<nsScrollPortEvent*>(mEvent);
|
static_cast<nsScrollPortEvent*>(mEvent);
|
||||||
nsScrollPortEvent* scrollPortEvent =
|
nsScrollPortEvent* scrollPortEvent =
|
||||||
new nsScrollPortEvent(false, msg, nullptr);
|
new nsScrollPortEvent(false, msg, nullptr);
|
||||||
scrollPortEvent->AssignGUIEventData(*oldScrollPortEvent, true);
|
scrollPortEvent->AssignScrollPortEventData(*oldScrollPortEvent, true);
|
||||||
scrollPortEvent->orient = oldScrollPortEvent->orient;
|
|
||||||
newEvent = scrollPortEvent;
|
newEvent = scrollPortEvent;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -672,8 +625,7 @@ nsDOMEvent::DuplicatePrivateData()
|
|||||||
static_cast<nsScrollAreaEvent*>(mEvent);
|
static_cast<nsScrollAreaEvent*>(mEvent);
|
||||||
nsScrollAreaEvent* scrollAreaEvent =
|
nsScrollAreaEvent* scrollAreaEvent =
|
||||||
new nsScrollAreaEvent(false, msg, nullptr);
|
new nsScrollAreaEvent(false, msg, nullptr);
|
||||||
scrollAreaEvent->AssignGUIEventData(*oldScrollAreaEvent, true);
|
scrollAreaEvent->AssignScrollAreaEventData(*oldScrollAreaEvent, true);
|
||||||
scrollAreaEvent->mArea = oldScrollAreaEvent->mArea;
|
|
||||||
newEvent = scrollAreaEvent;
|
newEvent = scrollAreaEvent;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -682,12 +634,7 @@ nsDOMEvent::DuplicatePrivateData()
|
|||||||
nsMutationEvent* mutationEvent = new nsMutationEvent(false, msg);
|
nsMutationEvent* mutationEvent = new nsMutationEvent(false, msg);
|
||||||
nsMutationEvent* oldMutationEvent =
|
nsMutationEvent* oldMutationEvent =
|
||||||
static_cast<nsMutationEvent*>(mEvent);
|
static_cast<nsMutationEvent*>(mEvent);
|
||||||
mutationEvent->AssignEventData(*oldMutationEvent, true);
|
mutationEvent->AssignMutationEventData(*oldMutationEvent, true);
|
||||||
mutationEvent->mRelatedNode = oldMutationEvent->mRelatedNode;
|
|
||||||
mutationEvent->mAttrName = oldMutationEvent->mAttrName;
|
|
||||||
mutationEvent->mPrevAttrValue = oldMutationEvent->mPrevAttrValue;
|
|
||||||
mutationEvent->mNewAttrValue = oldMutationEvent->mNewAttrValue;
|
|
||||||
mutationEvent->mAttrChange = oldMutationEvent->mAttrChange;
|
|
||||||
newEvent = mutationEvent;
|
newEvent = mutationEvent;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -695,7 +642,7 @@ nsDOMEvent::DuplicatePrivateData()
|
|||||||
{
|
{
|
||||||
nsFormEvent* oldFormEvent = static_cast<nsFormEvent*>(mEvent);
|
nsFormEvent* oldFormEvent = static_cast<nsFormEvent*>(mEvent);
|
||||||
nsFormEvent* formEvent = new nsFormEvent(false, msg);
|
nsFormEvent* formEvent = new nsFormEvent(false, msg);
|
||||||
formEvent->AssignEventData(*oldFormEvent, true);
|
formEvent->AssignFormEventData(*oldFormEvent, true);
|
||||||
newEvent = formEvent;
|
newEvent = formEvent;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -703,9 +650,7 @@ nsDOMEvent::DuplicatePrivateData()
|
|||||||
{
|
{
|
||||||
nsFocusEvent* newFocusEvent = new nsFocusEvent(false, msg);
|
nsFocusEvent* newFocusEvent = new nsFocusEvent(false, msg);
|
||||||
nsFocusEvent* oldFocusEvent = static_cast<nsFocusEvent*>(mEvent);
|
nsFocusEvent* oldFocusEvent = static_cast<nsFocusEvent*>(mEvent);
|
||||||
newFocusEvent->AssignGUIEventData(*oldFocusEvent, true);
|
newFocusEvent->AssignFocusEventData(*oldFocusEvent, true);
|
||||||
newFocusEvent->fromRaise = oldFocusEvent->fromRaise;
|
|
||||||
newFocusEvent->isRefocus = oldFocusEvent->isRefocus;
|
|
||||||
newEvent = newFocusEvent;
|
newEvent = newFocusEvent;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -715,7 +660,7 @@ nsDOMEvent::DuplicatePrivateData()
|
|||||||
nsCommandEvent* commandEvent =
|
nsCommandEvent* commandEvent =
|
||||||
new nsCommandEvent(false, mEvent->userType,
|
new nsCommandEvent(false, mEvent->userType,
|
||||||
oldCommandEvent->command, nullptr);
|
oldCommandEvent->command, nullptr);
|
||||||
commandEvent->AssignGUIEventData(*oldCommandEvent, true);
|
commandEvent->AssignCommandEventData(*oldCommandEvent, true);
|
||||||
newEvent = commandEvent;
|
newEvent = commandEvent;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -723,7 +668,7 @@ nsDOMEvent::DuplicatePrivateData()
|
|||||||
{
|
{
|
||||||
nsUIEvent* oldUIEvent = static_cast<nsUIEvent*>(mEvent);
|
nsUIEvent* oldUIEvent = static_cast<nsUIEvent*>(mEvent);
|
||||||
nsUIEvent* uiEvent = new nsUIEvent(false, msg, oldUIEvent->detail);
|
nsUIEvent* uiEvent = new nsUIEvent(false, msg, oldUIEvent->detail);
|
||||||
uiEvent->AssignEventData(*oldUIEvent, true);
|
uiEvent->AssignUIEventData(*oldUIEvent, true);
|
||||||
newEvent = uiEvent;
|
newEvent = uiEvent;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -741,7 +686,7 @@ nsDOMEvent::DuplicatePrivateData()
|
|||||||
nsUIEvent* oldUIEvent = static_cast<nsUIEvent*>(mEvent);
|
nsUIEvent* oldUIEvent = static_cast<nsUIEvent*>(mEvent);
|
||||||
nsUIEvent* uiEvent = new nsUIEvent(false, msg, 0);
|
nsUIEvent* uiEvent = new nsUIEvent(false, msg, 0);
|
||||||
uiEvent->eventStructType = NS_SMIL_TIME_EVENT;
|
uiEvent->eventStructType = NS_SMIL_TIME_EVENT;
|
||||||
uiEvent->AssignGUIEventData(*oldUIEvent, true);
|
uiEvent->AssignUIEventData(*oldUIEvent, true);
|
||||||
newEvent = uiEvent;
|
newEvent = uiEvent;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -751,10 +696,8 @@ nsDOMEvent::DuplicatePrivateData()
|
|||||||
static_cast<nsSimpleGestureEvent*>(mEvent);
|
static_cast<nsSimpleGestureEvent*>(mEvent);
|
||||||
nsSimpleGestureEvent* simpleGestureEvent =
|
nsSimpleGestureEvent* simpleGestureEvent =
|
||||||
new nsSimpleGestureEvent(false, msg, nullptr, 0, 0.0);
|
new nsSimpleGestureEvent(false, msg, nullptr, 0, 0.0);
|
||||||
simpleGestureEvent->AssignInputEventData(*oldSimpleGestureEvent, true);
|
simpleGestureEvent->
|
||||||
simpleGestureEvent->direction = oldSimpleGestureEvent->direction;
|
AssignSimpleGestureEventData(*oldSimpleGestureEvent, true);
|
||||||
simpleGestureEvent->delta = oldSimpleGestureEvent->delta;
|
|
||||||
simpleGestureEvent->clickCount = oldSimpleGestureEvent->clickCount;
|
|
||||||
newEvent = simpleGestureEvent;
|
newEvent = simpleGestureEvent;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -767,7 +710,7 @@ nsDOMEvent::DuplicatePrivateData()
|
|||||||
oldTransitionEvent->propertyName,
|
oldTransitionEvent->propertyName,
|
||||||
oldTransitionEvent->elapsedTime,
|
oldTransitionEvent->elapsedTime,
|
||||||
oldTransitionEvent->pseudoElement);
|
oldTransitionEvent->pseudoElement);
|
||||||
transitionEvent->AssignEventData(*oldTransitionEvent, true);
|
transitionEvent->AssignTransitionEventData(*oldTransitionEvent, true);
|
||||||
newEvent = transitionEvent;
|
newEvent = transitionEvent;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -780,7 +723,7 @@ nsDOMEvent::DuplicatePrivateData()
|
|||||||
oldAnimationEvent->animationName,
|
oldAnimationEvent->animationName,
|
||||||
oldAnimationEvent->elapsedTime,
|
oldAnimationEvent->elapsedTime,
|
||||||
oldAnimationEvent->pseudoElement);
|
oldAnimationEvent->pseudoElement);
|
||||||
animationEvent->AssignEventData(*oldAnimationEvent, true);
|
animationEvent->AssignAnimationEventData(*oldAnimationEvent, true);
|
||||||
newEvent = animationEvent;
|
newEvent = animationEvent;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -788,7 +731,7 @@ nsDOMEvent::DuplicatePrivateData()
|
|||||||
{
|
{
|
||||||
nsTouchEvent* oldTouchEvent = static_cast<nsTouchEvent*>(mEvent);
|
nsTouchEvent* oldTouchEvent = static_cast<nsTouchEvent*>(mEvent);
|
||||||
nsTouchEvent* touchEvent = new nsTouchEvent(false, oldTouchEvent);
|
nsTouchEvent* touchEvent = new nsTouchEvent(false, oldTouchEvent);
|
||||||
touchEvent->AssignInputEventData(*oldTouchEvent, true);
|
touchEvent->AssignTouchEventData(*oldTouchEvent, true);
|
||||||
newEvent = touchEvent;
|
newEvent = touchEvent;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -460,6 +460,9 @@ nsDOMUIEvent::ComputeModifierState(const nsAString& aModifiersList)
|
|||||||
bool
|
bool
|
||||||
nsDOMUIEvent::GetModifierStateInternal(const nsAString& aKey)
|
nsDOMUIEvent::GetModifierStateInternal(const nsAString& aKey)
|
||||||
{
|
{
|
||||||
|
if (!NS_IS_INPUT_EVENT(mEvent)) {
|
||||||
|
MOZ_CRASH("mEvent must be nsInputEvent or derived class");
|
||||||
|
}
|
||||||
nsInputEvent* inputEvent = static_cast<nsInputEvent*>(mEvent);
|
nsInputEvent* inputEvent = static_cast<nsInputEvent*>(mEvent);
|
||||||
if (aKey.EqualsLiteral(NS_DOM_KEYNAME_SHIFT)) {
|
if (aKey.EqualsLiteral(NS_DOM_KEYNAME_SHIFT)) {
|
||||||
return inputEvent->IsShift();
|
return inputEvent->IsShift();
|
||||||
|
@ -444,11 +444,8 @@ PannerNodeEngine::ComputeConeGain()
|
|||||||
ThreeDPoint sourceToListener = mListenerPosition - mPosition;
|
ThreeDPoint sourceToListener = mListenerPosition - mPosition;
|
||||||
sourceToListener.Normalize();
|
sourceToListener.Normalize();
|
||||||
|
|
||||||
ThreeDPoint normalizedSourceOrientation = mOrientation;
|
|
||||||
normalizedSourceOrientation.Normalize();
|
|
||||||
|
|
||||||
// Angle between the source orientation vector and the source-listener vector
|
// Angle between the source orientation vector and the source-listener vector
|
||||||
double dotProduct = sourceToListener.DotProduct(normalizedSourceOrientation);
|
double dotProduct = sourceToListener.DotProduct(mOrientation);
|
||||||
double angle = 180 * acos(dotProduct) / M_PI;
|
double angle = 180 * acos(dotProduct) / M_PI;
|
||||||
double absAngle = fabs(angle);
|
double absAngle = fabs(angle);
|
||||||
|
|
||||||
|
245
content/xslt/src/xpath/XPathEvaluator.cpp
Normal file
245
content/xslt/src/xpath/XPathEvaluator.cpp
Normal file
@ -0,0 +1,245 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#include "mozilla/dom/XPathEvaluator.h"
|
||||||
|
#include "nsCOMPtr.h"
|
||||||
|
#include "nsIAtom.h"
|
||||||
|
#include "nsXPathExpression.h"
|
||||||
|
#include "nsXPathNSResolver.h"
|
||||||
|
#include "nsXPathResult.h"
|
||||||
|
#include "nsContentCID.h"
|
||||||
|
#include "txExpr.h"
|
||||||
|
#include "txExprParser.h"
|
||||||
|
#include "nsError.h"
|
||||||
|
#include "txURIUtils.h"
|
||||||
|
#include "nsIDocument.h"
|
||||||
|
#include "nsIDOMDocument.h"
|
||||||
|
#include "nsDOMString.h"
|
||||||
|
#include "nsINameSpaceManager.h"
|
||||||
|
#include "nsContentUtils.h"
|
||||||
|
#include "mozilla/dom/XPathEvaluatorBinding.h"
|
||||||
|
|
||||||
|
extern nsresult
|
||||||
|
TX_ResolveFunctionCallXPCOM(const nsCString &aContractID, int32_t aNamespaceID,
|
||||||
|
nsIAtom *aName, nsISupports *aState,
|
||||||
|
FunctionCall **aFunction);
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace dom {
|
||||||
|
|
||||||
|
// txIParseContext implementation
|
||||||
|
class XPathEvaluatorParseContext : public txIParseContext
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
XPathEvaluatorParseContext(nsIDOMXPathNSResolver* aResolver,
|
||||||
|
bool aIsCaseSensitive)
|
||||||
|
: mResolver(aResolver),
|
||||||
|
mLastError(NS_OK),
|
||||||
|
mIsCaseSensitive(aIsCaseSensitive)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult getError()
|
||||||
|
{
|
||||||
|
return mLastError;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult resolveNamespacePrefix(nsIAtom* aPrefix, int32_t& aID);
|
||||||
|
nsresult resolveFunctionCall(nsIAtom* aName, int32_t aID,
|
||||||
|
FunctionCall** aFunction);
|
||||||
|
bool caseInsensitiveNameTests();
|
||||||
|
void SetErrorOffset(uint32_t aOffset);
|
||||||
|
|
||||||
|
private:
|
||||||
|
nsIDOMXPathNSResolver* mResolver;
|
||||||
|
nsresult mLastError;
|
||||||
|
bool mIsCaseSensitive;
|
||||||
|
};
|
||||||
|
|
||||||
|
NS_IMPL_ISUPPORTS1(XPathEvaluator, nsIDOMXPathEvaluator)
|
||||||
|
|
||||||
|
XPathEvaluator::XPathEvaluator(nsIDocument* aDocument)
|
||||||
|
: mDocument(do_GetWeakReference(aDocument))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
XPathEvaluator::CreateNSResolver(nsIDOMNode *aNodeResolver,
|
||||||
|
nsIDOMXPathNSResolver **aResult)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG(aNodeResolver);
|
||||||
|
if (!nsContentUtils::CanCallerAccess(aNodeResolver))
|
||||||
|
return NS_ERROR_DOM_SECURITY_ERR;
|
||||||
|
|
||||||
|
*aResult = new nsXPathNSResolver(aNodeResolver);
|
||||||
|
NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
|
||||||
|
|
||||||
|
NS_ADDREF(*aResult);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
XPathEvaluator::Evaluate(const nsAString & aExpression,
|
||||||
|
nsIDOMNode *aContextNode,
|
||||||
|
nsIDOMXPathNSResolver *aResolver,
|
||||||
|
uint16_t aType,
|
||||||
|
nsISupports *aInResult,
|
||||||
|
nsISupports **aResult)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIDOMXPathExpression> expression;
|
||||||
|
nsresult rv = CreateExpression(aExpression, aResolver,
|
||||||
|
getter_AddRefs(expression));
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
return expression->Evaluate(aContextNode, aType, aInResult, aResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
XPathEvaluator::CreateExpression(const nsAString & aExpression,
|
||||||
|
nsIDOMXPathNSResolver *aResolver,
|
||||||
|
nsIDOMXPathExpression **aResult)
|
||||||
|
{
|
||||||
|
nsresult rv;
|
||||||
|
if (!mRecycler) {
|
||||||
|
nsRefPtr<txResultRecycler> recycler = new txResultRecycler;
|
||||||
|
NS_ENSURE_TRUE(recycler, NS_ERROR_OUT_OF_MEMORY);
|
||||||
|
|
||||||
|
rv = recycler->init();
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
mRecycler = recycler;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
|
||||||
|
XPathEvaluatorParseContext pContext(aResolver, !(doc && doc->IsHTML()));
|
||||||
|
|
||||||
|
nsAutoPtr<Expr> expression;
|
||||||
|
rv = txExprParser::createExpr(PromiseFlatString(aExpression), &pContext,
|
||||||
|
getter_Transfers(expression));
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
if (rv == NS_ERROR_DOM_NAMESPACE_ERR) {
|
||||||
|
return NS_ERROR_DOM_NAMESPACE_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_ERROR_DOM_INVALID_EXPRESSION_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIDOMDocument> document = do_QueryReferent(mDocument);
|
||||||
|
|
||||||
|
*aResult = new nsXPathExpression(expression, mRecycler, document);
|
||||||
|
if (!*aResult) {
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_ADDREF(*aResult);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSObject*
|
||||||
|
XPathEvaluator::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
|
||||||
|
{
|
||||||
|
return dom::XPathEvaluatorBinding::Wrap(aCx, aScope, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
already_AddRefed<XPathEvaluator>
|
||||||
|
XPathEvaluator::Constructor(const GlobalObject& aGlobal,
|
||||||
|
ErrorResult& rv)
|
||||||
|
{
|
||||||
|
nsRefPtr<XPathEvaluator> newObj = new XPathEvaluator(nullptr);
|
||||||
|
return newObj.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
already_AddRefed<nsIDOMXPathExpression>
|
||||||
|
XPathEvaluator::CreateExpression(const nsAString& aExpression,
|
||||||
|
nsIDOMXPathNSResolver* aResolver,
|
||||||
|
ErrorResult& rv)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIDOMXPathExpression> expr;
|
||||||
|
rv = CreateExpression(aExpression, aResolver, getter_AddRefs(expr));
|
||||||
|
return expr.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
already_AddRefed<nsIDOMXPathNSResolver>
|
||||||
|
XPathEvaluator::CreateNSResolver(nsINode* aNodeResolver,
|
||||||
|
ErrorResult& rv)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIDOMNode> nodeResolver = do_QueryInterface(aNodeResolver);
|
||||||
|
nsCOMPtr<nsIDOMXPathNSResolver> res;
|
||||||
|
rv = CreateNSResolver(nodeResolver, getter_AddRefs(res));
|
||||||
|
return res.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
already_AddRefed<nsISupports>
|
||||||
|
XPathEvaluator::Evaluate(const nsAString& aExpression, nsINode* aContextNode,
|
||||||
|
nsIDOMXPathNSResolver* aResolver, uint16_t aType,
|
||||||
|
nsISupports* aResult, ErrorResult& rv)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIDOMNode> contextNode = do_QueryInterface(aContextNode);
|
||||||
|
nsCOMPtr<nsISupports> res;
|
||||||
|
rv = Evaluate(aExpression, contextNode, aResolver, aType,
|
||||||
|
aResult, getter_AddRefs(res));
|
||||||
|
return res.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Implementation of txIParseContext private to XPathEvaluator, based on a
|
||||||
|
* nsIDOMXPathNSResolver
|
||||||
|
*/
|
||||||
|
|
||||||
|
nsresult XPathEvaluatorParseContext::resolveNamespacePrefix
|
||||||
|
(nsIAtom* aPrefix, int32_t& aID)
|
||||||
|
{
|
||||||
|
aID = kNameSpaceID_Unknown;
|
||||||
|
|
||||||
|
if (!mResolver) {
|
||||||
|
return NS_ERROR_DOM_NAMESPACE_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsAutoString prefix;
|
||||||
|
if (aPrefix) {
|
||||||
|
aPrefix->ToString(prefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsVoidableString ns;
|
||||||
|
nsresult rv = mResolver->LookupNamespaceURI(prefix, ns);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
if (DOMStringIsNull(ns)) {
|
||||||
|
return NS_ERROR_DOM_NAMESPACE_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ns.IsEmpty()) {
|
||||||
|
aID = kNameSpaceID_None;
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the namespaceID for the URI
|
||||||
|
return nsContentUtils::NameSpaceManager()->RegisterNameSpace(ns, aID);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
XPathEvaluatorParseContext::resolveFunctionCall(nsIAtom* aName,
|
||||||
|
int32_t aID,
|
||||||
|
FunctionCall** aFn)
|
||||||
|
{
|
||||||
|
return NS_ERROR_XPATH_UNKNOWN_FUNCTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool XPathEvaluatorParseContext::caseInsensitiveNameTests()
|
||||||
|
{
|
||||||
|
return !mIsCaseSensitive;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
XPathEvaluatorParseContext::SetErrorOffset(uint32_t aOffset)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace dom
|
||||||
|
} // namespace mozilla
|
75
content/xslt/src/xpath/XPathEvaluator.h
Normal file
75
content/xslt/src/xpath/XPathEvaluator.h
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#ifndef mozilla_dom_XPathEvaluator_h
|
||||||
|
#define mozilla_dom_XPathEvaluator_h
|
||||||
|
|
||||||
|
#include "nsIDOMXPathEvaluator.h"
|
||||||
|
#include "nsIWeakReference.h"
|
||||||
|
#include "nsAutoPtr.h"
|
||||||
|
#include "nsString.h"
|
||||||
|
#include "mozilla/Attributes.h"
|
||||||
|
#include "mozilla/ErrorResult.h"
|
||||||
|
#include "nsIDocument.h"
|
||||||
|
|
||||||
|
class nsINode;
|
||||||
|
class txResultRecycler;
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace dom {
|
||||||
|
|
||||||
|
class GlobalObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class for evaluating an XPath expression string
|
||||||
|
*/
|
||||||
|
class XPathEvaluator MOZ_FINAL : public nsIDOMXPathEvaluator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
XPathEvaluator(nsIDocument* aDocument = nullptr);
|
||||||
|
|
||||||
|
NS_DECL_ISUPPORTS
|
||||||
|
|
||||||
|
// nsIDOMXPathEvaluator interface
|
||||||
|
NS_DECL_NSIDOMXPATHEVALUATOR
|
||||||
|
|
||||||
|
// WebIDL API
|
||||||
|
JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope);
|
||||||
|
already_AddRefed<nsIDocument> GetParentObject()
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
|
||||||
|
return doc.forget();
|
||||||
|
}
|
||||||
|
static already_AddRefed<XPathEvaluator>
|
||||||
|
Constructor(const GlobalObject& aGlobal, ErrorResult& rv);
|
||||||
|
already_AddRefed<nsIDOMXPathExpression>
|
||||||
|
CreateExpression(const nsAString& aExpression,
|
||||||
|
nsIDOMXPathNSResolver* aResolver,
|
||||||
|
ErrorResult& rv);
|
||||||
|
already_AddRefed<nsIDOMXPathNSResolver>
|
||||||
|
CreateNSResolver(nsINode* aNodeResolver, ErrorResult& rv);
|
||||||
|
already_AddRefed<nsISupports>
|
||||||
|
Evaluate(const nsAString& aExpression, nsINode* aContextNode,
|
||||||
|
nsIDOMXPathNSResolver* aResolver, uint16_t aType,
|
||||||
|
nsISupports* aResult, ErrorResult& rv);
|
||||||
|
private:
|
||||||
|
nsWeakPtr mDocument;
|
||||||
|
nsRefPtr<txResultRecycler> mRecycler;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline nsISupports*
|
||||||
|
ToSupports(XPathEvaluator* e)
|
||||||
|
{
|
||||||
|
return static_cast<nsIDOMXPathEvaluator*>(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* d0a75e02-b5e7-11d5-a7f2-df109fb8a1fc */
|
||||||
|
#define TRANSFORMIIX_XPATH_EVALUATOR_CID \
|
||||||
|
{ 0xd0a75e02, 0xb5e7, 0x11d5, { 0xa7, 0xf2, 0xdf, 0x10, 0x9f, 0xb8, 0xa1, 0xfc } }
|
||||||
|
|
||||||
|
} // namespace dom
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif /* mozilla_dom_XPathEvaluator_h */
|
@ -6,8 +6,12 @@
|
|||||||
|
|
||||||
MODULE = 'transformiix'
|
MODULE = 'transformiix'
|
||||||
|
|
||||||
|
EXPORTS.mozilla.dom += [
|
||||||
|
'XPathEvaluator.h',
|
||||||
|
]
|
||||||
|
|
||||||
CPP_SOURCES += [
|
CPP_SOURCES += [
|
||||||
'nsXPathEvaluator.cpp',
|
'XPathEvaluator.cpp',
|
||||||
'nsXPathExpression.cpp',
|
'nsXPathExpression.cpp',
|
||||||
'nsXPathNSResolver.cpp',
|
'nsXPathNSResolver.cpp',
|
||||||
'nsXPathResult.cpp',
|
'nsXPathResult.cpp',
|
||||||
|
@ -1,337 +0,0 @@
|
|||||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
||||||
|
|
||||||
#include "nsXPathEvaluator.h"
|
|
||||||
#include "nsCOMPtr.h"
|
|
||||||
#include "nsIAtom.h"
|
|
||||||
#include "nsXPathExpression.h"
|
|
||||||
#include "nsXPathNSResolver.h"
|
|
||||||
#include "nsXPathResult.h"
|
|
||||||
#include "nsContentCID.h"
|
|
||||||
#include "txExpr.h"
|
|
||||||
#include "txExprParser.h"
|
|
||||||
#include "nsError.h"
|
|
||||||
#include "txURIUtils.h"
|
|
||||||
#include "nsIDocument.h"
|
|
||||||
#include "nsIDOMDocument.h"
|
|
||||||
#include "nsDOMString.h"
|
|
||||||
#include "nsINameSpaceManager.h"
|
|
||||||
#include "nsContentUtils.h"
|
|
||||||
#include "mozilla/dom/XPathEvaluatorBinding.h"
|
|
||||||
|
|
||||||
using namespace mozilla;
|
|
||||||
using namespace mozilla::dom;
|
|
||||||
|
|
||||||
// txIParseContext implementation
|
|
||||||
class nsXPathEvaluatorParseContext : public txIParseContext
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
nsXPathEvaluatorParseContext(nsIDOMXPathNSResolver* aResolver,
|
|
||||||
nsTArray<int32_t> *aNamespaceIDs,
|
|
||||||
nsTArray<nsCString> *aContractIDs,
|
|
||||||
nsCOMArray<nsISupports> *aState,
|
|
||||||
bool aIsCaseSensitive)
|
|
||||||
: mResolver(aResolver),
|
|
||||||
mNamespaceIDs(aNamespaceIDs),
|
|
||||||
mContractIDs(aContractIDs),
|
|
||||||
mState(aState),
|
|
||||||
mLastError(NS_OK),
|
|
||||||
mIsCaseSensitive(aIsCaseSensitive)
|
|
||||||
{
|
|
||||||
NS_ASSERTION(mContractIDs ||
|
|
||||||
(!mNamespaceIDs || mNamespaceIDs->Length() == 0),
|
|
||||||
"Need contract IDs if there are namespaces.");
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult getError()
|
|
||||||
{
|
|
||||||
return mLastError;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult resolveNamespacePrefix(nsIAtom* aPrefix, int32_t& aID);
|
|
||||||
nsresult resolveFunctionCall(nsIAtom* aName, int32_t aID,
|
|
||||||
FunctionCall** aFunction);
|
|
||||||
bool caseInsensitiveNameTests();
|
|
||||||
void SetErrorOffset(uint32_t aOffset);
|
|
||||||
|
|
||||||
private:
|
|
||||||
nsIDOMXPathNSResolver* mResolver;
|
|
||||||
nsTArray<int32_t> *mNamespaceIDs;
|
|
||||||
nsTArray<nsCString> *mContractIDs;
|
|
||||||
nsCOMArray<nsISupports> *mState;
|
|
||||||
nsresult mLastError;
|
|
||||||
bool mIsCaseSensitive;
|
|
||||||
};
|
|
||||||
|
|
||||||
NS_IMPL_AGGREGATED(nsXPathEvaluator)
|
|
||||||
NS_INTERFACE_MAP_BEGIN_AGGREGATED(nsXPathEvaluator)
|
|
||||||
NS_INTERFACE_MAP_ENTRY(nsIDOMXPathEvaluator)
|
|
||||||
NS_INTERFACE_MAP_ENTRY(nsIXPathEvaluatorInternal)
|
|
||||||
NS_INTERFACE_MAP_END
|
|
||||||
|
|
||||||
nsXPathEvaluator::nsXPathEvaluator(nsISupports *aOuter)
|
|
||||||
{
|
|
||||||
NS_INIT_AGGREGATED(aOuter);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
nsXPathEvaluator::Init()
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIDOMDocument> document = do_QueryInterface(fOuter);
|
|
||||||
|
|
||||||
return document ? SetDocument(document) : NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsXPathEvaluator::CreateExpression(const nsAString & aExpression,
|
|
||||||
nsIDOMXPathNSResolver *aResolver,
|
|
||||||
nsIDOMXPathExpression **aResult)
|
|
||||||
{
|
|
||||||
return CreateExpression(aExpression, aResolver, (nsTArray<int32_t>*)nullptr,
|
|
||||||
nullptr, nullptr, aResult);
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsXPathEvaluator::CreateNSResolver(nsIDOMNode *aNodeResolver,
|
|
||||||
nsIDOMXPathNSResolver **aResult)
|
|
||||||
{
|
|
||||||
NS_ENSURE_ARG(aNodeResolver);
|
|
||||||
if (!nsContentUtils::CanCallerAccess(aNodeResolver))
|
|
||||||
return NS_ERROR_DOM_SECURITY_ERR;
|
|
||||||
|
|
||||||
*aResult = new nsXPathNSResolver(aNodeResolver);
|
|
||||||
NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
|
|
||||||
|
|
||||||
NS_ADDREF(*aResult);
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsXPathEvaluator::Evaluate(const nsAString & aExpression,
|
|
||||||
nsIDOMNode *aContextNode,
|
|
||||||
nsIDOMXPathNSResolver *aResolver,
|
|
||||||
uint16_t aType,
|
|
||||||
nsISupports *aInResult,
|
|
||||||
nsISupports **aResult)
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIDOMXPathExpression> expression;
|
|
||||||
nsresult rv = CreateExpression(aExpression, aResolver,
|
|
||||||
getter_AddRefs(expression));
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
return expression->Evaluate(aContextNode, aType, aInResult, aResult);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsXPathEvaluator::SetDocument(nsIDOMDocument* aDocument)
|
|
||||||
{
|
|
||||||
mDocument = do_GetWeakReference(aDocument);
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsXPathEvaluator::CreateExpression(const nsAString & aExpression,
|
|
||||||
nsIDOMXPathNSResolver *aResolver,
|
|
||||||
nsTArray<nsString> *aNamespaceURIs,
|
|
||||||
nsTArray<nsCString> *aContractIDs,
|
|
||||||
nsCOMArray<nsISupports> *aState,
|
|
||||||
nsIDOMXPathExpression **aResult)
|
|
||||||
{
|
|
||||||
nsTArray<int32_t> namespaceIDs;
|
|
||||||
if (aNamespaceURIs) {
|
|
||||||
uint32_t count = aNamespaceURIs->Length();
|
|
||||||
|
|
||||||
if (!aContractIDs || aContractIDs->Length() != count) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!namespaceIDs.SetLength(count)) {
|
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t i;
|
|
||||||
for (i = 0; i < count; ++i) {
|
|
||||||
if (aContractIDs->ElementAt(i).IsEmpty()) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsContentUtils::NameSpaceManager()->RegisterNameSpace(aNamespaceURIs->ElementAt(i), namespaceIDs[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return CreateExpression(aExpression, aResolver, &namespaceIDs, aContractIDs,
|
|
||||||
aState, aResult);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
nsXPathEvaluator::CreateExpression(const nsAString & aExpression,
|
|
||||||
nsIDOMXPathNSResolver *aResolver,
|
|
||||||
nsTArray<int32_t> *aNamespaceIDs,
|
|
||||||
nsTArray<nsCString> *aContractIDs,
|
|
||||||
nsCOMArray<nsISupports> *aState,
|
|
||||||
nsIDOMXPathExpression **aResult)
|
|
||||||
{
|
|
||||||
nsresult rv;
|
|
||||||
if (!mRecycler) {
|
|
||||||
nsRefPtr<txResultRecycler> recycler = new txResultRecycler;
|
|
||||||
NS_ENSURE_TRUE(recycler, NS_ERROR_OUT_OF_MEMORY);
|
|
||||||
|
|
||||||
rv = recycler->init();
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
mRecycler = recycler;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
|
|
||||||
nsXPathEvaluatorParseContext pContext(aResolver, aNamespaceIDs,
|
|
||||||
aContractIDs, aState,
|
|
||||||
!(doc && doc->IsHTML()));
|
|
||||||
|
|
||||||
nsAutoPtr<Expr> expression;
|
|
||||||
rv = txExprParser::createExpr(PromiseFlatString(aExpression), &pContext,
|
|
||||||
getter_Transfers(expression));
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
if (rv == NS_ERROR_DOM_NAMESPACE_ERR) {
|
|
||||||
return NS_ERROR_DOM_NAMESPACE_ERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_ERROR_DOM_INVALID_EXPRESSION_ERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMDocument> document = do_QueryReferent(mDocument);
|
|
||||||
|
|
||||||
*aResult = new nsXPathExpression(expression, mRecycler, document);
|
|
||||||
if (!*aResult) {
|
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_ADDREF(*aResult);
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
JSObject*
|
|
||||||
nsXPathEvaluator::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
|
|
||||||
{
|
|
||||||
return dom::XPathEvaluatorBinding::Wrap(aCx, aScope, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* static */
|
|
||||||
already_AddRefed<nsXPathEvaluator>
|
|
||||||
nsXPathEvaluator::Constructor(const GlobalObject& aGlobal,
|
|
||||||
ErrorResult& rv)
|
|
||||||
{
|
|
||||||
nsRefPtr<nsXPathEvaluator> newObj = new nsXPathEvaluator(nullptr);
|
|
||||||
newObj->Init();
|
|
||||||
return newObj.forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
already_AddRefed<nsIDOMXPathExpression>
|
|
||||||
nsXPathEvaluator::CreateExpression(const nsAString& aExpression,
|
|
||||||
nsIDOMXPathNSResolver* aResolver,
|
|
||||||
ErrorResult& rv)
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIDOMXPathExpression> expr;
|
|
||||||
rv = CreateExpression(aExpression, aResolver, getter_AddRefs(expr));
|
|
||||||
return expr.forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
already_AddRefed<nsIDOMXPathNSResolver>
|
|
||||||
nsXPathEvaluator::CreateNSResolver(nsINode* aNodeResolver,
|
|
||||||
ErrorResult& rv)
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIDOMNode> nodeResolver = do_QueryInterface(aNodeResolver);
|
|
||||||
nsCOMPtr<nsIDOMXPathNSResolver> res;
|
|
||||||
rv = CreateNSResolver(nodeResolver, getter_AddRefs(res));
|
|
||||||
return res.forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
already_AddRefed<nsISupports>
|
|
||||||
nsXPathEvaluator::Evaluate(const nsAString& aExpression, nsINode* aContextNode,
|
|
||||||
nsIDOMXPathNSResolver* aResolver, uint16_t aType,
|
|
||||||
nsISupports* aResult, ErrorResult& rv)
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIDOMNode> contextNode = do_QueryInterface(aContextNode);
|
|
||||||
nsCOMPtr<nsISupports> res;
|
|
||||||
rv = Evaluate(aExpression, contextNode, aResolver, aType,
|
|
||||||
aResult, getter_AddRefs(res));
|
|
||||||
return res.forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Implementation of txIParseContext private to nsXPathEvaluator, based on a
|
|
||||||
* nsIDOMXPathNSResolver
|
|
||||||
*/
|
|
||||||
|
|
||||||
nsresult nsXPathEvaluatorParseContext::resolveNamespacePrefix
|
|
||||||
(nsIAtom* aPrefix, int32_t& aID)
|
|
||||||
{
|
|
||||||
aID = kNameSpaceID_Unknown;
|
|
||||||
|
|
||||||
if (!mResolver) {
|
|
||||||
return NS_ERROR_DOM_NAMESPACE_ERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsAutoString prefix;
|
|
||||||
if (aPrefix) {
|
|
||||||
aPrefix->ToString(prefix);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsVoidableString ns;
|
|
||||||
nsresult rv = mResolver->LookupNamespaceURI(prefix, ns);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
if (DOMStringIsNull(ns)) {
|
|
||||||
return NS_ERROR_DOM_NAMESPACE_ERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ns.IsEmpty()) {
|
|
||||||
aID = kNameSpaceID_None;
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the namespaceID for the URI
|
|
||||||
return nsContentUtils::NameSpaceManager()->RegisterNameSpace(ns, aID);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern nsresult
|
|
||||||
TX_ResolveFunctionCallXPCOM(const nsCString &aContractID, int32_t aNamespaceID,
|
|
||||||
nsIAtom *aName, nsISupports *aState,
|
|
||||||
FunctionCall **aFunction);
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
nsXPathEvaluatorParseContext::resolveFunctionCall(nsIAtom* aName,
|
|
||||||
int32_t aID,
|
|
||||||
FunctionCall** aFn)
|
|
||||||
{
|
|
||||||
nsresult rv = NS_ERROR_XPATH_UNKNOWN_FUNCTION;
|
|
||||||
|
|
||||||
uint32_t i, count = mNamespaceIDs ? mNamespaceIDs->Length() : 0;
|
|
||||||
for (i = 0; i < count; ++i) {
|
|
||||||
if (mNamespaceIDs->ElementAt(i) == aID) {
|
|
||||||
nsISupports *state = mState ? mState->SafeObjectAt(i) : nullptr;
|
|
||||||
rv = TX_ResolveFunctionCallXPCOM(mContractIDs->ElementAt(i), aID,
|
|
||||||
aName, state, aFn);
|
|
||||||
if (NS_SUCCEEDED(rv)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool nsXPathEvaluatorParseContext::caseInsensitiveNameTests()
|
|
||||||
{
|
|
||||||
return !mIsCaseSensitive;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
nsXPathEvaluatorParseContext::SetErrorOffset(uint32_t aOffset)
|
|
||||||
{
|
|
||||||
}
|
|
@ -1,90 +0,0 @@
|
|||||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
||||||
|
|
||||||
#ifndef nsXPathEvaluator_h__
|
|
||||||
#define nsXPathEvaluator_h__
|
|
||||||
|
|
||||||
#include "nsIDOMXPathEvaluator.h"
|
|
||||||
#include "nsIXPathEvaluatorInternal.h"
|
|
||||||
#include "nsIWeakReference.h"
|
|
||||||
#include "nsAutoPtr.h"
|
|
||||||
#include "nsString.h"
|
|
||||||
#include "txResultRecycler.h"
|
|
||||||
#include "nsAgg.h"
|
|
||||||
#include "nsTArray.h"
|
|
||||||
#include "mozilla/Attributes.h"
|
|
||||||
#include "mozilla/ErrorResult.h"
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace dom {
|
|
||||||
class GlobalObject;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
class nsINode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A class for evaluating an XPath expression string
|
|
||||||
*/
|
|
||||||
class nsXPathEvaluator MOZ_FINAL : public nsIDOMXPathEvaluator,
|
|
||||||
public nsIXPathEvaluatorInternal
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
nsXPathEvaluator(nsISupports *aOuter);
|
|
||||||
|
|
||||||
nsresult Init();
|
|
||||||
|
|
||||||
// nsISupports interface (support aggregation)
|
|
||||||
NS_DECL_AGGREGATED
|
|
||||||
|
|
||||||
// nsIDOMXPathEvaluator interface
|
|
||||||
NS_DECL_NSIDOMXPATHEVALUATOR
|
|
||||||
|
|
||||||
// nsIXPathEvaluatorInternal interface
|
|
||||||
NS_IMETHOD SetDocument(nsIDOMDocument* aDocument) MOZ_OVERRIDE;
|
|
||||||
NS_IMETHOD CreateExpression(const nsAString &aExpression,
|
|
||||||
nsIDOMXPathNSResolver *aResolver,
|
|
||||||
nsTArray<nsString> *aNamespaceURIs,
|
|
||||||
nsTArray<nsCString> *aContractIDs,
|
|
||||||
nsCOMArray<nsISupports> *aState,
|
|
||||||
nsIDOMXPathExpression **aResult) MOZ_OVERRIDE;
|
|
||||||
|
|
||||||
// WebIDL API
|
|
||||||
JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope);
|
|
||||||
static already_AddRefed<nsXPathEvaluator>
|
|
||||||
Constructor(const mozilla::dom::GlobalObject& aGlobal,
|
|
||||||
mozilla::ErrorResult& rv);
|
|
||||||
already_AddRefed<nsIDOMXPathExpression>
|
|
||||||
CreateExpression(const nsAString& aExpression,
|
|
||||||
nsIDOMXPathNSResolver* aResolver,
|
|
||||||
mozilla::ErrorResult& rv);
|
|
||||||
already_AddRefed<nsIDOMXPathNSResolver>
|
|
||||||
CreateNSResolver(nsINode* aNodeResolver, mozilla::ErrorResult& rv);
|
|
||||||
already_AddRefed<nsISupports>
|
|
||||||
Evaluate(const nsAString& aExpression, nsINode* aContextNode,
|
|
||||||
nsIDOMXPathNSResolver* aResolver, uint16_t aType,
|
|
||||||
nsISupports* aResult, mozilla::ErrorResult& rv);
|
|
||||||
private:
|
|
||||||
nsresult CreateExpression(const nsAString & aExpression,
|
|
||||||
nsIDOMXPathNSResolver *aResolver,
|
|
||||||
nsTArray<int32_t> *aNamespaceIDs,
|
|
||||||
nsTArray<nsCString> *aContractIDs,
|
|
||||||
nsCOMArray<nsISupports> *aState,
|
|
||||||
nsIDOMXPathExpression **aResult);
|
|
||||||
|
|
||||||
nsWeakPtr mDocument;
|
|
||||||
nsRefPtr<txResultRecycler> mRecycler;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline nsISupports*
|
|
||||||
ToSupports(nsXPathEvaluator* e)
|
|
||||||
{
|
|
||||||
return static_cast<nsIDOMXPathEvaluator*>(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* d0a75e02-b5e7-11d5-a7f2-df109fb8a1fc */
|
|
||||||
#define TRANSFORMIIX_XPATH_EVALUATOR_CID \
|
|
||||||
{ 0xd0a75e02, 0xb5e7, 0x11d5, { 0xa7, 0xf2, 0xdf, 0x10, 0x9f, 0xb8, 0xa1, 0xfc } }
|
|
||||||
|
|
||||||
#endif
|
|
@ -3493,7 +3493,7 @@ XULDocument::OnStreamComplete(nsIStreamLoader* aLoader,
|
|||||||
// transcluded script completes. Compile and execute the script
|
// transcluded script completes. Compile and execute the script
|
||||||
// if the load was successful, then continue building content
|
// if the load was successful, then continue building content
|
||||||
// from the prototype.
|
// from the prototype.
|
||||||
nsresult rv;
|
nsresult rv = aStatus;
|
||||||
|
|
||||||
NS_ASSERTION(mCurrentScriptProto && mCurrentScriptProto->mSrcLoading,
|
NS_ASSERTION(mCurrentScriptProto && mCurrentScriptProto->mSrcLoading,
|
||||||
"script source not loading on unichar stream complete?");
|
"script source not loading on unichar stream complete?");
|
||||||
|
81
dom/base/MessageChannel.cpp
Normal file
81
dom/base/MessageChannel.cpp
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#include "MessageChannel.h"
|
||||||
|
#include "mozilla/Preferences.h"
|
||||||
|
#include "mozilla/dom/MessageChannelBinding.h"
|
||||||
|
#include "mozilla/dom/MessagePort.h"
|
||||||
|
#include "nsContentUtils.h"
|
||||||
|
#include "nsPIDOMWindow.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace dom {
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_3(MessageChannel, mWindow, mPort1, mPort2)
|
||||||
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(MessageChannel)
|
||||||
|
NS_IMPL_CYCLE_COLLECTING_RELEASE(MessageChannel)
|
||||||
|
|
||||||
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MessageChannel)
|
||||||
|
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||||
|
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||||
|
NS_INTERFACE_MAP_END
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
bool gPrefInitialized = false;
|
||||||
|
bool gPrefEnabled = false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* static */ bool
|
||||||
|
MessageChannel::PrefEnabled()
|
||||||
|
{
|
||||||
|
if (!gPrefInitialized) {
|
||||||
|
Preferences::AddBoolVarCache(&gPrefEnabled, "dom.messageChannel.enabled");
|
||||||
|
gPrefInitialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return gPrefEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageChannel::MessageChannel(nsPIDOMWindow* aWindow)
|
||||||
|
: mWindow(aWindow)
|
||||||
|
{
|
||||||
|
MOZ_COUNT_CTOR(MessageChannel);
|
||||||
|
SetIsDOMBinding();
|
||||||
|
|
||||||
|
mPort1 = new MessagePort(mWindow);
|
||||||
|
mPort2 = new MessagePort(mWindow);
|
||||||
|
|
||||||
|
mPort1->Entangle(mPort2);
|
||||||
|
mPort2->Entangle(mPort1);
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageChannel::~MessageChannel()
|
||||||
|
{
|
||||||
|
MOZ_COUNT_DTOR(MessageChannel);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSObject*
|
||||||
|
MessageChannel::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
|
||||||
|
{
|
||||||
|
return MessageChannelBinding::Wrap(aCx, aScope, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */ already_AddRefed<MessageChannel>
|
||||||
|
MessageChannel::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal.GetAsSupports());
|
||||||
|
if (!window) {
|
||||||
|
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsRefPtr<MessageChannel> channel = new MessageChannel(window);
|
||||||
|
return channel.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace dom
|
||||||
|
} // namespace mozilla
|
72
dom/base/MessageChannel.h
Normal file
72
dom/base/MessageChannel.h
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#ifndef mozilla_dom_MessageChannel_h
|
||||||
|
#define mozilla_dom_MessageChannel_h
|
||||||
|
|
||||||
|
#include "mozilla/Attributes.h"
|
||||||
|
#include "mozilla/ErrorResult.h"
|
||||||
|
#include "mozilla/dom/BindingDeclarations.h"
|
||||||
|
#include "nsCycleCollectionParticipant.h"
|
||||||
|
#include "nsWrapperCache.h"
|
||||||
|
#include "nsCOMPtr.h"
|
||||||
|
|
||||||
|
class nsPIDOMWindow;
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace dom {
|
||||||
|
|
||||||
|
class MessagePort;
|
||||||
|
|
||||||
|
class MessageChannel MOZ_FINAL : public nsISupports
|
||||||
|
, public nsWrapperCache
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||||
|
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(MessageChannel)
|
||||||
|
|
||||||
|
static bool PrefEnabled();
|
||||||
|
|
||||||
|
public:
|
||||||
|
MessageChannel(nsPIDOMWindow* aWindow);
|
||||||
|
|
||||||
|
~MessageChannel();
|
||||||
|
|
||||||
|
nsPIDOMWindow*
|
||||||
|
GetParentObject() const
|
||||||
|
{
|
||||||
|
return mWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual JSObject*
|
||||||
|
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
static already_AddRefed<MessageChannel>
|
||||||
|
Constructor(const GlobalObject& aGlobal, ErrorResult& aRv);
|
||||||
|
|
||||||
|
MessagePort*
|
||||||
|
Port1() const
|
||||||
|
{
|
||||||
|
return mPort1;
|
||||||
|
}
|
||||||
|
|
||||||
|
MessagePort*
|
||||||
|
Port2() const
|
||||||
|
{
|
||||||
|
return mPort2;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
nsCOMPtr<nsPIDOMWindow> mWindow;
|
||||||
|
|
||||||
|
nsRefPtr<MessagePort> mPort1;
|
||||||
|
nsRefPtr<MessagePort> mPort2;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace dom
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif // mozilla_dom_MessageChannel_h
|
476
dom/base/MessagePort.cpp
Normal file
476
dom/base/MessagePort.cpp
Normal file
@ -0,0 +1,476 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#include "MessagePort.h"
|
||||||
|
#include "mozilla/dom/MessageChannel.h"
|
||||||
|
#include "mozilla/dom/MessagePortBinding.h"
|
||||||
|
#include "mozilla/dom/StructuredCloneTags.h"
|
||||||
|
#include "nsGlobalWindow.h"
|
||||||
|
#include "nsContentUtils.h"
|
||||||
|
#include "nsEventDispatcher.h"
|
||||||
|
#include "nsPresContext.h"
|
||||||
|
#include "nsDOMEvent.h"
|
||||||
|
|
||||||
|
#include "nsIDocument.h"
|
||||||
|
#include "nsIDOMFile.h"
|
||||||
|
#include "nsIDOMFileList.h"
|
||||||
|
#include "nsIDOMMessageEvent.h"
|
||||||
|
#include "nsIPresShell.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace dom {
|
||||||
|
|
||||||
|
class DispatchEventRunnable : public nsRunnable
|
||||||
|
{
|
||||||
|
friend class MessagePort;
|
||||||
|
|
||||||
|
public:
|
||||||
|
DispatchEventRunnable(MessagePort* aPort)
|
||||||
|
: mPort(aPort)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHOD
|
||||||
|
Run()
|
||||||
|
{
|
||||||
|
nsRefPtr<DispatchEventRunnable> mKungFuDeathGrip(this);
|
||||||
|
|
||||||
|
mPort->mDispatchRunnable = nullptr;
|
||||||
|
mPort->Dispatch();
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
nsRefPtr<MessagePort> mPort;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PostMessageRunnable : public nsRunnable
|
||||||
|
{
|
||||||
|
friend class MessagePort;
|
||||||
|
|
||||||
|
public:
|
||||||
|
NS_DECL_NSIRUNNABLE
|
||||||
|
|
||||||
|
PostMessageRunnable()
|
||||||
|
: mMessage(nullptr)
|
||||||
|
, mMessageLen(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~PostMessageRunnable()
|
||||||
|
{
|
||||||
|
// Ensure that the buffer is freed
|
||||||
|
if (mMessage) {
|
||||||
|
JSAutoStructuredCloneBuffer buffer;
|
||||||
|
buffer.adopt(mMessage, mMessageLen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetJSData(JSAutoStructuredCloneBuffer& aBuffer)
|
||||||
|
{
|
||||||
|
NS_ASSERTION(!mMessage && mMessageLen == 0, "Don't call twice!");
|
||||||
|
aBuffer.steal(&mMessage, &mMessageLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StoreISupports(nsISupports* aSupports)
|
||||||
|
{
|
||||||
|
mSupportsArray.AppendElement(aSupports);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Dispatch(MessagePort* aPort)
|
||||||
|
{
|
||||||
|
mPort = aPort;
|
||||||
|
NS_DispatchToCurrentThread(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
nsRefPtr<MessagePort> mPort;
|
||||||
|
uint64_t* mMessage;
|
||||||
|
size_t mMessageLen;
|
||||||
|
|
||||||
|
nsTArray<nsCOMPtr<nsISupports> > mSupportsArray;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
struct StructuredCloneInfo
|
||||||
|
{
|
||||||
|
PostMessageRunnable* mEvent;
|
||||||
|
MessagePort* mPort;
|
||||||
|
};
|
||||||
|
|
||||||
|
static JSObject*
|
||||||
|
PostMessageReadStructuredClone(JSContext* cx,
|
||||||
|
JSStructuredCloneReader* reader,
|
||||||
|
uint32_t tag,
|
||||||
|
uint32_t data,
|
||||||
|
void* closure)
|
||||||
|
{
|
||||||
|
NS_ASSERTION(closure, "Must have closure!");
|
||||||
|
|
||||||
|
if (tag == SCTAG_DOM_BLOB || tag == SCTAG_DOM_FILELIST) {
|
||||||
|
NS_ASSERTION(!data, "Data should be empty");
|
||||||
|
|
||||||
|
nsISupports* supports;
|
||||||
|
if (JS_ReadBytes(reader, &supports, sizeof(supports))) {
|
||||||
|
JS::Rooted<JSObject*> global(cx, JS::CurrentGlobalOrNull(cx));
|
||||||
|
if (global) {
|
||||||
|
JS::Rooted<JS::Value> val(cx);
|
||||||
|
nsCOMPtr<nsIXPConnectJSObjectHolder> wrapper;
|
||||||
|
if (NS_SUCCEEDED(nsContentUtils::WrapNative(cx, global, supports,
|
||||||
|
val.address(),
|
||||||
|
getter_AddRefs(wrapper)))) {
|
||||||
|
return JSVAL_TO_OBJECT(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tag == SCTAG_DOM_MESSAGEPORT) {
|
||||||
|
NS_ASSERTION(!data, "Data should be empty");
|
||||||
|
|
||||||
|
MessagePort* port;
|
||||||
|
if (JS_ReadBytes(reader, &port, sizeof(port))) {
|
||||||
|
JS::Rooted<JSObject*> global(cx, JS::CurrentGlobalOrNull(cx));
|
||||||
|
if (global) {
|
||||||
|
JS::Rooted<JSObject*> obj(cx, port->WrapObject(cx, global));
|
||||||
|
if (JS_WrapObject(cx, obj.address())) {
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const JSStructuredCloneCallbacks* runtimeCallbacks =
|
||||||
|
js::GetContextStructuredCloneCallbacks(cx);
|
||||||
|
|
||||||
|
if (runtimeCallbacks) {
|
||||||
|
return runtimeCallbacks->read(cx, reader, tag, data, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
PostMessageWriteStructuredClone(JSContext* cx,
|
||||||
|
JSStructuredCloneWriter* writer,
|
||||||
|
JS::Handle<JSObject*> obj,
|
||||||
|
void *closure)
|
||||||
|
{
|
||||||
|
StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(closure);
|
||||||
|
NS_ASSERTION(scInfo, "Must have scInfo!");
|
||||||
|
|
||||||
|
nsCOMPtr<nsIXPConnectWrappedNative> wrappedNative;
|
||||||
|
nsContentUtils::XPConnect()->
|
||||||
|
GetWrappedNativeOfJSObject(cx, obj, getter_AddRefs(wrappedNative));
|
||||||
|
if (wrappedNative) {
|
||||||
|
uint32_t scTag = 0;
|
||||||
|
nsISupports* supports = wrappedNative->Native();
|
||||||
|
|
||||||
|
nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(supports);
|
||||||
|
if (blob) {
|
||||||
|
scTag = SCTAG_DOM_BLOB;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIDOMFileList> list = do_QueryInterface(supports);
|
||||||
|
if (list) {
|
||||||
|
scTag = SCTAG_DOM_FILELIST;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scTag) {
|
||||||
|
return JS_WriteUint32Pair(writer, scTag, 0) &&
|
||||||
|
JS_WriteBytes(writer, &supports, sizeof(supports)) &&
|
||||||
|
scInfo->mEvent->StoreISupports(supports);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MessagePort* port = nullptr;
|
||||||
|
nsresult rv = UNWRAP_OBJECT(MessagePort, cx, obj, port);
|
||||||
|
if (NS_SUCCEEDED(rv)) {
|
||||||
|
nsRefPtr<MessagePort> newPort = port->Clone(scInfo->mPort->GetOwner());
|
||||||
|
|
||||||
|
return JS_WriteUint32Pair(writer, SCTAG_DOM_MESSAGEPORT, 0) &&
|
||||||
|
JS_WriteBytes(writer, &newPort, sizeof(newPort)) &&
|
||||||
|
scInfo->mEvent->StoreISupports(newPort);
|
||||||
|
}
|
||||||
|
|
||||||
|
const JSStructuredCloneCallbacks* runtimeCallbacks =
|
||||||
|
js::GetContextStructuredCloneCallbacks(cx);
|
||||||
|
|
||||||
|
if (runtimeCallbacks) {
|
||||||
|
return runtimeCallbacks->write(cx, writer, obj, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSStructuredCloneCallbacks kPostMessageCallbacks = {
|
||||||
|
PostMessageReadStructuredClone,
|
||||||
|
PostMessageWriteStructuredClone,
|
||||||
|
nullptr
|
||||||
|
};
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
PostMessageRunnable::Run()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(mPort);
|
||||||
|
|
||||||
|
// Ensure that the buffer is freed even if we fail to post the message
|
||||||
|
JSAutoStructuredCloneBuffer buffer;
|
||||||
|
buffer.adopt(mMessage, mMessageLen);
|
||||||
|
mMessage = nullptr;
|
||||||
|
mMessageLen = 0;
|
||||||
|
|
||||||
|
// Get the JSContext for the target window
|
||||||
|
nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(mPort->GetOwner());
|
||||||
|
NS_ENSURE_STATE(sgo);
|
||||||
|
nsCOMPtr<nsIScriptContext> scriptContext = sgo->GetContext();
|
||||||
|
AutoPushJSContext cx(scriptContext ? scriptContext->GetNativeContext()
|
||||||
|
: nsContentUtils::GetSafeJSContext());
|
||||||
|
|
||||||
|
MOZ_ASSERT(cx);
|
||||||
|
|
||||||
|
// Deserialize the structured clone data
|
||||||
|
JS::Rooted<JS::Value> messageData(cx);
|
||||||
|
{
|
||||||
|
StructuredCloneInfo scInfo;
|
||||||
|
scInfo.mEvent = this;
|
||||||
|
scInfo.mPort = mPort;
|
||||||
|
|
||||||
|
if (!buffer.read(cx, messageData.address(), &kPostMessageCallbacks,
|
||||||
|
&scInfo)) {
|
||||||
|
return NS_ERROR_DOM_DATA_CLONE_ERR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the event
|
||||||
|
nsIDocument* doc = mPort->GetOwner()->GetExtantDoc();
|
||||||
|
if (!doc) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorResult error;
|
||||||
|
nsRefPtr<nsDOMEvent> event =
|
||||||
|
doc->CreateEvent(NS_LITERAL_STRING("MessageEvent"), error);
|
||||||
|
if (error.Failed()) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIDOMMessageEvent> message = do_QueryInterface(event);
|
||||||
|
nsresult rv = message->InitMessageEvent(NS_LITERAL_STRING("message"),
|
||||||
|
false /* non-bubbling */,
|
||||||
|
true /* cancelable */,
|
||||||
|
messageData,
|
||||||
|
EmptyString(),
|
||||||
|
EmptyString(),
|
||||||
|
mPort->GetOwner());
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
message->SetTrusted(true);
|
||||||
|
|
||||||
|
bool status;
|
||||||
|
mPort->DispatchEvent(event, &status);
|
||||||
|
return status ? NS_OK : NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_CLASS(MessagePort)
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(MessagePort,
|
||||||
|
nsDOMEventTargetHelper)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mEntangledPort)
|
||||||
|
|
||||||
|
// Custom unlink loop because this array contains nsRunnable objects
|
||||||
|
// which are not cycle colleactable.
|
||||||
|
while (!tmp->mMessageQueue.IsEmpty()) {
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mMessageQueue[0]->mPort);
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mMessageQueue[0]->mSupportsArray);
|
||||||
|
tmp->mMessageQueue.RemoveElementAt(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tmp->mDispatchRunnable) {
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDispatchRunnable->mPort);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(MessagePort,
|
||||||
|
nsDOMEventTargetHelper)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEntangledPort)
|
||||||
|
|
||||||
|
// Custom unlink loop because this array contains nsRunnable objects
|
||||||
|
// which are not cycle colleactable.
|
||||||
|
for (uint32_t i = 0, len = tmp->mMessageQueue.Length(); i < len; ++i) {
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMessageQueue[i]->mPort);
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMessageQueue[i]->mSupportsArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tmp->mDispatchRunnable) {
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDispatchRunnable->mPort);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||||
|
|
||||||
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(MessagePort)
|
||||||
|
NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
|
||||||
|
|
||||||
|
NS_IMPL_ADDREF_INHERITED(MessagePort, nsDOMEventTargetHelper)
|
||||||
|
NS_IMPL_RELEASE_INHERITED(MessagePort, nsDOMEventTargetHelper)
|
||||||
|
|
||||||
|
MessagePort::MessagePort(nsPIDOMWindow* aWindow)
|
||||||
|
: nsDOMEventTargetHelper(aWindow)
|
||||||
|
, mMessageQueueEnabled(false)
|
||||||
|
{
|
||||||
|
MOZ_COUNT_CTOR(MessagePort);
|
||||||
|
SetIsDOMBinding();
|
||||||
|
}
|
||||||
|
|
||||||
|
MessagePort::~MessagePort()
|
||||||
|
{
|
||||||
|
MOZ_COUNT_DTOR(MessagePort);
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
JSObject*
|
||||||
|
MessagePort::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
|
||||||
|
{
|
||||||
|
return MessagePortBinding::Wrap(aCx, aScope, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MessagePort::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||||
|
const Optional<JS::Handle<JS::Value> >& aTransfer,
|
||||||
|
ErrorResult& aRv)
|
||||||
|
{
|
||||||
|
nsRefPtr<PostMessageRunnable> event = new PostMessageRunnable();
|
||||||
|
|
||||||
|
// We *must* clone the data here, or the JS::Value could be modified
|
||||||
|
// by script
|
||||||
|
JSAutoStructuredCloneBuffer buffer;
|
||||||
|
StructuredCloneInfo scInfo;
|
||||||
|
scInfo.mEvent = event;
|
||||||
|
scInfo.mPort = this;
|
||||||
|
|
||||||
|
JS::Handle<JS::Value> transferable = aTransfer.WasPassed()
|
||||||
|
? aTransfer.Value()
|
||||||
|
: JS::UndefinedHandleValue;
|
||||||
|
|
||||||
|
if (!buffer.write(aCx, aMessage, transferable, &kPostMessageCallbacks,
|
||||||
|
&scInfo)) {
|
||||||
|
aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
event->SetJSData(buffer);
|
||||||
|
|
||||||
|
if (!mEntangledPort) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mEntangledPort->mMessageQueue.AppendElement(event);
|
||||||
|
mEntangledPort->Dispatch();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MessagePort::Start()
|
||||||
|
{
|
||||||
|
if (mMessageQueueEnabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mMessageQueueEnabled = true;
|
||||||
|
Dispatch();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MessagePort::Dispatch()
|
||||||
|
{
|
||||||
|
if (!mMessageQueueEnabled || mMessageQueue.IsEmpty() || mDispatchRunnable) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsRefPtr<PostMessageRunnable> event = mMessageQueue.ElementAt(0);
|
||||||
|
mMessageQueue.RemoveElementAt(0);
|
||||||
|
|
||||||
|
event->Dispatch(this);
|
||||||
|
|
||||||
|
mDispatchRunnable = new DispatchEventRunnable(this);
|
||||||
|
NS_DispatchToCurrentThread(mDispatchRunnable);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MessagePort::Close()
|
||||||
|
{
|
||||||
|
if (!mEntangledPort) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This avoids loops.
|
||||||
|
nsRefPtr<MessagePort> port = mEntangledPort;
|
||||||
|
mEntangledPort = nullptr;
|
||||||
|
|
||||||
|
// Let's disentangle the 2 ports symmetrically.
|
||||||
|
port->Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
EventHandlerNonNull*
|
||||||
|
MessagePort::GetOnmessage()
|
||||||
|
{
|
||||||
|
if (NS_IsMainThread()) {
|
||||||
|
return GetEventHandler(nsGkAtoms::onmessage, EmptyString());
|
||||||
|
}
|
||||||
|
return GetEventHandler(nullptr, NS_LITERAL_STRING("message"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MessagePort::SetOnmessage(EventHandlerNonNull* aCallback, ErrorResult& aRv)
|
||||||
|
{
|
||||||
|
if (NS_IsMainThread()) {
|
||||||
|
SetEventHandler(nsGkAtoms::onmessage, EmptyString(), aCallback, aRv);
|
||||||
|
} else {
|
||||||
|
SetEventHandler(nullptr, NS_LITERAL_STRING("message"), aCallback, aRv);
|
||||||
|
}
|
||||||
|
|
||||||
|
// When using onmessage, the call to start() is implied.
|
||||||
|
Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MessagePort::Entangle(MessagePort* aMessagePort)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aMessagePort);
|
||||||
|
MOZ_ASSERT(aMessagePort != this);
|
||||||
|
|
||||||
|
Close();
|
||||||
|
|
||||||
|
mEntangledPort = aMessagePort;
|
||||||
|
}
|
||||||
|
|
||||||
|
already_AddRefed<MessagePort>
|
||||||
|
MessagePort::Clone(nsPIDOMWindow* aWindow)
|
||||||
|
{
|
||||||
|
nsRefPtr<MessagePort> newPort = new MessagePort(aWindow->GetCurrentInnerWindow());
|
||||||
|
|
||||||
|
// Move all the events in the port message queue of original port.
|
||||||
|
newPort->mMessageQueue.SwapElements(mMessageQueue);
|
||||||
|
|
||||||
|
if (mEntangledPort) {
|
||||||
|
nsRefPtr<MessagePort> port = mEntangledPort;
|
||||||
|
mEntangledPort = nullptr;
|
||||||
|
|
||||||
|
newPort->Entangle(port);
|
||||||
|
port->Entangle(newPort);
|
||||||
|
}
|
||||||
|
|
||||||
|
return newPort.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace dom
|
||||||
|
} // namespace mozilla
|
86
dom/base/MessagePort.h
Normal file
86
dom/base/MessagePort.h
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#ifndef mozilla_dom_MessagePort_h
|
||||||
|
#define mozilla_dom_MessagePort_h
|
||||||
|
|
||||||
|
#include "mozilla/Attributes.h"
|
||||||
|
#include "mozilla/ErrorResult.h"
|
||||||
|
#include "nsDOMEventTargetHelper.h"
|
||||||
|
|
||||||
|
class nsPIDOMWindow;
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace dom {
|
||||||
|
|
||||||
|
class DispatchEventRunnable;
|
||||||
|
class PostMessageRunnable;
|
||||||
|
|
||||||
|
class MessagePort MOZ_FINAL : public nsDOMEventTargetHelper
|
||||||
|
{
|
||||||
|
friend class DispatchEventRunnable;
|
||||||
|
friend class PostMessageRunnable;
|
||||||
|
|
||||||
|
public:
|
||||||
|
NS_DECL_ISUPPORTS_INHERITED
|
||||||
|
NS_REALLY_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetHelper)
|
||||||
|
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(MessagePort,
|
||||||
|
nsDOMEventTargetHelper)
|
||||||
|
|
||||||
|
MessagePort(nsPIDOMWindow* aWindow);
|
||||||
|
~MessagePort();
|
||||||
|
|
||||||
|
virtual JSObject*
|
||||||
|
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
void
|
||||||
|
PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||||
|
const Optional<JS::Handle<JS::Value> >& aTransfer,
|
||||||
|
ErrorResult& aRv);
|
||||||
|
|
||||||
|
void
|
||||||
|
Start();
|
||||||
|
|
||||||
|
void
|
||||||
|
Close();
|
||||||
|
|
||||||
|
// The 'message' event handler has to call |Start()| method, so we
|
||||||
|
// cannot use IMPL_EVENT_HANDLER macro here.
|
||||||
|
EventHandlerNonNull*
|
||||||
|
GetOnmessage();
|
||||||
|
|
||||||
|
void
|
||||||
|
SetOnmessage(EventHandlerNonNull* aCallback, ErrorResult& aRv);
|
||||||
|
|
||||||
|
// Non WebIDL methods
|
||||||
|
|
||||||
|
// This method entangles this MessagePort with another one.
|
||||||
|
// If it is already entangled, it's disentangled first and enatangle to the
|
||||||
|
// new one.
|
||||||
|
void
|
||||||
|
Entangle(MessagePort* aMessagePort);
|
||||||
|
|
||||||
|
// Duplicate this message port. This method is used by the Structured Clone
|
||||||
|
// Algorithm and makes the new MessagePort active with the entangled
|
||||||
|
// MessagePort of this object.
|
||||||
|
already_AddRefed<MessagePort>
|
||||||
|
Clone(nsPIDOMWindow* aWindow);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Dispatch events from the Message Queue using a nsRunnable.
|
||||||
|
void Dispatch();
|
||||||
|
|
||||||
|
nsRefPtr<DispatchEventRunnable> mDispatchRunnable;
|
||||||
|
|
||||||
|
nsRefPtr<MessagePort> mEntangledPort;
|
||||||
|
|
||||||
|
nsTArray<nsRefPtr<PostMessageRunnable> > mMessageQueue;
|
||||||
|
bool mMessageQueueEnabled;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace dom
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif // mozilla_dom_MessagePort_h
|
@ -28,6 +28,7 @@ enum StructuredCloneTags {
|
|||||||
|
|
||||||
// These tags are used for both main thread and workers.
|
// These tags are used for both main thread and workers.
|
||||||
SCTAG_DOM_IMAGEDATA,
|
SCTAG_DOM_IMAGEDATA,
|
||||||
|
SCTAG_DOM_MESSAGEPORT,
|
||||||
|
|
||||||
SCTAG_DOM_MAX
|
SCTAG_DOM_MAX
|
||||||
};
|
};
|
||||||
|
@ -55,6 +55,8 @@ EXPORTS.mozilla.dom += [
|
|||||||
'DOMCursor.h',
|
'DOMCursor.h',
|
||||||
'DOMError.h',
|
'DOMError.h',
|
||||||
'DOMRequest.h',
|
'DOMRequest.h',
|
||||||
|
'MessageChannel.h',
|
||||||
|
'MessagePort.h',
|
||||||
'ScreenOrientation.h',
|
'ScreenOrientation.h',
|
||||||
'StructuredCloneTags.h',
|
'StructuredCloneTags.h',
|
||||||
'URL.h',
|
'URL.h',
|
||||||
@ -67,6 +69,8 @@ CPP_SOURCES += [
|
|||||||
'DOMError.cpp',
|
'DOMError.cpp',
|
||||||
'DOMRequest.cpp',
|
'DOMRequest.cpp',
|
||||||
'Navigator.cpp',
|
'Navigator.cpp',
|
||||||
|
'MessageChannel.cpp',
|
||||||
|
'MessagePort.cpp',
|
||||||
'nsContentPermissionHelper.cpp',
|
'nsContentPermissionHelper.cpp',
|
||||||
'nsDOMClassInfo.cpp',
|
'nsDOMClassInfo.cpp',
|
||||||
'nsDOMException.cpp',
|
'nsDOMException.cpp',
|
||||||
|
@ -189,6 +189,9 @@
|
|||||||
#include "prenv.h"
|
#include "prenv.h"
|
||||||
#include "prprf.h"
|
#include "prprf.h"
|
||||||
|
|
||||||
|
#include "mozilla/dom/MessageChannel.h"
|
||||||
|
#include "mozilla/dom/MessagePort.h"
|
||||||
|
#include "mozilla/dom/MessagePortBinding.h"
|
||||||
#include "mozilla/dom/indexedDB/IDBFactory.h"
|
#include "mozilla/dom/indexedDB/IDBFactory.h"
|
||||||
#include "mozilla/dom/quota/QuotaManager.h"
|
#include "mozilla/dom/quota/QuotaManager.h"
|
||||||
|
|
||||||
@ -6750,6 +6753,7 @@ namespace {
|
|||||||
struct StructuredCloneInfo {
|
struct StructuredCloneInfo {
|
||||||
PostMessageEvent* event;
|
PostMessageEvent* event;
|
||||||
bool subsumes;
|
bool subsumes;
|
||||||
|
nsPIDOMWindow* window;
|
||||||
};
|
};
|
||||||
|
|
||||||
static JSObject*
|
static JSObject*
|
||||||
@ -6779,6 +6783,21 @@ PostMessageReadStructuredClone(JSContext* cx,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (MessageChannel::PrefEnabled() && tag == SCTAG_DOM_MESSAGEPORT) {
|
||||||
|
NS_ASSERTION(!data, "Data should be empty");
|
||||||
|
|
||||||
|
MessagePort* port;
|
||||||
|
if (JS_ReadBytes(reader, &port, sizeof(port))) {
|
||||||
|
JS::Rooted<JSObject*> global(cx, JS::CurrentGlobalOrNull(cx));
|
||||||
|
if (global) {
|
||||||
|
JS::Rooted<JSObject*> obj(cx, port->WrapObject(cx, global));
|
||||||
|
if (JS_WrapObject(cx, obj.address())) {
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const JSStructuredCloneCallbacks* runtimeCallbacks =
|
const JSStructuredCloneCallbacks* runtimeCallbacks =
|
||||||
js::GetContextStructuredCloneCallbacks(cx);
|
js::GetContextStructuredCloneCallbacks(cx);
|
||||||
|
|
||||||
@ -6819,6 +6838,18 @@ PostMessageWriteStructuredClone(JSContext* cx,
|
|||||||
scInfo->event->StoreISupports(supports);
|
scInfo->event->StoreISupports(supports);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (MessageChannel::PrefEnabled()) {
|
||||||
|
MessagePort* port = nullptr;
|
||||||
|
nsresult rv = UNWRAP_OBJECT(MessagePort, cx, obj, port);
|
||||||
|
if (NS_SUCCEEDED(rv) && scInfo->subsumes) {
|
||||||
|
nsRefPtr<MessagePort> newPort = port->Clone(scInfo->window);
|
||||||
|
|
||||||
|
return JS_WriteUint32Pair(writer, SCTAG_DOM_MESSAGEPORT, 0) &&
|
||||||
|
JS_WriteBytes(writer, &newPort, sizeof(newPort)) &&
|
||||||
|
scInfo->event->StoreISupports(newPort);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const JSStructuredCloneCallbacks* runtimeCallbacks =
|
const JSStructuredCloneCallbacks* runtimeCallbacks =
|
||||||
js::GetContextStructuredCloneCallbacks(cx);
|
js::GetContextStructuredCloneCallbacks(cx);
|
||||||
|
|
||||||
@ -6910,6 +6941,7 @@ PostMessageEvent::Run()
|
|||||||
{
|
{
|
||||||
StructuredCloneInfo scInfo;
|
StructuredCloneInfo scInfo;
|
||||||
scInfo.event = this;
|
scInfo.event = this;
|
||||||
|
scInfo.window = targetWindow;
|
||||||
|
|
||||||
if (!buffer.read(cx, messageData.address(), &kPostMessageCallbacks,
|
if (!buffer.read(cx, messageData.address(), &kPostMessageCallbacks,
|
||||||
&scInfo)) {
|
&scInfo)) {
|
||||||
@ -7056,6 +7088,7 @@ nsGlobalWindow::PostMessageMoz(const JS::Value& aMessage,
|
|||||||
JSAutoStructuredCloneBuffer buffer;
|
JSAutoStructuredCloneBuffer buffer;
|
||||||
StructuredCloneInfo scInfo;
|
StructuredCloneInfo scInfo;
|
||||||
scInfo.event = event;
|
scInfo.event = event;
|
||||||
|
scInfo.window = this;
|
||||||
|
|
||||||
nsIPrincipal* principal = GetPrincipal();
|
nsIPrincipal* principal = GetPrincipal();
|
||||||
if (NS_FAILED(callerPrin->Subsumes(principal, &scInfo.subsumes)))
|
if (NS_FAILED(callerPrin->Subsumes(principal, &scInfo.subsumes)))
|
||||||
|
@ -31,6 +31,17 @@ MOCHITEST_FILES = \
|
|||||||
test_Image_constructor.html \
|
test_Image_constructor.html \
|
||||||
test_setting_opener.html \
|
test_setting_opener.html \
|
||||||
test_error.html \
|
test_error.html \
|
||||||
|
test_messageChannel.html \
|
||||||
|
test_messageChannel_cloning.html \
|
||||||
|
iframe_messageChannel_cloning.html \
|
||||||
|
test_messageChannel_post.html \
|
||||||
|
iframe_messageChannel_post.html \
|
||||||
|
test_messageChannel_transferable.html \
|
||||||
|
test_messageChannel_start.html \
|
||||||
|
test_messageChannel_pingpong.html \
|
||||||
|
iframe_messageChannel_pingpong.html \
|
||||||
|
test_messageChannel_unshipped.html \
|
||||||
|
test_messageChannel_pref.html \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
MOCHITEST_CHROME_FILES = \
|
MOCHITEST_CHROME_FILES = \
|
||||||
|
22
dom/base/test/iframe_messageChannel_cloning.html
Normal file
22
dom/base/test/iframe_messageChannel_cloning.html
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<script type="application/javascript">
|
||||||
|
|
||||||
|
function ok(a, msg) {
|
||||||
|
window.parent.postMessage({ status: a ? "OK" : "KO", message: msg }, "*");
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener('message', receiveMessage, false);
|
||||||
|
function receiveMessage(evt) {
|
||||||
|
ok (evt.data, "Data received");
|
||||||
|
ok (evt.data.port instanceof MessagePort, "Data contains a MessagePort");
|
||||||
|
|
||||||
|
var a = new MessageChannel();
|
||||||
|
window.parent.postMessage({ status: "FINISH", port: a.port2 }, '*');
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
33
dom/base/test/iframe_messageChannel_pingpong.html
Normal file
33
dom/base/test/iframe_messageChannel_pingpong.html
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<script type="application/javascript">
|
||||||
|
|
||||||
|
function ok(what, msg) {
|
||||||
|
window.parent.postMessage({type: what ? 'OK' : 'KO', msg: msg }, '*');
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener('message', receiveMessage, false);
|
||||||
|
function receiveMessage(evt) {
|
||||||
|
if (evt.data.type == 'PORT') {
|
||||||
|
var port = evt.data.port;
|
||||||
|
var counter = 0;
|
||||||
|
port.onmessage = function(evt) {
|
||||||
|
if (counter++ == 0) {
|
||||||
|
ok(!(evt.data % 2), "The number " + evt.data + " has been received correctly by the iframe");
|
||||||
|
|
||||||
|
window.parent.postMessage({ type: 'PORT', port: port }, '*');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ok(false, "Wrong message!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ok(false, "Unknown message");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
24
dom/base/test/iframe_messageChannel_post.html
Normal file
24
dom/base/test/iframe_messageChannel_post.html
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<script type="application/javascript">
|
||||||
|
|
||||||
|
var port;
|
||||||
|
|
||||||
|
window.addEventListener('message', receiveMessage, false);
|
||||||
|
function receiveMessage(evt) {
|
||||||
|
port = evt.data.port;
|
||||||
|
|
||||||
|
port.addEventListener('message', receivePostMessage, false);
|
||||||
|
function receivePostMessage(evt) {
|
||||||
|
port.postMessage(evt.data);
|
||||||
|
}
|
||||||
|
port.start();
|
||||||
|
|
||||||
|
window.parent.postMessage({ status: "READY" }, '*');
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
49
dom/base/test/test_messageChannel.html
Normal file
49
dom/base/test/test_messageChannel.html
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<!--
|
||||||
|
https://bugzilla.mozilla.org/show_bug.cgi?id=677638
|
||||||
|
-->
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Test for Bug 677638 - basic support</title>
|
||||||
|
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=677638">Mozilla Bug 677638</a>
|
||||||
|
<p id="display"></p>
|
||||||
|
<div id="content" style="display: none">
|
||||||
|
<iframe name="x" id="x"></iframe>
|
||||||
|
<iframe name="y" id="y"></iframe>
|
||||||
|
</div>
|
||||||
|
<pre id="test">
|
||||||
|
</pre>
|
||||||
|
<script type="application/javascript">
|
||||||
|
|
||||||
|
function runTest() {
|
||||||
|
/** Test for Bug 677638 **/
|
||||||
|
var a = new MessageChannel();
|
||||||
|
ok(a, "MessageChannel created");
|
||||||
|
|
||||||
|
var port1 = a.port1;
|
||||||
|
ok(port1, "MessageChannel.port1 exists");
|
||||||
|
is(port1, a.port1, "MessageChannel.port1 is port1");
|
||||||
|
|
||||||
|
var port2 = a.port2;
|
||||||
|
ok(port2, "MessageChannel.port1 exists");
|
||||||
|
is(port2, a.port2, "MessageChannel.port2 is port2");
|
||||||
|
|
||||||
|
[ 'postMessage', 'start', 'close' ].forEach(function(e) {
|
||||||
|
ok(e in port1, "MessagePort1." + e + " exists");
|
||||||
|
ok(e in port2, "MessagePort2." + e + " exists");
|
||||||
|
});
|
||||||
|
|
||||||
|
SimpleTest.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, runTest);
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
70
dom/base/test/test_messageChannel_cloning.html
Normal file
70
dom/base/test/test_messageChannel_cloning.html
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<!--
|
||||||
|
https://bugzilla.mozilla.org/show_bug.cgi?id=677638
|
||||||
|
-->
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Test for Bug 677638 - port cloning</title>
|
||||||
|
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=677638">Mozilla Bug 677638</a>
|
||||||
|
<div id="content"></div>
|
||||||
|
<pre id="test">
|
||||||
|
</pre>
|
||||||
|
<script type="application/javascript">
|
||||||
|
|
||||||
|
// This test checks if MessagePorts can be shared with iframes
|
||||||
|
function test_iframe() {
|
||||||
|
window.addEventListener('message', receiveMessage, false);
|
||||||
|
function receiveMessage(evt) {
|
||||||
|
if (evt.data.status == 'OK') {
|
||||||
|
ok(true, evt.data.message);
|
||||||
|
} else if (evt.data.status == 'KO') {
|
||||||
|
ok(false, evt.data.message);
|
||||||
|
} else if (evt.data.status == 'FINISH') {
|
||||||
|
ok (evt.data.port instanceof MessagePort, "Data contains a MessagePort");
|
||||||
|
window.removeEventListener('message', receiveMessage);
|
||||||
|
runTest();
|
||||||
|
} else {
|
||||||
|
ok(false, "Unknown message");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var a = new MessageChannel();
|
||||||
|
ok(a, "MessageChannel created");
|
||||||
|
|
||||||
|
var div = document.getElementById("content");
|
||||||
|
ok(div, "Parent exists");
|
||||||
|
|
||||||
|
var ifr = document.createElement("iframe");
|
||||||
|
ifr.addEventListener("load", iframeLoaded, false);
|
||||||
|
ifr.setAttribute('src', "iframe_messageChannel_cloning.html");
|
||||||
|
div.appendChild(ifr);
|
||||||
|
|
||||||
|
function iframeLoaded() {
|
||||||
|
ifr.contentWindow.postMessage({ port: a.port2 }, '*');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var tests = [
|
||||||
|
test_iframe
|
||||||
|
];
|
||||||
|
|
||||||
|
function runTest() {
|
||||||
|
if (!tests.length) {
|
||||||
|
SimpleTest.finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var test = tests.shift();
|
||||||
|
test();
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, runTest);
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
77
dom/base/test/test_messageChannel_pingpong.html
Normal file
77
dom/base/test/test_messageChannel_pingpong.html
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<!--
|
||||||
|
https://bugzilla.mozilla.org/show_bug.cgi?id=677638
|
||||||
|
-->
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Test for Bug 677638 - port cloning</title>
|
||||||
|
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=677638">Mozilla Bug 677638</a>
|
||||||
|
<div id="content"></div>
|
||||||
|
<pre id="test">
|
||||||
|
</pre>
|
||||||
|
<script type="application/javascript">
|
||||||
|
|
||||||
|
function runTest() {
|
||||||
|
var MAX = 100;
|
||||||
|
|
||||||
|
var a = new MessageChannel();
|
||||||
|
ok(a, "MessageChannel created");
|
||||||
|
|
||||||
|
// Populate the message queue of this port.
|
||||||
|
for (var i = 0; i < MAX; ++i) {
|
||||||
|
a.port1.postMessage(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener('message', receiveMessage, false);
|
||||||
|
function receiveMessage(evt) {
|
||||||
|
|
||||||
|
// This test sends the port from this window to the iframe and viceversa.
|
||||||
|
if (evt.data.type == 'PORT') {
|
||||||
|
var port = evt.data.port;
|
||||||
|
var counter = 0;
|
||||||
|
port.onmessage = function(evt) {
|
||||||
|
// only 1 message should be received by this port.
|
||||||
|
if (counter++ == 0) {
|
||||||
|
ok(evt.data % 2, "The number " + evt.data + " has been received correctly by the main window");
|
||||||
|
|
||||||
|
if (evt.data < MAX - 1) {
|
||||||
|
ifr.contentWindow.postMessage({ type: 'PORT', port: port }, '*');
|
||||||
|
} else {
|
||||||
|
SimpleTest.finish();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ok(false, "Wrong message!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (evt.data.type == 'OK') {
|
||||||
|
ok(true, evt.data.msg);
|
||||||
|
} else if (evt.data.type == 'KO') {
|
||||||
|
ok(false, evt.data.msg);
|
||||||
|
} else {
|
||||||
|
ok(false, "Unknown message");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var div = document.getElementById("content");
|
||||||
|
ok(div, "Parent exists");
|
||||||
|
|
||||||
|
var ifr = document.createElement("iframe");
|
||||||
|
ifr.addEventListener("load", iframeLoaded, false);
|
||||||
|
ifr.setAttribute('src', "iframe_messageChannel_pingpong.html");
|
||||||
|
div.appendChild(ifr);
|
||||||
|
|
||||||
|
function iframeLoaded() {
|
||||||
|
ifr.contentWindow.postMessage({ type: 'PORT', port: a.port2 }, '*');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, runTest);
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
72
dom/base/test/test_messageChannel_post.html
Normal file
72
dom/base/test/test_messageChannel_post.html
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<!--
|
||||||
|
https://bugzilla.mozilla.org/show_bug.cgi?id=677638
|
||||||
|
-->
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Test for Bug 677638 - port cloning</title>
|
||||||
|
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=677638">Mozilla Bug 677638</a>
|
||||||
|
<div id="content"></div>
|
||||||
|
<pre id="test">
|
||||||
|
</pre>
|
||||||
|
<script type="application/javascript">
|
||||||
|
|
||||||
|
function start() {
|
||||||
|
var a = new MessageChannel();
|
||||||
|
ok(a, "MessageChannel created");
|
||||||
|
|
||||||
|
window.addEventListener('message', receiveMessage, false);
|
||||||
|
function receiveMessage(evt) {
|
||||||
|
if (evt.data.status == 'READY') {
|
||||||
|
runTest();
|
||||||
|
} else {
|
||||||
|
ok(false, "Unknown message");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var div = document.getElementById("content");
|
||||||
|
ok(div, "Parent exists");
|
||||||
|
|
||||||
|
var ifr = document.createElement("iframe");
|
||||||
|
ifr.addEventListener("load", iframeLoaded, false);
|
||||||
|
ifr.setAttribute('src', "iframe_messageChannel_post.html");
|
||||||
|
div.appendChild(ifr);
|
||||||
|
|
||||||
|
function iframeLoaded() {
|
||||||
|
ifr.contentWindow.postMessage({ port: a.port2 }, '*');
|
||||||
|
}
|
||||||
|
|
||||||
|
var tests = [ 42,
|
||||||
|
null,
|
||||||
|
undefined,
|
||||||
|
"hello world",
|
||||||
|
new Blob([]),
|
||||||
|
true ];
|
||||||
|
|
||||||
|
a.port1.onmessage = function(evt) {
|
||||||
|
ok(tests.length, "We are waiting for a message");
|
||||||
|
is(tests[0], evt.data, "Value ok: " + tests[0]);
|
||||||
|
tests.shift();
|
||||||
|
runTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
function runTest() {
|
||||||
|
if (!tests.length) {
|
||||||
|
SimpleTest.finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.port1.postMessage(tests[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, start);
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
42
dom/base/test/test_messageChannel_pref.html
Normal file
42
dom/base/test/test_messageChannel_pref.html
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<!--
|
||||||
|
https://bugzilla.mozilla.org/show_bug.cgi?id=677638
|
||||||
|
-->
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Test for Bug 677638 - pref</title>
|
||||||
|
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=677638">Mozilla Bug 677638</a>
|
||||||
|
<div id="content"></div>
|
||||||
|
<pre id="test">
|
||||||
|
</pre>
|
||||||
|
<script type="application/javascript">
|
||||||
|
|
||||||
|
function runTest(what) {
|
||||||
|
var status;
|
||||||
|
try {
|
||||||
|
status = MessageChannel;
|
||||||
|
ok(what, "Should MessageChannel exist?");
|
||||||
|
} catch(e) {
|
||||||
|
ok(!what, "Should MessageChannel exist?");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
status = MessagePort;
|
||||||
|
ok(what, "Should MessagePort exist?");
|
||||||
|
} catch(e) {
|
||||||
|
ok(!what, "Should MessagePort exist?");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
|
||||||
|
runTest(false);
|
||||||
|
SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]},
|
||||||
|
function() { runTest(true); SimpleTest.finish(); });
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
234
dom/base/test/test_messageChannel_start.html
Normal file
234
dom/base/test/test_messageChannel_start.html
Normal file
@ -0,0 +1,234 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<!--
|
||||||
|
https://bugzilla.mozilla.org/show_bug.cgi?id=677638
|
||||||
|
-->
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Test for Bug 677638 - start/close</title>
|
||||||
|
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=677638">Mozilla Bug 677638</a>
|
||||||
|
<div id="content"></div>
|
||||||
|
<pre id="test">
|
||||||
|
</pre>
|
||||||
|
<script type="application/javascript">
|
||||||
|
|
||||||
|
function runTests() {
|
||||||
|
if (!tests.length) {
|
||||||
|
SimpleTest.finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var test = tests.shift();
|
||||||
|
test();
|
||||||
|
}
|
||||||
|
|
||||||
|
function testOnMessage() {
|
||||||
|
var a = new MessageChannel();
|
||||||
|
ok(a, "MessageChannel created");
|
||||||
|
|
||||||
|
a.port1.postMessage(42);
|
||||||
|
a.port2.postMessage(43);
|
||||||
|
ok(true, "MessagePort{1,2}.postmessage() invoked");
|
||||||
|
|
||||||
|
var events = 2;
|
||||||
|
|
||||||
|
a.port1.onmessage = function(evt) {
|
||||||
|
ok(true, "This method should be called");
|
||||||
|
if (!--events) runTests();
|
||||||
|
}
|
||||||
|
|
||||||
|
a.port2.onmessage = function(evt) {
|
||||||
|
ok(true, "This method should be called");
|
||||||
|
if (!--events) runTests();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function testAddEventListener() {
|
||||||
|
var a = new MessageChannel();
|
||||||
|
ok(a, "MessageChannel created");
|
||||||
|
|
||||||
|
a.port1.postMessage(42);
|
||||||
|
a.port2.postMessage(43);
|
||||||
|
ok(true, "MessagePort{1,2}.postmessage() invoked");
|
||||||
|
|
||||||
|
a.port1.addEventListener('message', function(evt) {
|
||||||
|
ok(false, "This method should not be called");
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
a.port2.addEventListener('message', function(evt) {
|
||||||
|
ok(false, "This method should not be called");
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
setTimeout(runTests, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testAddEventListenerAndStart() {
|
||||||
|
var a = new MessageChannel();
|
||||||
|
ok(a, "MessageChannel created");
|
||||||
|
|
||||||
|
a.port1.postMessage(42);
|
||||||
|
a.port2.postMessage(43);
|
||||||
|
ok(true, "MessagePort{1,2}.postmessage() invoked");
|
||||||
|
|
||||||
|
var events = 2;
|
||||||
|
|
||||||
|
a.port1.addEventListener('message', function(evt) {
|
||||||
|
ok(true, "This method should be called");
|
||||||
|
if (!--events) runTests();
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
a.port2.addEventListener('message', function(evt) {
|
||||||
|
ok(true, "This method should be called");
|
||||||
|
if (!--events) runTests();
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
a.port1.start();
|
||||||
|
a.port2.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
function testAddEventListener1AndStart() {
|
||||||
|
var a = new MessageChannel();
|
||||||
|
ok(a, "MessageChannel created");
|
||||||
|
|
||||||
|
a.port1.postMessage(42);
|
||||||
|
a.port2.postMessage(43);
|
||||||
|
ok(true, "MessagePort{1,2}.postmessage() invoked");
|
||||||
|
|
||||||
|
var events = 1;
|
||||||
|
|
||||||
|
a.port1.addEventListener('message', function(evt) {
|
||||||
|
ok(true, "This method should be called");
|
||||||
|
if (!--events) runTests();
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
a.port2.addEventListener('message', function(evt) {
|
||||||
|
ok(false, "This method should not be called");
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
a.port1.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
function testAddEventListener2AndStart() {
|
||||||
|
var a = new MessageChannel();
|
||||||
|
ok(a, "MessageChannel created");
|
||||||
|
|
||||||
|
a.port1.postMessage(42);
|
||||||
|
a.port2.postMessage(43);
|
||||||
|
ok(true, "MessagePort{1,2}.postmessage() invoked");
|
||||||
|
|
||||||
|
var events = 1;
|
||||||
|
|
||||||
|
a.port1.addEventListener('message', function(evt) {
|
||||||
|
ok(false, "This method should not be called");
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
a.port2.addEventListener('message', function(evt) {
|
||||||
|
ok(true, "This method should be called");
|
||||||
|
if (!--events) runTests();
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
a.port2.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
function testTimer() {
|
||||||
|
var a = new MessageChannel();
|
||||||
|
ok(a, "MessageChannel created");
|
||||||
|
|
||||||
|
a.port1.postMessage(42);
|
||||||
|
a.port2.postMessage(43);
|
||||||
|
ok(true, "MessagePort{1,2}.postmessage() invoked");
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
var events = 2;
|
||||||
|
a.port1.onmessage = function(evt) {
|
||||||
|
ok(true, "This method should be called");
|
||||||
|
if (!--events) runTests();
|
||||||
|
}
|
||||||
|
|
||||||
|
a.port2.onmessage = function(evt) {
|
||||||
|
ok(true, "This method should be called");
|
||||||
|
if (!--events) runTests();
|
||||||
|
}
|
||||||
|
}, 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testAddEventListenerAndStartWrongOrder() {
|
||||||
|
var a = new MessageChannel();
|
||||||
|
ok(a, "MessageChannel created");
|
||||||
|
|
||||||
|
a.port1.postMessage(42);
|
||||||
|
a.port2.postMessage(43);
|
||||||
|
ok(true, "MessagePort{1,2}.postmessage() invoked");
|
||||||
|
|
||||||
|
var events = 2;
|
||||||
|
|
||||||
|
a.port1.start();
|
||||||
|
a.port1.addEventListener('message', function(evt) {
|
||||||
|
ok(true, "This method should be called");
|
||||||
|
if (!--events) runTests();
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
a.port2.start();
|
||||||
|
a.port2.addEventListener('message', function(evt) {
|
||||||
|
ok(true, "This method should be called");
|
||||||
|
if (!--events) runTests();
|
||||||
|
}, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testOnMessageClone() {
|
||||||
|
var a = new MessageChannel();
|
||||||
|
ok(a, "MessageChannel created");
|
||||||
|
|
||||||
|
a.port1.postMessage(42);
|
||||||
|
a.port2.postMessage(43);
|
||||||
|
ok(true, "MessagePort{1,2}.postmessage() invoked");
|
||||||
|
|
||||||
|
var events = 2;
|
||||||
|
|
||||||
|
addEventListener('message', testOnMessageCloneCb, false);
|
||||||
|
function testOnMessageCloneCb(evt) {
|
||||||
|
a.port1.onmessage = function(evt) {
|
||||||
|
ok(true, "This method should be called");
|
||||||
|
testOnMessageCloneFinish();
|
||||||
|
}
|
||||||
|
|
||||||
|
evt.data.onmessage = function(evt) {
|
||||||
|
ok(true, "This method should be called");
|
||||||
|
testOnMessageCloneFinish();
|
||||||
|
}
|
||||||
|
|
||||||
|
a.port2.onmessage = function(evt) {
|
||||||
|
ok(false, "This method should not be called");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function testOnMessageCloneFinish() {
|
||||||
|
if (!--events) {
|
||||||
|
removeEventListener('message', testOnMessageCloneCb);
|
||||||
|
runTests();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
postMessage(a.port2, '*');
|
||||||
|
}
|
||||||
|
|
||||||
|
var tests = [
|
||||||
|
testOnMessage,
|
||||||
|
testAddEventListener,
|
||||||
|
testAddEventListenerAndStart,
|
||||||
|
testAddEventListener1AndStart,
|
||||||
|
testAddEventListener2AndStart,
|
||||||
|
testTimer,
|
||||||
|
testAddEventListenerAndStartWrongOrder,
|
||||||
|
testOnMessageClone,
|
||||||
|
];
|
||||||
|
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, runTests);
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
67
dom/base/test/test_messageChannel_transferable.html
Normal file
67
dom/base/test/test_messageChannel_transferable.html
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<!--
|
||||||
|
https://bugzilla.mozilla.org/show_bug.cgi?id=677638
|
||||||
|
-->
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Test for Bug 677638 - port cloning</title>
|
||||||
|
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=677638">Mozilla Bug 677638</a>
|
||||||
|
<div id="content"></div>
|
||||||
|
<pre id="test">
|
||||||
|
</pre>
|
||||||
|
<script type="application/javascript">
|
||||||
|
|
||||||
|
function start() {
|
||||||
|
var a = new MessageChannel();
|
||||||
|
ok(a, "MessageChannel created");
|
||||||
|
|
||||||
|
window.addEventListener('message', receiveMessage, false);
|
||||||
|
function receiveMessage(evt) {
|
||||||
|
if (evt.data.status == 'READY') {
|
||||||
|
runTest();
|
||||||
|
} else {
|
||||||
|
ok(false, "Unknown message");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var div = document.getElementById("content");
|
||||||
|
ok(div, "Parent exists");
|
||||||
|
|
||||||
|
var ifr = document.createElement("iframe");
|
||||||
|
ifr.addEventListener("load", iframeLoaded, false);
|
||||||
|
ifr.setAttribute('src', "iframe_messageChannel_post.html");
|
||||||
|
div.appendChild(ifr);
|
||||||
|
|
||||||
|
function iframeLoaded() {
|
||||||
|
ifr.contentWindow.postMessage({ port: a.port2 }, '*');
|
||||||
|
}
|
||||||
|
|
||||||
|
a.port1.addEventListener('message', receivePortMessage, false);
|
||||||
|
function receivePortMessage(evt) {
|
||||||
|
is(evt.data.ab.byteLength, size, "The size is: " + size + " == " + ab.byteLength);
|
||||||
|
SimpleTest.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start() is not implicity invoked when addEventListener is used.
|
||||||
|
a.port1.start();
|
||||||
|
|
||||||
|
var size = 1024 * 1024 * 32;
|
||||||
|
var ab = new ArrayBuffer(size);
|
||||||
|
is(ab.byteLength, size, "The size is: " + size + " == " + ab.byteLength);
|
||||||
|
|
||||||
|
function runTest() {
|
||||||
|
a.port1.postMessage({ab: ab, cb: ab}, [ab]);
|
||||||
|
ok(ab.byteLength == 0, "PostMessage - The size is: 0 == " + ab.byteLength)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, start);
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
123
dom/base/test/test_messageChannel_unshipped.html
Normal file
123
dom/base/test/test_messageChannel_unshipped.html
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<!--
|
||||||
|
https://bugzilla.mozilla.org/show_bug.cgi?id=677638
|
||||||
|
-->
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Test for Bug 677638 - unshipped message port queue</title>
|
||||||
|
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=677638">Mozilla Bug 677638</a>
|
||||||
|
<div id="content"></div>
|
||||||
|
<pre id="test">
|
||||||
|
</pre>
|
||||||
|
<script type="application/javascript">
|
||||||
|
|
||||||
|
function test_orderedMessages() {
|
||||||
|
var a = new MessageChannel();
|
||||||
|
ok(a, "MessageChannel created");
|
||||||
|
|
||||||
|
var b = new MessageChannel();
|
||||||
|
ok(b, "MessageChannel created");
|
||||||
|
|
||||||
|
var expectedNumber = 1;
|
||||||
|
function testEvent(number, id) {
|
||||||
|
is(expectedNumber, number, "This is the right number!");
|
||||||
|
ok(!((expectedNumber - id) % 4), "From the right port: " + expectedNumber + " " + id);
|
||||||
|
expectedNumber++;
|
||||||
|
|
||||||
|
if (expectedNumber >100) {
|
||||||
|
runTests();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
a.port1.onmessage = function(evt) {
|
||||||
|
testEvent(evt.data, 2);
|
||||||
|
};
|
||||||
|
|
||||||
|
a.port2.onmessage = function(evt) {
|
||||||
|
testEvent(evt.data, 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
b.port1.onmessage = function(evt) {
|
||||||
|
testEvent(evt.data, 4);
|
||||||
|
};
|
||||||
|
|
||||||
|
b.port2.onmessage = function(evt) {
|
||||||
|
testEvent(evt.data, 3);
|
||||||
|
};
|
||||||
|
|
||||||
|
for (var i = 0; i < 100;) {
|
||||||
|
a.port1.postMessage(++i);
|
||||||
|
a.port2.postMessage(++i);
|
||||||
|
b.port1.postMessage(++i);
|
||||||
|
b.port2.postMessage(++i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_unstarted() {
|
||||||
|
var a = new MessageChannel();
|
||||||
|
ok(a, "MessageChannel created");
|
||||||
|
|
||||||
|
var b = new MessageChannel();
|
||||||
|
ok(b, "MessageChannel created");
|
||||||
|
|
||||||
|
var expectedNumber = 1;
|
||||||
|
function testEvent(number, id) {
|
||||||
|
is(expectedNumber, number, "This is the right number!");
|
||||||
|
ok(!((expectedNumber - id) % 3), "From the right port: " + expectedNumber + " " + id);
|
||||||
|
expectedNumber++;
|
||||||
|
|
||||||
|
// 102 because it's the first multiple of 3.
|
||||||
|
if (expectedNumber > 102) {
|
||||||
|
runTests();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
a.port1.onmessage = function(evt) {
|
||||||
|
testEvent(evt.data, 2);
|
||||||
|
};
|
||||||
|
|
||||||
|
a.port2.onmessage = function(evt) {
|
||||||
|
testEvent(evt.data, 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
b.port1.addEventListener("message", function() {
|
||||||
|
ok(false, "shouldn't be called");
|
||||||
|
});
|
||||||
|
|
||||||
|
b.port2.onmessage = function(evt) {
|
||||||
|
testEvent(evt.data, 3);
|
||||||
|
};
|
||||||
|
|
||||||
|
for (var i = 0; i < 100;) {
|
||||||
|
a.port1.postMessage(++i);
|
||||||
|
a.port2.postMessage(++i);
|
||||||
|
b.port1.postMessage(++i);
|
||||||
|
b.port2.postMessage(1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var tests = [
|
||||||
|
test_orderedMessages,
|
||||||
|
test_unstarted
|
||||||
|
];
|
||||||
|
|
||||||
|
function runTests() {
|
||||||
|
if (!tests.length) {
|
||||||
|
SimpleTest.finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var test = tests.shift();
|
||||||
|
test();
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, runTests);
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -1459,8 +1459,6 @@ DOMInterfaces = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
'XPathEvaluator': {
|
'XPathEvaluator': {
|
||||||
'nativeType': 'nsXPathEvaluator',
|
|
||||||
'headerFile': 'nsXPathEvaluator.h',
|
|
||||||
'wrapperCache': False
|
'wrapperCache': False
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ const ContentPanning = {
|
|||||||
// If we are using an AsyncPanZoomController for the parent frame,
|
// If we are using an AsyncPanZoomController for the parent frame,
|
||||||
// it will handle subframe scrolling too. We don't need to listen for
|
// it will handle subframe scrolling too. We don't need to listen for
|
||||||
// these events.
|
// these events.
|
||||||
if (!docShell.asyncPanZoomEnabled) {
|
if (!this._asyncPanZoomForViewportFrame) {
|
||||||
let els = Cc["@mozilla.org/eventlistenerservice;1"]
|
let els = Cc["@mozilla.org/eventlistenerservice;1"]
|
||||||
.getService(Ci.nsIEventListenerService);
|
.getService(Ci.nsIEventListenerService);
|
||||||
|
|
||||||
@ -140,11 +140,23 @@ const ContentPanning = {
|
|||||||
let oldTarget = this.target;
|
let oldTarget = this.target;
|
||||||
[this.target, this.scrollCallback] = this.getPannable(this.pointerDownTarget);
|
[this.target, this.scrollCallback] = this.getPannable(this.pointerDownTarget);
|
||||||
|
|
||||||
// If we have a pointer down target, we may need to fill in for EventStateManager
|
// If we found a target, that means we have found a scrollable subframe. In
|
||||||
// in setting the active state on the target element. Set a timer to
|
// this case, and if we are using async panning and zooming on the parent
|
||||||
|
// frame, inform the pan/zoom controller that it should not attempt to
|
||||||
|
// handle any touch events it gets until the next batch (meaning the next
|
||||||
|
// time we get a touch end).
|
||||||
|
if (this.target != null && this._asyncPanZoomForViewportFrame) {
|
||||||
|
this.detectingScrolling = true;
|
||||||
|
var os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
|
||||||
|
os.notifyObservers(docShell, 'detect-scrollable-subframe', null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have a pointer down target and we're not async
|
||||||
|
// pan/zooming, we may need to fill in for EventStateManager in
|
||||||
|
// setting the active state on the target element. Set a timer to
|
||||||
// ensure the pointer-down target is active. (If it's already
|
// ensure the pointer-down target is active. (If it's already
|
||||||
// active, the timer is a no-op.)
|
// active, the timer is a no-op.)
|
||||||
if (this.pointerDownTarget !== null) {
|
if (this.pointerDownTarget !== null && !this.detectingScrolling) {
|
||||||
// If there's no possibility this is a drag/pan, activate now.
|
// If there's no possibility this is a drag/pan, activate now.
|
||||||
// Otherwise wait a little bit to see if the gesture isn't a
|
// Otherwise wait a little bit to see if the gesture isn't a
|
||||||
// tap.
|
// tap.
|
||||||
@ -214,6 +226,12 @@ const ContentPanning = {
|
|||||||
this.pointerDownTarget = null;
|
this.pointerDownTarget = null;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// True when there's an async pan-zoom controll watching the
|
||||||
|
// outermost scrollable frame, and we're waiting to see whether
|
||||||
|
// we're going to take over from it and synchronously scroll an
|
||||||
|
// inner scrollable frame.
|
||||||
|
detectingScrolling: false,
|
||||||
|
|
||||||
onTouchMove: function cp_onTouchMove(evt) {
|
onTouchMove: function cp_onTouchMove(evt) {
|
||||||
if (!this.dragging)
|
if (!this.dragging)
|
||||||
return;
|
return;
|
||||||
@ -242,6 +260,27 @@ const ContentPanning = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let isPan = KineticPanning.isPan();
|
let isPan = KineticPanning.isPan();
|
||||||
|
if (!isPan && this.detectingScrolling) {
|
||||||
|
// If panning distance is not large enough and we're waiting to
|
||||||
|
// see whether we should use the sync scroll fallback or not,
|
||||||
|
// don't attempt scrolling.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let isScroll = this.scrollCallback(delta.scale(-1));
|
||||||
|
|
||||||
|
if (this.detectingScrolling) {
|
||||||
|
this.detectingScrolling = false;
|
||||||
|
// Stop async-pan-zooming if the user is panning the subframe.
|
||||||
|
if (isScroll) {
|
||||||
|
// We're going to drive synchronously scrolling an inner frame.
|
||||||
|
Services.obs.notifyObservers(docShell, 'cancel-default-pan-zoom', null);
|
||||||
|
} else {
|
||||||
|
// Let AsyncPanZoomController handle the scrolling gesture.
|
||||||
|
this.scrollCallback = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If we've detected a pan gesture, cancel the active state of the
|
// If we've detected a pan gesture, cancel the active state of the
|
||||||
// current target.
|
// current target.
|
||||||
@ -317,6 +356,13 @@ const ContentPanning = {
|
|||||||
node = node.parentNode;
|
node = node.parentNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ContentPanning._asyncPanZoomForViewportFrame &&
|
||||||
|
nodeContent === content) {
|
||||||
|
// The parent context is asynchronously panning and zooming our
|
||||||
|
// root scrollable frame, so don't use our synchronous fallback.
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
if (nodeContent.scrollMaxX || nodeContent.scrollMaxY) {
|
if (nodeContent.scrollMaxX || nodeContent.scrollMaxY) {
|
||||||
return nodeContent;
|
return nodeContent;
|
||||||
}
|
}
|
||||||
@ -438,6 +484,10 @@ const ContentPanning = {
|
|||||||
this._domUtils.setContentState(elt, kStateActive);
|
this._domUtils.setContentState(elt, kStateActive);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
get _asyncPanZoomForViewportFrame() {
|
||||||
|
return docShell.asyncPanZoomEnabled;
|
||||||
|
},
|
||||||
|
|
||||||
_recvViewportChange: function(data) {
|
_recvViewportChange: function(data) {
|
||||||
let metrics = data.json;
|
let metrics = data.json;
|
||||||
this._viewport = new Rect(metrics.x, metrics.y,
|
this._viewport = new Rect(metrics.x, metrics.y,
|
||||||
@ -549,6 +599,7 @@ const ContentPanning = {
|
|||||||
_finishPanning: function() {
|
_finishPanning: function() {
|
||||||
this._resetActive();
|
this._resetActive();
|
||||||
this.dragging = false;
|
this.dragging = false;
|
||||||
|
this.detectingScrolling = false;
|
||||||
delete this.primaryPointerId;
|
delete this.primaryPointerId;
|
||||||
this._activationTimer.cancel();
|
this._activationTimer.cancel();
|
||||||
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
|
||||||
# THIS FILE IS AUTOGENERATED BY parseFailures.py - DO NOT EDIT
|
# THIS FILE IS AUTOGENERATED BY parseFailures.py - DO NOT EDIT
|
||||||
|
|
||||||
DIRS += [
|
DIRS += [
|
||||||
|
@ -12,8 +12,13 @@ include $(DEPTH)/config/autoconf.mk
|
|||||||
MOCHITEST_FILES := \
|
MOCHITEST_FILES := \
|
||||||
test_Document-open.html.json \
|
test_Document-open.html.json \
|
||||||
test_addRange.html.json \
|
test_addRange.html.json \
|
||||||
|
test_collapse.html.json \
|
||||||
|
test_collapseToStartEnd.html.json \
|
||||||
|
test_extend.html.json \
|
||||||
test_getSelection.html.json \
|
test_getSelection.html.json \
|
||||||
test_interfaces.html.json \
|
test_interfaces.html.json \
|
||||||
|
test_removeAllRanges.html.json \
|
||||||
|
test_selectAllChildren.html.json \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
include $(topsrcdir)/config/rules.mk
|
include $(topsrcdir)/config/rules.mk
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
|
||||||
# THIS FILE IS AUTOGENERATED BY parseFailures.py - DO NOT EDIT
|
# THIS FILE IS AUTOGENERATED BY parseFailures.py - DO NOT EDIT
|
||||||
|
|
||||||
DIRS += [
|
DIRS += [
|
||||||
|
2008
dom/imptests/failures/editing/selecttest/test_collapse.html.json
Normal file
2008
dom/imptests/failures/editing/selecttest/test_collapse.html.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
"Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0] collapseToStart()":true,
|
||||||
|
"Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0] collapseToEnd()":true,
|
||||||
|
"Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] collapseToStart()":true,
|
||||||
|
"Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] collapseToEnd()":true,
|
||||||
|
"Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] collapseToStart()":true,
|
||||||
|
"Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] collapseToEnd()":true,
|
||||||
|
"Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] collapseToStart()":true,
|
||||||
|
"Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] collapseToEnd()":true,
|
||||||
|
"Range 21 [foreignDoc.head, 1, foreignDoc.head, 1] collapseToStart()":true,
|
||||||
|
"Range 21 [foreignDoc.head, 1, foreignDoc.head, 1] collapseToEnd()":true,
|
||||||
|
"Range 22 [foreignDoc.body, 0, foreignDoc.body, 0] collapseToStart()":true,
|
||||||
|
"Range 22 [foreignDoc.body, 0, foreignDoc.body, 0] collapseToEnd()":true,
|
||||||
|
"Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] collapseToStart()":true,
|
||||||
|
"Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] collapseToEnd()":true,
|
||||||
|
"Range 41 [foreignDoc, 0, foreignDoc, 0] collapseToStart()":true,
|
||||||
|
"Range 41 [foreignDoc, 0, foreignDoc, 0] collapseToEnd()":true,
|
||||||
|
"Range 42 [foreignDoc, 1, foreignComment, 2] collapseToStart()":true,
|
||||||
|
"Range 42 [foreignDoc, 1, foreignComment, 2] collapseToEnd()":true,
|
||||||
|
"Range 43 [foreignDoc.body, 0, foreignTextNode, 36] collapseToStart()":true,
|
||||||
|
"Range 43 [foreignDoc.body, 0, foreignTextNode, 36] collapseToEnd()":true,
|
||||||
|
"Range 44 [xmlDoc, 0, xmlDoc, 0] collapseToStart()":true,
|
||||||
|
"Range 44 [xmlDoc, 0, xmlDoc, 0] collapseToEnd()":true,
|
||||||
|
"Range 45 [xmlDoc, 1, xmlComment, 0] collapseToStart()":true,
|
||||||
|
"Range 45 [xmlDoc, 1, xmlComment, 0] collapseToEnd()":true,
|
||||||
|
"Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7] collapseToStart()":true,
|
||||||
|
"Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7] collapseToEnd()":true,
|
||||||
|
"Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] collapseToStart()":true,
|
||||||
|
"Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] collapseToEnd()":true,
|
||||||
|
"Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7] collapseToStart()":true,
|
||||||
|
"Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7] collapseToEnd()":true,
|
||||||
|
"Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] collapseToStart()":true,
|
||||||
|
"Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] collapseToEnd()":true,
|
||||||
|
"Range 53 [detachedForeignComment, 0, detachedForeignComment, 1] collapseToStart()":true,
|
||||||
|
"Range 53 [detachedForeignComment, 0, detachedForeignComment, 1] collapseToEnd()":true,
|
||||||
|
"Range 54 [detachedForeignComment, 4, detachedForeignComment, 4] collapseToStart()":true,
|
||||||
|
"Range 54 [detachedForeignComment, 4, detachedForeignComment, 4] collapseToEnd()":true,
|
||||||
|
"Range 55 [detachedXmlComment, 2, detachedXmlComment, 6] collapseToStart()":true,
|
||||||
|
"Range 55 [detachedXmlComment, 2, detachedXmlComment, 6] collapseToEnd()":true,
|
||||||
|
"Range 57 [foreignDocfrag, 0, foreignDocfrag, 0] collapseToStart()":true,
|
||||||
|
"Range 57 [foreignDocfrag, 0, foreignDocfrag, 0] collapseToEnd()":true,
|
||||||
|
"Range 58 [xmlDocfrag, 0, xmlDocfrag, 0] collapseToStart()":true,
|
||||||
|
"Range 58 [xmlDocfrag, 0, xmlDocfrag, 0] collapseToEnd()":true
|
||||||
|
}
|
3928
dom/imptests/failures/editing/selecttest/test_extend.html.json
Normal file
3928
dom/imptests/failures/editing/selecttest/test_extend.html.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0] backwards":true,
|
||||||
|
"Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] backwards":true,
|
||||||
|
"Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] backwards":true,
|
||||||
|
"Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] backwards":true,
|
||||||
|
"Range 21 [foreignDoc.head, 1, foreignDoc.head, 1] backwards":true,
|
||||||
|
"Range 22 [foreignDoc.body, 0, foreignDoc.body, 0] backwards":true,
|
||||||
|
"Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] backwards":true,
|
||||||
|
"Range 41 [foreignDoc, 0, foreignDoc, 0] backwards":true,
|
||||||
|
"Range 42 [foreignDoc, 1, foreignComment, 2] backwards":true,
|
||||||
|
"Range 43 [foreignDoc.body, 0, foreignTextNode, 36] backwards":true,
|
||||||
|
"Range 44 [xmlDoc, 0, xmlDoc, 0] backwards":true,
|
||||||
|
"Range 45 [xmlDoc, 1, xmlComment, 0] backwards":true,
|
||||||
|
"Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7] backwards":true,
|
||||||
|
"Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] backwards":true,
|
||||||
|
"Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7] backwards":true,
|
||||||
|
"Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] backwards":true,
|
||||||
|
"Range 53 [detachedForeignComment, 0, detachedForeignComment, 1] backwards":true,
|
||||||
|
"Range 54 [detachedForeignComment, 4, detachedForeignComment, 4] backwards":true,
|
||||||
|
"Range 55 [detachedXmlComment, 2, detachedXmlComment, 6] backwards":true,
|
||||||
|
"Range 57 [foreignDocfrag, 0, foreignDocfrag, 0] backwards":true,
|
||||||
|
"Range 58 [xmlDocfrag, 0, xmlDocfrag, 0] backwards":true
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
@ -105,8 +105,10 @@ NS_IMPL_ISUPPORTS1(ContentListener, nsIDOMEventListener)
|
|||||||
|
|
||||||
static const CSSSize kDefaultViewportSize(980, 480);
|
static const CSSSize kDefaultViewportSize(980, 480);
|
||||||
|
|
||||||
|
static const char CANCEL_DEFAULT_PAN_ZOOM[] = "cancel-default-pan-zoom";
|
||||||
static const char BROWSER_ZOOM_TO_RECT[] = "browser-zoom-to-rect";
|
static const char BROWSER_ZOOM_TO_RECT[] = "browser-zoom-to-rect";
|
||||||
static const char BEFORE_FIRST_PAINT[] = "before-first-paint";
|
static const char BEFORE_FIRST_PAINT[] = "before-first-paint";
|
||||||
|
static const char DETECT_SCROLLABLE_SUBFRAME[] = "detect-scrollable-subframe";
|
||||||
|
|
||||||
static bool sCpowsEnabled = false;
|
static bool sCpowsEnabled = false;
|
||||||
|
|
||||||
@ -383,7 +385,13 @@ TabChild::Observe(nsISupports *aSubject,
|
|||||||
const char *aTopic,
|
const char *aTopic,
|
||||||
const PRUnichar *aData)
|
const PRUnichar *aData)
|
||||||
{
|
{
|
||||||
if (!strcmp(aTopic, BROWSER_ZOOM_TO_RECT)) {
|
if (!strcmp(aTopic, CANCEL_DEFAULT_PAN_ZOOM)) {
|
||||||
|
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(aSubject));
|
||||||
|
nsCOMPtr<nsITabChild> tabChild(GetTabChildFrom(docShell));
|
||||||
|
if (tabChild == this) {
|
||||||
|
mRemoteFrame->CancelDefaultPanZoom();
|
||||||
|
}
|
||||||
|
} else if (!strcmp(aTopic, BROWSER_ZOOM_TO_RECT)) {
|
||||||
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(aSubject));
|
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(aSubject));
|
||||||
nsCOMPtr<nsITabChild> tabChild(GetTabChildFrom(docShell));
|
nsCOMPtr<nsITabChild> tabChild(GetTabChildFrom(docShell));
|
||||||
if (tabChild == this) {
|
if (tabChild == this) {
|
||||||
@ -428,6 +436,12 @@ TabChild::Observe(nsISupports *aSubject,
|
|||||||
HandlePossibleViewportChange();
|
HandlePossibleViewportChange();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (!strcmp(aTopic, DETECT_SCROLLABLE_SUBFRAME)) {
|
||||||
|
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(aSubject));
|
||||||
|
nsCOMPtr<nsITabChild> tabChild(GetTabChildFrom(docShell));
|
||||||
|
if (tabChild == this) {
|
||||||
|
mRemoteFrame->DetectScrollableSubframe();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
@ -2165,8 +2179,10 @@ TabChild::RecvDestroy()
|
|||||||
nsCOMPtr<nsIObserverService> observerService =
|
nsCOMPtr<nsIObserverService> observerService =
|
||||||
do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
|
do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
|
||||||
|
|
||||||
|
observerService->RemoveObserver(this, CANCEL_DEFAULT_PAN_ZOOM);
|
||||||
observerService->RemoveObserver(this, BROWSER_ZOOM_TO_RECT);
|
observerService->RemoveObserver(this, BROWSER_ZOOM_TO_RECT);
|
||||||
observerService->RemoveObserver(this, BEFORE_FIRST_PAINT);
|
observerService->RemoveObserver(this, BEFORE_FIRST_PAINT);
|
||||||
|
observerService->RemoveObserver(this, DETECT_SCROLLABLE_SUBFRAME);
|
||||||
|
|
||||||
const InfallibleTArray<PIndexedDBChild*>& idbActors =
|
const InfallibleTArray<PIndexedDBChild*>& idbActors =
|
||||||
ManagedPIndexedDBChild();
|
ManagedPIndexedDBChild();
|
||||||
@ -2301,12 +2317,18 @@ TabChild::InitRenderingState()
|
|||||||
do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
|
do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
|
||||||
|
|
||||||
if (observerService) {
|
if (observerService) {
|
||||||
|
observerService->AddObserver(this,
|
||||||
|
CANCEL_DEFAULT_PAN_ZOOM,
|
||||||
|
false);
|
||||||
observerService->AddObserver(this,
|
observerService->AddObserver(this,
|
||||||
BROWSER_ZOOM_TO_RECT,
|
BROWSER_ZOOM_TO_RECT,
|
||||||
false);
|
false);
|
||||||
observerService->AddObserver(this,
|
observerService->AddObserver(this,
|
||||||
BEFORE_FIRST_PAINT,
|
BEFORE_FIRST_PAINT,
|
||||||
false);
|
false);
|
||||||
|
observerService->AddObserver(this,
|
||||||
|
DETECT_SCROLLABLE_SUBFRAME,
|
||||||
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This state can't really change during the lifetime of the child.
|
// This state can't really change during the lifetime of the child.
|
||||||
|
14
dom/webidl/MessageChannel.webidl
Normal file
14
dom/webidl/MessageChannel.webidl
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
/* -*- 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/.
|
||||||
|
*
|
||||||
|
* For more information on this interface, please see
|
||||||
|
* http://www.whatwg.org/specs/web-apps/current-work/#channel-messaging
|
||||||
|
*/
|
||||||
|
|
||||||
|
[Constructor, Pref="dom.messageChannel.enabled"]
|
||||||
|
interface MessageChannel {
|
||||||
|
readonly attribute MessagePort port1;
|
||||||
|
readonly attribute MessagePort port2;
|
||||||
|
};
|
23
dom/webidl/MessagePort.webidl
Normal file
23
dom/webidl/MessagePort.webidl
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
/* -*- 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/.
|
||||||
|
*
|
||||||
|
* For more information on this interface, please see
|
||||||
|
* http://www.whatwg.org/specs/web-apps/current-work/#channel-messaging
|
||||||
|
*/
|
||||||
|
|
||||||
|
[Pref="dom.messageChannel.enabled"]
|
||||||
|
interface MessagePort : EventTarget {
|
||||||
|
// TODO void postMessage(any message, optional sequence<Transferable> transfer);
|
||||||
|
[Throws]
|
||||||
|
void postMessage(any message, optional any transfer);
|
||||||
|
|
||||||
|
void start();
|
||||||
|
void close();
|
||||||
|
|
||||||
|
// event handlers
|
||||||
|
[SetterThrows]
|
||||||
|
attribute EventHandler onmessage;
|
||||||
|
};
|
||||||
|
// MessagePort implements Transferable;
|
@ -195,7 +195,9 @@ webidl_files = \
|
|||||||
MediaStreamAudioSourceNode.webidl \
|
MediaStreamAudioSourceNode.webidl \
|
||||||
MediaStreamEvent.webidl \
|
MediaStreamEvent.webidl \
|
||||||
MediaStreamTrack.webidl \
|
MediaStreamTrack.webidl \
|
||||||
|
MessageChannel.webidl \
|
||||||
MessageEvent.webidl \
|
MessageEvent.webidl \
|
||||||
|
MessagePort.webidl \
|
||||||
MimeType.webidl \
|
MimeType.webidl \
|
||||||
MimeTypeArray.webidl \
|
MimeTypeArray.webidl \
|
||||||
MobileMessageManager.webidl \
|
MobileMessageManager.webidl \
|
||||||
|
@ -294,7 +294,12 @@ private:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return worker->PostMessage(aCx, message, transferable);
|
if (!worker->PostMessage(aCx, message, transferable)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
JS_RVAL(aCx, aVp).setUndefined();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -853,7 +853,12 @@ private:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return scope->mWorker->PostMessageToParent(aCx, message, transferable);
|
if (!scope->mWorker->PostMessageToParent(aCx, message, transferable)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
JS_RVAL(aCx, aVp).setUndefined();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -106,6 +106,8 @@ MOCHITEST_FILES = \
|
|||||||
content_worker.js \
|
content_worker.js \
|
||||||
test_url.html \
|
test_url.html \
|
||||||
url_worker.js \
|
url_worker.js \
|
||||||
|
test_bug911085.html \
|
||||||
|
bug911085_worker.js \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
# Bug 842386 - Disabled on OSX due to intermittent failures.
|
# Bug 842386 - Disabled on OSX due to intermittent failures.
|
||||||
|
3
dom/workers/test/bug911085_worker.js
Normal file
3
dom/workers/test/bug911085_worker.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
onmessage = function(evt) {
|
||||||
|
postMessage(postMessage('ignore') == undefined);
|
||||||
|
}
|
32
dom/workers/test/test_bug911085.html
Normal file
32
dom/workers/test/test_bug911085.html
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<!--
|
||||||
|
Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
-->
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Test for bug 911085</title>
|
||||||
|
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script class="testbody" type="text/javascript">
|
||||||
|
|
||||||
|
var worker = new Worker("bug911085_worker.js");
|
||||||
|
|
||||||
|
worker.onmessage = function(event) {
|
||||||
|
if (event.data == 'ignore') return;
|
||||||
|
|
||||||
|
ok(event.data, "postMessage() returns 'undefined' in workers");
|
||||||
|
SimpleTest.finish();
|
||||||
|
};
|
||||||
|
|
||||||
|
is(worker.postMessage(42), undefined, "PostMessage() returns 'undefined' on main thread");
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
|
|
@ -35,11 +35,12 @@ function runTest() {
|
|||||||
|
|
||||||
var i = document.getElementById("i");
|
var i = document.getElementById("i");
|
||||||
i.focus();
|
i.focus();
|
||||||
|
var win = i.contentWindow;
|
||||||
var doc = i.contentDocument;
|
var doc = i.contentDocument;
|
||||||
var t = doc.getElementById("t");
|
var t = doc.getElementById("t");
|
||||||
t.focus();
|
t.focus();
|
||||||
// put the caret at the end
|
// put the caret at the end
|
||||||
getSelection().collapse(t.firstChild, 11);
|
win.getSelection().collapse(t.firstChild, 11);
|
||||||
|
|
||||||
// Simulate pression Option+Delete on Mac
|
// Simulate pression Option+Delete on Mac
|
||||||
// We do things this way because not every platform can invoke this
|
// We do things this way because not every platform can invoke this
|
||||||
|
@ -360,6 +360,24 @@ APZCTreeManager::UpdateCompositionBounds(const ScrollableLayerGuid& aGuid,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
APZCTreeManager::CancelDefaultPanZoom(const ScrollableLayerGuid& aGuid)
|
||||||
|
{
|
||||||
|
nsRefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(aGuid);
|
||||||
|
if (apzc) {
|
||||||
|
apzc->CancelDefaultPanZoom();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
APZCTreeManager::DetectScrollableSubframe(const ScrollableLayerGuid& aGuid)
|
||||||
|
{
|
||||||
|
nsRefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(aGuid);
|
||||||
|
if (apzc) {
|
||||||
|
apzc->DetectScrollableSubframe();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
APZCTreeManager::ZoomToRect(const ScrollableLayerGuid& aGuid,
|
APZCTreeManager::ZoomToRect(const ScrollableLayerGuid& aGuid,
|
||||||
const CSSRect& aRect)
|
const CSSRect& aRect)
|
||||||
|
@ -168,6 +168,22 @@ public:
|
|||||||
void UpdateCompositionBounds(const ScrollableLayerGuid& aGuid,
|
void UpdateCompositionBounds(const ScrollableLayerGuid& aGuid,
|
||||||
const ScreenIntRect& aCompositionBounds);
|
const ScreenIntRect& aCompositionBounds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We are scrolling a subframe, so disable our machinery until we hit
|
||||||
|
* a touch end or a new touch start. This prevents us from accidentally
|
||||||
|
* panning both the subframe and the parent frame.
|
||||||
|
*
|
||||||
|
* XXX/bug 775452: We should eventually be supporting async scrollable
|
||||||
|
* subframes.
|
||||||
|
*/
|
||||||
|
void CancelDefaultPanZoom(const ScrollableLayerGuid& aGuid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We have found a scrollable subframe, so we need to delay the scrolling
|
||||||
|
* gesture executed and let subframe do the scrolling first.
|
||||||
|
*/
|
||||||
|
void DetectScrollableSubframe(const ScrollableLayerGuid& aGuid);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Kicks an animation to zoom to a rect. This may be either a zoom out or zoom
|
* Kicks an animation to zoom to a rect. This may be either a zoom out or zoom
|
||||||
* in. The actual animation is done on the compositor thread after being set
|
* in. The actual animation is done on the compositor thread after being set
|
||||||
|
@ -212,7 +212,9 @@ AsyncPanZoomController::AsyncPanZoomController(uint64_t aLayersId,
|
|||||||
mLastAsyncScrollOffset(0, 0),
|
mLastAsyncScrollOffset(0, 0),
|
||||||
mCurrentAsyncScrollOffset(0, 0),
|
mCurrentAsyncScrollOffset(0, 0),
|
||||||
mAsyncScrollTimeoutTask(nullptr),
|
mAsyncScrollTimeoutTask(nullptr),
|
||||||
mHandlingTouchQueue(false)
|
mDisableNextTouchBatch(false),
|
||||||
|
mHandlingTouchQueue(false),
|
||||||
|
mDelayPanning(false)
|
||||||
{
|
{
|
||||||
MOZ_COUNT_CTOR(AsyncPanZoomController);
|
MOZ_COUNT_CTOR(AsyncPanZoomController);
|
||||||
|
|
||||||
@ -310,12 +312,29 @@ nsEventStatus AsyncPanZoomController::HandleInputEvent(const InputData& aEvent)
|
|||||||
nsEventStatus rv = nsEventStatus_eIgnore;
|
nsEventStatus rv = nsEventStatus_eIgnore;
|
||||||
|
|
||||||
nsRefPtr<GestureEventListener> listener = GetGestureEventListener();
|
nsRefPtr<GestureEventListener> listener = GetGestureEventListener();
|
||||||
if (listener) {
|
if (listener && !mDisableNextTouchBatch) {
|
||||||
rv = listener->HandleInputEvent(aEvent);
|
rv = listener->HandleInputEvent(aEvent);
|
||||||
if (rv == nsEventStatus_eConsumeNoDefault)
|
if (rv == nsEventStatus_eConsumeNoDefault)
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mDelayPanning && aEvent.mInputType == MULTITOUCH_INPUT) {
|
||||||
|
const MultiTouchInput& multiTouchInput = aEvent.AsMultiTouchInput();
|
||||||
|
if (multiTouchInput.mType == MultiTouchInput::MULTITOUCH_MOVE) {
|
||||||
|
// Let BrowserElementScrolling perform panning gesture first.
|
||||||
|
SetState(WAITING_LISTENERS);
|
||||||
|
mTouchQueue.AppendElement(multiTouchInput);
|
||||||
|
|
||||||
|
if (!mTouchListenerTimeoutTask) {
|
||||||
|
mTouchListenerTimeoutTask =
|
||||||
|
NewRunnableMethod(this, &AsyncPanZoomController::TimeoutTouchListeners);
|
||||||
|
|
||||||
|
PostDelayedTask(mTouchListenerTimeoutTask, gTouchListenerTimeout);
|
||||||
|
}
|
||||||
|
return nsEventStatus_eConsumeNoDefault;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (aEvent.mInputType) {
|
switch (aEvent.mInputType) {
|
||||||
case MULTITOUCH_INPUT: {
|
case MULTITOUCH_INPUT: {
|
||||||
const MultiTouchInput& multiTouchInput = aEvent.AsMultiTouchInput();
|
const MultiTouchInput& multiTouchInput = aEvent.AsMultiTouchInput();
|
||||||
@ -397,6 +416,10 @@ nsEventStatus AsyncPanZoomController::OnTouchStart(const MultiTouchInput& aEvent
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsEventStatus AsyncPanZoomController::OnTouchMove(const MultiTouchInput& aEvent) {
|
nsEventStatus AsyncPanZoomController::OnTouchMove(const MultiTouchInput& aEvent) {
|
||||||
|
if (mDisableNextTouchBatch) {
|
||||||
|
return nsEventStatus_eIgnore;
|
||||||
|
}
|
||||||
|
|
||||||
switch (mState) {
|
switch (mState) {
|
||||||
case FLING:
|
case FLING:
|
||||||
case NOTHING:
|
case NOTHING:
|
||||||
@ -436,6 +459,11 @@ nsEventStatus AsyncPanZoomController::OnTouchMove(const MultiTouchInput& aEvent)
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsEventStatus AsyncPanZoomController::OnTouchEnd(const MultiTouchInput& aEvent) {
|
nsEventStatus AsyncPanZoomController::OnTouchEnd(const MultiTouchInput& aEvent) {
|
||||||
|
if (mDisableNextTouchBatch) {
|
||||||
|
mDisableNextTouchBatch = false;
|
||||||
|
return nsEventStatus_eIgnore;
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
ReentrantMonitorAutoEnter lock(mMonitor);
|
ReentrantMonitorAutoEnter lock(mMonitor);
|
||||||
SendAsyncScrollEvent();
|
SendAsyncScrollEvent();
|
||||||
@ -1157,6 +1185,18 @@ void AsyncPanZoomController::UpdateCompositionBounds(const ScreenIntRect& aCompo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AsyncPanZoomController::CancelDefaultPanZoom() {
|
||||||
|
mDisableNextTouchBatch = true;
|
||||||
|
nsRefPtr<GestureEventListener> listener = GetGestureEventListener();
|
||||||
|
if (listener) {
|
||||||
|
listener->CancelGesture();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AsyncPanZoomController::DetectScrollableSubframe() {
|
||||||
|
mDelayPanning = true;
|
||||||
|
}
|
||||||
|
|
||||||
void AsyncPanZoomController::ZoomToRect(CSSRect aRect) {
|
void AsyncPanZoomController::ZoomToRect(CSSRect aRect) {
|
||||||
SetState(ANIMATING_ZOOM);
|
SetState(ANIMATING_ZOOM);
|
||||||
|
|
||||||
@ -1236,7 +1276,7 @@ void AsyncPanZoomController::ZoomToRect(CSSRect aRect) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AsyncPanZoomController::ContentReceivedTouch(bool aPreventDefault) {
|
void AsyncPanZoomController::ContentReceivedTouch(bool aPreventDefault) {
|
||||||
if (!mFrameMetrics.mMayHaveTouchListeners) {
|
if (!mFrameMetrics.mMayHaveTouchListeners && !mDelayPanning) {
|
||||||
mTouchQueue.Clear();
|
mTouchQueue.Clear();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1248,12 +1288,21 @@ void AsyncPanZoomController::ContentReceivedTouch(bool aPreventDefault) {
|
|||||||
|
|
||||||
if (mState == WAITING_LISTENERS) {
|
if (mState == WAITING_LISTENERS) {
|
||||||
if (!aPreventDefault) {
|
if (!aPreventDefault) {
|
||||||
SetState(NOTHING);
|
// Delayed scrolling gesture is pending at TOUCHING state.
|
||||||
|
if (mDelayPanning) {
|
||||||
|
SetState(TOUCHING);
|
||||||
|
} else {
|
||||||
|
SetState(NOTHING);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mHandlingTouchQueue = true;
|
mHandlingTouchQueue = true;
|
||||||
|
|
||||||
while (!mTouchQueue.IsEmpty()) {
|
while (!mTouchQueue.IsEmpty()) {
|
||||||
|
// we need to reset mDelayPanning before handling scrolling gesture.
|
||||||
|
if (!aPreventDefault && mTouchQueue[0].mType == MultiTouchInput::MULTITOUCH_MOVE) {
|
||||||
|
mDelayPanning = false;
|
||||||
|
}
|
||||||
if (!aPreventDefault) {
|
if (!aPreventDefault) {
|
||||||
HandleInputEvent(mTouchQueue[0]);
|
HandleInputEvent(mTouchQueue[0]);
|
||||||
}
|
}
|
||||||
|
@ -109,6 +109,22 @@ public:
|
|||||||
*/
|
*/
|
||||||
void UpdateCompositionBounds(const ScreenIntRect& aCompositionBounds);
|
void UpdateCompositionBounds(const ScreenIntRect& aCompositionBounds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We are scrolling a subframe, so disable our machinery until we hit
|
||||||
|
* a touch end or a new touch start. This prevents us from accidentally
|
||||||
|
* panning both the subframe and the parent frame.
|
||||||
|
*
|
||||||
|
* XXX/bug 775452: We should eventually be supporting async scrollable
|
||||||
|
* subframes.
|
||||||
|
*/
|
||||||
|
void CancelDefaultPanZoom();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We have found a scrollable subframe, so we need to delay the scrolling
|
||||||
|
* gesture executed and let subframe do the scrolling first.
|
||||||
|
*/
|
||||||
|
void DetectScrollableSubframe();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Kicks an animation to zoom to a rect. This may be either a zoom out or zoom
|
* Kicks an animation to zoom to a rect. This may be either a zoom out or zoom
|
||||||
* in. The actual animation is done on the compositor thread after being set
|
* in. The actual animation is done on the compositor thread after being set
|
||||||
@ -564,12 +580,22 @@ private:
|
|||||||
// ensures the last mozbrowserasyncscroll event is always been fired.
|
// ensures the last mozbrowserasyncscroll event is always been fired.
|
||||||
CancelableTask* mAsyncScrollTimeoutTask;
|
CancelableTask* mAsyncScrollTimeoutTask;
|
||||||
|
|
||||||
|
// Flag used to determine whether or not we should disable handling of the
|
||||||
|
// next batch of touch events. This is used for sync scrolling of subframes.
|
||||||
|
bool mDisableNextTouchBatch;
|
||||||
|
|
||||||
// Flag used to determine whether or not we should try to enter the
|
// Flag used to determine whether or not we should try to enter the
|
||||||
// WAITING_LISTENERS state. This is used in the case that we are processing a
|
// WAITING_LISTENERS state. This is used in the case that we are processing a
|
||||||
// queued up event block. If set, this means that we are handling this queue
|
// queued up event block. If set, this means that we are handling this queue
|
||||||
// and we don't want to queue the events back up again.
|
// and we don't want to queue the events back up again.
|
||||||
bool mHandlingTouchQueue;
|
bool mHandlingTouchQueue;
|
||||||
|
|
||||||
|
// Flag used to determine whether or not we should try scrolling by
|
||||||
|
// BrowserElementScrolling first. If set, we delay delivering
|
||||||
|
// touchmove events to GestureListener until BrowserElementScrolling
|
||||||
|
// decides whether it wants to handle panning for this touch series.
|
||||||
|
bool mDelayPanning;
|
||||||
|
|
||||||
friend class Axis;
|
friend class Axis;
|
||||||
|
|
||||||
/* The functions and members in this section are used to build a tree
|
/* The functions and members in this section are used to build a tree
|
||||||
|
@ -246,7 +246,9 @@ void nsRegion::Init()
|
|||||||
mRectListHead.prev = mRectListHead.next = &mRectListHead;
|
mRectListHead.prev = mRectListHead.next = &mRectListHead;
|
||||||
mCurRect = &mRectListHead;
|
mCurRect = &mRectListHead;
|
||||||
mRectCount = 0;
|
mRectCount = 0;
|
||||||
mBoundRect.SetRect (0, 0, 0, 0);
|
MOZ_ASSERT(mBoundRect.x == 0 && mBoundRect.y == 0 &&
|
||||||
|
mBoundRect.width == 0 && mBoundRect.height == 0,
|
||||||
|
"Caller must have initialized mBoundRect");
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void nsRegion::InsertBefore (RgnRect* aNewRect, RgnRect* aRelativeRect)
|
inline void nsRegion::InsertBefore (RgnRect* aNewRect, RgnRect* aRelativeRect)
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
#include "base/port.h" // Types that only need exist on certain systems
|
#include "base/port.h" // Types that only need exist on certain systems
|
||||||
|
|
||||||
#include "mozilla/Assertions.h"
|
#include "mozilla/Assertions.h"
|
||||||
#include <stdint.h>
|
#include "mozilla/IntegerPrintfMacros.h"
|
||||||
|
|
||||||
// A type to represent a Unicode code-point value. As of Unicode 4.0,
|
// A type to represent a Unicode code-point value. As of Unicode 4.0,
|
||||||
// such values require up to 21 bits.
|
// such values require up to 21 bits.
|
||||||
@ -35,15 +35,10 @@ const int64_t kint64max = (( int64_t) GG_LONGLONG(0x7FFFFFFFFFFFFFFF));
|
|||||||
|
|
||||||
// Platform- and hardware-dependent printf specifiers
|
// Platform- and hardware-dependent printf specifiers
|
||||||
# if defined(OS_POSIX)
|
# if defined(OS_POSIX)
|
||||||
# define __STDC_FORMAT_MACROS 1
|
|
||||||
# include <inttypes.h> // for 64-bit integer format macros
|
|
||||||
# define PRId64L "I64d"
|
# define PRId64L "I64d"
|
||||||
# define PRIu64L "I64u"
|
# define PRIu64L "I64u"
|
||||||
# define PRIx64L "I64x"
|
# define PRIx64L "I64x"
|
||||||
# elif defined(OS_WIN)
|
# elif defined(OS_WIN)
|
||||||
# define PRId64 "I64d"
|
|
||||||
# define PRIu64 "I64u"
|
|
||||||
# define PRIx64 "I64x"
|
|
||||||
# define PRId64L L"I64d"
|
# define PRId64L L"I64d"
|
||||||
# define PRIu64L L"I64u"
|
# define PRIu64L L"I64u"
|
||||||
# define PRIx64L L"I64x"
|
# define PRIx64L L"I64x"
|
||||||
|
@ -15,9 +15,17 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* The c99 defining the limit macros (UINT32_MAX for example), says:
|
* The c99 defining the limit macros (UINT32_MAX for example), says:
|
||||||
* C++ implementations should define these macros only when __STDC_LIMIT_MACROS
|
*
|
||||||
* is defined before <stdint.h> is included.
|
* C++ implementations should define these macros only when
|
||||||
|
* __STDC_LIMIT_MACROS is defined before <stdint.h> is included.
|
||||||
|
*
|
||||||
|
* The same also occurs with __STDC_CONSTANT_MACROS for the constant macros
|
||||||
|
* (INT8_C for example) used to specify a literal constant of the proper type,
|
||||||
|
* and with __STDC_FORMAT_MACROS for the format macros (PRId32 for example) used
|
||||||
|
* with the fprintf function family.
|
||||||
*/
|
*/
|
||||||
#define __STDC_LIMIT_MACROS
|
#define __STDC_LIMIT_MACROS
|
||||||
|
#define __STDC_CONSTANT_MACROS
|
||||||
|
#define __STDC_FORMAT_MACROS
|
||||||
|
|
||||||
#endif /* js_RequiredDefines_h */
|
#endif /* js_RequiredDefines_h */
|
||||||
|
@ -1359,6 +1359,16 @@ case "$host" in
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
dnl Check for using a custom <inttypes.h> implementation
|
||||||
|
dnl ========================================================
|
||||||
|
AC_MSG_CHECKING(for custom <inttypes.h> implementation)
|
||||||
|
if test "$MOZ_CUSTOM_INTTYPES_H"; then
|
||||||
|
AC_DEFINE_UNQUOTED(MOZ_CUSTOM_INTTYPES_H, "$MOZ_CUSTOM_INTTYPES_H")
|
||||||
|
AC_MSG_RESULT(using $MOZ_CUSTOM_INTTYPES_H)
|
||||||
|
else
|
||||||
|
AC_MSG_RESULT(none specified)
|
||||||
|
fi
|
||||||
|
|
||||||
MOZ_DOING_LTO(lto_is_enabled)
|
MOZ_DOING_LTO(lto_is_enabled)
|
||||||
|
|
||||||
dnl ========================================================
|
dnl ========================================================
|
||||||
|
@ -138,6 +138,11 @@ var ignoreFunctions = {
|
|||||||
"PR_ErrorInstallTable" : true,
|
"PR_ErrorInstallTable" : true,
|
||||||
"PR_SetThreadPrivate" : true,
|
"PR_SetThreadPrivate" : true,
|
||||||
"JSObject* js::GetWeakmapKeyDelegate(JSObject*)" : true, // FIXME: mark with AutoAssertNoGC instead
|
"JSObject* js::GetWeakmapKeyDelegate(JSObject*)" : true, // FIXME: mark with AutoAssertNoGC instead
|
||||||
|
|
||||||
|
// These are a little overzealous -- these destructors *can* GC if they end
|
||||||
|
// up wrapping a pending exception. See bug 898815 for the heavyweight fix.
|
||||||
|
"void js::AutoCompartment::~AutoCompartment(int32)" : true,
|
||||||
|
"void JSAutoCompartment::~JSAutoCompartment(int32)" : true,
|
||||||
};
|
};
|
||||||
|
|
||||||
function ignoreGCFunction(fun)
|
function ignoreGCFunction(fun)
|
||||||
|
@ -2796,6 +2796,9 @@ template <>
|
|||||||
Parser<SyntaxParseHandler>::bindLet(BindData<SyntaxParseHandler> *data,
|
Parser<SyntaxParseHandler>::bindLet(BindData<SyntaxParseHandler> *data,
|
||||||
HandlePropertyName name, Parser<SyntaxParseHandler> *parser)
|
HandlePropertyName name, Parser<SyntaxParseHandler> *parser)
|
||||||
{
|
{
|
||||||
|
if (!parser->checkStrictBinding(name, data->pn))
|
||||||
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2229,7 +2229,8 @@ class FunctionCompiler
|
|||||||
*loopEntry = NULL;
|
*loopEntry = NULL;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
*loopEntry = MBasicBlock::NewPendingLoopHeader(mirGraph(), info(), curBlock_, NULL);
|
*loopEntry = MBasicBlock::NewAsmJS(mirGraph(), info(), curBlock_,
|
||||||
|
MBasicBlock::PENDING_LOOP_HEADER);
|
||||||
if (!*loopEntry)
|
if (!*loopEntry)
|
||||||
return false;
|
return false;
|
||||||
mirGraph().addBlock(*loopEntry);
|
mirGraph().addBlock(*loopEntry);
|
||||||
@ -2287,7 +2288,8 @@ class FunctionCompiler
|
|||||||
if (curBlock_) {
|
if (curBlock_) {
|
||||||
JS_ASSERT(curBlock_->loopDepth() == loopStack_.length() + 1);
|
JS_ASSERT(curBlock_->loopDepth() == loopStack_.length() + 1);
|
||||||
curBlock_->end(MGoto::New(loopEntry));
|
curBlock_->end(MGoto::New(loopEntry));
|
||||||
loopEntry->setBackedge(curBlock_);
|
if (!loopEntry->setBackedgeAsmJS(curBlock_))
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
curBlock_ = afterLoop;
|
curBlock_ = afterLoop;
|
||||||
if (curBlock_)
|
if (curBlock_)
|
||||||
@ -2309,7 +2311,8 @@ class FunctionCompiler
|
|||||||
if (cond->isConstant()) {
|
if (cond->isConstant()) {
|
||||||
if (ToBoolean(cond->toConstant()->value())) {
|
if (ToBoolean(cond->toConstant()->value())) {
|
||||||
curBlock_->end(MGoto::New(loopEntry));
|
curBlock_->end(MGoto::New(loopEntry));
|
||||||
loopEntry->setBackedge(curBlock_);
|
if (!loopEntry->setBackedgeAsmJS(curBlock_))
|
||||||
|
return false;
|
||||||
curBlock_ = NULL;
|
curBlock_ = NULL;
|
||||||
} else {
|
} else {
|
||||||
MBasicBlock *afterLoop;
|
MBasicBlock *afterLoop;
|
||||||
@ -2323,7 +2326,8 @@ class FunctionCompiler
|
|||||||
if (!newBlock(curBlock_, &afterLoop, afterLoopStmt))
|
if (!newBlock(curBlock_, &afterLoop, afterLoopStmt))
|
||||||
return false;
|
return false;
|
||||||
curBlock_->end(MTest::New(cond, loopEntry, afterLoop));
|
curBlock_->end(MTest::New(cond, loopEntry, afterLoop));
|
||||||
loopEntry->setBackedge(curBlock_);
|
if (!loopEntry->setBackedgeAsmJS(curBlock_))
|
||||||
|
return false;
|
||||||
curBlock_ = afterLoop;
|
curBlock_ = afterLoop;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2449,7 +2453,7 @@ class FunctionCompiler
|
|||||||
|
|
||||||
bool newBlockWithDepth(MBasicBlock *pred, unsigned loopDepth, MBasicBlock **block, ParseNode *pn)
|
bool newBlockWithDepth(MBasicBlock *pred, unsigned loopDepth, MBasicBlock **block, ParseNode *pn)
|
||||||
{
|
{
|
||||||
*block = MBasicBlock::New(mirGraph(), info(), pred, /* pc = */ NULL, MBasicBlock::NORMAL);
|
*block = MBasicBlock::NewAsmJS(mirGraph(), info(), pred, MBasicBlock::NORMAL);
|
||||||
if (!*block)
|
if (!*block)
|
||||||
return false;
|
return false;
|
||||||
noteBasicBlockPosition(*block, pn);
|
noteBasicBlockPosition(*block, pn);
|
||||||
@ -3782,12 +3786,6 @@ CheckConditional(FunctionCompiler &f, ParseNode *ternary, MDefinition **def, Typ
|
|||||||
|
|
||||||
f.pushPhiInput(elseDef);
|
f.pushPhiInput(elseDef);
|
||||||
|
|
||||||
// next statement is actually not the else expr, but this is the closest stmt to the next
|
|
||||||
// one that is directly reachable
|
|
||||||
if (!f.joinIfElse(thenBlocks, elseExpr))
|
|
||||||
return false;
|
|
||||||
*def = f.popPhiOutput();
|
|
||||||
|
|
||||||
if (thenType.isInt() && elseType.isInt()) {
|
if (thenType.isInt() && elseType.isInt()) {
|
||||||
*type = Type::Int;
|
*type = Type::Int;
|
||||||
} else if (thenType.isDouble() && elseType.isDouble()) {
|
} else if (thenType.isDouble() && elseType.isDouble()) {
|
||||||
@ -3797,6 +3795,10 @@ CheckConditional(FunctionCompiler &f, ParseNode *ternary, MDefinition **def, Typ
|
|||||||
"current types are %s and %s", thenType.toChars(), elseType.toChars());
|
"current types are %s and %s", thenType.toChars(), elseType.toChars());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!f.joinIfElse(thenBlocks, elseExpr))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*def = f.popPhiOutput();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4311,12 +4313,9 @@ CheckIf(FunctionCompiler &f, ParseNode *ifStmt)
|
|||||||
|
|
||||||
MBasicBlock *thenBlock, *elseBlock;
|
MBasicBlock *thenBlock, *elseBlock;
|
||||||
|
|
||||||
ParseNode *elseBlockStmt = NULL;
|
|
||||||
// The second block given to branchAndStartThen contains either the else statement if
|
// The second block given to branchAndStartThen contains either the else statement if
|
||||||
// there is one, or the join block; so we need to give the next statement accordingly.
|
// there is one, or the join block; so we need to give the next statement accordingly.
|
||||||
elseBlockStmt = elseStmt;
|
ParseNode *elseBlockStmt = elseStmt ? elseStmt : nextStmt;
|
||||||
if (elseBlockStmt == NULL)
|
|
||||||
elseBlockStmt = nextStmt;
|
|
||||||
|
|
||||||
if (!f.branchAndStartThen(condDef, &thenBlock, &elseBlock, thenStmt, elseBlockStmt))
|
if (!f.branchAndStartThen(condDef, &thenBlock, &elseBlock, thenStmt, elseBlockStmt))
|
||||||
return false;
|
return false;
|
||||||
|
@ -5568,8 +5568,12 @@ CodeGenerator::link()
|
|||||||
IonCode *code = (executionMode == SequentialExecution)
|
IonCode *code = (executionMode == SequentialExecution)
|
||||||
? linker.newCodeForIonScript(cx)
|
? linker.newCodeForIonScript(cx)
|
||||||
: linker.newCode(cx, JSC::ION_CODE);
|
: linker.newCode(cx, JSC::ION_CODE);
|
||||||
if (!code)
|
if (!code) {
|
||||||
|
// Use js_free instead of IonScript::Destroy: the cache list and
|
||||||
|
// backedge list are still uninitialized.
|
||||||
|
js_free(ionScript);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
JSScript *script = gen->info().script();
|
JSScript *script = gen->info().script();
|
||||||
JS_ASSERT(!HasIonScript(script, executionMode));
|
JS_ASSERT(!HasIonScript(script, executionMode));
|
||||||
|
@ -1228,14 +1228,15 @@ OptimizeMIR(MIRGenerator *mir)
|
|||||||
if (mir->shouldCancel("Phi reverse mapping"))
|
if (mir->shouldCancel("Phi reverse mapping"))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// This pass also removes copies.
|
if (!mir->compilingAsmJS()) {
|
||||||
if (!ApplyTypeInformation(mir, graph))
|
if (!ApplyTypeInformation(mir, graph))
|
||||||
return false;
|
return false;
|
||||||
IonSpewPass("Apply types");
|
IonSpewPass("Apply types");
|
||||||
AssertExtendedGraphCoherency(graph);
|
AssertExtendedGraphCoherency(graph);
|
||||||
|
|
||||||
if (mir->shouldCancel("Apply types"))
|
if (mir->shouldCancel("Apply types"))
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (graph.entryBlock()->info().executionMode() == ParallelExecution) {
|
if (graph.entryBlock()->info().executionMode() == ParallelExecution) {
|
||||||
ParallelSafetyAnalysis analysis(mir, graph);
|
ParallelSafetyAnalysis analysis(mir, graph);
|
||||||
@ -1361,7 +1362,7 @@ OptimizeMIR(MIRGenerator *mir)
|
|||||||
// Passes after this point must not move instructions; these analyses
|
// Passes after this point must not move instructions; these analyses
|
||||||
// depend on knowing the final order in which instructions will execute.
|
// depend on knowing the final order in which instructions will execute.
|
||||||
|
|
||||||
if (js_IonOptions.edgeCaseAnalysis) {
|
if (js_IonOptions.edgeCaseAnalysis && !mir->compilingAsmJS()) {
|
||||||
EdgeCaseAnalysis edgeCaseAnalysis(mir, graph);
|
EdgeCaseAnalysis edgeCaseAnalysis(mir, graph);
|
||||||
if (!edgeCaseAnalysis.analyzeLate())
|
if (!edgeCaseAnalysis.analyzeLate())
|
||||||
return false;
|
return false;
|
||||||
@ -1372,14 +1373,16 @@ OptimizeMIR(MIRGenerator *mir)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: check elimination has to run after all other passes that move
|
if (!mir->compilingAsmJS()) {
|
||||||
// instructions. Since check uses are replaced with the actual index, code
|
// Note: check elimination has to run after all other passes that move
|
||||||
// motion after this pass could incorrectly move a load or store before its
|
// instructions. Since check uses are replaced with the actual index,
|
||||||
// bounds check.
|
// code motion after this pass could incorrectly move a load or store
|
||||||
if (!EliminateRedundantChecks(graph))
|
// before its bounds check.
|
||||||
return false;
|
if (!EliminateRedundantChecks(graph))
|
||||||
IonSpewPass("Bounds Check Elimination");
|
return false;
|
||||||
AssertGraphCoherency(graph);
|
IonSpewPass("Bounds Check Elimination");
|
||||||
|
AssertGraphCoherency(graph);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -625,12 +625,6 @@ MUnbox::printOpcode(FILE *fp) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MPhi *
|
|
||||||
MPhi::New(uint32_t slot)
|
|
||||||
{
|
|
||||||
return new MPhi(slot);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
MPhi::removeOperand(size_t index)
|
MPhi::removeOperand(size_t index)
|
||||||
{
|
{
|
||||||
|
@ -3845,7 +3845,7 @@ class MPhi MOZ_FINAL : public MDefinition, public InlineForwardListNode<MPhi>
|
|||||||
uint32_t capacity_;
|
uint32_t capacity_;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
MPhi(uint32_t slot)
|
MPhi(uint32_t slot, MIRType resultType)
|
||||||
: slot_(slot),
|
: slot_(slot),
|
||||||
hasBackedgeType_(false),
|
hasBackedgeType_(false),
|
||||||
triedToSpecialize_(false),
|
triedToSpecialize_(false),
|
||||||
@ -3855,7 +3855,7 @@ class MPhi MOZ_FINAL : public MDefinition, public InlineForwardListNode<MPhi>
|
|||||||
, capacity_(0)
|
, capacity_(0)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
setResultType(MIRType_Value);
|
setResultType(resultType);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -3865,7 +3865,9 @@ class MPhi MOZ_FINAL : public MDefinition, public InlineForwardListNode<MPhi>
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
INSTRUCTION_HEADER(Phi)
|
INSTRUCTION_HEADER(Phi)
|
||||||
static MPhi *New(uint32_t slot);
|
static MPhi *New(uint32_t slot, MIRType resultType = MIRType_Value) {
|
||||||
|
return new MPhi(slot, resultType);
|
||||||
|
}
|
||||||
|
|
||||||
void setOperand(size_t index, MDefinition *operand) {
|
void setOperand(size_t index, MDefinition *operand) {
|
||||||
// Note: after the initial IonBuilder pass, it is OK to change phi
|
// Note: after the initial IonBuilder pass, it is OK to change phi
|
||||||
|
@ -159,6 +159,8 @@ MBasicBlock *
|
|||||||
MBasicBlock::New(MIRGraph &graph, CompileInfo &info,
|
MBasicBlock::New(MIRGraph &graph, CompileInfo &info,
|
||||||
MBasicBlock *pred, jsbytecode *entryPc, Kind kind)
|
MBasicBlock *pred, jsbytecode *entryPc, Kind kind)
|
||||||
{
|
{
|
||||||
|
JS_ASSERT(entryPc != NULL);
|
||||||
|
|
||||||
MBasicBlock *block = new MBasicBlock(graph, info, entryPc, kind);
|
MBasicBlock *block = new MBasicBlock(graph, info, entryPc, kind);
|
||||||
if (!block->init())
|
if (!block->init())
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -212,7 +214,9 @@ MBasicBlock::NewPendingLoopHeader(MIRGraph &graph, CompileInfo &info,
|
|||||||
MBasicBlock *
|
MBasicBlock *
|
||||||
MBasicBlock::NewSplitEdge(MIRGraph &graph, CompileInfo &info, MBasicBlock *pred)
|
MBasicBlock::NewSplitEdge(MIRGraph &graph, CompileInfo &info, MBasicBlock *pred)
|
||||||
{
|
{
|
||||||
return MBasicBlock::New(graph, info, pred, pred->pc(), SPLIT_EDGE);
|
return pred->pc()
|
||||||
|
? MBasicBlock::New(graph, info, pred, pred->pc(), SPLIT_EDGE)
|
||||||
|
: MBasicBlock::NewAsmJS(graph, info, pred, SPLIT_EDGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
MBasicBlock *
|
MBasicBlock *
|
||||||
@ -235,6 +239,40 @@ MBasicBlock::NewAbortPar(MIRGraph &graph, CompileInfo &info,
|
|||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MBasicBlock *
|
||||||
|
MBasicBlock::NewAsmJS(MIRGraph &graph, CompileInfo &info, MBasicBlock *pred, Kind kind)
|
||||||
|
{
|
||||||
|
MBasicBlock *block = new MBasicBlock(graph, info, /* entryPC = */ NULL, kind);
|
||||||
|
if (!block->init())
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (pred) {
|
||||||
|
block->stackPosition_ = pred->stackPosition_;
|
||||||
|
|
||||||
|
if (block->kind_ == PENDING_LOOP_HEADER) {
|
||||||
|
for (size_t i = 0; i < block->stackPosition_; i++) {
|
||||||
|
MDefinition *predSlot = pred->getSlot(i);
|
||||||
|
|
||||||
|
JS_ASSERT(predSlot->type() != MIRType_Value);
|
||||||
|
MPhi *phi = MPhi::New(i, predSlot->type());
|
||||||
|
|
||||||
|
JS_ALWAYS_TRUE(phi->reserveLength(2));
|
||||||
|
phi->addInput(predSlot);
|
||||||
|
|
||||||
|
block->addPhi(phi);
|
||||||
|
block->setSlot(i, phi);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
block->copySlots(pred);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!block->predecessors_.append(pred))
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
MBasicBlock::MBasicBlock(MIRGraph &graph, CompileInfo &info, jsbytecode *pc, Kind kind)
|
MBasicBlock::MBasicBlock(MIRGraph &graph, CompileInfo &info, jsbytecode *pc, Kind kind)
|
||||||
: earlyAbort_(false),
|
: earlyAbort_(false),
|
||||||
graph_(graph),
|
graph_(graph),
|
||||||
@ -291,27 +329,23 @@ MBasicBlock::inherit(MBasicBlock *pred, uint32_t popped)
|
|||||||
stackPosition_ -= popped;
|
stackPosition_ -= popped;
|
||||||
if (kind_ != PENDING_LOOP_HEADER)
|
if (kind_ != PENDING_LOOP_HEADER)
|
||||||
copySlots(pred);
|
copySlots(pred);
|
||||||
} else if (pc()) {
|
} else {
|
||||||
uint32_t stackDepth = info().script()->analysis()->getCode(pc()).stackDepth;
|
uint32_t stackDepth = info().script()->analysis()->getCode(pc()).stackDepth;
|
||||||
stackPosition_ = info().firstStackSlot() + stackDepth;
|
stackPosition_ = info().firstStackSlot() + stackDepth;
|
||||||
JS_ASSERT(stackPosition_ >= popped);
|
JS_ASSERT(stackPosition_ >= popped);
|
||||||
stackPosition_ -= popped;
|
stackPosition_ -= popped;
|
||||||
} else {
|
|
||||||
stackPosition_ = info().firstStackSlot();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_ASSERT(info_.nslots() >= stackPosition_);
|
JS_ASSERT(info_.nslots() >= stackPosition_);
|
||||||
JS_ASSERT(!entryResumePoint_);
|
JS_ASSERT(!entryResumePoint_);
|
||||||
|
|
||||||
if (pc()) {
|
// Propagate the caller resume point from the inherited block.
|
||||||
// Propagate the caller resume point from the inherited block.
|
MResumePoint *callerResumePoint = pred ? pred->callerResumePoint() : NULL;
|
||||||
MResumePoint *callerResumePoint = pred ? pred->callerResumePoint() : NULL;
|
|
||||||
|
|
||||||
// Create a resume point using our initial stack state.
|
// Create a resume point using our initial stack state.
|
||||||
entryResumePoint_ = new MResumePoint(this, pc(), callerResumePoint, MResumePoint::ResumeAt);
|
entryResumePoint_ = new MResumePoint(this, pc(), callerResumePoint, MResumePoint::ResumeAt);
|
||||||
if (!entryResumePoint_->init())
|
if (!entryResumePoint_->init())
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
if (pred) {
|
if (pred) {
|
||||||
if (!predecessors_.append(pred))
|
if (!predecessors_.append(pred))
|
||||||
@ -324,14 +358,13 @@ MBasicBlock::inherit(MBasicBlock *pred, uint32_t popped)
|
|||||||
return false;
|
return false;
|
||||||
addPhi(phi);
|
addPhi(phi);
|
||||||
setSlot(i, phi);
|
setSlot(i, phi);
|
||||||
if (entryResumePoint())
|
entryResumePoint()->setOperand(i, phi);
|
||||||
entryResumePoint()->setOperand(i, phi);
|
|
||||||
}
|
}
|
||||||
} else if (entryResumePoint()) {
|
} else {
|
||||||
for (size_t i = 0; i < stackDepth(); i++)
|
for (size_t i = 0; i < stackDepth(); i++)
|
||||||
entryResumePoint()->setOperand(i, getSlot(i));
|
entryResumePoint()->setOperand(i, getSlot(i));
|
||||||
}
|
}
|
||||||
} else if (entryResumePoint()) {
|
} else {
|
||||||
/*
|
/*
|
||||||
* Don't leave the operands uninitialized for the caller, as it may not
|
* Don't leave the operands uninitialized for the caller, as it may not
|
||||||
* initialize them later on.
|
* initialize them later on.
|
||||||
@ -796,7 +829,11 @@ MBasicBlock::addPredecessorPopN(MBasicBlock *pred, uint32_t popped)
|
|||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
// Otherwise, create a new phi node.
|
// Otherwise, create a new phi node.
|
||||||
MPhi *phi = MPhi::New(i);
|
MPhi *phi;
|
||||||
|
if (mine->type() == other->type())
|
||||||
|
phi = MPhi::New(i, mine->type());
|
||||||
|
else
|
||||||
|
phi = MPhi::New(i);
|
||||||
addPhi(phi);
|
addPhi(phi);
|
||||||
|
|
||||||
// Prime the phi for each predecessor, so input(x) comes from
|
// Prime the phi for each predecessor, so input(x) comes from
|
||||||
@ -859,7 +896,7 @@ MBasicBlock::setBackedge(MBasicBlock *pred)
|
|||||||
// Predecessors must be finished, and at the correct stack depth.
|
// Predecessors must be finished, and at the correct stack depth.
|
||||||
JS_ASSERT(lastIns_);
|
JS_ASSERT(lastIns_);
|
||||||
JS_ASSERT(pred->lastIns_);
|
JS_ASSERT(pred->lastIns_);
|
||||||
JS_ASSERT_IF(entryResumePoint(), pred->stackDepth() == entryResumePoint()->stackDepth());
|
JS_ASSERT(pred->stackDepth() == entryResumePoint()->stackDepth());
|
||||||
|
|
||||||
// We must be a pending loop header
|
// We must be a pending loop header
|
||||||
JS_ASSERT(kind_ == PENDING_LOOP_HEADER);
|
JS_ASSERT(kind_ == PENDING_LOOP_HEADER);
|
||||||
@ -911,6 +948,53 @@ MBasicBlock::setBackedge(MBasicBlock *pred)
|
|||||||
return AbortReason_NoAbort;
|
return AbortReason_NoAbort;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
MBasicBlock::setBackedgeAsmJS(MBasicBlock *pred)
|
||||||
|
{
|
||||||
|
// Predecessors must be finished, and at the correct stack depth.
|
||||||
|
JS_ASSERT(lastIns_);
|
||||||
|
JS_ASSERT(pred->lastIns_);
|
||||||
|
JS_ASSERT(stackDepth() == pred->stackDepth());
|
||||||
|
|
||||||
|
// We must be a pending loop header
|
||||||
|
JS_ASSERT(kind_ == PENDING_LOOP_HEADER);
|
||||||
|
|
||||||
|
// Add exit definitions to each corresponding phi at the entry.
|
||||||
|
for (MPhiIterator phi = phisBegin(); phi != phisEnd(); phi++) {
|
||||||
|
MPhi *entryDef = *phi;
|
||||||
|
MDefinition *exitDef = pred->getSlot(entryDef->slot());
|
||||||
|
|
||||||
|
// Assert that we already placed phis for each slot.
|
||||||
|
JS_ASSERT(entryDef->block() == this);
|
||||||
|
|
||||||
|
// Assert that the phi already has the correct type.
|
||||||
|
JS_ASSERT(entryDef->type() == exitDef->type());
|
||||||
|
JS_ASSERT(entryDef->type() != MIRType_Value);
|
||||||
|
|
||||||
|
if (entryDef == exitDef) {
|
||||||
|
// If the exit def is the same as the entry def, make a redundant
|
||||||
|
// phi. Since loop headers have exactly two incoming edges, we
|
||||||
|
// know that that's just the first input.
|
||||||
|
//
|
||||||
|
// Note that we eliminate later rather than now, to avoid any
|
||||||
|
// weirdness around pending continue edges which might still hold
|
||||||
|
// onto phis.
|
||||||
|
exitDef = entryDef->getOperand(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// MBasicBlock::NewAsmJS calls reserveLength(2) for loop header phis.
|
||||||
|
entryDef->addInput(exitDef);
|
||||||
|
|
||||||
|
JS_ASSERT(entryDef->slot() < pred->stackDepth());
|
||||||
|
setSlot(entryDef->slot(), entryDef);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We are now a loop header proper
|
||||||
|
kind_ = LOOP_HEADER;
|
||||||
|
|
||||||
|
return predecessors_.append(pred);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MBasicBlock::clearLoopHeader()
|
MBasicBlock::clearLoopHeader()
|
||||||
{
|
{
|
||||||
|
@ -80,6 +80,8 @@ class MBasicBlock : public TempObject, public InlineListNode<MBasicBlock>
|
|||||||
static MBasicBlock *NewAbortPar(MIRGraph &graph, CompileInfo &info,
|
static MBasicBlock *NewAbortPar(MIRGraph &graph, CompileInfo &info,
|
||||||
MBasicBlock *pred, jsbytecode *entryPc,
|
MBasicBlock *pred, jsbytecode *entryPc,
|
||||||
MResumePoint *resumePoint);
|
MResumePoint *resumePoint);
|
||||||
|
static MBasicBlock *NewAsmJS(MIRGraph &graph, CompileInfo &info,
|
||||||
|
MBasicBlock *pred, Kind kind);
|
||||||
|
|
||||||
bool dominates(MBasicBlock *other);
|
bool dominates(MBasicBlock *other);
|
||||||
|
|
||||||
@ -196,6 +198,7 @@ class MBasicBlock : public TempObject, public InlineListNode<MBasicBlock>
|
|||||||
// the current loop as necessary. If the backedge introduces new types for
|
// the current loop as necessary. If the backedge introduces new types for
|
||||||
// phis at the loop header, returns a disabling abort.
|
// phis at the loop header, returns a disabling abort.
|
||||||
AbortReason setBackedge(MBasicBlock *block);
|
AbortReason setBackedge(MBasicBlock *block);
|
||||||
|
bool setBackedgeAsmJS(MBasicBlock *block);
|
||||||
|
|
||||||
// Resets a LOOP_HEADER block to a NORMAL block. This is needed when
|
// Resets a LOOP_HEADER block to a NORMAL block. This is needed when
|
||||||
// optimizations remove the backedge.
|
// optimizations remove the backedge.
|
||||||
|
@ -77,6 +77,7 @@ function testCollapsed(id, vPercent, startAt, expected) {
|
|||||||
var c = document.getElementById("c" + id);
|
var c = document.getElementById("c" + id);
|
||||||
var target = document.getElementById("target" + id);
|
var target = document.getElementById("target" + id);
|
||||||
if (target.contentDocument) {
|
if (target.contentDocument) {
|
||||||
|
selection = target.contentWindow.getSelection().QueryInterface(Components.interfaces.nsISelectionPrivate);
|
||||||
target = target.contentDocument.getElementById("target" + id);
|
target = target.contentDocument.getElementById("target" + id);
|
||||||
}
|
}
|
||||||
selection.collapse(target.parentNode, 0);
|
selection.collapse(target.parentNode, 0);
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user