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/
|
||||
#
|
||||
|
||||
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() {
|
||||
Cu.import('resource://gre/modules/Geometry.jsm');
|
||||
},
|
||||
@ -509,8 +622,7 @@ var Output = {
|
||||
},
|
||||
|
||||
Speech: function Speech(aDetails, aBrowser) {
|
||||
for each (let action in aDetails.actions)
|
||||
Logger.info('tts.' + action.method, '"' + action.data + '"', JSON.stringify(action.options));
|
||||
this.speechHelper.output(aDetails.actions);
|
||||
},
|
||||
|
||||
Visual: function Visual(aDetails, aBrowser) {
|
||||
|
@ -5,3 +5,4 @@
|
||||
toolkit.jar:
|
||||
content/global/accessibility/AccessFu.css (AccessFu.css)
|
||||
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/jar.xpt
|
||||
@BINPATH@/components/jsdebugger.xpt
|
||||
@BINPATH@/components/jsdownloads.xpt
|
||||
@BINPATH@/components/jsdservice.xpt
|
||||
@BINPATH@/components/jsinspector.xpt
|
||||
@BINPATH@/components/layout_base.xpt
|
||||
|
@ -1,4 +1,4 @@
|
||||
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 */
|
||||
/* globals Components, Services, XPCOMUtils, NetUtil, PrivateBrowsingUtils,
|
||||
dump, NetworkManager */
|
||||
dump, NetworkManager, PdfJsTelemetry */
|
||||
|
||||
'use strict';
|
||||
|
||||
@ -42,6 +42,9 @@ Cu.import('resource://pdf.js/network.js');
|
||||
XPCOMUtils.defineLazyModuleGetter(this, 'PrivateBrowsingUtils',
|
||||
'resource://gre/modules/PrivateBrowsingUtils.jsm');
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, 'PdfJsTelemetry',
|
||||
'resource://pdf.js/PdfJsTelemetry.jsm');
|
||||
|
||||
var Svc = {};
|
||||
XPCOMUtils.defineLazyServiceGetter(Svc, 'mime',
|
||||
'@mozilla.org/mime;1',
|
||||
@ -194,6 +197,12 @@ PdfDataListener.prototype = {
|
||||
function ChromeActions(domWindow, contentDispositionFilename) {
|
||||
this.domWindow = domWindow;
|
||||
this.contentDispositionFilename = contentDispositionFilename;
|
||||
this.telemetryState = {
|
||||
documentInfo: false,
|
||||
firstPageInfo: false,
|
||||
streamTypesUsed: [],
|
||||
startAt: Date.now()
|
||||
};
|
||||
}
|
||||
|
||||
ChromeActions.prototype = {
|
||||
@ -321,12 +330,49 @@ ChromeActions.prototype = {
|
||||
supportsDocumentColors: function() {
|
||||
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) {
|
||||
var self = this;
|
||||
var domWindow = this.domWindow;
|
||||
var strings = getLocalizedStrings('chrome.properties');
|
||||
var message = getLocalizedString(strings, 'unsupported_feature');
|
||||
|
||||
PdfJsTelemetry.onFallback();
|
||||
|
||||
var notificationBox = null;
|
||||
try {
|
||||
// Based on MDN's "Working with windows in chrome code"
|
||||
@ -730,6 +776,9 @@ PdfStreamConverter.prototype = {
|
||||
false);
|
||||
}
|
||||
|
||||
PdfJsTelemetry.onViewerIsUsed();
|
||||
PdfJsTelemetry.onDocumentSize(aRequest.contentLength);
|
||||
|
||||
if (!rangeRequest) {
|
||||
// Creating storage for PDF data
|
||||
var contentLength = aRequest.contentLength;
|
||||
|
@ -254,7 +254,7 @@ let PdfJs = {
|
||||
this._pdfStreamConverterFactory.unregister();
|
||||
delete this._pdfStreamConverterFactory;
|
||||
|
||||
this._pdfRedirectorFactory.unregister;
|
||||
this._pdfRedirectorFactory.unregister();
|
||||
delete this._pdfRedirectorFactory;
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
this.panel = panel;
|
||||
this.breakPoint = 0;
|
||||
@ -281,8 +300,29 @@ var Stepper = (function StepperClosure() {
|
||||
breakCell.appendChild(cbox);
|
||||
line.appendChild(breakCell);
|
||||
line.appendChild(c('td', i.toString()));
|
||||
line.appendChild(c('td', operatorList.fnArray[i]));
|
||||
line.appendChild(c('td', args.join(', ')));
|
||||
var fn = operatorList.fnArray[i];
|
||||
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() {
|
||||
|
@ -982,7 +982,7 @@ html[dir='rtl'] .outlineItem > a {
|
||||
}
|
||||
|
||||
canvas {
|
||||
margin: auto;
|
||||
margin: 0;
|
||||
display: block;
|
||||
}
|
||||
|
||||
@ -1105,6 +1105,9 @@ canvas {
|
||||
padding: 3px;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
.loadingInProgress #errorWrapper {
|
||||
top: 39px;
|
||||
}
|
||||
|
||||
#errorMessageLeft {
|
||||
float: left;
|
||||
|
@ -17,7 +17,7 @@
|
||||
/* globals PDFJS, PDFBug, FirefoxCom, Stats, Cache, PDFFindBar, CustomStyle,
|
||||
PDFFindController, ProgressBar, TextLayerBuilder, DownloadManager,
|
||||
getFileName, getOutputScale, scrollIntoView, getPDFFileNameFromURL,
|
||||
PDFHistory, noContextMenuHandler */
|
||||
PDFHistory, ThumbnailView, noContextMenuHandler */
|
||||
|
||||
'use strict';
|
||||
|
||||
@ -48,7 +48,7 @@ var FindStates = {
|
||||
};
|
||||
|
||||
PDFJS.imageResourcesPath = './images/';
|
||||
PDFJS.workerSrc = '../build/pdf.js';
|
||||
PDFJS.workerSrc = '../build/pdf.worker.js';
|
||||
|
||||
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) {
|
||||
var pageContent = this.pageContents[pageIndex];
|
||||
var query = this.state.query;
|
||||
@ -969,7 +975,7 @@ var PDFHistory = {
|
||||
// is opened in the web viewer.
|
||||
this.reInitialized = true;
|
||||
}
|
||||
window.history.replaceState({ fingerprint: this.fingerprint }, '', '');
|
||||
window.history.replaceState({ fingerprint: this.fingerprint }, '');
|
||||
}
|
||||
|
||||
var self = this;
|
||||
@ -1174,9 +1180,9 @@ var PDFHistory = {
|
||||
}
|
||||
}
|
||||
if (overwrite || this.uid === 0) {
|
||||
window.history.replaceState(this._stateObj(params), '', '');
|
||||
window.history.replaceState(this._stateObj(params), '');
|
||||
} else {
|
||||
window.history.pushState(this._stateObj(params), '', '');
|
||||
window.history.pushState(this._stateObj(params), '');
|
||||
}
|
||||
this.currentUid = this.uid++;
|
||||
this.current = params;
|
||||
@ -1248,8 +1254,6 @@ var PDFView = {
|
||||
currentScale: UNKNOWN_SCALE,
|
||||
currentScaleValue: null,
|
||||
initialBookmark: document.location.hash.substring(1),
|
||||
startedTextExtraction: false,
|
||||
pageText: [],
|
||||
container: null,
|
||||
thumbnailContainer: null,
|
||||
initialized: false,
|
||||
@ -1839,6 +1843,8 @@ var PDFView = {
|
||||
};
|
||||
}
|
||||
|
||||
PDFFindController.reset();
|
||||
|
||||
this.pdfDocument = pdfDocument;
|
||||
|
||||
var errorWrapper = document.getElementById('errorWrapper');
|
||||
@ -1876,8 +1882,6 @@ var PDFView = {
|
||||
this.pageRotation = 0;
|
||||
|
||||
var pages = this.pages = [];
|
||||
this.pageText = [];
|
||||
this.startedTextExtraction = false;
|
||||
var pagesRefMap = this.pagesRefMap = {};
|
||||
var thumbnails = this.thumbnails = [];
|
||||
|
||||
@ -2030,6 +2034,32 @@ var PDFView = {
|
||||
console.warn('Warning: AcroForm/XFA is not supported');
|
||||
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';
|
||||
}
|
||||
|
||||
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) {
|
||||
viewport = viewport.clone({ dontFlip: true });
|
||||
for (var i = 0; i < annotationsData.length; i++) {
|
||||
@ -2656,8 +2732,12 @@ var PageView = function pageView(container, id, scale,
|
||||
CustomStyle.setProp('transformOrigin', element, transformOriginStr);
|
||||
|
||||
if (data.subtype === 'Link' && !data.url) {
|
||||
if (data.action) {
|
||||
bindNamedAction(element, data.action);
|
||||
} else {
|
||||
bindLink(element, ('dest' in data) ? data.dest : null);
|
||||
}
|
||||
}
|
||||
|
||||
annotationsDiv.appendChild(element);
|
||||
}
|
||||
@ -2884,6 +2964,10 @@ var PageView = function pageView(container, id, scale,
|
||||
});
|
||||
div.dispatchEvent(event);
|
||||
|
||||
FirefoxCom.request('reportTelemetry', JSON.stringify({
|
||||
type: 'pageInfo'
|
||||
}));
|
||||
// TODO add stream types report here
|
||||
callback();
|
||||
}
|
||||
|
||||
@ -2990,6 +3074,7 @@ var PageView = function pageView(container, id, scale,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
var ThumbnailView = function thumbnailView(container, id, defaultViewport) {
|
||||
var anchor = document.createElement('a');
|
||||
anchor.href = PDFView.getAnchorUrl('#page=' + id);
|
||||
@ -2999,7 +3084,6 @@ var ThumbnailView = function thumbnailView(container, id, defaultViewport) {
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
this.pdfPage = undefined;
|
||||
this.viewport = defaultViewport;
|
||||
this.pdfPageRotate = defaultViewport.rotate;
|
||||
@ -3574,6 +3658,7 @@ document.addEventListener('DOMContentLoaded', function webViewerLoad(evt) {
|
||||
|
||||
var file = window.location.href.split('#')[0];
|
||||
|
||||
|
||||
document.getElementById('openFile').setAttribute('hidden', 'true');
|
||||
|
||||
// Special debugging flags in the hash section of the URL.
|
||||
@ -4034,8 +4119,12 @@ window.addEventListener('keydown', function keydown(evt) {
|
||||
break;
|
||||
case 48: // '0'
|
||||
case 96: // '0' on Numpad of Swedish keyboard
|
||||
// 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; // keeping it unhandled (to restore page zoom to 100%)
|
||||
});
|
||||
handled = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -2,8 +2,10 @@ chrome.manifest
|
||||
components/PdfRedirector.js
|
||||
components/PdfStreamConverter.js
|
||||
content/build/pdf.js
|
||||
content/build/pdf.worker.js
|
||||
content/network.js
|
||||
content/PdfJs.jsm
|
||||
content/PdfJsTelemetry.jsm
|
||||
content/web/debugger.js
|
||||
content/web/images/annotation-check.svg
|
||||
content/web/images/annotation-comment.svg
|
||||
|
@ -248,6 +248,7 @@
|
||||
@BINPATH@/components/jsdservice.xpt
|
||||
#endif
|
||||
@BINPATH@/components/jsdebugger.xpt
|
||||
@BINPATH@/components/jsdownloads.xpt
|
||||
@BINPATH@/components/jsinspector.xpt
|
||||
@BINPATH@/components/layout_base.xpt
|
||||
#ifdef NS_PRINTING
|
||||
|
@ -10,6 +10,9 @@ Cu.import("resource://gre/modules/Services.jsm");
|
||||
* JS modules
|
||||
*/
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this , "FormHistory",
|
||||
"resource://gre/modules/FormHistory.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
|
||||
"resource://gre/modules/PluralForm.jsm");
|
||||
|
||||
|
@ -143,8 +143,6 @@ var BrowserUI = {
|
||||
|
||||
// Login Manager and Form History initialization
|
||||
Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager);
|
||||
Cc["@mozilla.org/satchel/form-history;1"].getService(Ci.nsIFormHistory2);
|
||||
|
||||
messageManager.addMessageListener("Browser:MozApplicationManifest", OfflineApps);
|
||||
|
||||
try {
|
||||
|
@ -3,10 +3,6 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
|
||||
"resource://gre/modules/PlacesUtils.jsm");
|
||||
|
||||
function Sanitizer() {}
|
||||
|
||||
Sanitizer.prototype = {
|
||||
@ -17,9 +13,14 @@ Sanitizer.prototype = {
|
||||
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.",
|
||||
@ -39,22 +40,28 @@ Sanitizer.prototype = {
|
||||
var branch = Services.prefs.getBranch(this._prefDomain);
|
||||
var errors = null;
|
||||
for (var itemName in this.items) {
|
||||
var item = this.items[itemName];
|
||||
if ("clear" in item && item.canClear && branch.getBoolPref(itemName)) {
|
||||
if ("clear" in item && branch.getBoolPref(itemName)) {
|
||||
// Some of these clear() may raise exceptions (see bug #265028)
|
||||
// to sanitize as much as possible, we catch and store them,
|
||||
// rather than fail fast.
|
||||
// Callers should check returned errors and give user feedback
|
||||
// about items that could not be sanitized
|
||||
let clearCallback = (itemName, aCanClear) => {
|
||||
let item = this.items[itemName];
|
||||
try{
|
||||
if (aCanClear){
|
||||
item.clear();
|
||||
}
|
||||
} catch(er){
|
||||
if (!errors)
|
||||
if (!errors){
|
||||
errors = {};
|
||||
}
|
||||
errors[itemName] = er;
|
||||
dump("Error sanitizing " + itemName + ":" + er + "\n");
|
||||
}
|
||||
}
|
||||
this.canClearItem(itemName, clearCallback);
|
||||
}
|
||||
}
|
||||
return errors;
|
||||
},
|
||||
@ -185,15 +192,18 @@ Sanitizer.prototype = {
|
||||
searchBar.textbox.editor.transactionManager.clear();
|
||||
}
|
||||
}
|
||||
|
||||
var formHistory = Cc["@mozilla.org/satchel/form-history;1"].getService(Ci.nsIFormHistory2);
|
||||
formHistory.removeAllEntries();
|
||||
FormHistory.update({op : "remove"});
|
||||
},
|
||||
|
||||
get canClear()
|
||||
canClear : function(aCallback, aArg)
|
||||
{
|
||||
var formHistory = Cc["@mozilla.org/satchel/form-history;1"].getService(Ci.nsIFormHistory2);
|
||||
return formHistory.hasEntries;
|
||||
let count = 0;
|
||||
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);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -6,8 +6,7 @@
|
||||
"use strict";
|
||||
|
||||
function clearFormHistory() {
|
||||
var formHistory = Cc["@mozilla.org/satchel/form-history;1"].getService(Ci.nsIFormHistory2);
|
||||
formHistory.removeAllEntries();
|
||||
FormHistory.update({ op : "remove" });
|
||||
}
|
||||
|
||||
function test() {
|
||||
|
@ -82,13 +82,6 @@ public interface Actions {
|
||||
|
||||
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
|
||||
*/
|
||||
|
@ -460,41 +460,6 @@ public class FennecNativeActions implements Actions {
|
||||
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) {
|
||||
try {
|
||||
return (Cursor)mQuerySql.invoke(mRobocopApi, dbPath, sql);
|
||||
|
@ -15,7 +15,7 @@ include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
ANDROID_APK_NAME := robocop-debug
|
||||
|
||||
ROBOTIUM_PATH = $(srcdir)/robotium-solo-3.6.jar
|
||||
ROBOTIUM_PATH = $(srcdir)/robotium-solo-4.2.jar
|
||||
|
||||
JAVAFILES = \
|
||||
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:
|
||||
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:
|
||||
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
|
||||
|
||||
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
|
||||
MOZILLA_VERSION=`$PERL $srcdir/config/milestone.pl -topsrcdir $srcdir`
|
||||
MOZILLA_UAVERSION=`$PERL $srcdir/config/milestone.pl -topsrcdir $srcdir -uaversion`
|
||||
|
@ -61,7 +61,6 @@ EXPORTS += [
|
||||
'nsINodeList.h',
|
||||
'nsIScriptElement.h',
|
||||
'nsIStyleSheetLinkingElement.h',
|
||||
'nsIXPathEvaluatorInternal.h',
|
||||
'nsLineBreaker.h',
|
||||
'nsReferencedElement.h',
|
||||
'nsTreeSanitizer.h',
|
||||
|
@ -109,6 +109,7 @@ class ProcessingInstruction;
|
||||
class Touch;
|
||||
class TreeWalker;
|
||||
class UndoManager;
|
||||
class XPathEvaluator;
|
||||
template<typename> class OwningNonNull;
|
||||
template<typename> class Sequence;
|
||||
|
||||
@ -2171,6 +2172,8 @@ protected:
|
||||
return mContentType;
|
||||
}
|
||||
|
||||
mozilla::dom::XPathEvaluator* XPathEvaluator();
|
||||
|
||||
nsCString mReferrer;
|
||||
nsString mLastModified;
|
||||
|
||||
@ -2426,6 +2429,8 @@ protected:
|
||||
uint8_t mDefaultElementType;
|
||||
|
||||
uint32_t mInSyncOperationCount;
|
||||
|
||||
nsRefPtr<mozilla::dom::XPathEvaluator> mXPathEvaluator;
|
||||
};
|
||||
|
||||
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/xml/content/src \
|
||||
-I$(topsrcdir)/content/xml/document/src \
|
||||
-I$(topsrcdir)/content/xslt/src/xpath \
|
||||
-I$(topsrcdir)/content/xul/content/src \
|
||||
-I$(topsrcdir)/content/xul/document/src \
|
||||
-I$(topsrcdir)/dom/base \
|
||||
|
@ -99,10 +99,8 @@
|
||||
#include "nsBidiUtils.h"
|
||||
|
||||
#include "nsIDOMUserDataHandler.h"
|
||||
#include "nsIDOMXPathEvaluator.h"
|
||||
#include "nsIDOMXPathExpression.h"
|
||||
#include "nsIDOMXPathNSResolver.h"
|
||||
#include "nsIXPathEvaluatorInternal.h"
|
||||
#include "nsIParserService.h"
|
||||
#include "nsContentCreatorFunctions.h"
|
||||
|
||||
@ -213,6 +211,7 @@
|
||||
#include "nsIHttpChannelInternal.h"
|
||||
#include "nsISecurityConsoleMessage.h"
|
||||
#include "nsCharSeparatedTokenizer.h"
|
||||
#include "mozilla/dom/XPathEvaluator.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
@ -1582,23 +1581,11 @@ NS_INTERFACE_TABLE_HEAD(nsDocument)
|
||||
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIMutationObserver)
|
||||
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIApplicationCacheContainer)
|
||||
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIObserver)
|
||||
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDOMXPathEvaluator)
|
||||
NS_INTERFACE_TABLE_END
|
||||
NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(nsDocument)
|
||||
NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOMXPathNSResolver,
|
||||
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
|
||||
|
||||
|
||||
@ -1784,7 +1771,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsDocument)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChannel)
|
||||
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(mOnloadBlocker)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFirstBaseNodeWithHref)
|
||||
@ -1871,7 +1858,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDocument)
|
||||
}
|
||||
tmp->mFirstChild = nullptr;
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mXPathEvaluatorTearoff)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mXPathEvaluator)
|
||||
tmp->mCachedRootElement = nullptr; // Avoid a dangling pointer
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDisplayDocument)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mFirstBaseNodeWithHref)
|
||||
@ -11285,31 +11272,14 @@ nsIDocument::CreateExpression(const nsAString& aExpression,
|
||||
nsIDOMXPathNSResolver* aResolver,
|
||||
ErrorResult& rv)
|
||||
{
|
||||
nsCOMPtr<nsIDOMXPathEvaluator> evaluator = do_QueryInterface(this);
|
||||
if (!evaluator) {
|
||||
rv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMXPathExpression> expr;
|
||||
rv = evaluator->CreateExpression(aExpression, aResolver, getter_AddRefs(expr));
|
||||
return expr.forget();
|
||||
return XPathEvaluator()->CreateExpression(aExpression, aResolver, rv);
|
||||
}
|
||||
|
||||
already_AddRefed<nsIDOMXPathNSResolver>
|
||||
nsIDocument::CreateNSResolver(nsINode* aNodeResolver,
|
||||
ErrorResult& rv)
|
||||
{
|
||||
nsCOMPtr<nsIDOMXPathEvaluator> evaluator = do_QueryInterface(this);
|
||||
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();
|
||||
return XPathEvaluator()->CreateNSResolver(aNodeResolver, rv);
|
||||
}
|
||||
|
||||
already_AddRefed<nsISupports>
|
||||
@ -11317,17 +11287,32 @@ nsIDocument::Evaluate(const nsAString& aExpression, nsINode* aContextNode,
|
||||
nsIDOMXPathNSResolver* aResolver, uint16_t aType,
|
||||
nsISupports* aResult, ErrorResult& rv)
|
||||
{
|
||||
nsCOMPtr<nsIDOMXPathEvaluator> evaluator = do_QueryInterface(this);
|
||||
if (!evaluator) {
|
||||
rv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
return XPathEvaluator()->Evaluate(aExpression, aContextNode, aResolver, aType,
|
||||
aResult, rv);
|
||||
}
|
||||
|
||||
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
|
||||
@ -11381,6 +11366,15 @@ nsIDocument::WrapObject(JSContext *aCx, JS::Handle<JSObject*> aScope)
|
||||
return obj;
|
||||
}
|
||||
|
||||
XPathEvaluator*
|
||||
nsIDocument::XPathEvaluator()
|
||||
{
|
||||
if (!mXPathEvaluator) {
|
||||
mXPathEvaluator = new dom::XPathEvaluator(this);
|
||||
}
|
||||
return mXPathEvaluator;
|
||||
}
|
||||
|
||||
bool
|
||||
MarkDocumentTreeToBeInSyncOperation(nsIDocument* aDoc, void* aData)
|
||||
{
|
||||
|
@ -68,6 +68,7 @@
|
||||
#include "nsDataHashtable.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsIDOMXPathEvaluator.h"
|
||||
|
||||
#define XML_DECLARATION_BITS_DECLARATION_EXISTS (1 << 0)
|
||||
#define XML_DECLARATION_BITS_ENCODING_EXISTS (1 << 1)
|
||||
@ -504,7 +505,8 @@ class nsDocument : public nsIDocument,
|
||||
public nsIRadioGroupContainer,
|
||||
public nsIApplicationCacheContainer,
|
||||
public nsStubMutationObserver,
|
||||
public nsIObserver
|
||||
public nsIObserver,
|
||||
public nsIDOMXPathEvaluator
|
||||
{
|
||||
public:
|
||||
typedef mozilla::dom::Element Element;
|
||||
@ -784,6 +786,8 @@ public:
|
||||
// nsIObserver
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
NS_DECL_NSIDOMXPATHEVALUATOR
|
||||
|
||||
virtual nsresult Init();
|
||||
|
||||
virtual nsresult CreateElem(const nsAString& aName, nsIAtom *aPrefix,
|
||||
@ -1343,8 +1347,6 @@ private:
|
||||
nsDocument(const nsDocument& aOther);
|
||||
nsDocument& operator=(const nsDocument& aOther);
|
||||
|
||||
nsCOMPtr<nsISupports> mXPathEvaluatorTearoff;
|
||||
|
||||
// The layout history state that should be used by nodes in this
|
||||
// document. We only actually store a pointer to it when:
|
||||
// 1) We have no script global object.
|
||||
|
@ -25,6 +25,17 @@ public:
|
||||
nsCOMPtr<nsIAtom> mPrevAttrValue;
|
||||
nsCOMPtr<nsIAtom> mNewAttrValue;
|
||||
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
|
||||
|
@ -520,17 +520,6 @@ nsDOMEvent::DuplicatePrivateData()
|
||||
newEvent = guiEvent;
|
||||
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:
|
||||
{
|
||||
nsInputEvent* oldInputEvent = static_cast<nsInputEvent*>(mEvent);
|
||||
@ -561,15 +550,7 @@ nsDOMEvent::DuplicatePrivateData()
|
||||
nsDragEvent* oldDragEvent = static_cast<nsDragEvent*>(mEvent);
|
||||
nsDragEvent* dragEvent =
|
||||
new nsDragEvent(false, msg, nullptr);
|
||||
dragEvent->AssignInputEventData(*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;
|
||||
dragEvent->AssignDragEventData(*oldDragEvent, true);
|
||||
newEvent = dragEvent;
|
||||
break;
|
||||
}
|
||||
@ -577,8 +558,7 @@ nsDOMEvent::DuplicatePrivateData()
|
||||
{
|
||||
nsClipboardEvent* oldClipboardEvent = static_cast<nsClipboardEvent*>(mEvent);
|
||||
nsClipboardEvent* clipboardEvent = new nsClipboardEvent(false, msg);
|
||||
clipboardEvent->AssignEventData(*oldClipboardEvent, true);
|
||||
clipboardEvent->clipboardData = oldClipboardEvent->clipboardData;
|
||||
clipboardEvent->AssignClipboardEventData(*oldClipboardEvent, true);
|
||||
newEvent = clipboardEvent;
|
||||
break;
|
||||
}
|
||||
@ -587,8 +567,7 @@ nsDOMEvent::DuplicatePrivateData()
|
||||
nsScriptErrorEvent* oldScriptErrorEvent =
|
||||
static_cast<nsScriptErrorEvent*>(mEvent);
|
||||
nsScriptErrorEvent* scriptErrorEvent = new nsScriptErrorEvent(false, msg);
|
||||
scriptErrorEvent->AssignEventData(*oldScriptErrorEvent, true);
|
||||
scriptErrorEvent->lineNr = oldScriptErrorEvent->lineNr;
|
||||
scriptErrorEvent->AssignScriptErrorEventData(*oldScriptErrorEvent, true);
|
||||
newEvent = scriptErrorEvent;
|
||||
break;
|
||||
}
|
||||
@ -596,7 +575,7 @@ nsDOMEvent::DuplicatePrivateData()
|
||||
{
|
||||
nsTextEvent* oldTextEvent = static_cast<nsTextEvent*>(mEvent);
|
||||
nsTextEvent* textEvent = new nsTextEvent(false, msg, nullptr);
|
||||
textEvent->AssignGUIEventData(*oldTextEvent, true);
|
||||
textEvent->AssignTextEventData(*oldTextEvent, true);
|
||||
newEvent = textEvent;
|
||||
break;
|
||||
}
|
||||
@ -606,8 +585,7 @@ nsDOMEvent::DuplicatePrivateData()
|
||||
new nsCompositionEvent(false, msg, nullptr);
|
||||
nsCompositionEvent* oldCompositionEvent =
|
||||
static_cast<nsCompositionEvent*>(mEvent);
|
||||
compositionEvent->AssignGUIEventData(*oldCompositionEvent, true);
|
||||
compositionEvent->data = oldCompositionEvent->data;
|
||||
compositionEvent->AssignCompositionEventData(*oldCompositionEvent, true);
|
||||
newEvent = compositionEvent;
|
||||
break;
|
||||
}
|
||||
@ -617,14 +595,7 @@ nsDOMEvent::DuplicatePrivateData()
|
||||
static_cast<nsMouseScrollEvent*>(mEvent);
|
||||
nsMouseScrollEvent* mouseScrollEvent =
|
||||
new nsMouseScrollEvent(false, msg, nullptr);
|
||||
mouseScrollEvent->AssignInputEventData(*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;
|
||||
mouseScrollEvent->AssignMouseScrollEventData(*oldMouseScrollEvent, true);
|
||||
newEvent = mouseScrollEvent;
|
||||
break;
|
||||
}
|
||||
@ -634,24 +605,7 @@ nsDOMEvent::DuplicatePrivateData()
|
||||
static_cast<widget::WheelEvent*>(mEvent);
|
||||
widget::WheelEvent* wheelEvent =
|
||||
new widget::WheelEvent(false, msg, nullptr);
|
||||
wheelEvent->AssignInputEventData(*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;
|
||||
wheelEvent->AssignWheelEventData(*oldWheelEvent, true);
|
||||
newEvent = wheelEvent;
|
||||
break;
|
||||
}
|
||||
@ -661,8 +615,7 @@ nsDOMEvent::DuplicatePrivateData()
|
||||
static_cast<nsScrollPortEvent*>(mEvent);
|
||||
nsScrollPortEvent* scrollPortEvent =
|
||||
new nsScrollPortEvent(false, msg, nullptr);
|
||||
scrollPortEvent->AssignGUIEventData(*oldScrollPortEvent, true);
|
||||
scrollPortEvent->orient = oldScrollPortEvent->orient;
|
||||
scrollPortEvent->AssignScrollPortEventData(*oldScrollPortEvent, true);
|
||||
newEvent = scrollPortEvent;
|
||||
break;
|
||||
}
|
||||
@ -672,8 +625,7 @@ nsDOMEvent::DuplicatePrivateData()
|
||||
static_cast<nsScrollAreaEvent*>(mEvent);
|
||||
nsScrollAreaEvent* scrollAreaEvent =
|
||||
new nsScrollAreaEvent(false, msg, nullptr);
|
||||
scrollAreaEvent->AssignGUIEventData(*oldScrollAreaEvent, true);
|
||||
scrollAreaEvent->mArea = oldScrollAreaEvent->mArea;
|
||||
scrollAreaEvent->AssignScrollAreaEventData(*oldScrollAreaEvent, true);
|
||||
newEvent = scrollAreaEvent;
|
||||
break;
|
||||
}
|
||||
@ -682,12 +634,7 @@ nsDOMEvent::DuplicatePrivateData()
|
||||
nsMutationEvent* mutationEvent = new nsMutationEvent(false, msg);
|
||||
nsMutationEvent* oldMutationEvent =
|
||||
static_cast<nsMutationEvent*>(mEvent);
|
||||
mutationEvent->AssignEventData(*oldMutationEvent, true);
|
||||
mutationEvent->mRelatedNode = oldMutationEvent->mRelatedNode;
|
||||
mutationEvent->mAttrName = oldMutationEvent->mAttrName;
|
||||
mutationEvent->mPrevAttrValue = oldMutationEvent->mPrevAttrValue;
|
||||
mutationEvent->mNewAttrValue = oldMutationEvent->mNewAttrValue;
|
||||
mutationEvent->mAttrChange = oldMutationEvent->mAttrChange;
|
||||
mutationEvent->AssignMutationEventData(*oldMutationEvent, true);
|
||||
newEvent = mutationEvent;
|
||||
break;
|
||||
}
|
||||
@ -695,7 +642,7 @@ nsDOMEvent::DuplicatePrivateData()
|
||||
{
|
||||
nsFormEvent* oldFormEvent = static_cast<nsFormEvent*>(mEvent);
|
||||
nsFormEvent* formEvent = new nsFormEvent(false, msg);
|
||||
formEvent->AssignEventData(*oldFormEvent, true);
|
||||
formEvent->AssignFormEventData(*oldFormEvent, true);
|
||||
newEvent = formEvent;
|
||||
break;
|
||||
}
|
||||
@ -703,9 +650,7 @@ nsDOMEvent::DuplicatePrivateData()
|
||||
{
|
||||
nsFocusEvent* newFocusEvent = new nsFocusEvent(false, msg);
|
||||
nsFocusEvent* oldFocusEvent = static_cast<nsFocusEvent*>(mEvent);
|
||||
newFocusEvent->AssignGUIEventData(*oldFocusEvent, true);
|
||||
newFocusEvent->fromRaise = oldFocusEvent->fromRaise;
|
||||
newFocusEvent->isRefocus = oldFocusEvent->isRefocus;
|
||||
newFocusEvent->AssignFocusEventData(*oldFocusEvent, true);
|
||||
newEvent = newFocusEvent;
|
||||
break;
|
||||
}
|
||||
@ -715,7 +660,7 @@ nsDOMEvent::DuplicatePrivateData()
|
||||
nsCommandEvent* commandEvent =
|
||||
new nsCommandEvent(false, mEvent->userType,
|
||||
oldCommandEvent->command, nullptr);
|
||||
commandEvent->AssignGUIEventData(*oldCommandEvent, true);
|
||||
commandEvent->AssignCommandEventData(*oldCommandEvent, true);
|
||||
newEvent = commandEvent;
|
||||
break;
|
||||
}
|
||||
@ -723,7 +668,7 @@ nsDOMEvent::DuplicatePrivateData()
|
||||
{
|
||||
nsUIEvent* oldUIEvent = static_cast<nsUIEvent*>(mEvent);
|
||||
nsUIEvent* uiEvent = new nsUIEvent(false, msg, oldUIEvent->detail);
|
||||
uiEvent->AssignEventData(*oldUIEvent, true);
|
||||
uiEvent->AssignUIEventData(*oldUIEvent, true);
|
||||
newEvent = uiEvent;
|
||||
break;
|
||||
}
|
||||
@ -741,7 +686,7 @@ nsDOMEvent::DuplicatePrivateData()
|
||||
nsUIEvent* oldUIEvent = static_cast<nsUIEvent*>(mEvent);
|
||||
nsUIEvent* uiEvent = new nsUIEvent(false, msg, 0);
|
||||
uiEvent->eventStructType = NS_SMIL_TIME_EVENT;
|
||||
uiEvent->AssignGUIEventData(*oldUIEvent, true);
|
||||
uiEvent->AssignUIEventData(*oldUIEvent, true);
|
||||
newEvent = uiEvent;
|
||||
break;
|
||||
}
|
||||
@ -751,10 +696,8 @@ nsDOMEvent::DuplicatePrivateData()
|
||||
static_cast<nsSimpleGestureEvent*>(mEvent);
|
||||
nsSimpleGestureEvent* simpleGestureEvent =
|
||||
new nsSimpleGestureEvent(false, msg, nullptr, 0, 0.0);
|
||||
simpleGestureEvent->AssignInputEventData(*oldSimpleGestureEvent, true);
|
||||
simpleGestureEvent->direction = oldSimpleGestureEvent->direction;
|
||||
simpleGestureEvent->delta = oldSimpleGestureEvent->delta;
|
||||
simpleGestureEvent->clickCount = oldSimpleGestureEvent->clickCount;
|
||||
simpleGestureEvent->
|
||||
AssignSimpleGestureEventData(*oldSimpleGestureEvent, true);
|
||||
newEvent = simpleGestureEvent;
|
||||
break;
|
||||
}
|
||||
@ -767,7 +710,7 @@ nsDOMEvent::DuplicatePrivateData()
|
||||
oldTransitionEvent->propertyName,
|
||||
oldTransitionEvent->elapsedTime,
|
||||
oldTransitionEvent->pseudoElement);
|
||||
transitionEvent->AssignEventData(*oldTransitionEvent, true);
|
||||
transitionEvent->AssignTransitionEventData(*oldTransitionEvent, true);
|
||||
newEvent = transitionEvent;
|
||||
break;
|
||||
}
|
||||
@ -780,7 +723,7 @@ nsDOMEvent::DuplicatePrivateData()
|
||||
oldAnimationEvent->animationName,
|
||||
oldAnimationEvent->elapsedTime,
|
||||
oldAnimationEvent->pseudoElement);
|
||||
animationEvent->AssignEventData(*oldAnimationEvent, true);
|
||||
animationEvent->AssignAnimationEventData(*oldAnimationEvent, true);
|
||||
newEvent = animationEvent;
|
||||
break;
|
||||
}
|
||||
@ -788,7 +731,7 @@ nsDOMEvent::DuplicatePrivateData()
|
||||
{
|
||||
nsTouchEvent* oldTouchEvent = static_cast<nsTouchEvent*>(mEvent);
|
||||
nsTouchEvent* touchEvent = new nsTouchEvent(false, oldTouchEvent);
|
||||
touchEvent->AssignInputEventData(*oldTouchEvent, true);
|
||||
touchEvent->AssignTouchEventData(*oldTouchEvent, true);
|
||||
newEvent = touchEvent;
|
||||
break;
|
||||
}
|
||||
|
@ -460,6 +460,9 @@ nsDOMUIEvent::ComputeModifierState(const nsAString& aModifiersList)
|
||||
bool
|
||||
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);
|
||||
if (aKey.EqualsLiteral(NS_DOM_KEYNAME_SHIFT)) {
|
||||
return inputEvent->IsShift();
|
||||
|
@ -444,11 +444,8 @@ PannerNodeEngine::ComputeConeGain()
|
||||
ThreeDPoint sourceToListener = mListenerPosition - mPosition;
|
||||
sourceToListener.Normalize();
|
||||
|
||||
ThreeDPoint normalizedSourceOrientation = mOrientation;
|
||||
normalizedSourceOrientation.Normalize();
|
||||
|
||||
// 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 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'
|
||||
|
||||
EXPORTS.mozilla.dom += [
|
||||
'XPathEvaluator.h',
|
||||
]
|
||||
|
||||
CPP_SOURCES += [
|
||||
'nsXPathEvaluator.cpp',
|
||||
'XPathEvaluator.cpp',
|
||||
'nsXPathExpression.cpp',
|
||||
'nsXPathNSResolver.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
|
||||
// if the load was successful, then continue building content
|
||||
// from the prototype.
|
||||
nsresult rv;
|
||||
nsresult rv = aStatus;
|
||||
|
||||
NS_ASSERTION(mCurrentScriptProto && mCurrentScriptProto->mSrcLoading,
|
||||
"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.
|
||||
SCTAG_DOM_IMAGEDATA,
|
||||
SCTAG_DOM_MESSAGEPORT,
|
||||
|
||||
SCTAG_DOM_MAX
|
||||
};
|
||||
|
@ -55,6 +55,8 @@ EXPORTS.mozilla.dom += [
|
||||
'DOMCursor.h',
|
||||
'DOMError.h',
|
||||
'DOMRequest.h',
|
||||
'MessageChannel.h',
|
||||
'MessagePort.h',
|
||||
'ScreenOrientation.h',
|
||||
'StructuredCloneTags.h',
|
||||
'URL.h',
|
||||
@ -67,6 +69,8 @@ CPP_SOURCES += [
|
||||
'DOMError.cpp',
|
||||
'DOMRequest.cpp',
|
||||
'Navigator.cpp',
|
||||
'MessageChannel.cpp',
|
||||
'MessagePort.cpp',
|
||||
'nsContentPermissionHelper.cpp',
|
||||
'nsDOMClassInfo.cpp',
|
||||
'nsDOMException.cpp',
|
||||
|
@ -189,6 +189,9 @@
|
||||
#include "prenv.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/quota/QuotaManager.h"
|
||||
|
||||
@ -6750,6 +6753,7 @@ namespace {
|
||||
struct StructuredCloneInfo {
|
||||
PostMessageEvent* event;
|
||||
bool subsumes;
|
||||
nsPIDOMWindow* window;
|
||||
};
|
||||
|
||||
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 =
|
||||
js::GetContextStructuredCloneCallbacks(cx);
|
||||
|
||||
@ -6819,6 +6838,18 @@ PostMessageWriteStructuredClone(JSContext* cx,
|
||||
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 =
|
||||
js::GetContextStructuredCloneCallbacks(cx);
|
||||
|
||||
@ -6910,6 +6941,7 @@ PostMessageEvent::Run()
|
||||
{
|
||||
StructuredCloneInfo scInfo;
|
||||
scInfo.event = this;
|
||||
scInfo.window = targetWindow;
|
||||
|
||||
if (!buffer.read(cx, messageData.address(), &kPostMessageCallbacks,
|
||||
&scInfo)) {
|
||||
@ -7056,6 +7088,7 @@ nsGlobalWindow::PostMessageMoz(const JS::Value& aMessage,
|
||||
JSAutoStructuredCloneBuffer buffer;
|
||||
StructuredCloneInfo scInfo;
|
||||
scInfo.event = event;
|
||||
scInfo.window = this;
|
||||
|
||||
nsIPrincipal* principal = GetPrincipal();
|
||||
if (NS_FAILED(callerPrin->Subsumes(principal, &scInfo.subsumes)))
|
||||
|
@ -31,6 +31,17 @@ MOCHITEST_FILES = \
|
||||
test_Image_constructor.html \
|
||||
test_setting_opener.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)
|
||||
|
||||
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': {
|
||||
'nativeType': 'nsXPathEvaluator',
|
||||
'headerFile': 'nsXPathEvaluator.h',
|
||||
'wrapperCache': False
|
||||
},
|
||||
|
||||
|
@ -48,7 +48,7 @@ const ContentPanning = {
|
||||
// If we are using an AsyncPanZoomController for the parent frame,
|
||||
// it will handle subframe scrolling too. We don't need to listen for
|
||||
// these events.
|
||||
if (!docShell.asyncPanZoomEnabled) {
|
||||
if (!this._asyncPanZoomForViewportFrame) {
|
||||
let els = Cc["@mozilla.org/eventlistenerservice;1"]
|
||||
.getService(Ci.nsIEventListenerService);
|
||||
|
||||
@ -140,11 +140,23 @@ const ContentPanning = {
|
||||
let oldTarget = this.target;
|
||||
[this.target, this.scrollCallback] = this.getPannable(this.pointerDownTarget);
|
||||
|
||||
// If we have a pointer down target, we may need to fill in for EventStateManager
|
||||
// in setting the active state on the target element. Set a timer to
|
||||
// If we found a target, that means we have found a scrollable subframe. In
|
||||
// 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
|
||||
// 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.
|
||||
// Otherwise wait a little bit to see if the gesture isn't a
|
||||
// tap.
|
||||
@ -214,6 +226,12 @@ const ContentPanning = {
|
||||
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) {
|
||||
if (!this.dragging)
|
||||
return;
|
||||
@ -242,6 +260,27 @@ const ContentPanning = {
|
||||
}
|
||||
|
||||
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
|
||||
// current target.
|
||||
@ -317,6 +356,13 @@ const ContentPanning = {
|
||||
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) {
|
||||
return nodeContent;
|
||||
}
|
||||
@ -438,6 +484,10 @@ const ContentPanning = {
|
||||
this._domUtils.setContentState(elt, kStateActive);
|
||||
},
|
||||
|
||||
get _asyncPanZoomForViewportFrame() {
|
||||
return docShell.asyncPanZoomEnabled;
|
||||
},
|
||||
|
||||
_recvViewportChange: function(data) {
|
||||
let metrics = data.json;
|
||||
this._viewport = new Rect(metrics.x, metrics.y,
|
||||
@ -549,6 +599,7 @@ const ContentPanning = {
|
||||
_finishPanning: function() {
|
||||
this._resetActive();
|
||||
this.dragging = false;
|
||||
this.detectingScrolling = false;
|
||||
delete this.primaryPointerId;
|
||||
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
|
||||
|
||||
DIRS += [
|
||||
|
@ -12,8 +12,13 @@ include $(DEPTH)/config/autoconf.mk
|
||||
MOCHITEST_FILES := \
|
||||
test_Document-open.html.json \
|
||||
test_addRange.html.json \
|
||||
test_collapse.html.json \
|
||||
test_collapseToStartEnd.html.json \
|
||||
test_extend.html.json \
|
||||
test_getSelection.html.json \
|
||||
test_interfaces.html.json \
|
||||
test_removeAllRanges.html.json \
|
||||
test_selectAllChildren.html.json \
|
||||
$(NULL)
|
||||
|
||||
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
|
||||
|
||||
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 char CANCEL_DEFAULT_PAN_ZOOM[] = "cancel-default-pan-zoom";
|
||||
static const char BROWSER_ZOOM_TO_RECT[] = "browser-zoom-to-rect";
|
||||
static const char BEFORE_FIRST_PAINT[] = "before-first-paint";
|
||||
static const char DETECT_SCROLLABLE_SUBFRAME[] = "detect-scrollable-subframe";
|
||||
|
||||
static bool sCpowsEnabled = false;
|
||||
|
||||
@ -383,7 +385,13 @@ TabChild::Observe(nsISupports *aSubject,
|
||||
const char *aTopic,
|
||||
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<nsITabChild> tabChild(GetTabChildFrom(docShell));
|
||||
if (tabChild == this) {
|
||||
@ -428,6 +436,12 @@ TabChild::Observe(nsISupports *aSubject,
|
||||
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;
|
||||
@ -2165,8 +2179,10 @@ TabChild::RecvDestroy()
|
||||
nsCOMPtr<nsIObserverService> observerService =
|
||||
do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
|
||||
|
||||
observerService->RemoveObserver(this, CANCEL_DEFAULT_PAN_ZOOM);
|
||||
observerService->RemoveObserver(this, BROWSER_ZOOM_TO_RECT);
|
||||
observerService->RemoveObserver(this, BEFORE_FIRST_PAINT);
|
||||
observerService->RemoveObserver(this, DETECT_SCROLLABLE_SUBFRAME);
|
||||
|
||||
const InfallibleTArray<PIndexedDBChild*>& idbActors =
|
||||
ManagedPIndexedDBChild();
|
||||
@ -2301,12 +2317,18 @@ TabChild::InitRenderingState()
|
||||
do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
|
||||
|
||||
if (observerService) {
|
||||
observerService->AddObserver(this,
|
||||
CANCEL_DEFAULT_PAN_ZOOM,
|
||||
false);
|
||||
observerService->AddObserver(this,
|
||||
BROWSER_ZOOM_TO_RECT,
|
||||
false);
|
||||
observerService->AddObserver(this,
|
||||
BEFORE_FIRST_PAINT,
|
||||
false);
|
||||
observerService->AddObserver(this,
|
||||
DETECT_SCROLLABLE_SUBFRAME,
|
||||
false);
|
||||
}
|
||||
|
||||
// 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 \
|
||||
MediaStreamEvent.webidl \
|
||||
MediaStreamTrack.webidl \
|
||||
MessageChannel.webidl \
|
||||
MessageEvent.webidl \
|
||||
MessagePort.webidl \
|
||||
MimeType.webidl \
|
||||
MimeTypeArray.webidl \
|
||||
MobileMessageManager.webidl \
|
||||
|
@ -294,7 +294,12 @@ private:
|
||||
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 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 \
|
||||
test_url.html \
|
||||
url_worker.js \
|
||||
test_bug911085.html \
|
||||
bug911085_worker.js \
|
||||
$(NULL)
|
||||
|
||||
# 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");
|
||||
i.focus();
|
||||
var win = i.contentWindow;
|
||||
var doc = i.contentDocument;
|
||||
var t = doc.getElementById("t");
|
||||
t.focus();
|
||||
// put the caret at the end
|
||||
getSelection().collapse(t.firstChild, 11);
|
||||
win.getSelection().collapse(t.firstChild, 11);
|
||||
|
||||
// Simulate pression Option+Delete on Mac
|
||||
// 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
|
||||
APZCTreeManager::ZoomToRect(const ScrollableLayerGuid& aGuid,
|
||||
const CSSRect& aRect)
|
||||
|
@ -168,6 +168,22 @@ public:
|
||||
void UpdateCompositionBounds(const ScrollableLayerGuid& aGuid,
|
||||
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
|
||||
* 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),
|
||||
mCurrentAsyncScrollOffset(0, 0),
|
||||
mAsyncScrollTimeoutTask(nullptr),
|
||||
mHandlingTouchQueue(false)
|
||||
mDisableNextTouchBatch(false),
|
||||
mHandlingTouchQueue(false),
|
||||
mDelayPanning(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(AsyncPanZoomController);
|
||||
|
||||
@ -310,12 +312,29 @@ nsEventStatus AsyncPanZoomController::HandleInputEvent(const InputData& aEvent)
|
||||
nsEventStatus rv = nsEventStatus_eIgnore;
|
||||
|
||||
nsRefPtr<GestureEventListener> listener = GetGestureEventListener();
|
||||
if (listener) {
|
||||
if (listener && !mDisableNextTouchBatch) {
|
||||
rv = listener->HandleInputEvent(aEvent);
|
||||
if (rv == nsEventStatus_eConsumeNoDefault)
|
||||
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) {
|
||||
case MULTITOUCH_INPUT: {
|
||||
const MultiTouchInput& multiTouchInput = aEvent.AsMultiTouchInput();
|
||||
@ -397,6 +416,10 @@ nsEventStatus AsyncPanZoomController::OnTouchStart(const MultiTouchInput& aEvent
|
||||
}
|
||||
|
||||
nsEventStatus AsyncPanZoomController::OnTouchMove(const MultiTouchInput& aEvent) {
|
||||
if (mDisableNextTouchBatch) {
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
switch (mState) {
|
||||
case FLING:
|
||||
case NOTHING:
|
||||
@ -436,6 +459,11 @@ nsEventStatus AsyncPanZoomController::OnTouchMove(const MultiTouchInput& aEvent)
|
||||
}
|
||||
|
||||
nsEventStatus AsyncPanZoomController::OnTouchEnd(const MultiTouchInput& aEvent) {
|
||||
if (mDisableNextTouchBatch) {
|
||||
mDisableNextTouchBatch = false;
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
{
|
||||
ReentrantMonitorAutoEnter lock(mMonitor);
|
||||
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) {
|
||||
SetState(ANIMATING_ZOOM);
|
||||
|
||||
@ -1236,7 +1276,7 @@ void AsyncPanZoomController::ZoomToRect(CSSRect aRect) {
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::ContentReceivedTouch(bool aPreventDefault) {
|
||||
if (!mFrameMetrics.mMayHaveTouchListeners) {
|
||||
if (!mFrameMetrics.mMayHaveTouchListeners && !mDelayPanning) {
|
||||
mTouchQueue.Clear();
|
||||
return;
|
||||
}
|
||||
@ -1248,12 +1288,21 @@ void AsyncPanZoomController::ContentReceivedTouch(bool aPreventDefault) {
|
||||
|
||||
if (mState == WAITING_LISTENERS) {
|
||||
if (!aPreventDefault) {
|
||||
// Delayed scrolling gesture is pending at TOUCHING state.
|
||||
if (mDelayPanning) {
|
||||
SetState(TOUCHING);
|
||||
} else {
|
||||
SetState(NOTHING);
|
||||
}
|
||||
}
|
||||
|
||||
mHandlingTouchQueue = true;
|
||||
|
||||
while (!mTouchQueue.IsEmpty()) {
|
||||
// we need to reset mDelayPanning before handling scrolling gesture.
|
||||
if (!aPreventDefault && mTouchQueue[0].mType == MultiTouchInput::MULTITOUCH_MOVE) {
|
||||
mDelayPanning = false;
|
||||
}
|
||||
if (!aPreventDefault) {
|
||||
HandleInputEvent(mTouchQueue[0]);
|
||||
}
|
||||
|
@ -109,6 +109,22 @@ public:
|
||||
*/
|
||||
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
|
||||
* 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.
|
||||
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
|
||||
// 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
|
||||
// and we don't want to queue the events back up again.
|
||||
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;
|
||||
|
||||
/* 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;
|
||||
mCurRect = &mRectListHead;
|
||||
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)
|
||||
|
@ -12,7 +12,7 @@
|
||||
#include "base/port.h" // Types that only need exist on certain systems
|
||||
|
||||
#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,
|
||||
// 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
|
||||
# if defined(OS_POSIX)
|
||||
# define __STDC_FORMAT_MACROS 1
|
||||
# include <inttypes.h> // for 64-bit integer format macros
|
||||
# define PRId64L "I64d"
|
||||
# define PRIu64L "I64u"
|
||||
# define PRIx64L "I64x"
|
||||
# elif defined(OS_WIN)
|
||||
# define PRId64 "I64d"
|
||||
# define PRIu64 "I64u"
|
||||
# define PRIx64 "I64x"
|
||||
# define PRId64L L"I64d"
|
||||
# define PRIu64L L"I64u"
|
||||
# define PRIx64L L"I64x"
|
||||
|
@ -15,9 +15,17 @@
|
||||
|
||||
/*
|
||||
* 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_CONSTANT_MACROS
|
||||
#define __STDC_FORMAT_MACROS
|
||||
|
||||
#endif /* js_RequiredDefines_h */
|
||||
|
@ -1359,6 +1359,16 @@ case "$host" in
|
||||
;;
|
||||
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)
|
||||
|
||||
dnl ========================================================
|
||||
|
@ -138,6 +138,11 @@ var ignoreFunctions = {
|
||||
"PR_ErrorInstallTable" : true,
|
||||
"PR_SetThreadPrivate" : true,
|
||||
"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)
|
||||
|
@ -2796,6 +2796,9 @@ template <>
|
||||
Parser<SyntaxParseHandler>::bindLet(BindData<SyntaxParseHandler> *data,
|
||||
HandlePropertyName name, Parser<SyntaxParseHandler> *parser)
|
||||
{
|
||||
if (!parser->checkStrictBinding(name, data->pn))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2229,7 +2229,8 @@ class FunctionCompiler
|
||||
*loopEntry = NULL;
|
||||
return true;
|
||||
}
|
||||
*loopEntry = MBasicBlock::NewPendingLoopHeader(mirGraph(), info(), curBlock_, NULL);
|
||||
*loopEntry = MBasicBlock::NewAsmJS(mirGraph(), info(), curBlock_,
|
||||
MBasicBlock::PENDING_LOOP_HEADER);
|
||||
if (!*loopEntry)
|
||||
return false;
|
||||
mirGraph().addBlock(*loopEntry);
|
||||
@ -2287,7 +2288,8 @@ class FunctionCompiler
|
||||
if (curBlock_) {
|
||||
JS_ASSERT(curBlock_->loopDepth() == loopStack_.length() + 1);
|
||||
curBlock_->end(MGoto::New(loopEntry));
|
||||
loopEntry->setBackedge(curBlock_);
|
||||
if (!loopEntry->setBackedgeAsmJS(curBlock_))
|
||||
return false;
|
||||
}
|
||||
curBlock_ = afterLoop;
|
||||
if (curBlock_)
|
||||
@ -2309,7 +2311,8 @@ class FunctionCompiler
|
||||
if (cond->isConstant()) {
|
||||
if (ToBoolean(cond->toConstant()->value())) {
|
||||
curBlock_->end(MGoto::New(loopEntry));
|
||||
loopEntry->setBackedge(curBlock_);
|
||||
if (!loopEntry->setBackedgeAsmJS(curBlock_))
|
||||
return false;
|
||||
curBlock_ = NULL;
|
||||
} else {
|
||||
MBasicBlock *afterLoop;
|
||||
@ -2323,7 +2326,8 @@ class FunctionCompiler
|
||||
if (!newBlock(curBlock_, &afterLoop, afterLoopStmt))
|
||||
return false;
|
||||
curBlock_->end(MTest::New(cond, loopEntry, afterLoop));
|
||||
loopEntry->setBackedge(curBlock_);
|
||||
if (!loopEntry->setBackedgeAsmJS(curBlock_))
|
||||
return false;
|
||||
curBlock_ = afterLoop;
|
||||
}
|
||||
}
|
||||
@ -2449,7 +2453,7 @@ class FunctionCompiler
|
||||
|
||||
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)
|
||||
return false;
|
||||
noteBasicBlockPosition(*block, pn);
|
||||
@ -3782,12 +3786,6 @@ CheckConditional(FunctionCompiler &f, ParseNode *ternary, MDefinition **def, Typ
|
||||
|
||||
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()) {
|
||||
*type = Type::Int;
|
||||
} 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());
|
||||
}
|
||||
|
||||
if (!f.joinIfElse(thenBlocks, elseExpr))
|
||||
return false;
|
||||
|
||||
*def = f.popPhiOutput();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -4311,12 +4313,9 @@ CheckIf(FunctionCompiler &f, ParseNode *ifStmt)
|
||||
|
||||
MBasicBlock *thenBlock, *elseBlock;
|
||||
|
||||
ParseNode *elseBlockStmt = NULL;
|
||||
// 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.
|
||||
elseBlockStmt = elseStmt;
|
||||
if (elseBlockStmt == NULL)
|
||||
elseBlockStmt = nextStmt;
|
||||
ParseNode *elseBlockStmt = elseStmt ? elseStmt : nextStmt;
|
||||
|
||||
if (!f.branchAndStartThen(condDef, &thenBlock, &elseBlock, thenStmt, elseBlockStmt))
|
||||
return false;
|
||||
|
@ -5568,8 +5568,12 @@ CodeGenerator::link()
|
||||
IonCode *code = (executionMode == SequentialExecution)
|
||||
? linker.newCodeForIonScript(cx)
|
||||
: 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;
|
||||
}
|
||||
|
||||
JSScript *script = gen->info().script();
|
||||
JS_ASSERT(!HasIonScript(script, executionMode));
|
||||
|
@ -1228,7 +1228,7 @@ OptimizeMIR(MIRGenerator *mir)
|
||||
if (mir->shouldCancel("Phi reverse mapping"))
|
||||
return false;
|
||||
|
||||
// This pass also removes copies.
|
||||
if (!mir->compilingAsmJS()) {
|
||||
if (!ApplyTypeInformation(mir, graph))
|
||||
return false;
|
||||
IonSpewPass("Apply types");
|
||||
@ -1236,6 +1236,7 @@ OptimizeMIR(MIRGenerator *mir)
|
||||
|
||||
if (mir->shouldCancel("Apply types"))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (graph.entryBlock()->info().executionMode() == ParallelExecution) {
|
||||
ParallelSafetyAnalysis analysis(mir, graph);
|
||||
@ -1361,7 +1362,7 @@ OptimizeMIR(MIRGenerator *mir)
|
||||
// Passes after this point must not move instructions; these analyses
|
||||
// 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);
|
||||
if (!edgeCaseAnalysis.analyzeLate())
|
||||
return false;
|
||||
@ -1372,14 +1373,16 @@ OptimizeMIR(MIRGenerator *mir)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mir->compilingAsmJS()) {
|
||||
// Note: check elimination has to run after all other passes that move
|
||||
// instructions. Since check uses are replaced with the actual index, code
|
||||
// motion after this pass could incorrectly move a load or store before its
|
||||
// bounds check.
|
||||
// instructions. Since check uses are replaced with the actual index,
|
||||
// code motion after this pass could incorrectly move a load or store
|
||||
// before its bounds check.
|
||||
if (!EliminateRedundantChecks(graph))
|
||||
return false;
|
||||
IonSpewPass("Bounds Check Elimination");
|
||||
AssertGraphCoherency(graph);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -625,12 +625,6 @@ MUnbox::printOpcode(FILE *fp) const
|
||||
}
|
||||
}
|
||||
|
||||
MPhi *
|
||||
MPhi::New(uint32_t slot)
|
||||
{
|
||||
return new MPhi(slot);
|
||||
}
|
||||
|
||||
void
|
||||
MPhi::removeOperand(size_t index)
|
||||
{
|
||||
|
@ -3845,7 +3845,7 @@ class MPhi MOZ_FINAL : public MDefinition, public InlineForwardListNode<MPhi>
|
||||
uint32_t capacity_;
|
||||
#endif
|
||||
|
||||
MPhi(uint32_t slot)
|
||||
MPhi(uint32_t slot, MIRType resultType)
|
||||
: slot_(slot),
|
||||
hasBackedgeType_(false),
|
||||
triedToSpecialize_(false),
|
||||
@ -3855,7 +3855,7 @@ class MPhi MOZ_FINAL : public MDefinition, public InlineForwardListNode<MPhi>
|
||||
, capacity_(0)
|
||||
#endif
|
||||
{
|
||||
setResultType(MIRType_Value);
|
||||
setResultType(resultType);
|
||||
}
|
||||
|
||||
protected:
|
||||
@ -3865,7 +3865,9 @@ class MPhi MOZ_FINAL : public MDefinition, public InlineForwardListNode<MPhi>
|
||||
|
||||
public:
|
||||
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) {
|
||||
// Note: after the initial IonBuilder pass, it is OK to change phi
|
||||
|
@ -159,6 +159,8 @@ MBasicBlock *
|
||||
MBasicBlock::New(MIRGraph &graph, CompileInfo &info,
|
||||
MBasicBlock *pred, jsbytecode *entryPc, Kind kind)
|
||||
{
|
||||
JS_ASSERT(entryPc != NULL);
|
||||
|
||||
MBasicBlock *block = new MBasicBlock(graph, info, entryPc, kind);
|
||||
if (!block->init())
|
||||
return NULL;
|
||||
@ -212,7 +214,9 @@ MBasicBlock::NewPendingLoopHeader(MIRGraph &graph, CompileInfo &info,
|
||||
MBasicBlock *
|
||||
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 *
|
||||
@ -235,6 +239,40 @@ MBasicBlock::NewAbortPar(MIRGraph &graph, CompileInfo &info,
|
||||
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)
|
||||
: earlyAbort_(false),
|
||||
graph_(graph),
|
||||
@ -291,19 +329,16 @@ MBasicBlock::inherit(MBasicBlock *pred, uint32_t popped)
|
||||
stackPosition_ -= popped;
|
||||
if (kind_ != PENDING_LOOP_HEADER)
|
||||
copySlots(pred);
|
||||
} else if (pc()) {
|
||||
} else {
|
||||
uint32_t stackDepth = info().script()->analysis()->getCode(pc()).stackDepth;
|
||||
stackPosition_ = info().firstStackSlot() + stackDepth;
|
||||
JS_ASSERT(stackPosition_ >= popped);
|
||||
stackPosition_ -= popped;
|
||||
} else {
|
||||
stackPosition_ = info().firstStackSlot();
|
||||
}
|
||||
|
||||
JS_ASSERT(info_.nslots() >= stackPosition_);
|
||||
JS_ASSERT(!entryResumePoint_);
|
||||
|
||||
if (pc()) {
|
||||
// Propagate the caller resume point from the inherited block.
|
||||
MResumePoint *callerResumePoint = pred ? pred->callerResumePoint() : NULL;
|
||||
|
||||
@ -311,7 +346,6 @@ MBasicBlock::inherit(MBasicBlock *pred, uint32_t popped)
|
||||
entryResumePoint_ = new MResumePoint(this, pc(), callerResumePoint, MResumePoint::ResumeAt);
|
||||
if (!entryResumePoint_->init())
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pred) {
|
||||
if (!predecessors_.append(pred))
|
||||
@ -324,14 +358,13 @@ MBasicBlock::inherit(MBasicBlock *pred, uint32_t popped)
|
||||
return false;
|
||||
addPhi(phi);
|
||||
setSlot(i, phi);
|
||||
if (entryResumePoint())
|
||||
entryResumePoint()->setOperand(i, phi);
|
||||
}
|
||||
} else if (entryResumePoint()) {
|
||||
} else {
|
||||
for (size_t i = 0; i < stackDepth(); i++)
|
||||
entryResumePoint()->setOperand(i, getSlot(i));
|
||||
}
|
||||
} else if (entryResumePoint()) {
|
||||
} else {
|
||||
/*
|
||||
* Don't leave the operands uninitialized for the caller, as it may not
|
||||
* initialize them later on.
|
||||
@ -796,7 +829,11 @@ MBasicBlock::addPredecessorPopN(MBasicBlock *pred, uint32_t popped)
|
||||
return false;
|
||||
} else {
|
||||
// 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);
|
||||
|
||||
// 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.
|
||||
JS_ASSERT(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
|
||||
JS_ASSERT(kind_ == PENDING_LOOP_HEADER);
|
||||
@ -911,6 +948,53 @@ MBasicBlock::setBackedge(MBasicBlock *pred)
|
||||
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
|
||||
MBasicBlock::clearLoopHeader()
|
||||
{
|
||||
|
@ -80,6 +80,8 @@ class MBasicBlock : public TempObject, public InlineListNode<MBasicBlock>
|
||||
static MBasicBlock *NewAbortPar(MIRGraph &graph, CompileInfo &info,
|
||||
MBasicBlock *pred, jsbytecode *entryPc,
|
||||
MResumePoint *resumePoint);
|
||||
static MBasicBlock *NewAsmJS(MIRGraph &graph, CompileInfo &info,
|
||||
MBasicBlock *pred, Kind kind);
|
||||
|
||||
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
|
||||
// phis at the loop header, returns a disabling abort.
|
||||
AbortReason setBackedge(MBasicBlock *block);
|
||||
bool setBackedgeAsmJS(MBasicBlock *block);
|
||||
|
||||
// Resets a LOOP_HEADER block to a NORMAL block. This is needed when
|
||||
// optimizations remove the backedge.
|
||||
|
@ -77,6 +77,7 @@ function testCollapsed(id, vPercent, startAt, expected) {
|
||||
var c = document.getElementById("c" + id);
|
||||
var target = document.getElementById("target" + id);
|
||||
if (target.contentDocument) {
|
||||
selection = target.contentWindow.getSelection().QueryInterface(Components.interfaces.nsISelectionPrivate);
|
||||
target = target.contentDocument.getElementById("target" + id);
|
||||
}
|
||||
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