mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-11 12:25:53 +00:00
Merge mozilla-inbound to mozilla-central
This commit is contained in:
commit
d524aacc84
@ -645,3 +645,5 @@ pref("memory_info_dumper.watch_fifo.directory", "/data/local");
|
||||
// <input type='file'> implementation is not complete. We have to disable the
|
||||
// type to web content to help them do feature detection.
|
||||
pref("dom.disable_input_file", true);
|
||||
|
||||
pref("general.useragent.enable_overrides", true);
|
||||
|
@ -1,2 +0,0 @@
|
||||
Components.utils.import('resource://gre/modules/UserAgentOverrides.jsm');
|
||||
UserAgentOverrides.init();
|
@ -25,8 +25,6 @@ chrome.jar:
|
||||
content/payment.js (content/payment.js)
|
||||
content/identity.js (content/identity.js)
|
||||
|
||||
content/UAO_child.js (content/UAO_child.js)
|
||||
|
||||
% override chrome://global/content/netError.xhtml chrome://browser/content/netError.xhtml
|
||||
% override chrome://global/skin/netError.css chrome://browser/content/netError.css
|
||||
% override chrome://global/skin/media/videocontrols.css chrome://browser/content/touchcontrols.css
|
||||
|
@ -57,17 +57,6 @@ ProcessGlobal.prototype = {
|
||||
' '));
|
||||
break;
|
||||
}
|
||||
case 'remote-browser-frame-shown': {
|
||||
let frameLoader = subject.QueryInterface(Ci.nsIFrameLoader);
|
||||
let mm = frameLoader.messageManager;
|
||||
|
||||
const kFrameScript = "chrome://browser/content/UAO_child.js";
|
||||
try {
|
||||
mm.loadFrameScript(kFrameScript, true);
|
||||
} catch (e) {
|
||||
dump('Error loading ' + kFrameScript + ' as frame script: ' + e + '\n');
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
@ -4,5 +4,11 @@
|
||||
"digest": "e0b98a75831313171781d91ab4c3b8ae66e3af7fcec433a33d75fbc647cb3bba311f790ccb9cd9c8be8c5549210b759d6b85afe7395ada74c2c319a29556fd8e",
|
||||
"algorithm": "sha512",
|
||||
"filename": "gonk.tar.xz"
|
||||
},
|
||||
{
|
||||
"size": 2116507,
|
||||
"digest": "be67a012963a5c162834f9fcb989bcebd2d047dcb4e17ee23031b694dcf7cdfd6d7a6545d7a1f5e7293b6d24415403972f4ea1ab8c6c78fefcabfaf3f6875214",
|
||||
"algorithm": "sha512",
|
||||
"filename": "download-panda.tar.bz2"
|
||||
}
|
||||
]
|
||||
|
@ -36,7 +36,7 @@ ifneq (,$(filter windows cocoa gtk2, $(MOZ_WIDGET_TOOLKIT)))
|
||||
DEFINES += -DCONTEXT_COPY_IMAGE_CONTENTS=1
|
||||
endif
|
||||
|
||||
ifneq (,$(filter windows, $(MOZ_WIDGET_TOOLKIT)))
|
||||
ifneq (,$(filter windows cocoa, $(MOZ_WIDGET_TOOLKIT)))
|
||||
DEFINES += -DCAN_DRAW_IN_TITLEBAR=1
|
||||
endif
|
||||
|
||||
|
@ -489,6 +489,7 @@
|
||||
#ifdef CAN_DRAW_IN_TITLEBAR
|
||||
<vbox id="titlebar">
|
||||
<hbox id="titlebar-content">
|
||||
#ifdef MENUBAR_CAN_AUTOHIDE
|
||||
<hbox id="appmenu-button-container">
|
||||
<button id="appmenu-button"
|
||||
type="menu"
|
||||
@ -497,6 +498,7 @@
|
||||
#include browser-appmenu.inc
|
||||
</button>
|
||||
</hbox>
|
||||
#endif
|
||||
<spacer id="titlebar-spacer" flex="1"/>
|
||||
<hbox id="titlebar-buttonbox-container" align="start">
|
||||
<hbox id="titlebar-buttonbox">
|
||||
|
@ -456,18 +456,17 @@ var tests = {
|
||||
ok(!window.SocialChatBar.hasChats, "first window should start with no chats");
|
||||
openChat(function() {
|
||||
ok(window.SocialChatBar.hasChats, "first window has the chat");
|
||||
// create a second window - although this will be the "most recent",
|
||||
// the fact the first window has a chat open means the first will be targetted.
|
||||
// create a second window - this will be the "most recent" and will
|
||||
// therefore be the window that hosts the new chat (see bug 835111)
|
||||
let secondWindow = OpenBrowserWindow();
|
||||
secondWindow.addEventListener("load", function loadListener() {
|
||||
secondWindow.removeEventListener("load", loadListener);
|
||||
ok(!secondWindow.SocialChatBar.hasChats, "second window has no chats");
|
||||
openChat(function() {
|
||||
ok(!secondWindow.SocialChatBar.hasChats, "second window still has no chats");
|
||||
is(window.SocialChatBar.chatbar.childElementCount, 2, "first window now has 2 chats");
|
||||
ok(secondWindow.SocialChatBar.hasChats, "second window now has chats");
|
||||
is(window.SocialChatBar.chatbar.childElementCount, 1, "first window still has 1 chat");
|
||||
window.SocialChatBar.chatbar.removeAll();
|
||||
// now open another chat - it should open in the second window (as
|
||||
// it is the "most recent" and no other windows have chats)
|
||||
// now open another chat - it should still open in the second.
|
||||
openChat(function() {
|
||||
ok(!window.SocialChatBar.hasChats, "first window has no chats");
|
||||
ok(secondWindow.SocialChatBar.hasChats, "second window has a chat");
|
||||
|
@ -1037,8 +1037,8 @@ DownloadsPlacesView.prototype = {
|
||||
else {
|
||||
shell.dataItem = null;
|
||||
// Move it below the session-download items;
|
||||
if (this._lastSessionDownloadElement == shell.dataItem) {
|
||||
this._lastSessionDownloadElement = shell.dataItem.previousSibling;
|
||||
if (this._lastSessionDownloadElement == shell.element) {
|
||||
this._lastSessionDownloadElement = shell.element.previousSibling;
|
||||
}
|
||||
else {
|
||||
let before = this._lastSessionDownloadElement ?
|
||||
|
@ -14,4 +14,7 @@ ac_add_options --enable-stdcxx-compat
|
||||
# Package js shell.
|
||||
export MOZ_PACKAGE_JSSHELL=1
|
||||
|
||||
# Need this to prevent name conflicts with the normal nightly build packages
|
||||
export MOZ_PKG_SPECIAL=asan
|
||||
|
||||
. "$topsrcdir/build/mozconfig.common.override"
|
||||
|
@ -16,4 +16,7 @@ ac_add_options --enable-stdcxx-compat
|
||||
# Package js shell.
|
||||
export MOZ_PACKAGE_JSSHELL=1
|
||||
|
||||
# Need this to prevent name conflicts with the normal nightly build packages
|
||||
export MOZ_PKG_SPECIAL=asan
|
||||
|
||||
. "$topsrcdir/build/mozconfig.common.override"
|
||||
|
@ -14,4 +14,7 @@ ac_add_options --enable-stdcxx-compat
|
||||
# Package js shell.
|
||||
export MOZ_PACKAGE_JSSHELL=1
|
||||
|
||||
# Need this to prevent name conflicts with the normal nightly build packages
|
||||
export MOZ_PKG_SPECIAL=asan
|
||||
|
||||
. "$topsrcdir/build/mozconfig.common.override"
|
||||
|
@ -16,4 +16,7 @@ ac_add_options --enable-stdcxx-compat
|
||||
# Package js shell.
|
||||
export MOZ_PACKAGE_JSSHELL=1
|
||||
|
||||
# Need this to prevent name conflicts with the normal nightly build packages
|
||||
export MOZ_PKG_SPECIAL=asan
|
||||
|
||||
. "$topsrcdir/build/mozconfig.common.override"
|
||||
|
@ -10,4 +10,7 @@ export MOZ_PACKAGE_JSSHELL=1
|
||||
|
||||
ac_add_options --with-macbundlename-prefix=Firefox
|
||||
|
||||
# Need this to prevent name conflicts with the normal nightly build packages
|
||||
export MOZ_PKG_SPECIAL=asan
|
||||
|
||||
. "$topsrcdir/build/mozconfig.common.override"
|
||||
|
@ -1,4 +1,4 @@
|
||||
This is the pdf.js project output, https://github.com/mozilla/pdf.js
|
||||
|
||||
Current extension version is: 0.7.82
|
||||
Current extension version is: 0.7.180
|
||||
|
||||
|
@ -201,9 +201,10 @@ PdfDataListener.prototype = {
|
||||
};
|
||||
|
||||
// All the priviledged actions.
|
||||
function ChromeActions(domWindow, dataListener) {
|
||||
function ChromeActions(domWindow, dataListener, contentDispositionFilename) {
|
||||
this.domWindow = domWindow;
|
||||
this.dataListener = dataListener;
|
||||
this.contentDispositionFilename = contentDispositionFilename;
|
||||
}
|
||||
|
||||
ChromeActions.prototype = {
|
||||
@ -232,6 +233,7 @@ ChromeActions.prototype = {
|
||||
return docIsPrivate;
|
||||
},
|
||||
download: function(data, sendResponse) {
|
||||
var self = this;
|
||||
var originalUrl = data.originalUrl;
|
||||
// The data may not be downloaded so we need just retry getting the pdf with
|
||||
// the original url.
|
||||
@ -259,9 +261,13 @@ ChromeActions.prototype = {
|
||||
// so the filename will be correct.
|
||||
let channel = Cc['@mozilla.org/network/input-stream-channel;1'].
|
||||
createInstance(Ci.nsIInputStreamChannel);
|
||||
channel.QueryInterface(Ci.nsIChannel);
|
||||
channel.contentDisposition = Ci.nsIChannel.DISPOSITION_ATTACHMENT;
|
||||
if (self.contentDispositionFilename) {
|
||||
channel.contentDispositionFilename = self.contentDispositionFilename;
|
||||
}
|
||||
channel.setURI(originalUri);
|
||||
channel.contentStream = aInputStream;
|
||||
channel.QueryInterface(Ci.nsIChannel);
|
||||
if ('nsIPrivateBrowsingChannel' in Ci &&
|
||||
channel instanceof Ci.nsIPrivateBrowsingChannel) {
|
||||
channel.setPrivate(docIsPrivate);
|
||||
@ -583,6 +589,10 @@ PdfStreamConverter.prototype = {
|
||||
// Creating storage for PDF data
|
||||
var contentLength = aRequest.contentLength;
|
||||
var dataListener = new PdfDataListener(contentLength);
|
||||
var contentDispositionFilename;
|
||||
try {
|
||||
contentDispositionFilename = aRequest.contentDispositionFilename;
|
||||
} catch (e) {}
|
||||
this.dataListener = dataListener;
|
||||
this.binaryStream = Cc['@mozilla.org/binaryinputstream;1']
|
||||
.createInstance(Ci.nsIBinaryInputStream);
|
||||
@ -613,7 +623,8 @@ PdfStreamConverter.prototype = {
|
||||
var domWindow = getDOMWindow(channel);
|
||||
// Double check the url is still the correct one.
|
||||
if (domWindow.document.documentURIObject.equals(aRequest.URI)) {
|
||||
let actions = new ChromeActions(domWindow, dataListener);
|
||||
let actions = new ChromeActions(domWindow, dataListener,
|
||||
contentDispositionFilename);
|
||||
let requestListener = new RequestListener(actions);
|
||||
domWindow.addEventListener(PDFJS_EVENT_ID, function(event) {
|
||||
requestListener.receive(event);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -94,20 +94,15 @@
|
||||
// get a localized string
|
||||
get: translateString,
|
||||
|
||||
// get|set the document language and direction
|
||||
get language() {
|
||||
return {
|
||||
// get|set the document language (ISO-639-1)
|
||||
get code() { return gLanguage; },
|
||||
// get the document language
|
||||
getLanguage: function() { return gLanguage; },
|
||||
|
||||
// get the direction (ltr|rtl) of the current language
|
||||
get direction() {
|
||||
// http://www.w3.org/International/questions/qa-scripts
|
||||
// Arabic, Hebrew, Farsi, Pashto, Urdu
|
||||
var rtlList = ['ar', 'he', 'fa', 'ps', 'ur'];
|
||||
return (rtlList.indexOf(gLanguage) >= 0) ? 'rtl' : 'ltr';
|
||||
}
|
||||
};
|
||||
// get the direction (ltr|rtl) of the current language
|
||||
getDirection: function() {
|
||||
// http://www.w3.org/International/questions/qa-scripts
|
||||
// Arabic, Hebrew, Farsi, Pashto, Urdu
|
||||
var rtlList = ['ar', 'he', 'fa', 'ps', 'ur'];
|
||||
return (rtlList.indexOf(gLanguage) >= 0) ? 'rtl' : 'ltr';
|
||||
}
|
||||
};
|
||||
})(this);
|
||||
|
@ -665,7 +665,6 @@ html[dir='rtl'] .dropdownToolbarButton {
|
||||
}
|
||||
|
||||
.dropdownToolbarButton {
|
||||
min-width: 120px;
|
||||
max-width: 120px;
|
||||
padding: 3px 2px 2px;
|
||||
overflow: hidden;
|
||||
|
@ -14,7 +14,7 @@ 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.
|
||||
-->
|
||||
<html dir="ltr">
|
||||
<html dir="ltr" mozdisallowselectionprint>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
@ -81,8 +81,8 @@ limitations under the License.
|
||||
<div id="toolbarContainer">
|
||||
<div id="toolbarViewer">
|
||||
<div id="toolbarViewerLeft">
|
||||
<button id="sidebarToggle" class="toolbarButton" title="Toggle Sidebar" tabindex="3" data-l10n-id="toggle_slider">
|
||||
<span data-l10n-id="toggle_slider_label">Toggle Sidebar</span>
|
||||
<button id="sidebarToggle" class="toolbarButton" title="Toggle Sidebar" tabindex="3" data-l10n-id="toggle_sidebar">
|
||||
<span data-l10n-id="toggle_sidebar_label">Toggle Sidebar</span>
|
||||
</button>
|
||||
<div class="toolbarButtonSpacer"></div>
|
||||
<button id="viewFind" class="toolbarButton group" title="Find in Document" tabindex="4" data-l10n-id="findbar">
|
||||
|
@ -57,7 +57,13 @@ function getFileName(url) {
|
||||
}
|
||||
|
||||
function scrollIntoView(element, spot) {
|
||||
// Assuming offsetParent is available (it's not available when viewer is in
|
||||
// hidden iframe or object). We have to scroll: if the offsetParent is not set
|
||||
// producing the error. See also animationStartedClosure.
|
||||
var parent = element.offsetParent, offsetY = element.offsetTop;
|
||||
if (!parent) {
|
||||
error('offsetParent is not set -- cannot scroll');
|
||||
}
|
||||
while (parent.clientHeight == parent.scrollHeight) {
|
||||
offsetY += parent.offsetTop;
|
||||
parent = parent.offsetParent;
|
||||
@ -1038,6 +1044,13 @@ var PDFView = {
|
||||
'Invalid or corrupted PDF file.');
|
||||
}
|
||||
|
||||
if (exception && exception.name === 'MissingPDFException') {
|
||||
// special message for missing PDF's
|
||||
var loadingErrorMessage = mozL10n.get('missing_file_error', null,
|
||||
'Missing PDF file.');
|
||||
|
||||
}
|
||||
|
||||
var loadingIndicator = document.getElementById('loading');
|
||||
loadingIndicator.textContent = mozL10n.get('loading_error_indicator',
|
||||
null, 'Error');
|
||||
@ -1285,7 +1298,8 @@ var PDFView = {
|
||||
});
|
||||
|
||||
// outline and initial view depends on destinations and pagesRefMap
|
||||
var promises = [pagesPromise, destinationsPromise, storePromise];
|
||||
var promises = [pagesPromise, destinationsPromise, storePromise,
|
||||
PDFView.animationStartedPromise];
|
||||
PDFJS.Promise.all(promises).then(function() {
|
||||
pdfDocument.getOutline().then(function(outline) {
|
||||
self.outline = new DocumentOutlineView(outline);
|
||||
@ -1326,6 +1340,11 @@ var PDFView = {
|
||||
|
||||
if (pdfTitle)
|
||||
self.setTitle(pdfTitle + ' - ' + document.title);
|
||||
|
||||
if (info.IsAcroFormPresent) {
|
||||
// AcroForm/XFA was found
|
||||
PDFView.fallback();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
@ -1936,10 +1955,6 @@ var PageView = function pageView(container, pdfPage, id, scale,
|
||||
if (textAnnotation)
|
||||
div.appendChild(textAnnotation);
|
||||
break;
|
||||
case 'Widget':
|
||||
// TODO: support forms
|
||||
PDFView.fallback();
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -2059,6 +2074,9 @@ var PageView = function pageView(container, pdfPage, id, scale,
|
||||
}
|
||||
|
||||
var ctx = canvas.getContext('2d');
|
||||
// TODO(mack): use data attributes to store these
|
||||
ctx._scaleX = outputScale.sx;
|
||||
ctx._scaleY = outputScale.sy;
|
||||
ctx.save();
|
||||
ctx.fillStyle = 'rgb(255, 255, 255)';
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
@ -2072,7 +2090,12 @@ var PageView = function pageView(container, pdfPage, id, scale,
|
||||
// Rendering area
|
||||
|
||||
var self = this;
|
||||
var renderingWasReset = false;
|
||||
function pageViewDrawCallback(error) {
|
||||
if (renderingWasReset) {
|
||||
return;
|
||||
}
|
||||
|
||||
self.renderingState = RenderingStates.FINISHED;
|
||||
|
||||
if (self.loadingIconDiv) {
|
||||
@ -2105,6 +2128,12 @@ var PageView = function pageView(container, pdfPage, id, scale,
|
||||
viewport: this.viewport,
|
||||
textLayer: textLayer,
|
||||
continueCallback: function pdfViewcContinueCallback(cont) {
|
||||
if (self.renderingState === RenderingStates.INITIAL) {
|
||||
// The page update() was called, we just need to abort any rendering.
|
||||
renderingWasReset = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (PDFView.highestPriorityPage !== 'page' + self.id) {
|
||||
self.renderingState = RenderingStates.PAUSED;
|
||||
self.resume = function resumeCallback() {
|
||||
@ -2885,9 +2914,19 @@ document.addEventListener('DOMContentLoaded', function webViewerLoad(evt) {
|
||||
PDFView.download();
|
||||
});
|
||||
|
||||
document.getElementById('pageNumber').addEventListener('click',
|
||||
function() {
|
||||
this.select();
|
||||
});
|
||||
|
||||
document.getElementById('pageNumber').addEventListener('change',
|
||||
function() {
|
||||
PDFView.page = this.value;
|
||||
// Handle the user inputting a floating point number.
|
||||
PDFView.page = (this.value | 0);
|
||||
|
||||
if (this.value !== (this.value | 0).toString()) {
|
||||
this.value = PDFView.page;
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById('scaleSelect').addEventListener('change',
|
||||
@ -3039,6 +3078,16 @@ function selectScaleOption(value) {
|
||||
|
||||
window.addEventListener('localized', function localized(evt) {
|
||||
document.getElementsByTagName('html')[0].dir = mozL10n.getDirection();
|
||||
|
||||
// Adjust the width of the zoom box to fit the content.
|
||||
var container = document.getElementById('scaleSelectContainer');
|
||||
var select = document.getElementById('scaleSelect');
|
||||
|
||||
select.setAttribute('style', 'min-width: inherit;');
|
||||
var width = select.clientWidth + 8;
|
||||
container.setAttribute('style', 'min-width: ' + width + 'px; ' +
|
||||
'max-width: ' + width + 'px;');
|
||||
select.setAttribute('style', 'min-width: ' + (width + 20) + 'px;');
|
||||
}, true);
|
||||
|
||||
window.addEventListener('scalechange', function scalechange(evt) {
|
||||
@ -3280,4 +3329,19 @@ window.addEventListener('afterprint', function afterPrint(evt) {
|
||||
window.addEventListener('webkitfullscreenchange', fullscreenChange, false);
|
||||
})();
|
||||
|
||||
(function animationStartedClosure() {
|
||||
// The offsetParent is not set until the pdf.js iframe or object is visible.
|
||||
// Waiting for first animation.
|
||||
var requestAnimationFrame = window.requestAnimationFrame ||
|
||||
window.mozRequestAnimationFrame ||
|
||||
window.webkitRequestAnimationFrame ||
|
||||
window.oRequestAnimationFrame ||
|
||||
window.msRequestAnimationFrame ||
|
||||
function startAtOnce(callback) { callback(); };
|
||||
PDFView.animationStartedPromise = new PDFJS.Promise();
|
||||
requestAnimationFrame(function onAnimationFrame() {
|
||||
PDFView.animationStartedPromise.resolve();
|
||||
});
|
||||
})();
|
||||
|
||||
|
||||
|
@ -44,8 +44,8 @@ bookmark_label=Current View
|
||||
# Tooltips and alt text for side panel toolbar buttons
|
||||
# (the _label strings are alt text for the buttons, the .title strings are
|
||||
# tooltips)
|
||||
toggle_slider.title=Toggle Slider
|
||||
toggle_slider_label=Toggle Slider
|
||||
toggle_sidebar.title=Toggle Sidebar
|
||||
toggle_sidebar_label=Toggle Sidebar
|
||||
outline.title=Show Document Outline
|
||||
outline_label=Document Outline
|
||||
thumbs.title=Show Thumbnails
|
||||
@ -111,6 +111,7 @@ page_scale_actual=Actual Size
|
||||
loading_error_indicator=Error
|
||||
loading_error=An error occurred while loading the PDF.
|
||||
invalid_file_error=Invalid or corrupted PDF file.
|
||||
missing_file_error=Missing PDF file.
|
||||
|
||||
# LOCALIZATION NOTE (text_annotation_type): This is used as a tooltip.
|
||||
# "{{type}}" will be replaced with an annotation type from a list defined in
|
||||
|
@ -1289,6 +1289,13 @@ toolbar[iconsize="small"] #webrtc-status-button {
|
||||
list-style-image: url(chrome://mozapps/skin/plugins/notifyPluginBlocked.png);
|
||||
}
|
||||
|
||||
#notification-popup-box[hidden] {
|
||||
/* Override display:none to make the pluginBlockedNotification animation work
|
||||
when showing the notification repeatedly. */
|
||||
display: -moz-box;
|
||||
visibility: collapse;
|
||||
}
|
||||
|
||||
#blocked-plugins-notification-icon[showing] {
|
||||
animation: pluginBlockedNotification 500ms ease 0s 5 alternate both;
|
||||
}
|
||||
|
@ -38,6 +38,15 @@
|
||||
background-color: #eeeeee;
|
||||
}
|
||||
|
||||
#titlebar-buttonbox-container,
|
||||
#titlebar:not(:-moz-lwtheme) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#main-window[drawintitlebar="true"] > #titlebar {
|
||||
height: 22px;
|
||||
}
|
||||
|
||||
#main-window[chromehidden~="toolbar"][chromehidden~="location"][chromehidden~="directories"] {
|
||||
border-top: 1px solid rgba(0,0,0,0.65);
|
||||
}
|
||||
@ -3076,6 +3085,13 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
|
||||
}
|
||||
}
|
||||
|
||||
#notification-popup-box[hidden] {
|
||||
/* Override display:none to make the pluginBlockedNotification animation work
|
||||
when showing the notification repeatedly. */
|
||||
display: -moz-box;
|
||||
visibility: collapse;
|
||||
}
|
||||
|
||||
#blocked-plugins-notification-icon[showing] {
|
||||
animation: pluginBlockedNotification 500ms ease 0s 5 alternate both;
|
||||
}
|
||||
|
@ -2353,6 +2353,13 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] {
|
||||
list-style-image: url(chrome://mozapps/skin/plugins/notifyPluginBlocked.png);
|
||||
}
|
||||
|
||||
#notification-popup-box[hidden] {
|
||||
/* Override display:none to make the pluginBlockedNotification animation work
|
||||
when showing the notification repeatedly. */
|
||||
display: -moz-box;
|
||||
visibility: collapse;
|
||||
}
|
||||
|
||||
#blocked-plugins-notification-icon[showing] {
|
||||
animation: pluginBlockedNotification 500ms ease 0s 5 alternate both;
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ extern PRLogModuleInfo* GetDataChannelLog();
|
||||
#include "nsDOMClassInfo.h"
|
||||
#include "nsDOMEventTargetHelper.h"
|
||||
|
||||
#include "jsval.h"
|
||||
#include "js/Value.h"
|
||||
|
||||
#include "nsError.h"
|
||||
#include "nsAutoPtr.h"
|
||||
|
@ -46,7 +46,7 @@ static WebGLenum InternalFormatForFormatAndType(WebGLenum format, WebGLenum type
|
||||
void
|
||||
WebGLContext::ActiveTexture(WebGLenum texture)
|
||||
{
|
||||
if (!IsContextStable())
|
||||
if (!IsContextStable())
|
||||
return;
|
||||
|
||||
if (texture < LOCAL_GL_TEXTURE0 ||
|
||||
@ -4194,6 +4194,15 @@ WebGLContext::CompileShader(WebGLShader *shader)
|
||||
|
||||
int compileOptions = SH_ATTRIBUTES_UNIFORMS |
|
||||
SH_ENFORCE_PACKING_RESTRICTIONS;
|
||||
|
||||
// we want to do this everywhere, but:
|
||||
#ifndef XP_WIN // to do this on Windows, we need ANGLE r1719, 1733, 1734.
|
||||
#ifndef XP_MACOSX // to do this on Mac, we need to do it only on Mac OSX > 10.6 as this
|
||||
// causes the shader compiler in 10.6 to crash
|
||||
compileOptions |= SH_CLAMP_INDIRECT_ARRAY_BOUNDS;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (useShaderSourceTranslation) {
|
||||
compileOptions |= SH_OBJECT_CODE
|
||||
| SH_MAP_LONG_VARIABLE_NAMES;
|
||||
|
@ -106,7 +106,7 @@ TextComposition::CompositionEventDispatcher::CompositionEventDispatcher(
|
||||
mPresContext(aPresContext), mEventTarget(aEventTarget),
|
||||
mEventMessage(aEventMessage), mData(aData)
|
||||
{
|
||||
mWidget = mPresContext->GetNearestWidget();
|
||||
mWidget = mPresContext->GetRootWidget();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -127,7 +127,7 @@ nsIMEStateManager::OnDestroyPresContext(nsPresContext* aPresContext)
|
||||
|
||||
DestroyTextStateManager();
|
||||
|
||||
nsCOMPtr<nsIWidget> widget = sPresContext->GetNearestWidget();
|
||||
nsCOMPtr<nsIWidget> widget = sPresContext->GetRootWidget();
|
||||
if (widget) {
|
||||
IMEState newState = GetNewIMEState(sPresContext, nullptr);
|
||||
InputContextAction action(InputContextAction::CAUSE_UNKNOWN,
|
||||
@ -157,7 +157,7 @@ nsIMEStateManager::OnRemoveContent(nsPresContext* aPresContext,
|
||||
// is called during the content being removed. Then, the native
|
||||
// composition events which are caused by following APIs are ignored due
|
||||
// to unsafe to run script (in PresShell::HandleEvent()).
|
||||
nsCOMPtr<nsIWidget> widget = aPresContext->GetNearestWidget();
|
||||
nsCOMPtr<nsIWidget> widget = aPresContext->GetRootWidget();
|
||||
if (widget) {
|
||||
nsresult rv =
|
||||
storedComposition.NotifyIME(REQUEST_TO_CANCEL_COMPOSITION);
|
||||
@ -187,7 +187,7 @@ nsIMEStateManager::OnRemoveContent(nsPresContext* aPresContext,
|
||||
DestroyTextStateManager();
|
||||
|
||||
// Current IME transaction should commit
|
||||
nsCOMPtr<nsIWidget> widget = sPresContext->GetNearestWidget();
|
||||
nsCOMPtr<nsIWidget> widget = sPresContext->GetRootWidget();
|
||||
if (widget) {
|
||||
IMEState newState = GetNewIMEState(sPresContext, nullptr);
|
||||
InputContextAction action(InputContextAction::CAUSE_UNKNOWN,
|
||||
@ -219,7 +219,7 @@ nsIMEStateManager::OnChangeFocusInternal(nsPresContext* aPresContext,
|
||||
(sContent != aContent || sPresContext != aPresContext);
|
||||
|
||||
nsCOMPtr<nsIWidget> oldWidget =
|
||||
sPresContext ? sPresContext->GetNearestWidget() : nullptr;
|
||||
sPresContext ? sPresContext->GetRootWidget() : nullptr;
|
||||
if (oldWidget && focusActuallyChanging) {
|
||||
// If we're deactivating, we shouldn't commit composition forcibly because
|
||||
// the user may want to continue the composition.
|
||||
@ -239,7 +239,7 @@ nsIMEStateManager::OnChangeFocusInternal(nsPresContext* aPresContext,
|
||||
|
||||
nsCOMPtr<nsIWidget> widget =
|
||||
(sPresContext == aPresContext) ? oldWidget.get() :
|
||||
aPresContext->GetNearestWidget();
|
||||
aPresContext->GetRootWidget();
|
||||
if (!widget) {
|
||||
return NS_OK;
|
||||
}
|
||||
@ -326,7 +326,7 @@ nsIMEStateManager::OnClickInEditor(nsPresContext* aPresContext,
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIWidget> widget = aPresContext->GetNearestWidget();
|
||||
nsCOMPtr<nsIWidget> widget = aPresContext->GetRootWidget();
|
||||
NS_ENSURE_TRUE_VOID(widget);
|
||||
|
||||
bool isTrusted;
|
||||
@ -384,7 +384,7 @@ nsIMEStateManager::UpdateIMEState(const IMEState &aNewIMEState,
|
||||
NS_WARNING("ISM doesn't know which editor has focus");
|
||||
return;
|
||||
}
|
||||
nsCOMPtr<nsIWidget> widget = sPresContext->GetNearestWidget();
|
||||
nsCOMPtr<nsIWidget> widget = sPresContext->GetRootWidget();
|
||||
if (!widget) {
|
||||
NS_WARNING("focused widget is not found");
|
||||
return;
|
||||
@ -683,7 +683,7 @@ nsIMEStateManager::NotifyIME(NotificationToIME aNotification,
|
||||
{
|
||||
NS_ENSURE_TRUE(aPresContext, NS_ERROR_INVALID_ARG);
|
||||
|
||||
nsIWidget* widget = aPresContext->GetNearestWidget();
|
||||
nsIWidget* widget = aPresContext->GetRootWidget();
|
||||
if (!widget) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
@ -1093,7 +1093,7 @@ nsIMEStateManager::CreateTextStateManager()
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIWidget> widget = sPresContext->GetNearestWidget();
|
||||
nsCOMPtr<nsIWidget> widget = sPresContext->GetRootWidget();
|
||||
if (!widget) {
|
||||
return; // Sometimes, there are no widgets.
|
||||
}
|
||||
|
@ -1092,11 +1092,17 @@ namespace {
|
||||
|
||||
class MediaStreamGraphThreadRunnable : public nsRunnable {
|
||||
public:
|
||||
explicit MediaStreamGraphThreadRunnable(MediaStreamGraphImpl* aGraph)
|
||||
: mGraph(aGraph)
|
||||
{
|
||||
}
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
gGraph->RunThread();
|
||||
mGraph->RunThread();
|
||||
return NS_OK;
|
||||
}
|
||||
private:
|
||||
MediaStreamGraphImpl* mGraph;
|
||||
};
|
||||
|
||||
class MediaStreamGraphShutDownRunnable : public nsRunnable {
|
||||
@ -1125,13 +1131,19 @@ private:
|
||||
|
||||
class MediaStreamGraphStableStateRunnable : public nsRunnable {
|
||||
public:
|
||||
explicit MediaStreamGraphStableStateRunnable(MediaStreamGraphImpl* aGraph)
|
||||
: mGraph(aGraph)
|
||||
{
|
||||
}
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
if (gGraph) {
|
||||
gGraph->RunInStableState();
|
||||
if (mGraph) {
|
||||
mGraph->RunInStableState();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
private:
|
||||
MediaStreamGraphImpl* mGraph;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -1200,17 +1212,19 @@ MediaStreamGraphImpl::RunInStableState()
|
||||
// Start the thread now. We couldn't start it earlier because
|
||||
// the graph might exit immediately on finding it has no streams. The
|
||||
// first message for a new graph must create a stream.
|
||||
nsCOMPtr<nsIRunnable> event = new MediaStreamGraphThreadRunnable();
|
||||
nsCOMPtr<nsIRunnable> event = new MediaStreamGraphThreadRunnable(this);
|
||||
NS_NewThread(getter_AddRefs(mThread), event);
|
||||
}
|
||||
|
||||
if (mCurrentTaskMessageQueue.IsEmpty()) {
|
||||
if (mLifecycleState == LIFECYCLE_WAITING_FOR_MAIN_THREAD_CLEANUP && IsEmpty()) {
|
||||
NS_ASSERTION(gGraph == this, "Not current graph??");
|
||||
// Complete shutdown. First, ensure that this graph is no longer used.
|
||||
// A new graph graph will be created if one is needed.
|
||||
LOG(PR_LOG_DEBUG, ("Disconnecting MediaStreamGraph %p", gGraph));
|
||||
gGraph = nullptr;
|
||||
LOG(PR_LOG_DEBUG, ("Disconnecting MediaStreamGraph %p", this));
|
||||
if (this == gGraph) {
|
||||
// null out gGraph if that's the graph being shut down
|
||||
gGraph = nullptr;
|
||||
}
|
||||
// Asynchronously clean up old graph. We don't want to do this
|
||||
// synchronously because it spins the event loop waiting for threads
|
||||
// to shut down, and we don't want to do that in a stable state handler.
|
||||
@ -1232,7 +1246,7 @@ MediaStreamGraphImpl::RunInStableState()
|
||||
// Revive the MediaStreamGraph since we have more messages going to it.
|
||||
// Note that we need to put messages into its queue before reviving it,
|
||||
// or it might exit immediately.
|
||||
nsCOMPtr<nsIRunnable> event = new MediaStreamGraphThreadRunnable();
|
||||
nsCOMPtr<nsIRunnable> event = new MediaStreamGraphThreadRunnable(this);
|
||||
mThread->Dispatch(event, 0);
|
||||
}
|
||||
}
|
||||
@ -1261,7 +1275,7 @@ MediaStreamGraphImpl::EnsureRunInStableState()
|
||||
if (mPostedRunInStableState)
|
||||
return;
|
||||
mPostedRunInStableState = true;
|
||||
nsCOMPtr<nsIRunnable> event = new MediaStreamGraphStableStateRunnable();
|
||||
nsCOMPtr<nsIRunnable> event = new MediaStreamGraphStableStateRunnable(this);
|
||||
nsCOMPtr<nsIAppShell> appShell = do_GetService(kAppShellCID);
|
||||
if (appShell) {
|
||||
appShell->RunInStableState(event);
|
||||
@ -1278,7 +1292,7 @@ MediaStreamGraphImpl::EnsureStableStateEventPosted()
|
||||
if (mPostedRunInStableStateEvent)
|
||||
return;
|
||||
mPostedRunInStableStateEvent = true;
|
||||
nsCOMPtr<nsIRunnable> event = new MediaStreamGraphStableStateRunnable();
|
||||
nsCOMPtr<nsIRunnable> event = new MediaStreamGraphStableStateRunnable(this);
|
||||
NS_DispatchToMainThread(event);
|
||||
}
|
||||
|
||||
@ -1300,9 +1314,10 @@ MediaStreamGraphImpl::AppendMessage(ControlMessage* aMessage)
|
||||
aMessage->RunDuringShutdown();
|
||||
delete aMessage;
|
||||
if (IsEmpty()) {
|
||||
NS_ASSERTION(gGraph == this, "Switched managers during forced shutdown?");
|
||||
gGraph = nullptr;
|
||||
delete this;
|
||||
if (gGraph == this) {
|
||||
gGraph = nullptr;
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -1323,13 +1338,20 @@ MediaStream::Init()
|
||||
MediaStreamGraphImpl*
|
||||
MediaStream::GraphImpl()
|
||||
{
|
||||
return gGraph;
|
||||
return mGraph;
|
||||
}
|
||||
|
||||
MediaStreamGraph*
|
||||
MediaStream::Graph()
|
||||
{
|
||||
return gGraph;
|
||||
return mGraph;
|
||||
}
|
||||
|
||||
void
|
||||
MediaStream::SetGraphImpl(MediaStreamGraphImpl* aGraph)
|
||||
{
|
||||
MOZ_ASSERT(!mGraph, "Should only be called once");
|
||||
mGraph = aGraph;
|
||||
}
|
||||
|
||||
StreamTime
|
||||
@ -1787,13 +1809,20 @@ MediaInputPort::Destroy()
|
||||
MediaStreamGraphImpl*
|
||||
MediaInputPort::GraphImpl()
|
||||
{
|
||||
return gGraph;
|
||||
return mGraph;
|
||||
}
|
||||
|
||||
MediaStreamGraph*
|
||||
MediaInputPort::Graph()
|
||||
{
|
||||
return gGraph;
|
||||
return mGraph;
|
||||
}
|
||||
|
||||
void
|
||||
MediaInputPort::SetGraphImpl(MediaStreamGraphImpl* aGraph)
|
||||
{
|
||||
MOZ_ASSERT(!mGraph, "Should only be called once");
|
||||
mGraph = aGraph;
|
||||
}
|
||||
|
||||
already_AddRefed<MediaInputPort>
|
||||
@ -1815,6 +1844,7 @@ ProcessedMediaStream::AllocateInputPort(MediaStream* aStream, uint32_t aFlags)
|
||||
nsRefPtr<MediaInputPort> mPort;
|
||||
};
|
||||
nsRefPtr<MediaInputPort> port = new MediaInputPort(aStream, this, aFlags);
|
||||
port->SetGraphImpl(GraphImpl());
|
||||
GraphImpl()->AppendMessage(new Message(port));
|
||||
return port.forget();
|
||||
}
|
||||
@ -1930,7 +1960,9 @@ MediaStreamGraph::CreateSourceStream(nsDOMMediaStream* aWrapper)
|
||||
{
|
||||
SourceMediaStream* stream = new SourceMediaStream(aWrapper);
|
||||
NS_ADDREF(stream);
|
||||
static_cast<MediaStreamGraphImpl*>(this)->AppendMessage(new CreateMessage(stream));
|
||||
MediaStreamGraphImpl* graph = static_cast<MediaStreamGraphImpl*>(this);
|
||||
stream->SetGraphImpl(graph);
|
||||
graph->AppendMessage(new CreateMessage(stream));
|
||||
return stream;
|
||||
}
|
||||
|
||||
@ -1939,7 +1971,9 @@ MediaStreamGraph::CreateTrackUnionStream(nsDOMMediaStream* aWrapper)
|
||||
{
|
||||
TrackUnionStream* stream = new TrackUnionStream(aWrapper);
|
||||
NS_ADDREF(stream);
|
||||
static_cast<MediaStreamGraphImpl*>(this)->AppendMessage(new CreateMessage(stream));
|
||||
MediaStreamGraphImpl* graph = static_cast<MediaStreamGraphImpl*>(this);
|
||||
stream->SetGraphImpl(graph);
|
||||
graph->AppendMessage(new CreateMessage(stream));
|
||||
return stream;
|
||||
}
|
||||
|
||||
@ -1948,7 +1982,9 @@ MediaStreamGraph::CreateAudioNodeStream(AudioNodeEngine* aEngine)
|
||||
{
|
||||
AudioNodeStream* stream = new AudioNodeStream(aEngine);
|
||||
NS_ADDREF(stream);
|
||||
static_cast<MediaStreamGraphImpl*>(this)->AppendMessage(new CreateMessage(stream));
|
||||
MediaStreamGraphImpl* graph = static_cast<MediaStreamGraphImpl*>(this);
|
||||
stream->SetGraphImpl(graph);
|
||||
graph->AppendMessage(new CreateMessage(stream));
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
@ -272,6 +272,7 @@ public:
|
||||
, mMainThreadCurrentTime(0)
|
||||
, mMainThreadFinished(false)
|
||||
, mMainThreadDestroyed(false)
|
||||
, mGraph(nullptr)
|
||||
{
|
||||
}
|
||||
virtual ~MediaStream()
|
||||
@ -286,6 +287,10 @@ public:
|
||||
*/
|
||||
MediaStreamGraphImpl* GraphImpl();
|
||||
MediaStreamGraph* Graph();
|
||||
/**
|
||||
* Sets the graph that owns this stream. Should only be called once.
|
||||
*/
|
||||
void SetGraphImpl(MediaStreamGraphImpl* aGraph);
|
||||
|
||||
// Control API.
|
||||
// Since a stream can be played multiple ways, we need to combine independent
|
||||
@ -515,6 +520,9 @@ protected:
|
||||
StreamTime mMainThreadCurrentTime;
|
||||
bool mMainThreadFinished;
|
||||
bool mMainThreadDestroyed;
|
||||
|
||||
// Our media stream graph
|
||||
MediaStreamGraphImpl* mGraph;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -703,6 +711,7 @@ public:
|
||||
: mSource(aSource)
|
||||
, mDest(aDest)
|
||||
, mFlags(aFlags)
|
||||
, mGraph(nullptr)
|
||||
{
|
||||
MOZ_COUNT_CTOR(MediaInputPort);
|
||||
}
|
||||
@ -743,6 +752,10 @@ public:
|
||||
*/
|
||||
MediaStreamGraphImpl* GraphImpl();
|
||||
MediaStreamGraph* Graph();
|
||||
/**
|
||||
* Sets the graph that owns this stream. Should only be called once.
|
||||
*/
|
||||
void SetGraphImpl(MediaStreamGraphImpl* aGraph);
|
||||
|
||||
protected:
|
||||
friend class MediaStreamGraphImpl;
|
||||
@ -752,6 +765,9 @@ protected:
|
||||
MediaStream* mSource;
|
||||
ProcessedMediaStream* mDest;
|
||||
uint32_t mFlags;
|
||||
|
||||
// Our media stream graph
|
||||
MediaStreamGraphImpl* mGraph;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -14,6 +14,7 @@ MODULE = shistory
|
||||
LIBRARY_NAME = shistory_s
|
||||
FORCE_STATIC_LIB = 1
|
||||
LIBXUL_LIBRARY = 1
|
||||
FAIL_ON_WARNINGS = 1
|
||||
|
||||
EXPORTS = nsSHEntryShared.h \
|
||||
$(NULL)
|
||||
|
@ -560,11 +560,12 @@ nsDOMWindowUtils::SendMouseEvent(const nsAString& aType,
|
||||
int32_t aModifiers,
|
||||
bool aIgnoreRootScrollFrame,
|
||||
float aPressure,
|
||||
unsigned short aInputSourceArg)
|
||||
unsigned short aInputSourceArg,
|
||||
bool *aPreventDefault)
|
||||
{
|
||||
return SendMouseEventCommon(aType, aX, aY, aButton, aClickCount, aModifiers,
|
||||
aIgnoreRootScrollFrame, aPressure,
|
||||
aInputSourceArg, false);
|
||||
aInputSourceArg, false, aPreventDefault);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -581,7 +582,7 @@ nsDOMWindowUtils::SendMouseEventToWindow(const nsAString& aType,
|
||||
SAMPLE_LABEL("nsDOMWindowUtils", "SendMouseEventToWindow");
|
||||
return SendMouseEventCommon(aType, aX, aY, aButton, aClickCount, aModifiers,
|
||||
aIgnoreRootScrollFrame, aPressure,
|
||||
aInputSourceArg, true);
|
||||
aInputSourceArg, true, nullptr);
|
||||
}
|
||||
|
||||
static nsIntPoint
|
||||
@ -604,7 +605,8 @@ nsDOMWindowUtils::SendMouseEventCommon(const nsAString& aType,
|
||||
bool aIgnoreRootScrollFrame,
|
||||
float aPressure,
|
||||
unsigned short aInputSourceArg,
|
||||
bool aToWindow)
|
||||
bool aToWindow,
|
||||
bool *aPreventDefault)
|
||||
{
|
||||
if (!nsContentUtils::IsCallerChrome()) {
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
@ -631,7 +633,9 @@ nsDOMWindowUtils::SendMouseEventCommon(const nsAString& aType,
|
||||
else if (aType.EqualsLiteral("contextmenu")) {
|
||||
msg = NS_CONTEXTMENU;
|
||||
contextMenuKey = (aButton == 0);
|
||||
} else
|
||||
} else if (aType.EqualsLiteral("MozMouseHittest"))
|
||||
msg = NS_MOUSE_MOZHITTEST;
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (aInputSourceArg == nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN) {
|
||||
@ -672,7 +676,10 @@ nsDOMWindowUtils::SendMouseEventCommon(const nsAString& aType,
|
||||
status = nsEventStatus_eIgnore;
|
||||
return presShell->HandleEvent(view->GetFrame(), &event, false, &status);
|
||||
}
|
||||
return widget->DispatchEvent(&event, status);
|
||||
nsresult rv = widget->DispatchEvent(&event, status);
|
||||
*aPreventDefault = (status == nsEventStatus_eConsumeNoDefault);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -47,7 +47,8 @@ protected:
|
||||
bool aIgnoreRootScrollFrame,
|
||||
float aPressure,
|
||||
unsigned short aInputSourceArg,
|
||||
bool aToWindow);
|
||||
bool aToWindow,
|
||||
bool *aPreventDefault);
|
||||
|
||||
static mozilla::widget::Modifiers GetWidgetModifiers(int32_t aModifiers);
|
||||
};
|
||||
|
@ -526,6 +526,15 @@ DOMInterfaces = {
|
||||
'register': False
|
||||
},
|
||||
|
||||
'MediaStream': [{
|
||||
'nativeType': 'nsIDOMMediaStream',
|
||||
},
|
||||
{
|
||||
'nativeType': 'JSObject',
|
||||
'workers': True,
|
||||
'skipGen': True
|
||||
}],
|
||||
|
||||
'MediaStreamList': {
|
||||
'headerFile': 'MediaStreamList.h',
|
||||
'wrapperCache': False,
|
||||
@ -870,9 +879,13 @@ DOMInterfaces = {
|
||||
'implicitJSContext': [ 'encode' ],
|
||||
}],
|
||||
|
||||
'URL' : {
|
||||
'URL' : [{
|
||||
'concrete': False,
|
||||
},
|
||||
{
|
||||
'implicitJSContext': [ 'createObjectURL', 'revokeObjectURL' ],
|
||||
'workers': True,
|
||||
}],
|
||||
|
||||
'WebGLActiveInfo': {
|
||||
'nativeType': 'mozilla::WebGLActiveInfo',
|
||||
@ -1232,7 +1245,6 @@ addExternalIface('HTMLCanvasElement', nativeType='mozilla::dom::HTMLCanvasElemen
|
||||
addExternalIface('imgINotificationObserver', nativeType='imgINotificationObserver')
|
||||
addExternalIface('imgIRequest', nativeType='imgIRequest', notflattened=True)
|
||||
addExternalIface('LockedFile')
|
||||
addExternalIface('MediaStream')
|
||||
addExternalIface('MozBoxObject', nativeType='nsIBoxObject')
|
||||
addExternalIface('MozControllers', nativeType='nsIControllers')
|
||||
addExternalIface('MozFrameLoader', nativeType='nsIFrameLoader', notflattened=True)
|
||||
|
@ -30,6 +30,10 @@
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsXPCOM.h"
|
||||
|
||||
#if defined(MOZ_WIDGET_GONK)
|
||||
#include "cutils/properties.h"
|
||||
#endif
|
||||
|
||||
#if defined(MOZ_B2G_BT)
|
||||
# if defined(MOZ_BLUETOOTH_GONK)
|
||||
# include "BluetoothGonkService.h"
|
||||
@ -44,6 +48,8 @@
|
||||
#define BLUETOOTH_ENABLED_SETTING "bluetooth.enabled"
|
||||
#define BLUETOOTH_DEBUGGING_SETTING "bluetooth.debugging.enabled"
|
||||
|
||||
#define PROP_BLUETOOTH_ENABLED "bluetooth.isEnabled"
|
||||
|
||||
#define DEFAULT_SHUTDOWN_TIMER_MS 5000
|
||||
|
||||
bool gBluetoothDebugFlag = false;
|
||||
@ -184,6 +190,19 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
// This is requested in Bug 836516. With settings this property, WLAN
|
||||
// firmware could be aware of Bluetooth has been turned on/off, so that the
|
||||
// mecahnism of handling coexistence of WIFI and Bluetooth could be started.
|
||||
//
|
||||
// In the future, we may have our own way instead of setting a system
|
||||
// property to let firmware developers be able to sense that Bluetooth has
|
||||
// been toggled.
|
||||
#if defined(MOZ_WIDGET_GONK)
|
||||
if (property_set(PROP_BLUETOOTH_ENABLED, mEnabled ? "true" : "false") != 0) {
|
||||
NS_WARNING("Failed to set bluetooth enabled property");
|
||||
}
|
||||
#endif
|
||||
|
||||
nsCOMPtr<nsIRunnable> ackTask = new BluetoothService::ToggleBtAck(mEnabled);
|
||||
if (NS_FAILED(NS_DispatchToMainThread(ackTask))) {
|
||||
NS_WARNING("Failed to dispatch to main thread!");
|
||||
@ -358,13 +377,22 @@ BluetoothService::UnregisterBluetoothSignalHandler(
|
||||
}
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
RemoveAllSignalHandlers(const nsAString& aKey,
|
||||
nsAutoPtr<BluetoothSignalObserverList>& aData,
|
||||
void* aUserArg)
|
||||
{
|
||||
aData->RemoveObserver(static_cast<BluetoothSignalObserver*>(aUserArg));
|
||||
return aData->Length() ? PL_DHASH_NEXT : PL_DHASH_REMOVE;
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothService::UnregisterAllSignalHandlers(BluetoothSignalObserver* aHandler)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aHandler);
|
||||
|
||||
mBluetoothSignalObserverTable.Clear();
|
||||
mBluetoothSignalObserverTable.Enumerate(RemoveAllSignalHandlers, aHandler);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -41,7 +41,7 @@ interface nsIDOMClientRect;
|
||||
interface nsIURI;
|
||||
interface nsIDOMEventTarget;
|
||||
|
||||
[scriptable, uuid(458f5b08-4966-4a91-8617-258afb87070e)]
|
||||
[scriptable, uuid(020deb5a-cba6-41dd-8551-72a880d01970)]
|
||||
interface nsIDOMWindowUtils : nsISupports {
|
||||
|
||||
/**
|
||||
@ -213,7 +213,8 @@ interface nsIDOMWindowUtils : nsISupports {
|
||||
const long MODIFIER_OS = 0x0400;
|
||||
|
||||
/** Synthesize a mouse event. The event types supported are:
|
||||
* mousedown, mouseup, mousemove, mouseover, mouseout, contextmenu
|
||||
* mousedown, mouseup, mousemove, mouseover, mouseout, contextmenu,
|
||||
* MozMouseHitTest
|
||||
*
|
||||
* Events are sent in coordinates offset by aX and aY from the window.
|
||||
*
|
||||
@ -244,16 +245,18 @@ interface nsIDOMWindowUtils : nsISupports {
|
||||
* @param aPressure touch input pressure: 0.0 -> 1.0
|
||||
* @param aInputSourceArg input source, see nsIDOMMouseEvent for values,
|
||||
* defaults to mouse input.
|
||||
*
|
||||
* returns true if the page called prevent default on this event
|
||||
*/
|
||||
void sendMouseEvent(in AString aType,
|
||||
in float aX,
|
||||
in float aY,
|
||||
in long aButton,
|
||||
in long aClickCount,
|
||||
in long aModifiers,
|
||||
[optional] in boolean aIgnoreRootScrollFrame,
|
||||
[optional] in float aPressure,
|
||||
[optional] in unsigned short aInputSourceArg);
|
||||
boolean sendMouseEvent(in AString aType,
|
||||
in float aX,
|
||||
in float aY,
|
||||
in long aButton,
|
||||
in long aClickCount,
|
||||
in long aModifiers,
|
||||
[optional] in boolean aIgnoreRootScrollFrame,
|
||||
[optional] in float aPressure,
|
||||
[optional] in unsigned short aInputSourceArg);
|
||||
|
||||
/** Synthesize a touch event. The event types supported are:
|
||||
* touchstart, touchend, touchmove, and touchcancel
|
||||
|
@ -133,8 +133,13 @@ TabChild::PreloadSlowThings()
|
||||
!tab->InitTabChildGlobal(DONT_LOAD_SCRIPTS)) {
|
||||
return;
|
||||
}
|
||||
// Just load and compile these scripts, but don't run them.
|
||||
tab->TryCacheLoadAndCompileScript(BROWSER_ELEMENT_CHILD_SCRIPT);
|
||||
tab->RecvLoadRemoteScript(NS_LITERAL_STRING("chrome://global/content/preload.js"));
|
||||
tab->TryCacheLoadAndCompileScript(
|
||||
NS_LITERAL_STRING("chrome://browser/content/forms.js"));
|
||||
// Load, compile, and run these scripts.
|
||||
tab->RecvLoadRemoteScript(
|
||||
NS_LITERAL_STRING("chrome://global/content/preload.js"));
|
||||
|
||||
nsCOMPtr<nsIDocShell> docShell = do_GetInterface(tab->mWebNav);
|
||||
nsCOMPtr<nsIPresShell> presShell;
|
||||
@ -1359,8 +1364,9 @@ TabChild::RecvMouseEvent(const nsString& aType,
|
||||
{
|
||||
nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils());
|
||||
NS_ENSURE_TRUE(utils, true);
|
||||
bool ignored = false;
|
||||
utils->SendMouseEvent(aType, aX, aY, aButton, aClickCount, aModifiers,
|
||||
aIgnoreRootScrollFrame, 0, 0);
|
||||
aIgnoreRootScrollFrame, 0, 0, &ignored);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -28,6 +28,10 @@
|
||||
Cu.import("resource://gre/modules/SettingsDB.jsm");
|
||||
Cu.import("resource://gre/modules/SettingsQueue.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
if (Services.prefs.getBoolPref("general.useragent.enable_overrides")) {
|
||||
Cu.import('resource://gre/modules/UserAgentOverrides.jsm');
|
||||
UserAgentOverrides.init();
|
||||
}
|
||||
|
||||
Cc["@mozilla.org/appshell/appShellService;1"].getService(Ci["nsIAppShellService"]);
|
||||
Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci["nsIWindowMediator"]);
|
||||
@ -70,6 +74,8 @@
|
||||
Cc["@mozilla.org/toolkit/app-startup;1"].getService(Ci["nsIAppStartup"]);
|
||||
Cc["@mozilla.org/uriloader;1"].getService(Ci["nsIURILoader"]);
|
||||
|
||||
Services.io.getProtocolHandler("app");
|
||||
|
||||
docShell.isActive = false;
|
||||
docShell.createAboutBlankContentViewer(null);
|
||||
|
||||
|
@ -2775,7 +2775,7 @@ RILNetworkInterface.prototype = {
|
||||
classInfo: XPCOMUtils.generateCI({classID: RILNETWORKINTERFACE_CID,
|
||||
classDescription: "RILNetworkInterface",
|
||||
interfaces: [Ci.nsINetworkInterface,
|
||||
Ci.nsIRIODataCallback]}),
|
||||
Ci.nsIRILDataCallback]}),
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkInterface,
|
||||
Ci.nsIRILDataCallback]),
|
||||
|
||||
|
@ -32,6 +32,7 @@ CPPSRCS = \
|
||||
Principal.cpp \
|
||||
RuntimeService.cpp \
|
||||
ScriptLoader.cpp \
|
||||
URL.cpp \
|
||||
TextDecoder.cpp \
|
||||
TextEncoder.cpp \
|
||||
Worker.cpp \
|
||||
@ -56,6 +57,7 @@ EXPORTS_mozilla/dom/workers/bindings = \
|
||||
EventListenerManager.h \
|
||||
EventTarget.h \
|
||||
FileReaderSync.h \
|
||||
URL.h \
|
||||
TextDecoder.h \
|
||||
TextEncoder.h \
|
||||
WorkerFeature.h \
|
||||
|
233
dom/workers/URL.cpp
Normal file
233
dom/workers/URL.cpp
Normal file
@ -0,0 +1,233 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* 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 "URL.h"
|
||||
#include "File.h"
|
||||
|
||||
#include "nsTraceRefcnt.h"
|
||||
|
||||
#include "WorkerPrivate.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsGlobalWindow.h"
|
||||
#include "nsHostObjectProtocolHandler.h"
|
||||
|
||||
#include "nsIDOMFile.h"
|
||||
|
||||
USING_WORKERS_NAMESPACE
|
||||
using mozilla::dom::WorkerGlobalObject;
|
||||
|
||||
// Base class for the Revoke and Create runnable objects.
|
||||
class URLRunnable : public nsRunnable
|
||||
{
|
||||
protected:
|
||||
WorkerPrivate* mWorkerPrivate;
|
||||
uint32_t mSyncQueueKey;
|
||||
|
||||
private:
|
||||
class ResponseRunnable : public WorkerSyncRunnable
|
||||
{
|
||||
uint32_t mSyncQueueKey;
|
||||
|
||||
public:
|
||||
ResponseRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
uint32_t aSyncQueueKey)
|
||||
: WorkerSyncRunnable(aWorkerPrivate, aSyncQueueKey, false),
|
||||
mSyncQueueKey(aSyncQueueKey)
|
||||
{
|
||||
NS_ASSERTION(aWorkerPrivate, "Don't hand me a null WorkerPrivate!");
|
||||
}
|
||||
|
||||
bool
|
||||
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
|
||||
{
|
||||
aWorkerPrivate->StopSyncLoop(mSyncQueueKey, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
PreDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
PostDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
|
||||
bool aDispatchResult)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
}
|
||||
};
|
||||
|
||||
protected:
|
||||
URLRunnable(WorkerPrivate* aWorkerPrivate)
|
||||
: mWorkerPrivate(aWorkerPrivate)
|
||||
{
|
||||
mWorkerPrivate->AssertIsOnWorkerThread();
|
||||
}
|
||||
|
||||
public:
|
||||
bool
|
||||
Dispatch(JSContext* aCx)
|
||||
{
|
||||
mWorkerPrivate->AssertIsOnWorkerThread();
|
||||
mSyncQueueKey = mWorkerPrivate->CreateNewSyncLoop();
|
||||
|
||||
if (NS_FAILED(NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL))) {
|
||||
JS_ReportError(aCx, "Failed to dispatch to main thread!");
|
||||
mWorkerPrivate->StopSyncLoop(mSyncQueueKey, false);
|
||||
return false;
|
||||
}
|
||||
|
||||
return mWorkerPrivate->RunSyncLoop(aCx, mSyncQueueKey);
|
||||
}
|
||||
|
||||
private:
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
MainThreadRun();
|
||||
|
||||
nsRefPtr<ResponseRunnable> response =
|
||||
new ResponseRunnable(mWorkerPrivate, mSyncQueueKey);
|
||||
if (!response->Dispatch(nullptr)) {
|
||||
NS_WARNING("Failed to dispatch response!");
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void
|
||||
MainThreadRun() = 0;
|
||||
};
|
||||
|
||||
// This class creates an URL from a DOM Blob on the main thread.
|
||||
class CreateURLRunnable : public URLRunnable
|
||||
{
|
||||
private:
|
||||
nsIDOMBlob* mBlob;
|
||||
nsString& mURL;
|
||||
|
||||
public:
|
||||
CreateURLRunnable(WorkerPrivate* aWorkerPrivate, nsIDOMBlob* aBlob,
|
||||
const mozilla::dom::objectURLOptionsWorkers& aOptions,
|
||||
nsString& aURL)
|
||||
: URLRunnable(aWorkerPrivate),
|
||||
mBlob(aBlob),
|
||||
mURL(aURL)
|
||||
{
|
||||
MOZ_ASSERT(aBlob);
|
||||
}
|
||||
|
||||
void
|
||||
MainThreadRun()
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> window = mWorkerPrivate->GetWindow();
|
||||
nsIDocument* doc = window->GetExtantDoc();
|
||||
if (!doc) {
|
||||
SetDOMStringToNull(mURL);
|
||||
return;
|
||||
}
|
||||
|
||||
nsCString url;
|
||||
nsresult rv = nsHostObjectProtocolHandler::AddDataEntry(
|
||||
NS_LITERAL_CSTRING(BLOBURI_SCHEME),
|
||||
mBlob, doc->NodePrincipal(), url);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Failed to add data entry for the blob!");
|
||||
SetDOMStringToNull(mURL);
|
||||
return;
|
||||
}
|
||||
|
||||
doc->RegisterHostObjectUri(url);
|
||||
mURL = NS_ConvertUTF8toUTF16(url);
|
||||
}
|
||||
};
|
||||
|
||||
// This class revokes an URL on the main thread.
|
||||
class RevokeURLRunnable : public URLRunnable
|
||||
{
|
||||
private:
|
||||
const nsString mURL;
|
||||
|
||||
public:
|
||||
RevokeURLRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
const nsAString& aURL)
|
||||
: URLRunnable(aWorkerPrivate),
|
||||
mURL(aURL)
|
||||
{}
|
||||
|
||||
void
|
||||
MainThreadRun()
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> window = mWorkerPrivate->GetWindow();
|
||||
nsIDocument* doc = window->GetExtantDoc();
|
||||
if (!doc) {
|
||||
return;
|
||||
}
|
||||
|
||||
NS_ConvertUTF16toUTF8 url(mURL);
|
||||
|
||||
nsIPrincipal* principal =
|
||||
nsHostObjectProtocolHandler::GetDataEntryPrincipal(url);
|
||||
|
||||
bool subsumes;
|
||||
if (principal &&
|
||||
NS_SUCCEEDED(doc->NodePrincipal()->Subsumes(principal, &subsumes)) &&
|
||||
subsumes) {
|
||||
doc->UnregisterHostObjectUri(url);
|
||||
nsHostObjectProtocolHandler::RemoveDataEntry(url);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// static
|
||||
void
|
||||
URL::CreateObjectURL(const WorkerGlobalObject& aGlobal, JSObject* aBlob,
|
||||
const mozilla::dom::objectURLOptionsWorkers& aOptions,
|
||||
nsString& aResult, mozilla::ErrorResult& aRv)
|
||||
{
|
||||
JSContext* cx = aGlobal.GetContext();
|
||||
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(cx);
|
||||
|
||||
nsCOMPtr<nsIDOMBlob> blob = file::GetDOMBlobFromJSObject(aBlob);
|
||||
if (!blob) {
|
||||
SetDOMStringToNull(aResult);
|
||||
aRv.Throw(NS_ERROR_TYPE_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<CreateURLRunnable> runnable =
|
||||
new CreateURLRunnable(workerPrivate, blob, aOptions, aResult);
|
||||
|
||||
if (!runnable->Dispatch(cx)) {
|
||||
JS_ReportPendingException(cx);
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
URL::RevokeObjectURL(const WorkerGlobalObject& aGlobal, const nsAString& aUrl)
|
||||
{
|
||||
JSContext* cx = aGlobal.GetContext();
|
||||
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(cx);
|
||||
|
||||
nsRefPtr<RevokeURLRunnable> runnable =
|
||||
new RevokeURLRunnable(workerPrivate, aUrl);
|
||||
|
||||
if (!runnable->Dispatch(cx)) {
|
||||
JS_ReportPendingException(cx);
|
||||
}
|
||||
}
|
||||
|
30
dom/workers/URL.h
Normal file
30
dom/workers/URL.h
Normal file
@ -0,0 +1,30 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* 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
|
||||
* url, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_workers_url_h__
|
||||
#define mozilla_dom_workers_url_h__
|
||||
|
||||
#include "mozilla/dom/URLBinding.h"
|
||||
|
||||
#include "EventTarget.h"
|
||||
|
||||
BEGIN_WORKERS_NAMESPACE
|
||||
|
||||
class URL : public EventTarget
|
||||
{
|
||||
public: // Methods for WebIDL
|
||||
static void
|
||||
CreateObjectURL(const WorkerGlobalObject& aGlobal,
|
||||
JSObject* aArg, const objectURLOptionsWorkers& aOptions,
|
||||
nsString& aResult, ErrorResult& aRv);
|
||||
|
||||
static void
|
||||
RevokeObjectURL(const WorkerGlobalObject& aGlobal, const nsAString& aUrl);
|
||||
};
|
||||
|
||||
END_WORKERS_NAMESPACE
|
||||
|
||||
#endif /* mozilla_dom_workers_url_h__ */
|
@ -17,6 +17,7 @@
|
||||
#include "mozilla/dom/TextEncoderBinding.h"
|
||||
#include "mozilla/dom/XMLHttpRequestBinding.h"
|
||||
#include "mozilla/dom/XMLHttpRequestUploadBinding.h"
|
||||
#include "mozilla/dom/URLBinding.h"
|
||||
#include "mozilla/OSFileConstants.h"
|
||||
#include "nsTraceRefcnt.h"
|
||||
#include "xpcpublic.h"
|
||||
@ -986,7 +987,8 @@ CreateDedicatedWorkerGlobalScope(JSContext* aCx)
|
||||
!TextDecoderBinding_workers::GetConstructorObject(aCx, global) ||
|
||||
!TextEncoderBinding_workers::GetConstructorObject(aCx, global) ||
|
||||
!XMLHttpRequestBinding_workers::GetConstructorObject(aCx, global) ||
|
||||
!XMLHttpRequestUploadBinding_workers::GetConstructorObject(aCx, global)) {
|
||||
!XMLHttpRequestUploadBinding_workers::GetConstructorObject(aCx, global) ||
|
||||
!URLBinding_workers::GetConstructorObject(aCx, global)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -108,6 +108,8 @@ MOCHITEST_FILES = \
|
||||
errorwarning_worker.js \
|
||||
test_contentWorker.html \
|
||||
content_worker.js \
|
||||
test_url.html \
|
||||
url_worker.js \
|
||||
$(NULL)
|
||||
|
||||
_SUBDIRMOCHITEST_FILES = \
|
||||
|
53
dom/workers/test/test_url.html
Normal file
53
dom/workers/test/test_url.html
Normal file
@ -0,0 +1,53 @@
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for URL object in workers</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test"></pre>
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
var worker = new Worker("url_worker.js");
|
||||
|
||||
worker.onmessage = function(event) {
|
||||
is(event.target, worker);
|
||||
|
||||
if (event.data.type == 'finish') {
|
||||
SimpleTest.finish();
|
||||
} else if (event.data.type == 'status') {
|
||||
ok(event.data.status, event.data.msg);
|
||||
} else if (event.data.type == 'url') {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', event.data.url, false);
|
||||
xhr.onreadystatechange = function() {
|
||||
if (xhr.readyState == 4) {
|
||||
ok(true, "Blob readable!");
|
||||
}
|
||||
}
|
||||
xhr.send();
|
||||
}
|
||||
};
|
||||
|
||||
worker.onerror = function(event) {
|
||||
is(event.target, worker);
|
||||
ok(false, "Worker had an error: " + event.data);
|
||||
SimpleTest.finish();
|
||||
};
|
||||
|
||||
worker.postMessage(true);
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
63
dom/workers/test/url_worker.js
Normal file
63
dom/workers/test/url_worker.js
Normal file
@ -0,0 +1,63 @@
|
||||
onmessage = function() {
|
||||
status = false;
|
||||
try {
|
||||
if ((URL instanceof Object)) {
|
||||
status = true;
|
||||
}
|
||||
} catch(e) {
|
||||
}
|
||||
|
||||
postMessage({type: 'status', status: status, msg: 'URL object:' + URL});
|
||||
|
||||
status = false;
|
||||
var blob = null;
|
||||
try {
|
||||
blob = new Blob([]);
|
||||
status = true;
|
||||
} catch(e) {
|
||||
}
|
||||
|
||||
postMessage({type: 'status', status: status, msg: 'Blob:' + blob});
|
||||
|
||||
status = false;
|
||||
var url = null;
|
||||
try {
|
||||
url = URL.createObjectURL(blob);
|
||||
status = true;
|
||||
} catch(e) {
|
||||
}
|
||||
|
||||
postMessage({type: 'status', status: status, msg: 'Blob URL:' + url});
|
||||
|
||||
status = false;
|
||||
try {
|
||||
URL.revokeObjectURL(url);
|
||||
status = true;
|
||||
} catch(e) {
|
||||
}
|
||||
|
||||
postMessage({type: 'status', status: status, msg: 'Blob Revoke URL'});
|
||||
|
||||
status = false;
|
||||
var url = null;
|
||||
try {
|
||||
url = URL.createObjectURL(true);
|
||||
} catch(e) {
|
||||
status = true;
|
||||
}
|
||||
|
||||
postMessage({type: 'status', status: status, msg: 'CreateObjectURL should fail if the arg is not a blob'});
|
||||
|
||||
status = false;
|
||||
var url = null;
|
||||
try {
|
||||
url = URL.createObjectURL(blob);
|
||||
status = true;
|
||||
} catch(e) {
|
||||
}
|
||||
|
||||
postMessage({type: 'status', status: status, msg: 'Blob URL2:' + url});
|
||||
postMessage({type: 'url', url: url});
|
||||
|
||||
postMessage({type: 'finish' });
|
||||
}
|
@ -12,6 +12,7 @@ TransGaming Inc.
|
||||
3DLabs Inc. Ltd.
|
||||
|
||||
Adobe Systems Inc.
|
||||
Apple Inc.
|
||||
Autodesk, Inc.
|
||||
Cloud Party, Inc.
|
||||
Intel Corporation
|
||||
|
@ -56,6 +56,7 @@ DEFINES += -DCOMPILER_IMPLEMENTATION
|
||||
VPATH += $(srcdir)/src/compiler
|
||||
# src/compiler:
|
||||
CPPSRCS += \
|
||||
ArrayBoundsClamper.cpp \
|
||||
BuiltInFunctionEmulator.cpp \
|
||||
Compiler.cpp \
|
||||
compiler_debug.cpp \
|
||||
|
@ -26,6 +26,10 @@ In this order:
|
||||
Adds emulation for faceforward(float,float,float), which is needed to
|
||||
prevent crashing on Mac+Intel. See bug 771406.
|
||||
|
||||
angle-r1638.patch
|
||||
Adds uniform array index clamping on non-Windows platforms.
|
||||
Windows would require r1719, r1733, r1734.
|
||||
|
||||
In addition to these patches, the Makefile.in files are ours, they're not present in
|
||||
upsteam ANGLE. Therefore, changes made to the Makefile.in files should not be stored
|
||||
in the local .patch files.
|
||||
|
475
gfx/angle/angle-r1638.patch
Normal file
475
gfx/angle/angle-r1638.patch
Normal file
@ -0,0 +1,475 @@
|
||||
# HG changeset patch
|
||||
# Parent faf255e4400222ee23c29ddcc76fb3dce56145f4
|
||||
|
||||
diff --git a/gfx/angle/AUTHORS b/gfx/angle/AUTHORS
|
||||
--- a/gfx/angle/AUTHORS
|
||||
+++ b/gfx/angle/AUTHORS
|
||||
@@ -7,16 +7,17 @@
|
||||
# Name or Organization
|
||||
# Email addresses for individuals are tracked elsewhere to avoid spam.
|
||||
|
||||
Google Inc.
|
||||
TransGaming Inc.
|
||||
3DLabs Inc. Ltd.
|
||||
|
||||
Adobe Systems Inc.
|
||||
+Apple Inc.
|
||||
Autodesk, Inc.
|
||||
Cloud Party, Inc.
|
||||
Intel Corporation
|
||||
Mozilla Corporation
|
||||
Turbulenz
|
||||
Klarälvdalens Datakonsult AB
|
||||
|
||||
Jacek Caban
|
||||
diff --git a/gfx/angle/Makefile.in b/gfx/angle/Makefile.in
|
||||
--- a/gfx/angle/Makefile.in
|
||||
+++ b/gfx/angle/Makefile.in
|
||||
@@ -51,16 +51,17 @@ LOCAL_INCLUDES += \
|
||||
-I$(srcdir)/include/KHR \
|
||||
-I$(srcdir)/src
|
||||
|
||||
DEFINES += -DCOMPILER_IMPLEMENTATION
|
||||
|
||||
VPATH += $(srcdir)/src/compiler
|
||||
# src/compiler:
|
||||
CPPSRCS += \
|
||||
+ ArrayBoundsClamper.cpp \
|
||||
BuiltInFunctionEmulator.cpp \
|
||||
Compiler.cpp \
|
||||
compiler_debug.cpp \
|
||||
DetectRecursion.cpp \
|
||||
Diagnostics.cpp \
|
||||
DirectiveHandler.cpp \
|
||||
ForLoopUnroll.cpp \
|
||||
glslang_lex.cpp \
|
||||
diff --git a/gfx/angle/README.mozilla b/gfx/angle/README.mozilla
|
||||
--- a/gfx/angle/README.mozilla
|
||||
+++ b/gfx/angle/README.mozilla
|
||||
@@ -21,16 +21,20 @@ In this order:
|
||||
|
||||
angle-long-ident-spooky-hash.patch:
|
||||
Use Spooky Hash for long identifier hashing. See bug 676071.
|
||||
|
||||
angle-faceforward-emu.patch:
|
||||
Adds emulation for faceforward(float,float,float), which is needed to
|
||||
prevent crashing on Mac+Intel. See bug 771406.
|
||||
|
||||
+ angle-r1638.patch
|
||||
+ Adds uniform array index clamping on non-Windows platforms.
|
||||
+ Windows would require r1719, r1733, r1734.
|
||||
+
|
||||
In addition to these patches, the Makefile.in files are ours, they're not present in
|
||||
upsteam ANGLE. Therefore, changes made to the Makefile.in files should not be stored
|
||||
in the local .patch files.
|
||||
|
||||
|
||||
== How to do a clean-slate upgrade ==
|
||||
1. Backup our moz-specific files:
|
||||
README.mozilla
|
||||
diff --git a/gfx/angle/include/GLSLANG/ShaderLang.h b/gfx/angle/include/GLSLANG/ShaderLang.h
|
||||
--- a/gfx/angle/include/GLSLANG/ShaderLang.h
|
||||
+++ b/gfx/angle/include/GLSLANG/ShaderLang.h
|
||||
@@ -145,17 +145,23 @@ typedef enum {
|
||||
// restrictions on fragment shaders.
|
||||
// This flag only has an effect if all of the following are true:
|
||||
// - The shader spec is SH_WEBGL_SPEC.
|
||||
// - The compile options contain the SH_TIMING_RESTRICTIONS flag.
|
||||
// - The shader type is SH_FRAGMENT_SHADER.
|
||||
SH_DEPENDENCY_GRAPH = 0x0400,
|
||||
|
||||
// Enforce the GLSL 1.017 Appendix A section 7 packing restrictions.
|
||||
- SH_ENFORCE_PACKING_RESTRICTIONS = 0x0800
|
||||
+ SH_ENFORCE_PACKING_RESTRICTIONS = 0x0800,
|
||||
+
|
||||
+ // This flag ensures all indirect (expression-based) array indexing
|
||||
+ // is clamped to the bounds of the array. This ensures, for example,
|
||||
+ // that you cannot read off the end of a uniform, whether an array
|
||||
+ // vec234, or mat234 type.
|
||||
+ SH_CLAMP_INDIRECT_ARRAY_BOUNDS = 0x1000
|
||||
} ShCompileOptions;
|
||||
|
||||
//
|
||||
// Driver must call this first, once, before doing any other
|
||||
// compiler operations.
|
||||
// If the function succeeds, the return value is nonzero, else zero.
|
||||
//
|
||||
COMPILER_EXPORT int ShInitialize();
|
||||
diff --git a/gfx/angle/src/build_angle.gypi b/gfx/angle/src/build_angle.gypi
|
||||
--- a/gfx/angle/src/build_angle.gypi
|
||||
+++ b/gfx/angle/src/build_angle.gypi
|
||||
@@ -54,16 +54,18 @@
|
||||
'include_dirs': [
|
||||
'.',
|
||||
'../include',
|
||||
],
|
||||
'defines': [
|
||||
'COMPILER_IMPLEMENTATION',
|
||||
],
|
||||
'sources': [
|
||||
+ 'compiler/ArrayBoundsClamper.cpp',
|
||||
+ 'compiler/ArrayBoundsClamper.h',
|
||||
'compiler/BaseTypes.h',
|
||||
'compiler/BuiltInFunctionEmulator.cpp',
|
||||
'compiler/BuiltInFunctionEmulator.h',
|
||||
'compiler/Common.h',
|
||||
'compiler/Compiler.cpp',
|
||||
'compiler/ConstantUnion.h',
|
||||
'compiler/debug.cpp',
|
||||
'compiler/debug.h',
|
||||
diff --git a/gfx/angle/src/compiler/Compiler.cpp b/gfx/angle/src/compiler/Compiler.cpp
|
||||
--- a/gfx/angle/src/compiler/Compiler.cpp
|
||||
+++ b/gfx/angle/src/compiler/Compiler.cpp
|
||||
@@ -1,14 +1,15 @@
|
||||
//
|
||||
// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
|
||||
+#include "compiler/ArrayBoundsClamper.h"
|
||||
#include "compiler/BuiltInFunctionEmulator.h"
|
||||
#include "compiler/DetectRecursion.h"
|
||||
#include "compiler/ForLoopUnroll.h"
|
||||
#include "compiler/Initialize.h"
|
||||
#include "compiler/InitializeParseContext.h"
|
||||
#include "compiler/MapLongVariableNames.h"
|
||||
#include "compiler/ParseHelper.h"
|
||||
#include "compiler/RenameFunction.h"
|
||||
@@ -187,16 +188,20 @@ bool TCompiler::compile(const char* cons
|
||||
// Unroll for-loop markup needs to happen after validateLimitations pass.
|
||||
if (success && (compileOptions & SH_UNROLL_FOR_LOOP_WITH_INTEGER_INDEX))
|
||||
ForLoopUnroll::MarkForLoopsWithIntegerIndicesForUnrolling(root);
|
||||
|
||||
// Built-in function emulation needs to happen after validateLimitations pass.
|
||||
if (success && (compileOptions & SH_EMULATE_BUILT_IN_FUNCTIONS))
|
||||
builtInFunctionEmulator.MarkBuiltInFunctionsForEmulation(root);
|
||||
|
||||
+ // Clamping uniform array bounds needs to happen after validateLimitations pass.
|
||||
+ if (success && (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS))
|
||||
+ arrayBoundsClamper.MarkIndirectArrayBoundsForClamping(root);
|
||||
+
|
||||
// Call mapLongVariableNames() before collectAttribsUniforms() so in
|
||||
// collectAttribsUniforms() we already have the mapped symbol names and
|
||||
// we could composite mapped and original variable names.
|
||||
// Also, if we hash all the names, then no need to do this for long names.
|
||||
if (success && (compileOptions & SH_MAP_LONG_VARIABLE_NAMES) && hashFunction == NULL)
|
||||
mapLongVariableNames(root);
|
||||
|
||||
if (success && (compileOptions & SH_ATTRIBUTES_UNIFORMS)) {
|
||||
@@ -232,16 +237,17 @@ bool TCompiler::InitBuiltInSymbolTable(c
|
||||
|
||||
builtIns.initialize(shaderType, shaderSpec, resources);
|
||||
return InitializeSymbolTable(builtIns.getBuiltInStrings(),
|
||||
shaderType, shaderSpec, resources, infoSink, symbolTable);
|
||||
}
|
||||
|
||||
void TCompiler::clearResults()
|
||||
{
|
||||
+ arrayBoundsClamper.Cleanup();
|
||||
infoSink.info.erase();
|
||||
infoSink.obj.erase();
|
||||
infoSink.debug.erase();
|
||||
|
||||
attribs.clear();
|
||||
uniforms.clear();
|
||||
|
||||
builtInFunctionEmulator.Cleanup();
|
||||
@@ -348,8 +354,14 @@ const TExtensionBehavior& TCompiler::get
|
||||
{
|
||||
return extensionBehavior;
|
||||
}
|
||||
|
||||
const BuiltInFunctionEmulator& TCompiler::getBuiltInFunctionEmulator() const
|
||||
{
|
||||
return builtInFunctionEmulator;
|
||||
}
|
||||
+
|
||||
+const ArrayBoundsClamper& TCompiler::getArrayBoundsClamper() const
|
||||
+{
|
||||
+ return arrayBoundsClamper;
|
||||
+}
|
||||
+
|
||||
diff --git a/gfx/angle/src/compiler/OutputGLSLBase.cpp b/gfx/angle/src/compiler/OutputGLSLBase.cpp
|
||||
--- a/gfx/angle/src/compiler/OutputGLSLBase.cpp
|
||||
+++ b/gfx/angle/src/compiler/OutputGLSLBase.cpp
|
||||
@@ -207,18 +207,47 @@ bool TOutputGLSLBase::visitBinary(Visit
|
||||
case EOpVectorTimesMatrixAssign:
|
||||
case EOpVectorTimesScalarAssign:
|
||||
case EOpMatrixTimesScalarAssign:
|
||||
case EOpMatrixTimesMatrixAssign:
|
||||
writeTriplet(visit, "(", " *= ", ")");
|
||||
break;
|
||||
|
||||
case EOpIndexDirect:
|
||||
+ writeTriplet(visit, NULL, "[", "]");
|
||||
+ break;
|
||||
case EOpIndexIndirect:
|
||||
- writeTriplet(visit, NULL, "[", "]");
|
||||
+ if (node->getAddIndexClamp())
|
||||
+ {
|
||||
+ if (visit == InVisit)
|
||||
+ {
|
||||
+ out << "[webgl_int_clamp(";
|
||||
+ }
|
||||
+ else if (visit == PostVisit)
|
||||
+ {
|
||||
+ int maxSize;
|
||||
+ TIntermTyped *left = node->getLeft();
|
||||
+ TType leftType = left->getType();
|
||||
+
|
||||
+ if (left->isArray())
|
||||
+ {
|
||||
+ // The shader will fail validation if the array length is not > 0.
|
||||
+ maxSize = leftType.getArraySize() - 1;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ maxSize = leftType.getNominalSize() - 1;
|
||||
+ }
|
||||
+ out << ", 0, " << maxSize << ")]";
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ writeTriplet(visit, NULL, "[", "]");
|
||||
+ }
|
||||
break;
|
||||
case EOpIndexDirectStruct:
|
||||
if (visit == InVisit)
|
||||
{
|
||||
out << ".";
|
||||
// TODO(alokp): ASSERT
|
||||
out << hashName(node->getType().getFieldName());
|
||||
visitChildren = false;
|
||||
diff --git a/gfx/angle/src/compiler/ShHandle.h b/gfx/angle/src/compiler/ShHandle.h
|
||||
--- a/gfx/angle/src/compiler/ShHandle.h
|
||||
+++ b/gfx/angle/src/compiler/ShHandle.h
|
||||
@@ -11,16 +11,17 @@
|
||||
// Machine independent part of the compiler private objects
|
||||
// sent as ShHandle to the driver.
|
||||
//
|
||||
// This should not be included by driver code.
|
||||
//
|
||||
|
||||
#include "GLSLANG/ShaderLang.h"
|
||||
|
||||
+#include "compiler/ArrayBoundsClamper.h"
|
||||
#include "compiler/BuiltInFunctionEmulator.h"
|
||||
#include "compiler/ExtensionBehavior.h"
|
||||
#include "compiler/HashNames.h"
|
||||
#include "compiler/InfoSink.h"
|
||||
#include "compiler/SymbolTable.h"
|
||||
#include "compiler/VariableInfo.h"
|
||||
|
||||
class LongNameMap;
|
||||
@@ -101,30 +102,32 @@ protected:
|
||||
// Returns true if the shader does not use samplers.
|
||||
bool enforceVertexShaderTimingRestrictions(TIntermNode* root);
|
||||
// Returns true if the shader does not use sampler dependent values to affect control
|
||||
// flow or in operations whose time can depend on the input values.
|
||||
bool enforceFragmentShaderTimingRestrictions(const TDependencyGraph& graph);
|
||||
// Get built-in extensions with default behavior.
|
||||
const TExtensionBehavior& getExtensionBehavior() const;
|
||||
|
||||
+ const ArrayBoundsClamper& getArrayBoundsClamper() const;
|
||||
const BuiltInFunctionEmulator& getBuiltInFunctionEmulator() const;
|
||||
|
||||
private:
|
||||
ShShaderType shaderType;
|
||||
ShShaderSpec shaderSpec;
|
||||
|
||||
int maxUniformVectors;
|
||||
|
||||
// Built-in symbol table for the given language, spec, and resources.
|
||||
// It is preserved from compile-to-compile.
|
||||
TSymbolTable symbolTable;
|
||||
// Built-in extensions with default behavior.
|
||||
TExtensionBehavior extensionBehavior;
|
||||
|
||||
+ ArrayBoundsClamper arrayBoundsClamper;
|
||||
BuiltInFunctionEmulator builtInFunctionEmulator;
|
||||
|
||||
// Results of compilation.
|
||||
TInfoSink infoSink; // Output sink.
|
||||
TVariableInfoList attribs; // Active attributes in the compiled shader.
|
||||
TVariableInfoList uniforms; // Active uniforms in the compiled shader.
|
||||
|
||||
// Cached copy of the ref-counted singleton.
|
||||
diff --git a/gfx/angle/src/compiler/TranslatorESSL.cpp b/gfx/angle/src/compiler/TranslatorESSL.cpp
|
||||
--- a/gfx/angle/src/compiler/TranslatorESSL.cpp
|
||||
+++ b/gfx/angle/src/compiler/TranslatorESSL.cpp
|
||||
@@ -17,16 +17,19 @@ void TranslatorESSL::translate(TIntermNo
|
||||
|
||||
// Write built-in extension behaviors.
|
||||
writeExtensionBehavior();
|
||||
|
||||
// Write emulated built-in functions if needed.
|
||||
getBuiltInFunctionEmulator().OutputEmulatedFunctionDefinition(
|
||||
sink, getShaderType() == SH_FRAGMENT_SHADER);
|
||||
|
||||
+ // Write array bounds clamping emulation if needed.
|
||||
+ getArrayBoundsClamper().OutputClampingFunctionDefinition(sink);
|
||||
+
|
||||
// Write translated shader.
|
||||
TOutputESSL outputESSL(sink, getHashFunction(), getNameMap(), getSymbolTable());
|
||||
root->traverse(&outputESSL);
|
||||
}
|
||||
|
||||
void TranslatorESSL::writeExtensionBehavior() {
|
||||
TInfoSinkBase& sink = getInfoSink().obj;
|
||||
const TExtensionBehavior& extensionBehavior = getExtensionBehavior();
|
||||
diff --git a/gfx/angle/src/compiler/TranslatorGLSL.cpp b/gfx/angle/src/compiler/TranslatorGLSL.cpp
|
||||
--- a/gfx/angle/src/compiler/TranslatorGLSL.cpp
|
||||
+++ b/gfx/angle/src/compiler/TranslatorGLSL.cpp
|
||||
@@ -30,12 +30,15 @@ void TranslatorGLSL::translate(TIntermNo
|
||||
|
||||
// Write GLSL version.
|
||||
writeVersion(getShaderType(), root, sink);
|
||||
|
||||
// Write emulated built-in functions if needed.
|
||||
getBuiltInFunctionEmulator().OutputEmulatedFunctionDefinition(
|
||||
sink, false);
|
||||
|
||||
+ // Write array bounds clamping emulation if needed.
|
||||
+ getArrayBoundsClamper().OutputClampingFunctionDefinition(sink);
|
||||
+
|
||||
// Write translated shader.
|
||||
TOutputGLSL outputGLSL(sink, getHashFunction(), getNameMap(), getSymbolTable());
|
||||
root->traverse(&outputGLSL);
|
||||
}
|
||||
diff --git a/gfx/angle/src/compiler/intermOut.cpp b/gfx/angle/src/compiler/intermOut.cpp
|
||||
--- a/gfx/angle/src/compiler/intermOut.cpp
|
||||
+++ b/gfx/angle/src/compiler/intermOut.cpp
|
||||
@@ -37,17 +37,17 @@ protected:
|
||||
|
||||
TString TType::getCompleteString() const
|
||||
{
|
||||
TStringStream stream;
|
||||
|
||||
if (qualifier != EvqTemporary && qualifier != EvqGlobal)
|
||||
stream << getQualifierString() << " " << getPrecisionString() << " ";
|
||||
if (array)
|
||||
- stream << "array of ";
|
||||
+ stream << "array[" << getArraySize() << "] of ";
|
||||
if (matrix)
|
||||
stream << size << "X" << size << " matrix of ";
|
||||
else if (size > 1)
|
||||
stream << size << "-component vector of ";
|
||||
|
||||
stream << getBasicString();
|
||||
return stream.str();
|
||||
}
|
||||
diff --git a/gfx/angle/src/compiler/intermediate.h b/gfx/angle/src/compiler/intermediate.h
|
||||
--- a/gfx/angle/src/compiler/intermediate.h
|
||||
+++ b/gfx/angle/src/compiler/intermediate.h
|
||||
@@ -386,30 +386,36 @@ protected:
|
||||
TOperator op;
|
||||
};
|
||||
|
||||
//
|
||||
// Nodes for all the basic binary math operators.
|
||||
//
|
||||
class TIntermBinary : public TIntermOperator {
|
||||
public:
|
||||
- TIntermBinary(TOperator o) : TIntermOperator(o) {}
|
||||
+ TIntermBinary(TOperator o) : TIntermOperator(o), addIndexClamp(false) {}
|
||||
|
||||
virtual TIntermBinary* getAsBinaryNode() { return this; }
|
||||
virtual void traverse(TIntermTraverser*);
|
||||
|
||||
void setLeft(TIntermTyped* n) { left = n; }
|
||||
void setRight(TIntermTyped* n) { right = n; }
|
||||
TIntermTyped* getLeft() const { return left; }
|
||||
TIntermTyped* getRight() const { return right; }
|
||||
bool promote(TInfoSink&);
|
||||
|
||||
+ void setAddIndexClamp() { addIndexClamp = true; }
|
||||
+ bool getAddIndexClamp() { return addIndexClamp; }
|
||||
+
|
||||
protected:
|
||||
TIntermTyped* left;
|
||||
TIntermTyped* right;
|
||||
+
|
||||
+ // If set to true, wrap any EOpIndexIndirect with a clamp to bounds.
|
||||
+ bool addIndexClamp;
|
||||
};
|
||||
|
||||
//
|
||||
// Nodes for unary math operators.
|
||||
//
|
||||
class TIntermUnary : public TIntermOperator {
|
||||
public:
|
||||
TIntermUnary(TOperator o, TType& t) : TIntermOperator(o, t), operand(0), useEmulatedFunction(false) {}
|
||||
diff --git a/gfx/angle/src/compiler/translator_common.vcxproj b/gfx/angle/src/compiler/translator_common.vcxproj
|
||||
--- a/gfx/angle/src/compiler/translator_common.vcxproj
|
||||
+++ b/gfx/angle/src/compiler/translator_common.vcxproj
|
||||
@@ -133,16 +133,17 @@
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<DisableSpecificWarnings>4100;4127;4189;4239;4244;4245;4267;4512;4702;4718;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
+ <ClCompile Include="ArrayBoundsClamper.cpp" />
|
||||
<ClCompile Include="BuiltInFunctionEmulator.cpp" />
|
||||
<ClCompile Include="Compiler.cpp" />
|
||||
<ClCompile Include="debug.cpp" />
|
||||
<ClCompile Include="DetectRecursion.cpp" />
|
||||
<ClCompile Include="Diagnostics.cpp" />
|
||||
<ClCompile Include="DirectiveHandler.cpp" />
|
||||
<ClCompile Include="ForLoopUnroll.cpp" />
|
||||
<ClCompile Include="InfoSink.cpp" />
|
||||
@@ -220,16 +221,17 @@
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
</Message>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
</Command>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(Outputs)</Outputs>
|
||||
</CustomBuild>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
+ <ClInclude Include="ArrayBoundsClamper.h" />
|
||||
<ClInclude Include="BaseTypes.h" />
|
||||
<ClInclude Include="BuiltInFunctionEmulator.h" />
|
||||
<ClInclude Include="Common.h" />
|
||||
<ClInclude Include="ConstantUnion.h" />
|
||||
<ClInclude Include="debug.h" />
|
||||
<ClInclude Include="DetectRecursion.h" />
|
||||
<ClInclude Include="Diagnostics.h" />
|
||||
<ClInclude Include="DirectiveHandler.h" />
|
||||
@@ -274,9 +276,9 @@
|
||||
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
|
||||
<LinkLibraryDependencies>true</LinkLibraryDependencies>
|
||||
<UseLibraryDependencyInputs>true</UseLibraryDependencyInputs>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
-</Project>
|
||||
\ No newline at end of file
|
||||
+</Project>
|
||||
diff --git a/gfx/angle/src/libGLESv2/Makefile.in b/gfx/angle/src/libGLESv2/Makefile.in
|
||||
--- a/gfx/angle/src/libGLESv2/Makefile.in
|
||||
+++ b/gfx/angle/src/libGLESv2/Makefile.in
|
||||
@@ -64,16 +64,17 @@ LOCAL_INCLUDES = \
|
||||
-I$(srcdir)/../../include/KHR \
|
||||
-I$(srcdir)/..
|
||||
|
||||
DEFINES += -DCOMPILER_IMPLEMENTATION
|
||||
|
||||
VPATH += $(srcdir)/../compiler
|
||||
# src/compiler:
|
||||
CPPSRCS += \
|
||||
+ ArrayBoundsClamper.cpp \
|
||||
BuiltInFunctionEmulator.cpp \
|
||||
Compiler.cpp \
|
||||
compiler_debug.cpp \
|
||||
DetectRecursion.cpp \
|
||||
Diagnostics.cpp \
|
||||
DirectiveHandler.cpp \
|
||||
ForLoopUnroll.cpp \
|
||||
glslang_lex.cpp \
|
@ -150,7 +150,13 @@ typedef enum {
|
||||
SH_DEPENDENCY_GRAPH = 0x0400,
|
||||
|
||||
// Enforce the GLSL 1.017 Appendix A section 7 packing restrictions.
|
||||
SH_ENFORCE_PACKING_RESTRICTIONS = 0x0800
|
||||
SH_ENFORCE_PACKING_RESTRICTIONS = 0x0800,
|
||||
|
||||
// This flag ensures all indirect (expression-based) array indexing
|
||||
// is clamped to the bounds of the array. This ensures, for example,
|
||||
// that you cannot read off the end of a uniform, whether an array
|
||||
// vec234, or mat234 type.
|
||||
SH_CLAMP_INDIRECT_ARRAY_BOUNDS = 0x1000
|
||||
} ShCompileOptions;
|
||||
|
||||
//
|
||||
|
@ -59,6 +59,8 @@
|
||||
'COMPILER_IMPLEMENTATION',
|
||||
],
|
||||
'sources': [
|
||||
'compiler/ArrayBoundsClamper.cpp',
|
||||
'compiler/ArrayBoundsClamper.h',
|
||||
'compiler/BaseTypes.h',
|
||||
'compiler/BuiltInFunctionEmulator.cpp',
|
||||
'compiler/BuiltInFunctionEmulator.h',
|
||||
|
88
gfx/angle/src/compiler/ArrayBoundsClamper.cpp
Normal file
88
gfx/angle/src/compiler/ArrayBoundsClamper.cpp
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (C) 2012 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE, INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE, INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "compiler/ArrayBoundsClamper.h"
|
||||
|
||||
const char* kIntClampBegin = "// BEGIN: Generated code for array bounds clamping\n\n";
|
||||
const char* kIntClampEnd = "// END: Generated code for array bounds clamping\n\n";
|
||||
const char* kIntClampDefinition = "int webgl_int_clamp(int value, int minValue, int maxValue) { return ((value < minValue) ? minValue : ((value > maxValue) ? maxValue : value)); }\n\n";
|
||||
|
||||
namespace {
|
||||
|
||||
class ArrayBoundsClamperMarker : public TIntermTraverser {
|
||||
public:
|
||||
ArrayBoundsClamperMarker()
|
||||
: mNeedsClamp(false)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool visitBinary(Visit visit, TIntermBinary* node)
|
||||
{
|
||||
if (node->getOp() == EOpIndexIndirect)
|
||||
{
|
||||
TIntermTyped* left = node->getLeft();
|
||||
if (left->isArray() || left->isVector() || left->isMatrix())
|
||||
{
|
||||
node->setAddIndexClamp();
|
||||
mNeedsClamp = true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GetNeedsClamp() { return mNeedsClamp; }
|
||||
|
||||
private:
|
||||
bool mNeedsClamp;
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
ArrayBoundsClamper::ArrayBoundsClamper()
|
||||
: mArrayBoundsClampDefinitionNeeded(false)
|
||||
{
|
||||
}
|
||||
|
||||
void ArrayBoundsClamper::OutputClampingFunctionDefinition(TInfoSinkBase& out) const
|
||||
{
|
||||
if (!mArrayBoundsClampDefinitionNeeded)
|
||||
{
|
||||
return;
|
||||
}
|
||||
out << kIntClampBegin << kIntClampDefinition << kIntClampEnd;
|
||||
}
|
||||
|
||||
void ArrayBoundsClamper::MarkIndirectArrayBoundsForClamping(TIntermNode* root)
|
||||
{
|
||||
ASSERT(root);
|
||||
|
||||
ArrayBoundsClamperMarker clamper;
|
||||
root->traverse(&clamper);
|
||||
if (clamper.GetNeedsClamp())
|
||||
{
|
||||
SetArrayBoundsClampDefinitionNeeded();
|
||||
}
|
||||
}
|
||||
|
57
gfx/angle/src/compiler/ArrayBoundsClamper.h
Normal file
57
gfx/angle/src/compiler/ArrayBoundsClamper.h
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) 2012 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE, INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE, INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef COMPILER_ARRAY_BOUNDS_CLAMPER_H_
|
||||
#define COMPILER_ARRAY_BOUNDS_CLAMPER_H_
|
||||
|
||||
#include "GLSLANG/ShaderLang.h"
|
||||
|
||||
#include "compiler/InfoSink.h"
|
||||
#include "compiler/intermediate.h"
|
||||
|
||||
class ArrayBoundsClamper {
|
||||
public:
|
||||
ArrayBoundsClamper();
|
||||
|
||||
// Output array clamp function source into the shader source.
|
||||
void OutputClampingFunctionDefinition(TInfoSinkBase& out) const;
|
||||
|
||||
// Marks nodes in the tree that index arrays indirectly as
|
||||
// requiring clamping.
|
||||
void MarkIndirectArrayBoundsForClamping(TIntermNode* root);
|
||||
|
||||
void Cleanup()
|
||||
{
|
||||
mArrayBoundsClampDefinitionNeeded = false;
|
||||
}
|
||||
|
||||
private:
|
||||
bool GetArrayBoundsClampDefinitionNeeded() const { return mArrayBoundsClampDefinitionNeeded; }
|
||||
void SetArrayBoundsClampDefinitionNeeded() { mArrayBoundsClampDefinitionNeeded = true; }
|
||||
|
||||
bool mArrayBoundsClampDefinitionNeeded;
|
||||
};
|
||||
|
||||
#endif // COMPILER_ARRAY_BOUNDS_CLAMPER_H_
|
@ -4,6 +4,7 @@
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
|
||||
#include "compiler/ArrayBoundsClamper.h"
|
||||
#include "compiler/BuiltInFunctionEmulator.h"
|
||||
#include "compiler/DetectRecursion.h"
|
||||
#include "compiler/ForLoopUnroll.h"
|
||||
@ -192,6 +193,10 @@ bool TCompiler::compile(const char* const shaderStrings[],
|
||||
if (success && (compileOptions & SH_EMULATE_BUILT_IN_FUNCTIONS))
|
||||
builtInFunctionEmulator.MarkBuiltInFunctionsForEmulation(root);
|
||||
|
||||
// Clamping uniform array bounds needs to happen after validateLimitations pass.
|
||||
if (success && (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS))
|
||||
arrayBoundsClamper.MarkIndirectArrayBoundsForClamping(root);
|
||||
|
||||
// Call mapLongVariableNames() before collectAttribsUniforms() so in
|
||||
// collectAttribsUniforms() we already have the mapped symbol names and
|
||||
// we could composite mapped and original variable names.
|
||||
@ -237,6 +242,7 @@ bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources& resources)
|
||||
|
||||
void TCompiler::clearResults()
|
||||
{
|
||||
arrayBoundsClamper.Cleanup();
|
||||
infoSink.info.erase();
|
||||
infoSink.obj.erase();
|
||||
infoSink.debug.erase();
|
||||
@ -353,3 +359,9 @@ const BuiltInFunctionEmulator& TCompiler::getBuiltInFunctionEmulator() const
|
||||
{
|
||||
return builtInFunctionEmulator;
|
||||
}
|
||||
|
||||
const ArrayBoundsClamper& TCompiler::getArrayBoundsClamper() const
|
||||
{
|
||||
return arrayBoundsClamper;
|
||||
}
|
||||
|
||||
|
@ -212,9 +212,38 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary* node)
|
||||
break;
|
||||
|
||||
case EOpIndexDirect:
|
||||
case EOpIndexIndirect:
|
||||
writeTriplet(visit, NULL, "[", "]");
|
||||
break;
|
||||
case EOpIndexIndirect:
|
||||
if (node->getAddIndexClamp())
|
||||
{
|
||||
if (visit == InVisit)
|
||||
{
|
||||
out << "[webgl_int_clamp(";
|
||||
}
|
||||
else if (visit == PostVisit)
|
||||
{
|
||||
int maxSize;
|
||||
TIntermTyped *left = node->getLeft();
|
||||
TType leftType = left->getType();
|
||||
|
||||
if (left->isArray())
|
||||
{
|
||||
// The shader will fail validation if the array length is not > 0.
|
||||
maxSize = leftType.getArraySize() - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
maxSize = leftType.getNominalSize() - 1;
|
||||
}
|
||||
out << ", 0, " << maxSize << ")]";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
writeTriplet(visit, NULL, "[", "]");
|
||||
}
|
||||
break;
|
||||
case EOpIndexDirectStruct:
|
||||
if (visit == InVisit)
|
||||
{
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
#include "GLSLANG/ShaderLang.h"
|
||||
|
||||
#include "compiler/ArrayBoundsClamper.h"
|
||||
#include "compiler/BuiltInFunctionEmulator.h"
|
||||
#include "compiler/ExtensionBehavior.h"
|
||||
#include "compiler/HashNames.h"
|
||||
@ -106,6 +107,7 @@ protected:
|
||||
// Get built-in extensions with default behavior.
|
||||
const TExtensionBehavior& getExtensionBehavior() const;
|
||||
|
||||
const ArrayBoundsClamper& getArrayBoundsClamper() const;
|
||||
const BuiltInFunctionEmulator& getBuiltInFunctionEmulator() const;
|
||||
|
||||
private:
|
||||
@ -120,6 +122,7 @@ private:
|
||||
// Built-in extensions with default behavior.
|
||||
TExtensionBehavior extensionBehavior;
|
||||
|
||||
ArrayBoundsClamper arrayBoundsClamper;
|
||||
BuiltInFunctionEmulator builtInFunctionEmulator;
|
||||
|
||||
// Results of compilation.
|
||||
|
@ -22,6 +22,9 @@ void TranslatorESSL::translate(TIntermNode* root) {
|
||||
getBuiltInFunctionEmulator().OutputEmulatedFunctionDefinition(
|
||||
sink, getShaderType() == SH_FRAGMENT_SHADER);
|
||||
|
||||
// Write array bounds clamping emulation if needed.
|
||||
getArrayBoundsClamper().OutputClampingFunctionDefinition(sink);
|
||||
|
||||
// Write translated shader.
|
||||
TOutputESSL outputESSL(sink, getHashFunction(), getNameMap(), getSymbolTable());
|
||||
root->traverse(&outputESSL);
|
||||
|
@ -35,6 +35,9 @@ void TranslatorGLSL::translate(TIntermNode* root) {
|
||||
getBuiltInFunctionEmulator().OutputEmulatedFunctionDefinition(
|
||||
sink, false);
|
||||
|
||||
// Write array bounds clamping emulation if needed.
|
||||
getArrayBoundsClamper().OutputClampingFunctionDefinition(sink);
|
||||
|
||||
// Write translated shader.
|
||||
TOutputGLSL outputGLSL(sink, getHashFunction(), getNameMap(), getSymbolTable());
|
||||
root->traverse(&outputGLSL);
|
||||
|
@ -42,7 +42,7 @@ TString TType::getCompleteString() const
|
||||
if (qualifier != EvqTemporary && qualifier != EvqGlobal)
|
||||
stream << getQualifierString() << " " << getPrecisionString() << " ";
|
||||
if (array)
|
||||
stream << "array of ";
|
||||
stream << "array[" << getArraySize() << "] of ";
|
||||
if (matrix)
|
||||
stream << size << "X" << size << " matrix of ";
|
||||
else if (size > 1)
|
||||
|
@ -391,7 +391,7 @@ protected:
|
||||
//
|
||||
class TIntermBinary : public TIntermOperator {
|
||||
public:
|
||||
TIntermBinary(TOperator o) : TIntermOperator(o) {}
|
||||
TIntermBinary(TOperator o) : TIntermOperator(o), addIndexClamp(false) {}
|
||||
|
||||
virtual TIntermBinary* getAsBinaryNode() { return this; }
|
||||
virtual void traverse(TIntermTraverser*);
|
||||
@ -402,9 +402,15 @@ public:
|
||||
TIntermTyped* getRight() const { return right; }
|
||||
bool promote(TInfoSink&);
|
||||
|
||||
void setAddIndexClamp() { addIndexClamp = true; }
|
||||
bool getAddIndexClamp() { return addIndexClamp; }
|
||||
|
||||
protected:
|
||||
TIntermTyped* left;
|
||||
TIntermTyped* right;
|
||||
|
||||
// If set to true, wrap any EOpIndexIndirect with a clamp to bounds.
|
||||
bool addIndexClamp;
|
||||
};
|
||||
|
||||
//
|
||||
|
@ -138,6 +138,7 @@
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="ArrayBoundsClamper.cpp" />
|
||||
<ClCompile Include="BuiltInFunctionEmulator.cpp" />
|
||||
<ClCompile Include="Compiler.cpp" />
|
||||
<ClCompile Include="debug.cpp" />
|
||||
@ -225,6 +226,7 @@
|
||||
</CustomBuild>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="ArrayBoundsClamper.h" />
|
||||
<ClInclude Include="BaseTypes.h" />
|
||||
<ClInclude Include="BuiltInFunctionEmulator.h" />
|
||||
<ClInclude Include="Common.h" />
|
||||
@ -279,4 +281,4 @@
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
@ -69,6 +69,7 @@ DEFINES += -DCOMPILER_IMPLEMENTATION
|
||||
VPATH += $(srcdir)/../compiler
|
||||
# src/compiler:
|
||||
CPPSRCS += \
|
||||
ArrayBoundsClamper.cpp \
|
||||
BuiltInFunctionEmulator.cpp \
|
||||
Compiler.cpp \
|
||||
compiler_debug.cpp \
|
||||
|
163
js/public/Anchor.h
Normal file
163
js/public/Anchor.h
Normal file
@ -0,0 +1,163 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=4 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* 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/. */
|
||||
|
||||
/* JS::Anchor implementation. */
|
||||
|
||||
#ifndef js_Anchor_h___
|
||||
#define js_Anchor_h___
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
class JSFunction;
|
||||
class JSObject;
|
||||
class JSScript;
|
||||
class JSString;
|
||||
|
||||
namespace JS { class Value; }
|
||||
|
||||
namespace JS {
|
||||
|
||||
/*
|
||||
* Protecting non-Value, non-JSObject *, non-JSString * values from collection
|
||||
*
|
||||
* Most of the time, the garbage collector's conservative stack scanner works
|
||||
* behind the scenes, finding all live values and protecting them from being
|
||||
* collected. However, when JSAPI client code obtains a pointer to data the
|
||||
* scanner does not know about, owned by an object the scanner does know about,
|
||||
* Care Must Be Taken.
|
||||
*
|
||||
* The scanner recognizes only a select set of types: pointers to JSObjects and
|
||||
* similar things (JSFunctions, and so on), pointers to JSStrings, and Values.
|
||||
* So while the scanner finds all live |JSString| pointers, it does not notice
|
||||
* |jschar| pointers.
|
||||
*
|
||||
* So suppose we have:
|
||||
*
|
||||
* void f(JSString *str) {
|
||||
* const jschar *ch = JS_GetStringCharsZ(str);
|
||||
* ... do stuff with ch, but no uses of str ...;
|
||||
* }
|
||||
*
|
||||
* After the call to |JS_GetStringCharsZ|, there are no further uses of
|
||||
* |str|, which means that the compiler is within its rights to not store
|
||||
* it anywhere. But because the stack scanner will not notice |ch|, there
|
||||
* is no longer any live value in this frame that would keep the string
|
||||
* alive. If |str| is the last reference to that |JSString|, and the
|
||||
* collector runs while we are using |ch|, the string's array of |jschar|s
|
||||
* may be freed out from under us.
|
||||
*
|
||||
* Note that there is only an issue when 1) we extract a thing X the scanner
|
||||
* doesn't recognize from 2) a thing Y the scanner does recognize, and 3) if Y
|
||||
* gets garbage-collected, then X gets freed. If we have code like this:
|
||||
*
|
||||
* void g(JSObject *obj) {
|
||||
* JS::Value x;
|
||||
* JS_GetProperty(obj, "x", &x);
|
||||
* ... do stuff with x ...
|
||||
* }
|
||||
*
|
||||
* there's no problem, because the value we've extracted, x, is a Value, a
|
||||
* type that the conservative scanner recognizes.
|
||||
*
|
||||
* Conservative GC frees us from the obligation to explicitly root the types it
|
||||
* knows about, but when we work with derived values like |ch|, we must root
|
||||
* their owners, as the derived value alone won't keep them alive.
|
||||
*
|
||||
* A JS::Anchor is a kind of GC root that allows us to keep the owners of
|
||||
* derived values like |ch| alive throughout the Anchor's lifetime. We could
|
||||
* fix the above code as follows:
|
||||
*
|
||||
* void f(JSString *str) {
|
||||
* JS::Anchor<JSString *> a_str(str);
|
||||
* const jschar *ch = JS_GetStringCharsZ(str);
|
||||
* ... do stuff with ch, but no uses of str ...;
|
||||
* }
|
||||
*
|
||||
* This simply ensures that |str| will be live until |a_str| goes out of scope.
|
||||
* As long as we don't retain a pointer to the string's characters for longer
|
||||
* than that, we have avoided all garbage collection hazards.
|
||||
*/
|
||||
template<typename T> class AnchorPermitted;
|
||||
template<> class AnchorPermitted<JSObject *> { };
|
||||
template<> class AnchorPermitted<const JSObject *> { };
|
||||
template<> class AnchorPermitted<JSFunction *> { };
|
||||
template<> class AnchorPermitted<const JSFunction *> { };
|
||||
template<> class AnchorPermitted<JSString *> { };
|
||||
template<> class AnchorPermitted<const JSString *> { };
|
||||
template<> class AnchorPermitted<Value> { };
|
||||
template<> class AnchorPermitted<const JSScript *> { };
|
||||
template<> class AnchorPermitted<JSScript *> { };
|
||||
|
||||
template<typename T>
|
||||
class Anchor : AnchorPermitted<T>
|
||||
{
|
||||
public:
|
||||
Anchor() { }
|
||||
explicit Anchor(T t) { hold = t; }
|
||||
inline ~Anchor();
|
||||
T &get() { return hold; }
|
||||
const T &get() const { return hold; }
|
||||
void set(const T &t) { hold = t; }
|
||||
void operator=(const T &t) { hold = t; }
|
||||
void clear() { hold = 0; }
|
||||
|
||||
private:
|
||||
T hold;
|
||||
Anchor(const Anchor &other) MOZ_DELETE;
|
||||
void operator=(const Anchor &other) MOZ_DELETE;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline Anchor<T>::~Anchor()
|
||||
{
|
||||
#ifdef __GNUC__
|
||||
/*
|
||||
* No code is generated for this. But because this is marked 'volatile', G++ will
|
||||
* assume it has important side-effects, and won't delete it. (G++ never looks at
|
||||
* the actual text and notices it's empty.) And because we have passed |hold| to
|
||||
* it, GCC will keep |hold| alive until this point.
|
||||
*
|
||||
* The "memory" clobber operand ensures that G++ will not move prior memory
|
||||
* accesses after the asm --- it's a barrier. Unfortunately, it also means that
|
||||
* G++ will assume that all memory has changed after the asm, as it would for a
|
||||
* call to an unknown function. I don't know of a way to avoid that consequence.
|
||||
*/
|
||||
asm volatile("":: "g" (hold) : "memory");
|
||||
#else
|
||||
/*
|
||||
* An adequate portable substitute, for non-structure types.
|
||||
*
|
||||
* The compiler promises that, by the end of an expression statement, the
|
||||
* last-stored value to a volatile object is the same as it would be in an
|
||||
* unoptimized, direct implementation (the "abstract machine" whose behavior the
|
||||
* language spec describes). However, the compiler is still free to reorder
|
||||
* non-volatile accesses across this store --- which is what we must prevent. So
|
||||
* assigning the held value to a volatile variable, as we do here, is not enough.
|
||||
*
|
||||
* In our case, however, garbage collection only occurs at function calls, so it
|
||||
* is sufficient to ensure that the destructor's store isn't moved earlier across
|
||||
* any function calls that could collect. It is hard to imagine the compiler
|
||||
* analyzing the program so thoroughly that it could prove that such motion was
|
||||
* safe. In practice, compilers treat calls to the collector as opaque operations
|
||||
* --- in particular, as operations which could access volatile variables, across
|
||||
* which this destructor must not be moved.
|
||||
*
|
||||
* ("Objection, your honor! *Alleged* killer whale!")
|
||||
*
|
||||
* The disadvantage of this approach is that it does generate code for the store.
|
||||
* We do need to use Anchors in some cases where cycles are tight.
|
||||
*
|
||||
* Note that there is a Anchor<Value>::~Anchor() specialization in Value.h.
|
||||
*/
|
||||
volatile T sink;
|
||||
sink = hold;
|
||||
#endif /* defined(__GNUC__) */
|
||||
}
|
||||
|
||||
} // namespace JS
|
||||
|
||||
#endif /* js_Anchor_h___ */
|
99
js/public/PropertyKey.h
Normal file
99
js/public/PropertyKey.h
Normal file
@ -0,0 +1,99 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=4 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* 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/. */
|
||||
|
||||
/* JS::PropertyKey implementation. */
|
||||
|
||||
#ifndef js_PropertyKey_h___
|
||||
#define js_PropertyKey_h___
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
#include "js/Value.h"
|
||||
|
||||
struct JSContext;
|
||||
|
||||
namespace JS {
|
||||
|
||||
class PropertyKey;
|
||||
|
||||
namespace detail {
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
ToPropertyKeySlow(JSContext *cx, HandleValue v, PropertyKey *key);
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/*
|
||||
* A PropertyKey is a key used to access some property on an object. It is a
|
||||
* natural way to represent a property accessed using a JavaScript value.
|
||||
*
|
||||
* PropertyKey can represent indexes, named properties, and ES6 symbols. The
|
||||
* latter aren't implemented in SpiderMonkey yet, but PropertyKey carves out
|
||||
* space for them.
|
||||
*/
|
||||
class PropertyKey
|
||||
{
|
||||
Value v;
|
||||
friend bool detail::ToPropertyKeySlow(JSContext *cx, HandleValue v, PropertyKey *key);
|
||||
|
||||
public:
|
||||
explicit PropertyKey(uint32_t index) : v(PrivateUint32Value(index)) {}
|
||||
|
||||
/*
|
||||
* An index is a string property name whose characters exactly spell out an
|
||||
* unsigned 32-bit integer in decimal: "0", "1", "2", ...., "4294967294",
|
||||
* "4294967295".
|
||||
*/
|
||||
bool isIndex(uint32_t *index) {
|
||||
// The implementation here assumes that private uint32_t are stored
|
||||
// using the int32_t representation. This is purely an implementation
|
||||
// detail: embedders must not rely upon this!
|
||||
if (!v.isInt32())
|
||||
return false;
|
||||
*index = v.toPrivateUint32();
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* A name is a string property name which is *not* an index. Note that by
|
||||
* the ECMAScript language grammar, any dotted property access |obj.prop|
|
||||
* will access a named property.
|
||||
*/
|
||||
bool isName(JSString **str) {
|
||||
uint32_t dummy;
|
||||
if (isIndex(&dummy))
|
||||
return false;
|
||||
*str = v.toString();
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* A symbol is a property name that's a Symbol, a particular kind of object
|
||||
* in ES6. It is the only kind of property name that's not a string.
|
||||
*
|
||||
* SpiderMonkey doesn't yet implement symbols, but we're carving out API
|
||||
* space for them in advance.
|
||||
*/
|
||||
bool isSymbol() {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
inline bool
|
||||
ToPropertyKey(JSContext *cx, HandleValue v, PropertyKey *key)
|
||||
{
|
||||
if (v.isInt32() && v.toInt32() >= 0) {
|
||||
*key = PropertyKey(uint32_t(v.toInt32()));
|
||||
return true;
|
||||
}
|
||||
|
||||
return detail::ToPropertyKeySlow(cx, v, key);
|
||||
}
|
||||
|
||||
} // namespace JS
|
||||
|
||||
#endif /* js_PropertyKey_h___ */
|
1821
js/public/Value.h
Normal file
1821
js/public/Value.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -127,6 +127,7 @@ CPPSRCS = \
|
||||
GlobalObject.cpp \
|
||||
Object.cpp \
|
||||
ObjectImpl.cpp \
|
||||
PropertyKey.cpp \
|
||||
ScopeObject.cpp \
|
||||
Shape.cpp \
|
||||
Stack.cpp \
|
||||
@ -190,7 +191,6 @@ INSTALLED_HEADERS = \
|
||||
jsutil.h \
|
||||
jsversion.h \
|
||||
jswrapper.h \
|
||||
jsval.h \
|
||||
$(NULL)
|
||||
|
||||
######################################################
|
||||
@ -224,14 +224,17 @@ EXPORTS_NAMESPACES += js
|
||||
# that we ensure we don't over-expose our internal integer typedefs. Note that
|
||||
# LegacyIntTypes.h below is deliberately exempted from this requirement.
|
||||
EXPORTS_js = \
|
||||
Anchor.h \
|
||||
CharacterEncoding.h \
|
||||
GCAPI.h \
|
||||
HashTable.h \
|
||||
HeapAPI.h \
|
||||
GCAPI.h \
|
||||
LegacyIntTypes.h \
|
||||
MemoryMetrics.h \
|
||||
PropertyKey.h \
|
||||
TemplateLib.h \
|
||||
Utility.h \
|
||||
Value.h \
|
||||
Vector.h \
|
||||
$(NULL)
|
||||
|
||||
|
@ -582,9 +582,9 @@ bool
|
||||
GlobalObject::initIntlObject(JSContext *cx, Handle<GlobalObject*> global)
|
||||
{
|
||||
RootedObject Intl(cx);
|
||||
Intl = NewObjectWithGivenProto(cx, &IntlClass,
|
||||
global->getOrCreateObjectPrototype(cx), global);
|
||||
if (!Intl || !JSObject::setSingletonType(cx, Intl))
|
||||
Intl = NewObjectWithGivenProto(cx, &IntlClass, global->getOrCreateObjectPrototype(cx),
|
||||
global, SingletonObject);
|
||||
if (!Intl)
|
||||
return false;
|
||||
|
||||
global->setReservedSlot(JSProto_Intl, ObjectValue(*Intl));
|
||||
|
@ -1006,10 +1006,10 @@ ParallelArrayObject::initClass(JSContext *cx, JSObject *obj)
|
||||
RootedId shapeId(cx, AtomToId(cx->names().shape));
|
||||
unsigned flags = JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_GETTER;
|
||||
|
||||
RootedObject scriptedLength(cx, js_NewFunction(cx, NullPtr(), NonGenericMethod<lengthGetter>,
|
||||
0, JSFunction::NATIVE_FUN, global, NullPtr()));
|
||||
RootedObject scriptedShape(cx, js_NewFunction(cx, NullPtr(), NonGenericMethod<dimensionsGetter>,
|
||||
0, JSFunction::NATIVE_FUN, global, NullPtr()));
|
||||
RootedObject scriptedLength(cx, NewFunction(cx, NullPtr(), NonGenericMethod<lengthGetter>,
|
||||
0, JSFunction::NATIVE_FUN, global, NullPtr()));
|
||||
RootedObject scriptedShape(cx, NewFunction(cx, NullPtr(), NonGenericMethod<dimensionsGetter>,
|
||||
0, JSFunction::NATIVE_FUN, global, NullPtr()));
|
||||
|
||||
RootedValue value(cx, UndefinedValue());
|
||||
if (!scriptedLength || !scriptedShape ||
|
||||
|
@ -1086,7 +1086,8 @@ Parser::newFunction(ParseContext *pc, HandleAtom atom, FunctionSyntaxKind kind)
|
||||
JSFunction::Flags flags = (kind == Expression)
|
||||
? JSFunction::INTERPRETED_LAMBDA
|
||||
: JSFunction::INTERPRETED;
|
||||
fun = js_NewFunction(context, NullPtr(), NULL, 0, flags, parent, atom);
|
||||
fun = NewFunction(context, NullPtr(), NULL, 0, flags, parent, atom,
|
||||
JSFunction::FinalizeKind, MaybeSingletonObject);
|
||||
if (selfHostingMode)
|
||||
fun->setIsSelfHostedBuiltin();
|
||||
if (fun && !compileAndGo) {
|
||||
|
@ -34,6 +34,16 @@ struct Arena;
|
||||
struct ArenaHeader;
|
||||
struct Chunk;
|
||||
|
||||
/*
|
||||
* This flag allows an allocation site to request a specific heap based upon the
|
||||
* estimated lifetime or lifetime requirements of objects allocated from that
|
||||
* site.
|
||||
*/
|
||||
enum InitialHeap {
|
||||
DefaultHeap,
|
||||
TenuredHeap
|
||||
};
|
||||
|
||||
/* The GC allocation kinds. */
|
||||
enum AllocKind {
|
||||
FINALIZE_OBJECT0,
|
||||
|
@ -72,12 +72,12 @@ mozilla.prettyprinters.clear_module_printers(__name__)
|
||||
#
|
||||
# In detail:
|
||||
#
|
||||
# - jsval (jsapi.h) is a typedef for JS::Value.
|
||||
# - jsval (Value.h) is a typedef for JS::Value.
|
||||
#
|
||||
# - JS::Value (jsapi.h) is a class with a lot of methods and a single data
|
||||
# - JS::Value (Value.h) is a class with a lot of methods and a single data
|
||||
# member, of type jsval_layout.
|
||||
#
|
||||
# - jsval_layout (jsval.h) is a helper type for picking apart values. This
|
||||
# - jsval_layout (Value.h) is a helper type for picking apart values. This
|
||||
# is always 64 bits long, with a variant for each address size (32 bits
|
||||
# or 64 bits) and endianness (little- or big-endian).
|
||||
#
|
||||
|
@ -2047,9 +2047,15 @@ CodeGenerator::visitCreateThis(LCreateThis *lir)
|
||||
return callVM(CreateThisInfo, lir);
|
||||
}
|
||||
|
||||
static JSObject *
|
||||
CreateThisForFunctionWithProtoWrapper(JSContext *cx, js::HandleObject callee, JSObject *proto)
|
||||
{
|
||||
return CreateThisForFunctionWithProto(cx, callee, proto);
|
||||
}
|
||||
|
||||
typedef JSObject *(*CreateThisWithProtoFn)(JSContext *cx, HandleObject callee, JSObject *proto);
|
||||
static const VMFunction CreateThisWithProtoInfo =
|
||||
FunctionInfo<CreateThisWithProtoFn>(js_CreateThisForFunctionWithProto);
|
||||
FunctionInfo<CreateThisWithProtoFn>(CreateThisForFunctionWithProtoWrapper);
|
||||
|
||||
bool
|
||||
CodeGenerator::visitCreateThisWithProto(LCreateThisWithProto *lir)
|
||||
|
@ -331,7 +331,7 @@ IonCode::New(JSContext *cx, uint8_t *code, uint32_t bufferSize, JSC::ExecutableP
|
||||
{
|
||||
AssertCanGC();
|
||||
|
||||
IonCode *codeObj = gc::NewGCThing<IonCode, CanGC>(cx, gc::FINALIZE_IONCODE, sizeof(IonCode));
|
||||
IonCode *codeObj = gc::NewGCThing<IonCode, CanGC>(cx, gc::FINALIZE_IONCODE, sizeof(IonCode), gc::DefaultHeap);
|
||||
if (!codeObj) {
|
||||
pool->release();
|
||||
return NULL;
|
||||
@ -1466,7 +1466,7 @@ ion::CanEnter(JSContext *cx, JSScript *script, AbstractFramePtr fp,
|
||||
if (isConstructing && fp.thisValue().isPrimitive()) {
|
||||
RootedScript scriptRoot(cx, script);
|
||||
RootedObject callee(cx, &fp.callee());
|
||||
RootedObject obj(cx, js_CreateThisForFunction(cx, callee, newType));
|
||||
RootedObject obj(cx, CreateThisForFunction(cx, callee, newType));
|
||||
if (!obj)
|
||||
return Method_Skipped;
|
||||
fp.thisValue().setObject(*obj);
|
||||
|
@ -3775,7 +3775,7 @@ IonBuilder::createThisScriptedSingleton(HandleFunction target, MDefinition *call
|
||||
if (!types::TypeScript::ThisTypes(target->nonLazyScript())->hasType(types::Type::ObjectType(type)))
|
||||
return NULL;
|
||||
|
||||
RootedObject templateObject(cx, js_CreateThisForFunctionWithProto(cx, target, proto));
|
||||
RootedObject templateObject(cx, CreateThisForFunctionWithProto(cx, target, proto));
|
||||
if (!templateObject)
|
||||
return NULL;
|
||||
|
||||
@ -4351,15 +4351,13 @@ IonBuilder::jsop_compare(JSOp op)
|
||||
JSObject *
|
||||
IonBuilder::getNewArrayTemplateObject(uint32_t count)
|
||||
{
|
||||
RootedObject templateObject(cx, NewDenseUnallocatedArray(cx, count));
|
||||
RootedScript scriptRoot(cx, script());
|
||||
NewObjectKind newKind = types::UseNewTypeForInitializer(cx, scriptRoot, pc, JSProto_Array);
|
||||
RootedObject templateObject(cx, NewDenseUnallocatedArray(cx, count, NULL, newKind));
|
||||
if (!templateObject)
|
||||
return NULL;
|
||||
|
||||
RootedScript scriptRoot(cx, script());
|
||||
if (types::UseNewTypeForInitializer(cx, scriptRoot, pc, JSProto_Array)) {
|
||||
if (!JSObject::setSingletonType(cx, templateObject))
|
||||
return NULL;
|
||||
} else {
|
||||
if (newKind != SingletonObject) {
|
||||
types::TypeObject *type = types::TypeScript::InitObject(cx, scriptRoot, pc, JSProto_Array);
|
||||
if (!type)
|
||||
return NULL;
|
||||
@ -4397,21 +4395,19 @@ IonBuilder::jsop_newobject(HandleObject baseObj)
|
||||
|
||||
RootedObject templateObject(cx);
|
||||
|
||||
RootedScript scriptRoot(cx, script());
|
||||
NewObjectKind newKind = types::UseNewTypeForInitializer(cx, scriptRoot, pc, JSProto_Object);
|
||||
if (baseObj) {
|
||||
templateObject = CopyInitializerObject(cx, baseObj);
|
||||
templateObject = CopyInitializerObject(cx, baseObj, newKind);
|
||||
} else {
|
||||
gc::AllocKind kind = GuessObjectGCKind(0);
|
||||
templateObject = NewBuiltinClassInstance(cx, &ObjectClass, kind);
|
||||
gc::AllocKind allocKind = GuessObjectGCKind(0);
|
||||
templateObject = NewBuiltinClassInstance(cx, &ObjectClass, allocKind, newKind);
|
||||
}
|
||||
|
||||
if (!templateObject)
|
||||
return false;
|
||||
|
||||
RootedScript scriptRoot(cx, script());
|
||||
if (types::UseNewTypeForInitializer(cx, scriptRoot, pc, JSProto_Object)) {
|
||||
if (!JSObject::setSingletonType(cx, templateObject))
|
||||
return false;
|
||||
} else {
|
||||
if (newKind != SingletonObject) {
|
||||
types::TypeObject *type = types::TypeScript::InitObject(cx, scriptRoot, pc, JSProto_Object);
|
||||
if (!type)
|
||||
return false;
|
||||
|
@ -9,8 +9,8 @@
|
||||
#define jsion_ion_compartment_h__
|
||||
|
||||
#include "IonCode.h"
|
||||
#include "jsval.h"
|
||||
#include "jsweakcache.h"
|
||||
#include "js/Value.h"
|
||||
#include "vm/Stack.h"
|
||||
#include "IonFrames.h"
|
||||
|
||||
|
@ -116,7 +116,7 @@ InvokeFunction(JSContext *cx, HandleFunction fun0, uint32_t argc, Value *argv, V
|
||||
JSObject *
|
||||
NewGCThing(JSContext *cx, gc::AllocKind allocKind, size_t thingSize)
|
||||
{
|
||||
return gc::NewGCThing<JSObject, CanGC>(cx, allocKind, thingSize);
|
||||
return gc::NewGCThing<JSObject, CanGC>(cx, allocKind, thingSize, gc::DefaultHeap);
|
||||
}
|
||||
|
||||
bool
|
||||
@ -269,18 +269,15 @@ JSObject*
|
||||
NewInitArray(JSContext *cx, uint32_t count, types::TypeObject *typeArg)
|
||||
{
|
||||
RootedTypeObject type(cx, typeArg);
|
||||
RootedObject obj(cx, NewDenseAllocatedArray(cx, count));
|
||||
NewObjectKind newKind = !type ? SingletonObject : GenericObject;
|
||||
RootedObject obj(cx, NewDenseAllocatedArray(cx, count, NULL, newKind));
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
if (!type) {
|
||||
if (!JSObject::setSingletonType(cx, obj))
|
||||
return NULL;
|
||||
|
||||
if (!type)
|
||||
types::TypeScript::Monitor(cx, ObjectValue(*obj));
|
||||
} else {
|
||||
else
|
||||
obj->setType(type);
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
@ -288,19 +285,16 @@ NewInitArray(JSContext *cx, uint32_t count, types::TypeObject *typeArg)
|
||||
JSObject*
|
||||
NewInitObject(JSContext *cx, HandleObject templateObject)
|
||||
{
|
||||
RootedObject obj(cx, CopyInitializerObject(cx, templateObject));
|
||||
NewObjectKind newKind = templateObject->hasSingletonType() ? SingletonObject : GenericObject;
|
||||
RootedObject obj(cx, CopyInitializerObject(cx, templateObject, newKind));
|
||||
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
if (templateObject->hasSingletonType()) {
|
||||
if (!JSObject::setSingletonType(cx, obj))
|
||||
return NULL;
|
||||
|
||||
if (templateObject->hasSingletonType())
|
||||
types::TypeScript::Monitor(cx, ObjectValue(*obj));
|
||||
} else {
|
||||
else
|
||||
obj->setType(templateObject->type());
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
@ -499,7 +493,7 @@ CreateThis(JSContext *cx, HandleObject callee, MutableHandleValue rval)
|
||||
if (callee->isFunction()) {
|
||||
JSFunction *fun = callee->toFunction();
|
||||
if (fun->isInterpreted())
|
||||
rval.set(ObjectValue(*js_CreateThisForFunction(cx, callee, false)));
|
||||
rval.set(ObjectValue(*CreateThisForFunction(cx, callee, false)));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -16,13 +16,17 @@
|
||||
#include "jscpucfg.h"
|
||||
#include "jspubtd.h"
|
||||
#include "jstypes.h"
|
||||
#include "jsval.h"
|
||||
|
||||
#include "js/Anchor.h"
|
||||
#include "js/CharacterEncoding.h"
|
||||
#include "js/GCAPI.h"
|
||||
#include "js/HashTable.h"
|
||||
#include "js/HeapAPI.h"
|
||||
#include "js/MemoryMetrics.h"
|
||||
#include "js/PropertyKey.h"
|
||||
#include "js/TemplateLib.h"
|
||||
#include "js/Utility.h"
|
||||
#include "js/Value.h"
|
||||
#include "js/Vector.h"
|
||||
|
||||
/*
|
||||
|
@ -3375,7 +3375,7 @@ JS_NewObjectForConstructor(JSContext *cx, JSClass *clasp, const jsval *vp)
|
||||
assertSameCompartment(cx, *vp);
|
||||
|
||||
RootedObject obj(cx, JSVAL_TO_OBJECT(*vp));
|
||||
return js_CreateThis(cx, Valueify(clasp), obj);
|
||||
return CreateThis(cx, Valueify(clasp), obj);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
@ -4760,7 +4760,7 @@ JS_NewFunction(JSContext *cx, JSNative native, unsigned nargs, unsigned flags,
|
||||
}
|
||||
|
||||
JSFunction::Flags funFlags = JSAPIToJSFunctionFlags(flags);
|
||||
return js_NewFunction(cx, NullPtr(), native, nargs, funFlags, parent, atom);
|
||||
return NewFunction(cx, NullPtr(), native, nargs, funFlags, parent, atom);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSFunction *)
|
||||
@ -4776,7 +4776,7 @@ JS_NewFunctionById(JSContext *cx, JSNative native, unsigned nargs, unsigned flag
|
||||
|
||||
RootedAtom atom(cx, JSID_TO_ATOM(id));
|
||||
JSFunction::Flags funFlags = JSAPIToJSFunctionFlags(flags);
|
||||
return js_NewFunction(cx, NullPtr(), native, nargs, funFlags, parent, atom);
|
||||
return NewFunction(cx, NullPtr(), native, nargs, funFlags, parent, atom);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSObject *)
|
||||
@ -4934,9 +4934,10 @@ JS_DefineFunctions(JSContext *cx, JSObject *objArg, JSFunctionSpec *fs)
|
||||
}
|
||||
|
||||
flags &= ~JSFUN_GENERIC_NATIVE;
|
||||
JSFunction *fun = js_DefineFunction(cx, ctor, id, js_generic_native_method_dispatcher,
|
||||
fs->nargs + 1, flags,
|
||||
JSFunction::ExtendedFinalizeKind);
|
||||
JSFunction *fun = DefineFunction(cx, ctor, id,
|
||||
js_generic_native_method_dispatcher,
|
||||
fs->nargs + 1, flags,
|
||||
JSFunction::ExtendedFinalizeKind);
|
||||
if (!fun)
|
||||
return JS_FALSE;
|
||||
|
||||
@ -4959,16 +4960,15 @@ JS_DefineFunctions(JSContext *cx, JSObject *objArg, JSFunctionSpec *fs)
|
||||
|
||||
/*
|
||||
* Delay cloning self-hosted functions until they are called. This is
|
||||
* achieved by passing js_DefineFunction a NULL JSNative which
|
||||
* achieved by passing DefineFunction a NULL JSNative which
|
||||
* produces an interpreted JSFunction where !hasScript. Interpreted
|
||||
* call paths then call InitializeLazyFunctionScript if !hasScript.
|
||||
*/
|
||||
if (fs->selfHostedName) {
|
||||
RootedFunction fun(cx, js_DefineFunction(cx, obj, id, /* native = */ NULL, fs->nargs, 0,
|
||||
JSFunction::ExtendedFinalizeKind));
|
||||
RootedFunction fun(cx, DefineFunction(cx, obj, id, /* native = */ NULL, fs->nargs, 0,
|
||||
JSFunction::ExtendedFinalizeKind, SingletonObject));
|
||||
if (!fun)
|
||||
return JS_FALSE;
|
||||
JSFunction::setSingletonType(cx, fun);
|
||||
fun->setIsSelfHostedBuiltin();
|
||||
fun->setExtendedSlot(0, PrivateValue(fs));
|
||||
RootedAtom shAtom(cx, Atomize(cx, fs->selfHostedName, strlen(fs->selfHostedName)));
|
||||
@ -4981,7 +4981,7 @@ JS_DefineFunctions(JSContext *cx, JSObject *objArg, JSFunctionSpec *fs)
|
||||
return JS_FALSE;
|
||||
}
|
||||
} else {
|
||||
JSFunction *fun = js_DefineFunction(cx, obj, id, fs->call.op, fs->nargs, flags);
|
||||
JSFunction *fun = DefineFunction(cx, obj, id, fs->call.op, fs->nargs, flags);
|
||||
if (!fun)
|
||||
return JS_FALSE;
|
||||
if (fs->call.info)
|
||||
@ -5004,7 +5004,7 @@ JS_DefineFunction(JSContext *cx, JSObject *objArg, const char *name, JSNative ca
|
||||
if (!atom)
|
||||
return NULL;
|
||||
Rooted<jsid> id(cx, AtomToId(atom));
|
||||
return js_DefineFunction(cx, obj, id, call, nargs, attrs);
|
||||
return DefineFunction(cx, obj, id, call, nargs, attrs);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSFunction *)
|
||||
@ -5021,7 +5021,7 @@ JS_DefineUCFunction(JSContext *cx, JSObject *objArg,
|
||||
if (!atom)
|
||||
return NULL;
|
||||
Rooted<jsid> id(cx, AtomToId(atom));
|
||||
return js_DefineFunction(cx, obj, id, call, nargs, attrs);
|
||||
return DefineFunction(cx, obj, id, call, nargs, attrs);
|
||||
}
|
||||
|
||||
extern JS_PUBLIC_API(JSFunction *)
|
||||
@ -5034,7 +5034,7 @@ JS_DefineFunctionById(JSContext *cx, JSObject *objArg, jsid id_, JSNative call,
|
||||
AssertHeapIsIdle(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
assertSameCompartment(cx, obj);
|
||||
return js_DefineFunction(cx, obj, id, call, nargs, attrs);
|
||||
return DefineFunction(cx, obj, id, call, nargs, attrs);
|
||||
}
|
||||
|
||||
struct AutoLastFrameCheck
|
||||
@ -5350,7 +5350,7 @@ JS::CompileFunction(JSContext *cx, HandleObject obj, CompileOptions options,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RootedFunction fun(cx, js_NewFunction(cx, NullPtr(), NULL, 0, JSFunction::INTERPRETED, obj, funAtom));
|
||||
RootedFunction fun(cx, NewFunction(cx, NullPtr(), NULL, 0, JSFunction::INTERPRETED, obj, funAtom));
|
||||
if (!fun)
|
||||
return NULL;
|
||||
|
||||
@ -6142,7 +6142,7 @@ JS_GetStringEncodingLength(JSContext *cx, JSString *str)
|
||||
const jschar *chars = str->getChars(cx);
|
||||
if (!chars)
|
||||
return size_t(-1);
|
||||
return GetDeflatedStringLength(cx, chars, str->length());
|
||||
return str->length();
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(size_t)
|
||||
@ -6165,7 +6165,7 @@ JS_EncodeStringToBuffer(JSContext *cx, JSString *str, char *buffer, size_t lengt
|
||||
return writtenLength;
|
||||
}
|
||||
JS_ASSERT(writtenLength <= length);
|
||||
size_t necessaryLength = GetDeflatedStringLength(NULL, chars, str->length());
|
||||
size_t necessaryLength = str->length();
|
||||
if (necessaryLength == size_t(-1))
|
||||
return size_t(-1);
|
||||
JS_ASSERT(writtenLength == length); // C strings are NOT encoded.
|
||||
|
1188
js/src/jsapi.h
1188
js/src/jsapi.h
File diff suppressed because it is too large
Load Diff
@ -2456,7 +2456,7 @@ js_InitArrayClass(JSContext *cx, HandleObject obj)
|
||||
RootedShape shape(cx, EmptyShape::getInitialShape(cx, &ArrayClass, TaggedProto(proto), proto->getParent(),
|
||||
gc::FINALIZE_OBJECT0));
|
||||
|
||||
RootedObject arrayProto(cx, JSObject::createArray(cx, gc::FINALIZE_OBJECT4, shape, type, 0));
|
||||
RootedObject arrayProto(cx, JSObject::createArray(cx, gc::FINALIZE_OBJECT4, gc::TenuredHeap, shape, type, 0));
|
||||
if (!arrayProto || !JSObject::setSingletonType(cx, arrayProto) || !AddLengthProperty(cx, arrayProto))
|
||||
return NULL;
|
||||
|
||||
@ -2512,17 +2512,19 @@ EnsureNewArrayElements(JSContext *cx, JSObject *obj, uint32_t length)
|
||||
|
||||
template<bool allocateCapacity>
|
||||
static JS_ALWAYS_INLINE JSObject *
|
||||
NewArray(JSContext *cx, uint32_t length, RawObject protoArg)
|
||||
NewArray(JSContext *cx, uint32_t length, RawObject protoArg, NewObjectKind newKind = GenericObject)
|
||||
{
|
||||
gc::AllocKind kind = GuessArrayGCKind(length);
|
||||
JS_ASSERT(CanBeFinalizedInBackground(kind, &ArrayClass));
|
||||
kind = GetBackgroundAllocKind(kind);
|
||||
gc::AllocKind allocKind = GuessArrayGCKind(length);
|
||||
JS_ASSERT(CanBeFinalizedInBackground(allocKind, &ArrayClass));
|
||||
allocKind = GetBackgroundAllocKind(allocKind);
|
||||
|
||||
NewObjectCache &cache = cx->runtime->newObjectCache;
|
||||
|
||||
NewObjectCache::EntryIndex entry = -1;
|
||||
if (cache.lookupGlobal(&ArrayClass, cx->global(), kind, &entry)) {
|
||||
RootedObject obj(cx, cache.newObjectFromHit(cx, entry));
|
||||
if (newKind != SingletonObject &&
|
||||
cache.lookupGlobal(&ArrayClass, cx->global(), allocKind, &entry))
|
||||
{
|
||||
RootedObject obj(cx, cache.newObjectFromHit(cx, entry, InitialHeapForNewKind(newKind)));
|
||||
if (obj) {
|
||||
/* Fixup the elements pointer and length, which may be incorrect. */
|
||||
obj->setFixedElements();
|
||||
@ -2553,7 +2555,7 @@ NewArray(JSContext *cx, uint32_t length, RawObject protoArg)
|
||||
if (!shape)
|
||||
return NULL;
|
||||
|
||||
RootedObject obj(cx, JSObject::createArray(cx, kind, shape, type, length));
|
||||
RootedObject obj(cx, JSObject::createArray(cx, allocKind, gc::DefaultHeap, shape, type, length));
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
@ -2564,8 +2566,11 @@ NewArray(JSContext *cx, uint32_t length, RawObject protoArg)
|
||||
EmptyShape::insertInitialShape(cx, shape, proto);
|
||||
}
|
||||
|
||||
if (newKind == SingletonObject && !JSObject::setSingletonType(cx, obj))
|
||||
return NULL;
|
||||
|
||||
if (entry != -1)
|
||||
cache.fillGlobal(entry, &ArrayClass, cx->global(), kind, obj);
|
||||
cache.fillGlobal(entry, &ArrayClass, cx->global(), allocKind, obj);
|
||||
|
||||
if (allocateCapacity && !EnsureNewArrayElements(cx, obj, length))
|
||||
return NULL;
|
||||
@ -2575,19 +2580,22 @@ NewArray(JSContext *cx, uint32_t length, RawObject protoArg)
|
||||
}
|
||||
|
||||
JSObject * JS_FASTCALL
|
||||
js::NewDenseEmptyArray(JSContext *cx, RawObject proto /* = NULL */)
|
||||
js::NewDenseEmptyArray(JSContext *cx, RawObject proto /* = NULL */,
|
||||
NewObjectKind newKind /* = GenericObject */)
|
||||
{
|
||||
return NewArray<false>(cx, 0, proto);
|
||||
}
|
||||
|
||||
JSObject * JS_FASTCALL
|
||||
js::NewDenseAllocatedArray(JSContext *cx, uint32_t length, RawObject proto /* = NULL */)
|
||||
js::NewDenseAllocatedArray(JSContext *cx, uint32_t length, RawObject proto /* = NULL */,
|
||||
NewObjectKind newKind /* = GenericObject */)
|
||||
{
|
||||
return NewArray<true>(cx, length, proto);
|
||||
return NewArray<true>(cx, length, proto, newKind);
|
||||
}
|
||||
|
||||
JSObject * JS_FASTCALL
|
||||
js::NewDenseUnallocatedArray(JSContext *cx, uint32_t length, RawObject proto /* = NULL */)
|
||||
js::NewDenseUnallocatedArray(JSContext *cx, uint32_t length, RawObject proto /* = NULL */,
|
||||
NewObjectKind newKind /* = GenericObject */)
|
||||
{
|
||||
return NewArray<false>(cx, length, proto);
|
||||
}
|
||||
@ -2628,7 +2636,7 @@ js::NewDenseCopiedArray(JSContext *cx, uint32_t length, HandleObject src, uint32
|
||||
// values must point at already-rooted Value objects
|
||||
JSObject *
|
||||
js::NewDenseCopiedArray(JSContext *cx, uint32_t length, const Value *values,
|
||||
RawObject proto /* = NULL */)
|
||||
RawObject proto /* = NULL */, NewObjectKind newKind /* = GenericObject */)
|
||||
{
|
||||
JSObject* obj = NewArray<true>(cx, length, proto);
|
||||
if (!obj)
|
||||
|
@ -46,18 +46,21 @@ namespace js {
|
||||
|
||||
/* Create a dense array with no capacity allocated, length set to 0. */
|
||||
extern JSObject * JS_FASTCALL
|
||||
NewDenseEmptyArray(JSContext *cx, RawObject proto = NULL);
|
||||
NewDenseEmptyArray(JSContext *cx, RawObject proto = NULL,
|
||||
NewObjectKind newKind = GenericObject);
|
||||
|
||||
/* Create a dense array with length and capacity == 'length', initialized length set to 0. */
|
||||
extern JSObject * JS_FASTCALL
|
||||
NewDenseAllocatedArray(JSContext *cx, uint32_t length, RawObject proto = NULL);
|
||||
NewDenseAllocatedArray(JSContext *cx, uint32_t length, RawObject proto = NULL,
|
||||
NewObjectKind newKind = GenericObject);
|
||||
|
||||
/*
|
||||
* Create a dense array with a set length, but without allocating space for the
|
||||
* contents. This is useful, e.g., when accepting length from the user.
|
||||
*/
|
||||
extern JSObject * JS_FASTCALL
|
||||
NewDenseUnallocatedArray(JSContext *cx, uint32_t length, RawObject proto = NULL);
|
||||
NewDenseUnallocatedArray(JSContext *cx, uint32_t length, RawObject proto = NULL,
|
||||
NewObjectKind newKind = GenericObject);
|
||||
|
||||
/* Create a dense array with a copy of the dense array elements in src. */
|
||||
extern JSObject *
|
||||
@ -65,7 +68,8 @@ NewDenseCopiedArray(JSContext *cx, uint32_t length, HandleObject src, uint32_t e
|
||||
|
||||
/* Create a dense array from the given array values, which must be rooted */
|
||||
extern JSObject *
|
||||
NewDenseCopiedArray(JSContext *cx, uint32_t length, const Value *values, RawObject proto = NULL);
|
||||
NewDenseCopiedArray(JSContext *cx, uint32_t length, const Value *values, RawObject proto = NULL,
|
||||
NewObjectKind newKind = GenericObject);
|
||||
|
||||
/* Get the common shape used by all dense arrays with a prototype at globalObj. */
|
||||
extern UnrootedShape
|
||||
|
@ -167,8 +167,8 @@ js_InitBooleanClass(JSContext *cx, HandleObject obj)
|
||||
|
||||
Handle<PropertyName*> valueOfName = cx->names().valueOf;
|
||||
RootedFunction
|
||||
valueOf(cx, js_NewFunction(cx, NullPtr(), bool_valueOf, 0, JSFunction::NATIVE_FUN,
|
||||
global, valueOfName));
|
||||
valueOf(cx, NewFunction(cx, NullPtr(), bool_valueOf, 0, JSFunction::NATIVE_FUN,
|
||||
global, valueOfName));
|
||||
if (!valueOf)
|
||||
return NULL;
|
||||
|
||||
|
@ -341,7 +341,7 @@ class NewObjectCache
|
||||
* NULL if returning the object could possibly trigger GC (does not
|
||||
* indicate failure).
|
||||
*/
|
||||
inline JSObject *newObjectFromHit(JSContext *cx, EntryIndex entry);
|
||||
inline JSObject *newObjectFromHit(JSContext *cx, EntryIndex entry, js::gc::InitialHeap heap);
|
||||
|
||||
/* Fill an entry after a cache miss. */
|
||||
inline void fillProto(EntryIndex entry, Class *clasp, js::TaggedProto proto, gc::AllocKind kind, JSObject *obj);
|
||||
|
@ -100,12 +100,12 @@ NewObjectCache::fillType(EntryIndex entry, Class *clasp, js::types::TypeObject *
|
||||
}
|
||||
|
||||
inline JSObject *
|
||||
NewObjectCache::newObjectFromHit(JSContext *cx, EntryIndex entry_)
|
||||
NewObjectCache::newObjectFromHit(JSContext *cx, EntryIndex entry_, js::gc::InitialHeap heap)
|
||||
{
|
||||
JS_ASSERT(unsigned(entry_) < mozilla::ArrayLength(entries));
|
||||
Entry *entry = &entries[entry_];
|
||||
|
||||
JSObject *obj = js_NewGCObject<NoGC>(cx, entry->kind);
|
||||
JSObject *obj = js_NewGCObject<NoGC>(cx, entry->kind, heap);
|
||||
if (obj) {
|
||||
copyCachedToObject(obj, reinterpret_cast<JSObject *>(&entry->templateObject));
|
||||
Probes::createObject(cx, obj);
|
||||
|
@ -392,8 +392,7 @@ struct JSCompartment : private JS::shadow::Zone, public js::gc::GraphNodeBase<JS
|
||||
js::types::TypeObject *getNewType(JSContext *cx, js::Class *clasp, js::TaggedProto proto,
|
||||
JSFunction *fun = NULL);
|
||||
|
||||
js::types::TypeObject *getLazyType(JSContext *cx, js::Class *clasp,
|
||||
js::Handle<js::TaggedProto> proto);
|
||||
js::types::TypeObject *getLazyType(JSContext *cx, js::Class *clasp, js::TaggedProto proto);
|
||||
|
||||
/*
|
||||
* Hash table of all manually call site-cloned functions from within
|
||||
|
@ -119,8 +119,8 @@ JS_NewObjectWithUniqueType(JSContext *cx, JSClass *clasp, JSObject *protoArg, JS
|
||||
* TypeObject attached to our proto with information about our object, since
|
||||
* we're not going to be using that TypeObject anyway.
|
||||
*/
|
||||
RootedObject obj(cx, JS_NewObjectWithGivenProto(cx, clasp, NULL, parent));
|
||||
if (!obj || !JSObject::setSingletonType(cx, obj))
|
||||
RootedObject obj(cx, NewObjectWithGivenProto(cx, (js::Class *)clasp, NULL, parent, SingletonObject));
|
||||
if (!obj)
|
||||
return NULL;
|
||||
if (!JS_SplicePrototype(cx, obj, proto))
|
||||
return NULL;
|
||||
@ -276,7 +276,7 @@ JS_DefineFunctionsWithHelp(JSContext *cx, JSObject *objArg, const JSFunctionSpec
|
||||
return false;
|
||||
|
||||
Rooted<jsid> id(cx, AtomToId(atom));
|
||||
RootedFunction fun(cx, js_DefineFunction(cx, obj, id, fs->call, fs->nargs, fs->flags));
|
||||
RootedFunction fun(cx, DefineFunction(cx, obj, id, fs->call, fs->nargs, fs->flags));
|
||||
if (!fun)
|
||||
return false;
|
||||
|
||||
@ -401,7 +401,7 @@ js::DefineFunctionWithReserved(JSContext *cx, JSObject *objArg, const char *name
|
||||
if (!atom)
|
||||
return NULL;
|
||||
Rooted<jsid> id(cx, AtomToId(atom));
|
||||
return js_DefineFunction(cx, obj, id, call, nargs, attrs, JSFunction::ExtendedFinalizeKind);
|
||||
return DefineFunction(cx, obj, id, call, nargs, attrs, JSFunction::ExtendedFinalizeKind);
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSFunction *)
|
||||
@ -422,8 +422,8 @@ js::NewFunctionWithReserved(JSContext *cx, JSNative native, unsigned nargs, unsi
|
||||
}
|
||||
|
||||
JSFunction::Flags funFlags = JSAPIToJSFunctionFlags(flags);
|
||||
return js_NewFunction(cx, NullPtr(), native, nargs, funFlags, parent, atom,
|
||||
JSFunction::ExtendedFinalizeKind);
|
||||
return NewFunction(cx, NullPtr(), native, nargs, funFlags, parent, atom,
|
||||
JSFunction::ExtendedFinalizeKind);
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSFunction *)
|
||||
@ -438,8 +438,8 @@ js::NewFunctionByIdWithReserved(JSContext *cx, JSNative native, unsigned nargs,
|
||||
|
||||
RootedAtom atom(cx, JSID_TO_ATOM(id));
|
||||
JSFunction::Flags funFlags = JSAPIToJSFunctionFlags(flags);
|
||||
return js_NewFunction(cx, NullPtr(), native, nargs, funFlags, parent, atom,
|
||||
JSFunction::ExtendedFinalizeKind);
|
||||
return NewFunction(cx, NullPtr(), native, nargs, funFlags, parent, atom,
|
||||
JSFunction::ExtendedFinalizeKind);
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSObject *)
|
||||
|
@ -266,8 +266,8 @@ ResolveInterpretedFunctionPrototype(JSContext *cx, HandleObject obj)
|
||||
RawObject objProto = obj->global().getOrCreateObjectPrototype(cx);
|
||||
if (!objProto)
|
||||
return NULL;
|
||||
RootedObject proto(cx, NewObjectWithGivenProto(cx, &ObjectClass, objProto, NULL));
|
||||
if (!proto || !JSObject::setSingletonType(cx, proto))
|
||||
RootedObject proto(cx, NewObjectWithGivenProto(cx, &ObjectClass, objProto, NULL, SingletonObject));
|
||||
if (!proto)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
@ -407,7 +407,7 @@ js::XDRInterpretedFunction(XDRState<mode> *xdr, HandleObject enclosingScope, Han
|
||||
atom = fun->atom();
|
||||
script = fun->nonLazyScript();
|
||||
} else {
|
||||
fun = js_NewFunction(cx, NullPtr(), NULL, 0, JSFunction::INTERPRETED, NullPtr(), NullPtr());
|
||||
fun = NewFunction(cx, NullPtr(), NULL, 0, JSFunction::INTERPRETED, NullPtr(), NullPtr());
|
||||
if (!fun)
|
||||
return false;
|
||||
atom = NULL;
|
||||
@ -454,8 +454,8 @@ js::CloneInterpretedFunction(JSContext *cx, HandleObject enclosingScope, HandleF
|
||||
|
||||
/* NB: Keep this in sync with XDRInterpretedFunction. */
|
||||
|
||||
RootedFunction clone(cx, js_NewFunction(cx, NullPtr(), NULL, 0,
|
||||
JSFunction::INTERPRETED, NullPtr(), NullPtr()));
|
||||
RootedFunction clone(cx, NewFunction(cx, NullPtr(), NULL, 0,
|
||||
JSFunction::INTERPRETED, NullPtr(), NullPtr()));
|
||||
if (!clone)
|
||||
return NULL;
|
||||
|
||||
@ -1177,8 +1177,8 @@ js_fun_bind(JSContext *cx, HandleObject target, HandleValue thisArg,
|
||||
/* Step 4-6, 10-11. */
|
||||
RootedAtom name(cx, target->isFunction() ? target->toFunction()->atom() : NULL);
|
||||
|
||||
RootedObject funobj(cx, js_NewFunction(cx, NullPtr(), CallOrConstructBoundFunction, length,
|
||||
JSFunction::NATIVE_CTOR, target, name));
|
||||
RootedObject funobj(cx, NewFunction(cx, NullPtr(), CallOrConstructBoundFunction, length,
|
||||
JSFunction::NATIVE_CTOR, target, name));
|
||||
if (!funobj)
|
||||
return NULL;
|
||||
|
||||
@ -1403,8 +1403,8 @@ js::Function(JSContext *cx, unsigned argc, Value *vp)
|
||||
* and so would a call to f from another top-level's script or function.
|
||||
*/
|
||||
RootedAtom anonymousAtom(cx, cx->names().anonymous);
|
||||
RootedFunction fun(cx, js_NewFunction(cx, NullPtr(), NULL, 0, JSFunction::INTERPRETED_LAMBDA,
|
||||
global, anonymousAtom));
|
||||
RootedFunction fun(cx, NewFunction(cx, NullPtr(), NULL, 0, JSFunction::INTERPRETED_LAMBDA,
|
||||
global, anonymousAtom));
|
||||
if (!fun)
|
||||
return false;
|
||||
|
||||
@ -1423,11 +1423,12 @@ js::IsBuiltinFunctionConstructor(JSFunction *fun)
|
||||
}
|
||||
|
||||
JSFunction *
|
||||
js_NewFunction(JSContext *cx, HandleObject funobjArg, Native native, unsigned nargs,
|
||||
JSFunction::Flags flags, HandleObject parent, HandleAtom atom,
|
||||
js::gc::AllocKind kind)
|
||||
js::NewFunction(JSContext *cx, HandleObject funobjArg, Native native, unsigned nargs,
|
||||
JSFunction::Flags flags, HandleObject parent, HandleAtom atom,
|
||||
gc::AllocKind allocKind /* = JSFunction::FinalizeKind */,
|
||||
NewObjectKind newKind /* = GenericObject */)
|
||||
{
|
||||
JS_ASSERT(kind == JSFunction::FinalizeKind || kind == JSFunction::ExtendedFinalizeKind);
|
||||
JS_ASSERT(allocKind == JSFunction::FinalizeKind || allocKind == JSFunction::ExtendedFinalizeKind);
|
||||
JS_ASSERT(sizeof(JSFunction) <= gc::Arena::thingSize(JSFunction::FinalizeKind));
|
||||
JS_ASSERT(sizeof(FunctionExtended) <= gc::Arena::thingSize(JSFunction::ExtendedFinalizeKind));
|
||||
|
||||
@ -1435,8 +1436,11 @@ js_NewFunction(JSContext *cx, HandleObject funobjArg, Native native, unsigned na
|
||||
if (funobj) {
|
||||
JS_ASSERT(funobj->isFunction());
|
||||
JS_ASSERT(funobj->getParent() == parent);
|
||||
JS_ASSERT_IF(native && cx->typeInferenceEnabled(), funobj->hasSingletonType());
|
||||
} else {
|
||||
funobj = NewObjectWithClassProto(cx, &FunctionClass, NULL, SkipScopeParent(parent), kind);
|
||||
if (native)
|
||||
newKind = SingletonObject;
|
||||
funobj = NewObjectWithClassProto(cx, &FunctionClass, NULL, SkipScopeParent(parent), allocKind, newKind);
|
||||
if (!funobj)
|
||||
return NULL;
|
||||
}
|
||||
@ -1454,28 +1458,28 @@ js_NewFunction(JSContext *cx, HandleObject funobjArg, Native native, unsigned na
|
||||
JS_ASSERT(native);
|
||||
fun->initNative(native, NULL);
|
||||
}
|
||||
if (kind == JSFunction::ExtendedFinalizeKind) {
|
||||
if (allocKind == JSFunction::ExtendedFinalizeKind) {
|
||||
fun->flags |= JSFunction::EXTENDED;
|
||||
fun->initializeExtended();
|
||||
}
|
||||
fun->initAtom(atom);
|
||||
|
||||
if (native && !JSObject::setSingletonType(cx, fun))
|
||||
return NULL;
|
||||
|
||||
return fun;
|
||||
}
|
||||
|
||||
JSFunction *
|
||||
js::CloneFunctionObject(JSContext *cx, HandleFunction fun, HandleObject parent,
|
||||
gc::AllocKind kind)
|
||||
js::CloneFunctionObject(JSContext *cx, HandleFunction fun, HandleObject parent, gc::AllocKind allocKind)
|
||||
{
|
||||
AssertCanGC();
|
||||
JS_ASSERT(parent);
|
||||
JS_ASSERT(!fun->isBoundFunction());
|
||||
|
||||
JSObject *cloneobj =
|
||||
NewObjectWithClassProto(cx, &FunctionClass, NULL, SkipScopeParent(parent), kind);
|
||||
bool useSameScript = cx->compartment == fun->compartment() &&
|
||||
!fun->hasSingletonType() &&
|
||||
!types::UseNewTypeForClone(fun);
|
||||
NewObjectKind newKind = useSameScript ? GenericObject : SingletonObject;
|
||||
JSObject *cloneobj = NewObjectWithClassProto(cx, &FunctionClass, NULL, SkipScopeParent(parent),
|
||||
allocKind, newKind);
|
||||
if (!cloneobj)
|
||||
return NULL;
|
||||
JSFunction *clone = cloneobj->toFunction();
|
||||
@ -1497,15 +1501,12 @@ js::CloneFunctionObject(JSContext *cx, HandleFunction fun, HandleObject parent,
|
||||
}
|
||||
clone->initAtom(fun->displayAtom());
|
||||
|
||||
if (kind == JSFunction::ExtendedFinalizeKind) {
|
||||
if (allocKind == JSFunction::ExtendedFinalizeKind) {
|
||||
clone->flags |= JSFunction::EXTENDED;
|
||||
clone->initializeExtended();
|
||||
}
|
||||
|
||||
if (cx->compartment == fun->compartment() &&
|
||||
!fun->hasSingletonType() &&
|
||||
!types::UseNewTypeForClone(fun))
|
||||
{
|
||||
if (useSameScript) {
|
||||
/*
|
||||
* Clone the function, reusing its script. We can use the same type as
|
||||
* the original function provided that its prototype is correct.
|
||||
@ -1517,9 +1518,6 @@ js::CloneFunctionObject(JSContext *cx, HandleFunction fun, HandleObject parent,
|
||||
|
||||
RootedFunction cloneRoot(cx, clone);
|
||||
|
||||
if (!JSObject::setSingletonType(cx, cloneRoot))
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* Across compartments we have to clone the script for interpreted
|
||||
* functions. Cross-compartment cloning only happens via JSAPI
|
||||
@ -1533,8 +1531,9 @@ js::CloneFunctionObject(JSContext *cx, HandleFunction fun, HandleObject parent,
|
||||
}
|
||||
|
||||
JSFunction *
|
||||
js_DefineFunction(JSContext *cx, HandleObject obj, HandleId id, Native native,
|
||||
unsigned nargs, unsigned flags, AllocKind kind)
|
||||
js::DefineFunction(JSContext *cx, HandleObject obj, HandleId id, Native native,
|
||||
unsigned nargs, unsigned flags, AllocKind allocKind /* = FinalizeKind */,
|
||||
NewObjectKind newKind /* = GenericObject */)
|
||||
{
|
||||
PropertyOp gop;
|
||||
StrictPropertyOp sop;
|
||||
@ -1562,7 +1561,7 @@ js_DefineFunction(JSContext *cx, HandleObject obj, HandleId id, Native native,
|
||||
else
|
||||
funFlags = JSAPIToJSFunctionFlags(flags);
|
||||
RootedAtom atom(cx, JSID_IS_ATOM(id) ? JSID_TO_ATOM(id) : NULL);
|
||||
fun = js_NewFunction(cx, NullPtr(), native, nargs, funFlags, obj, atom, kind);
|
||||
fun = NewFunction(cx, NullPtr(), native, nargs, funFlags, obj, atom, allocKind, newKind);
|
||||
if (!fun)
|
||||
return NULL;
|
||||
|
||||
|
@ -331,18 +331,20 @@ JSAPIToJSFunctionFlags(unsigned flags)
|
||||
: JSFunction::NATIVE_FUN;
|
||||
}
|
||||
|
||||
extern JSFunction *
|
||||
js_NewFunction(JSContext *cx, js::HandleObject funobj, JSNative native, unsigned nargs,
|
||||
JSFunction::Flags flags, js::HandleObject parent, js::HandleAtom atom,
|
||||
js::gc::AllocKind kind = JSFunction::FinalizeKind);
|
||||
|
||||
extern JSFunction *
|
||||
js_DefineFunction(JSContext *cx, js::HandleObject obj, js::HandleId id, JSNative native,
|
||||
unsigned nargs, unsigned flags,
|
||||
js::gc::AllocKind kind = JSFunction::FinalizeKind);
|
||||
|
||||
namespace js {
|
||||
|
||||
extern JSFunction *
|
||||
NewFunction(JSContext *cx, HandleObject funobj, JSNative native, unsigned nargs,
|
||||
JSFunction::Flags flags, HandleObject parent, HandleAtom atom,
|
||||
gc::AllocKind allocKind = JSFunction::FinalizeKind,
|
||||
NewObjectKind newKind = GenericObject);
|
||||
|
||||
extern JSFunction *
|
||||
DefineFunction(JSContext *cx, HandleObject obj, HandleId id, JSNative native,
|
||||
unsigned nargs, unsigned flags,
|
||||
gc::AllocKind allocKind = JSFunction::FinalizeKind,
|
||||
NewObjectKind newKind = GenericObject);
|
||||
|
||||
/*
|
||||
* Function extended with reserved slots for use by various kinds of functions.
|
||||
* Most functions do not have these extensions, but enough are that efficient
|
||||
|
@ -480,7 +480,7 @@ typedef GCCompartmentGroupIter GCZoneGroupIter;
|
||||
|
||||
template <typename T, AllowGC allowGC>
|
||||
inline T *
|
||||
NewGCThing(JSContext *cx, js::gc::AllocKind kind, size_t thingSize)
|
||||
NewGCThing(JSContext *cx, AllocKind kind, size_t thingSize, InitialHeap heap)
|
||||
{
|
||||
if (allowGC)
|
||||
AssertCanGC();
|
||||
@ -513,8 +513,10 @@ NewGCThing(JSContext *cx, js::gc::AllocKind kind, size_t thingSize)
|
||||
t->arenaHeader()->allocatedDuringIncremental);
|
||||
|
||||
#if defined(JSGC_GENERATIONAL) && defined(JS_GC_ZEAL)
|
||||
if (cx->runtime->gcVerifyPostData && IsNurseryAllocable(kind)
|
||||
&& !IsAtomsCompartment(cx->compartment))
|
||||
if (cx->runtime->gcVerifyPostData &&
|
||||
IsNurseryAllocable(kind) &&
|
||||
!IsAtomsCompartment(cx->compartment) &&
|
||||
heap != TenuredHeap)
|
||||
{
|
||||
zone->gcNursery.insertPointer(t);
|
||||
}
|
||||
@ -557,50 +559,55 @@ class AutoSuppressGC
|
||||
|
||||
template <js::AllowGC allowGC>
|
||||
inline JSObject *
|
||||
js_NewGCObject(JSContext *cx, js::gc::AllocKind kind)
|
||||
js_NewGCObject(JSContext *cx, js::gc::AllocKind kind, js::gc::InitialHeap heap)
|
||||
{
|
||||
JS_ASSERT(kind >= js::gc::FINALIZE_OBJECT0 && kind <= js::gc::FINALIZE_OBJECT_LAST);
|
||||
return js::gc::NewGCThing<JSObject, allowGC>(cx, kind, js::gc::Arena::thingSize(kind));
|
||||
return js::gc::NewGCThing<JSObject, allowGC>(cx, kind, js::gc::Arena::thingSize(kind), heap);
|
||||
}
|
||||
|
||||
template <js::AllowGC allowGC>
|
||||
inline JSString *
|
||||
js_NewGCString(JSContext *cx)
|
||||
{
|
||||
return js::gc::NewGCThing<JSString, allowGC>(cx, js::gc::FINALIZE_STRING, sizeof(JSString));
|
||||
return js::gc::NewGCThing<JSString, allowGC>(cx, js::gc::FINALIZE_STRING,
|
||||
sizeof(JSString), js::gc::TenuredHeap);
|
||||
}
|
||||
|
||||
template <js::AllowGC allowGC>
|
||||
inline JSShortString *
|
||||
js_NewGCShortString(JSContext *cx)
|
||||
{
|
||||
return js::gc::NewGCThing<JSShortString, allowGC>(cx, js::gc::FINALIZE_SHORT_STRING, sizeof(JSShortString));
|
||||
return js::gc::NewGCThing<JSShortString, allowGC>(cx, js::gc::FINALIZE_SHORT_STRING,
|
||||
sizeof(JSShortString), js::gc::TenuredHeap);
|
||||
}
|
||||
|
||||
inline JSExternalString *
|
||||
js_NewGCExternalString(JSContext *cx)
|
||||
{
|
||||
return js::gc::NewGCThing<JSExternalString, js::CanGC>(cx, js::gc::FINALIZE_EXTERNAL_STRING,
|
||||
sizeof(JSExternalString));
|
||||
sizeof(JSExternalString), js::gc::TenuredHeap);
|
||||
}
|
||||
|
||||
inline JSScript *
|
||||
js_NewGCScript(JSContext *cx)
|
||||
{
|
||||
return js::gc::NewGCThing<JSScript, js::CanGC>(cx, js::gc::FINALIZE_SCRIPT, sizeof(JSScript));
|
||||
return js::gc::NewGCThing<JSScript, js::CanGC>(cx, js::gc::FINALIZE_SCRIPT,
|
||||
sizeof(JSScript), js::gc::TenuredHeap);
|
||||
}
|
||||
|
||||
inline js::UnrootedShape
|
||||
js_NewGCShape(JSContext *cx)
|
||||
{
|
||||
return js::gc::NewGCThing<js::Shape, js::CanGC>(cx, js::gc::FINALIZE_SHAPE, sizeof(js::Shape));
|
||||
return js::gc::NewGCThing<js::Shape, js::CanGC>(cx, js::gc::FINALIZE_SHAPE,
|
||||
sizeof(js::Shape), js::gc::TenuredHeap);
|
||||
}
|
||||
|
||||
template <js::AllowGC allowGC>
|
||||
inline js::UnrootedBaseShape
|
||||
js_NewGCBaseShape(JSContext *cx)
|
||||
{
|
||||
return js::gc::NewGCThing<js::BaseShape, allowGC>(cx, js::gc::FINALIZE_BASE_SHAPE, sizeof(js::BaseShape));
|
||||
return js::gc::NewGCThing<js::BaseShape, allowGC>(cx, js::gc::FINALIZE_BASE_SHAPE,
|
||||
sizeof(js::BaseShape), js::gc::TenuredHeap);
|
||||
}
|
||||
|
||||
#endif /* jsgcinlines_h___ */
|
||||
|
@ -2389,7 +2389,8 @@ TypeCompartment::newTypeObject(JSContext *cx, Class *clasp, Handle<TaggedProto>
|
||||
{
|
||||
JS_ASSERT_IF(proto.isObject(), cx->compartment == proto.toObject()->compartment());
|
||||
|
||||
TypeObject *object = gc::NewGCThing<TypeObject, CanGC>(cx, gc::FINALIZE_TYPE_OBJECT, sizeof(TypeObject));
|
||||
TypeObject *object = gc::NewGCThing<TypeObject, CanGC>(cx, gc::FINALIZE_TYPE_OBJECT,
|
||||
sizeof(TypeObject), gc::TenuredHeap);
|
||||
if (!object)
|
||||
return NULL;
|
||||
new(object) TypeObject(clasp, proto, clasp == &FunctionClass, unknown);
|
||||
@ -2584,7 +2585,7 @@ types::UseNewType(JSContext *cx, JSScript *script, jsbytecode *pc)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
NewObjectKind
|
||||
types::UseNewTypeForInitializer(JSContext *cx, JSScript *script, jsbytecode *pc, JSProtoKey key)
|
||||
{
|
||||
/*
|
||||
@ -2594,17 +2595,26 @@ types::UseNewTypeForInitializer(JSContext *cx, JSScript *script, jsbytecode *pc,
|
||||
*/
|
||||
|
||||
if (!cx->typeInferenceEnabled() || (script->function() && !script->treatAsRunOnce))
|
||||
return false;
|
||||
return GenericObject;
|
||||
|
||||
if (key != JSProto_Object && !(key >= JSProto_Int8Array && key <= JSProto_Uint8ClampedArray))
|
||||
return false;
|
||||
return GenericObject;
|
||||
|
||||
AutoEnterAnalysis enter(cx);
|
||||
|
||||
if (!script->ensureRanAnalysis(cx))
|
||||
return false;
|
||||
return GenericObject;
|
||||
|
||||
return !script->analysis()->getCode(pc).inLoop;
|
||||
if (script->analysis()->getCode(pc).inLoop)
|
||||
return GenericObject;
|
||||
|
||||
return SingletonObject;
|
||||
}
|
||||
|
||||
NewObjectKind
|
||||
types::UseNewTypeForInitializer(JSContext *cx, JSScript *script, jsbytecode *pc, Class *clasp)
|
||||
{
|
||||
return UseNewTypeForInitializer(cx, script, pc, JSCLASS_CACHED_PROTO_KEY(clasp));
|
||||
}
|
||||
|
||||
static inline bool
|
||||
@ -5823,7 +5833,7 @@ JSScript::makeAnalysis(JSContext *cx)
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
JSFunction::setTypeForScriptedFunction(JSContext *cx, HandleFunction fun, bool singleton)
|
||||
JSFunction::setTypeForScriptedFunction(JSContext *cx, HandleFunction fun, bool singleton /* = false */)
|
||||
{
|
||||
JS_ASSERT(fun->nonLazyScript());
|
||||
JS_ASSERT(fun->nonLazyScript()->function() == fun);
|
||||
@ -6190,12 +6200,12 @@ JSObject::getNewType(JSContext *cx, Class *clasp, JSFunction *fun)
|
||||
}
|
||||
|
||||
TypeObject *
|
||||
JSCompartment::getLazyType(JSContext *cx, Class *clasp, Handle<TaggedProto> proto)
|
||||
JSCompartment::getLazyType(JSContext *cx, Class *clasp, TaggedProto proto)
|
||||
{
|
||||
JS_ASSERT(cx->compartment == this);
|
||||
JS_ASSERT_IF(proto.isObject(), cx->compartment == proto.toObject()->compartment());
|
||||
|
||||
MaybeCheckStackRoots(cx);
|
||||
AutoEnterAnalysis enter(cx);
|
||||
|
||||
TypeObjectSet &table = cx->compartment->lazyTypeObjects;
|
||||
|
||||
@ -6210,7 +6220,8 @@ JSCompartment::getLazyType(JSContext *cx, Class *clasp, Handle<TaggedProto> prot
|
||||
return type;
|
||||
}
|
||||
|
||||
TypeObject *type = cx->compartment->types.newTypeObject(cx, clasp, proto, false);
|
||||
Rooted<TaggedProto> protoRoot(cx, proto);
|
||||
TypeObject *type = cx->compartment->types.newTypeObject(cx, clasp, protoRoot, false);
|
||||
if (!type)
|
||||
return NULL;
|
||||
|
||||
|
@ -1122,10 +1122,6 @@ typedef HashSet<ReadBarriered<TypeObject>, TypeObjectEntry, SystemAllocPolicy> T
|
||||
bool
|
||||
UseNewType(JSContext *cx, JSScript *script, jsbytecode *pc);
|
||||
|
||||
/* Whether to use a new type object for an initializer opcode at script/pc. */
|
||||
bool
|
||||
UseNewTypeForInitializer(JSContext *cx, JSScript *script, jsbytecode *pc, JSProtoKey key);
|
||||
|
||||
/*
|
||||
* Whether Array.prototype, or an object on its proto chain, has an
|
||||
* indexed property.
|
||||
|
@ -868,6 +868,13 @@ struct AllocationSiteKey {
|
||||
}
|
||||
};
|
||||
|
||||
/* Whether to use a new type object for an initializer opcode at script/pc. */
|
||||
js::NewObjectKind
|
||||
UseNewTypeForInitializer(JSContext *cx, JSScript *script, jsbytecode *pc, JSProtoKey key);
|
||||
|
||||
js::NewObjectKind
|
||||
UseNewTypeForInitializer(JSContext *cx, JSScript *script, jsbytecode *pc, Class *clasp);
|
||||
|
||||
/* static */ inline TypeObject *
|
||||
TypeScript::InitObject(JSContext *cx, JSScript *script, jsbytecode *pc, JSProtoKey kind)
|
||||
{
|
||||
@ -896,17 +903,17 @@ TypeScript::InitObject(JSContext *cx, JSScript *script, jsbytecode *pc, JSProtoK
|
||||
|
||||
/* Set the type to use for obj according to the site it was allocated at. */
|
||||
static inline bool
|
||||
SetInitializerObjectType(JSContext *cx, HandleScript script, jsbytecode *pc, HandleObject obj)
|
||||
SetInitializerObjectType(JSContext *cx, HandleScript script, jsbytecode *pc, HandleObject obj, NewObjectKind kind)
|
||||
{
|
||||
if (!cx->typeInferenceEnabled())
|
||||
return true;
|
||||
|
||||
JSProtoKey key = JSCLASS_CACHED_PROTO_KEY(obj->getClass());
|
||||
JS_ASSERT(key != JSProto_Null);
|
||||
JS_ASSERT(kind == UseNewTypeForInitializer(cx, script, pc, key));
|
||||
|
||||
if (UseNewTypeForInitializer(cx, script, pc, key)) {
|
||||
if (!JSObject::setSingletonType(cx, obj))
|
||||
return false;
|
||||
if (kind == SingletonObject) {
|
||||
JS_ASSERT(obj->hasSingletonType());
|
||||
|
||||
/*
|
||||
* Inference does not account for types of run-once initializer
|
||||
|
@ -2625,8 +2625,12 @@ BEGIN_CASE(JSOP_REST)
|
||||
if (!rest)
|
||||
goto error;
|
||||
PUSH_COPY(ObjectValue(*rest));
|
||||
if (!SetInitializerObjectType(cx, script, regs.pc, rest))
|
||||
if (!SetInitializerObjectType(cx, script, regs.pc, rest, GenericObject))
|
||||
goto error;
|
||||
rootType0 = GetTypeCallerInitObject(cx, JSProto_Array);
|
||||
if (!rootType0)
|
||||
goto error;
|
||||
rest->setType(rootType0);
|
||||
}
|
||||
END_CASE(JSOP_REST)
|
||||
|
||||
@ -2851,13 +2855,16 @@ BEGIN_CASE(JSOP_NEWINIT)
|
||||
JS_ASSERT(i == JSProto_Array || i == JSProto_Object);
|
||||
|
||||
RootedObject &obj = rootObject0;
|
||||
NewObjectKind newKind;
|
||||
if (i == JSProto_Array) {
|
||||
obj = NewDenseEmptyArray(cx);
|
||||
newKind = UseNewTypeForInitializer(cx, script, regs.pc, &ArrayClass);
|
||||
obj = NewDenseEmptyArray(cx, NULL, newKind);
|
||||
} else {
|
||||
gc::AllocKind kind = GuessObjectGCKind(0);
|
||||
obj = NewBuiltinClassInstance(cx, &ObjectClass, kind);
|
||||
gc::AllocKind allocKind = GuessObjectGCKind(0);
|
||||
newKind = UseNewTypeForInitializer(cx, script, regs.pc, &ObjectClass);
|
||||
obj = NewBuiltinClassInstance(cx, &ObjectClass, allocKind, newKind);
|
||||
}
|
||||
if (!obj || !SetInitializerObjectType(cx, script, regs.pc, obj))
|
||||
if (!obj || !SetInitializerObjectType(cx, script, regs.pc, obj, newKind))
|
||||
goto error;
|
||||
|
||||
PUSH_OBJECT(*obj);
|
||||
@ -2869,8 +2876,9 @@ BEGIN_CASE(JSOP_NEWARRAY)
|
||||
{
|
||||
unsigned count = GET_UINT24(regs.pc);
|
||||
RootedObject &obj = rootObject0;
|
||||
obj = NewDenseAllocatedArray(cx, count);
|
||||
if (!obj || !SetInitializerObjectType(cx, script, regs.pc, obj))
|
||||
NewObjectKind newKind = UseNewTypeForInitializer(cx, script, regs.pc, &ArrayClass);
|
||||
obj = NewDenseAllocatedArray(cx, count, NULL, newKind);
|
||||
if (!obj || !SetInitializerObjectType(cx, script, regs.pc, obj, newKind))
|
||||
goto error;
|
||||
|
||||
PUSH_OBJECT(*obj);
|
||||
@ -2884,8 +2892,9 @@ BEGIN_CASE(JSOP_NEWOBJECT)
|
||||
baseobj = script->getObject(regs.pc);
|
||||
|
||||
RootedObject &obj = rootObject1;
|
||||
obj = CopyInitializerObject(cx, baseobj);
|
||||
if (!obj || !SetInitializerObjectType(cx, script, regs.pc, obj))
|
||||
NewObjectKind newKind = UseNewTypeForInitializer(cx, script, regs.pc, baseobj->getClass());
|
||||
obj = CopyInitializerObject(cx, baseobj, newKind);
|
||||
if (!obj || !SetInitializerObjectType(cx, script, regs.pc, obj, newKind))
|
||||
goto error;
|
||||
|
||||
PUSH_OBJECT(*obj);
|
||||
|
@ -390,7 +390,7 @@ NewPropertyIteratorObject(JSContext *cx, unsigned flags)
|
||||
if (!shape)
|
||||
return NULL;
|
||||
|
||||
RawObject obj = JSObject::create(cx, ITERATOR_FINALIZE_KIND, shape, type, NULL);
|
||||
RawObject obj = JSObject::create(cx, ITERATOR_FINALIZE_KIND, gc::DefaultHeap, shape, type, NULL);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
|
@ -713,8 +713,8 @@ static JSFunctionSpec math_static_methods[] = {
|
||||
JSObject *
|
||||
js_InitMathClass(JSContext *cx, HandleObject obj)
|
||||
{
|
||||
RootedObject Math(cx, NewObjectWithClassProto(cx, &MathClass, NULL, obj));
|
||||
if (!Math || !JSObject::setSingletonType(cx, Math))
|
||||
RootedObject Math(cx, NewObjectWithClassProto(cx, &MathClass, NULL, obj, SingletonObject));
|
||||
if (!Math)
|
||||
return NULL;
|
||||
|
||||
if (!JS_DefineProperty(cx, obj, js_Math_str, OBJECT_TO_JSVAL(Math),
|
||||
|
@ -1028,7 +1028,7 @@ js::InitRuntimeNumberState(JSRuntime *rt)
|
||||
|
||||
/*
|
||||
* Our NaN must be one particular canonical value, because we rely on NaN
|
||||
* encoding for our value representation. See jsval.h.
|
||||
* encoding for our value representation. See Value.h.
|
||||
*/
|
||||
d = MOZ_DOUBLE_SPECIFIC_NaN(0, 0x8000000000000ULL);
|
||||
number_constants[NC_NaN].dval = js_NaN = d;
|
||||
|
124
js/src/jsobj.cpp
124
js/src/jsobj.cpp
@ -1178,7 +1178,7 @@ NewObjectGCKind(js::Class *clasp)
|
||||
|
||||
static inline JSObject *
|
||||
NewObject(JSContext *cx, Class *clasp, types::TypeObject *type_, JSObject *parent,
|
||||
gc::AllocKind kind)
|
||||
gc::AllocKind kind, NewObjectKind newKind)
|
||||
{
|
||||
AssertCanGC();
|
||||
JS_ASSERT(clasp != &ArrayClass);
|
||||
@ -1197,12 +1197,22 @@ NewObject(JSContext *cx, Class *clasp, types::TypeObject *type_, JSObject *paren
|
||||
if (!PreallocateObjectDynamicSlots(cx, shape, &slots))
|
||||
return NULL;
|
||||
|
||||
JSObject *obj = JSObject::create(cx, kind, shape, type, slots);
|
||||
gc::InitialHeap heap = InitialHeapForNewKind(newKind);
|
||||
JSObject *obj = JSObject::create(cx, kind, heap, shape, type, slots);
|
||||
if (!obj) {
|
||||
js_free(slots);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (newKind == SingletonObject) {
|
||||
RootedObject nobj(cx, obj);
|
||||
if (!JSObject::setSingletonType(cx, nobj)) {
|
||||
js_free(slots);
|
||||
return NULL;
|
||||
}
|
||||
obj = nobj;
|
||||
}
|
||||
|
||||
/*
|
||||
* This will cancel an already-running incremental GC from doing any more
|
||||
* slices, and it will prevent any future incremental GCs.
|
||||
@ -1217,22 +1227,22 @@ NewObject(JSContext *cx, Class *clasp, types::TypeObject *type_, JSObject *paren
|
||||
JSObject *
|
||||
js::NewObjectWithGivenProto(JSContext *cx, js::Class *clasp,
|
||||
js::TaggedProto proto_, JSObject *parent_,
|
||||
gc::AllocKind kind)
|
||||
gc::AllocKind allocKind, NewObjectKind newKind)
|
||||
{
|
||||
Rooted<TaggedProto> proto(cx, proto_);
|
||||
RootedObject parent(cx, parent_);
|
||||
|
||||
if (CanBeFinalizedInBackground(kind, clasp))
|
||||
kind = GetBackgroundAllocKind(kind);
|
||||
if (CanBeFinalizedInBackground(allocKind, clasp))
|
||||
allocKind = GetBackgroundAllocKind(allocKind);
|
||||
|
||||
NewObjectCache &cache = cx->runtime->newObjectCache;
|
||||
|
||||
NewObjectCache::EntryIndex entry = -1;
|
||||
if (proto.isObject() &&
|
||||
if (proto.isObject() && newKind != SingletonObject &&
|
||||
(!parent || parent == proto.toObject()->getParent()) && !proto.toObject()->isGlobal())
|
||||
{
|
||||
if (cache.lookupProto(clasp, proto.toObject(), kind, &entry)) {
|
||||
JSObject *obj = cache.newObjectFromHit(cx, entry);
|
||||
if (cache.lookupProto(clasp, proto.toObject(), allocKind, &entry)) {
|
||||
JSObject *obj = cache.newObjectFromHit(cx, entry, InitialHeapForNewKind(newKind));
|
||||
if (obj)
|
||||
return obj;
|
||||
}
|
||||
@ -1249,25 +1259,25 @@ js::NewObjectWithGivenProto(JSContext *cx, js::Class *clasp,
|
||||
if (!parent && proto.isObject())
|
||||
parent = proto.toObject()->getParent();
|
||||
|
||||
JSObject *obj = NewObject(cx, clasp, type, parent, kind);
|
||||
RootedObject obj(cx, NewObject(cx, clasp, type, parent, allocKind, newKind));
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
if (entry != -1 && !obj->hasDynamicSlots())
|
||||
cache.fillProto(entry, clasp, proto, kind, obj);
|
||||
cache.fillProto(entry, clasp, proto, allocKind, obj);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
JSObject *
|
||||
js::NewObjectWithClassProto(JSContext *cx, js::Class *clasp, JSObject *protoArg, JSObject *parentArg,
|
||||
gc::AllocKind kind)
|
||||
js::NewObjectWithClassProtoCommon(JSContext *cx, js::Class *clasp, JSObject *protoArg, JSObject *parentArg,
|
||||
gc::AllocKind allocKind, NewObjectKind newKind)
|
||||
{
|
||||
if (protoArg)
|
||||
return NewObjectWithGivenProto(cx, clasp, protoArg, parentArg, kind);
|
||||
return NewObjectWithGivenProto(cx, clasp, protoArg, parentArg, allocKind, newKind);
|
||||
|
||||
if (CanBeFinalizedInBackground(kind, clasp))
|
||||
kind = GetBackgroundAllocKind(kind);
|
||||
if (CanBeFinalizedInBackground(allocKind, clasp))
|
||||
allocKind = GetBackgroundAllocKind(allocKind);
|
||||
|
||||
if (!parentArg)
|
||||
parentArg = cx->global();
|
||||
@ -1286,9 +1296,9 @@ js::NewObjectWithClassProto(JSContext *cx, js::Class *clasp, JSObject *protoArg,
|
||||
NewObjectCache &cache = cx->runtime->newObjectCache;
|
||||
|
||||
NewObjectCache::EntryIndex entry = -1;
|
||||
if (parentArg->isGlobal() && protoKey != JSProto_Null) {
|
||||
if (cache.lookupGlobal(clasp, &parentArg->asGlobal(), kind, &entry)) {
|
||||
JSObject *obj = cache.newObjectFromHit(cx, entry);
|
||||
if (parentArg->isGlobal() && protoKey != JSProto_Null && newKind != SingletonObject) {
|
||||
if (cache.lookupGlobal(clasp, &parentArg->asGlobal(), allocKind, &entry)) {
|
||||
JSObject *obj = cache.newObjectFromHit(cx, entry, InitialHeapForNewKind(newKind));
|
||||
if (obj)
|
||||
return obj;
|
||||
}
|
||||
@ -1304,43 +1314,44 @@ js::NewObjectWithClassProto(JSContext *cx, js::Class *clasp, JSObject *protoArg,
|
||||
if (!type)
|
||||
return NULL;
|
||||
|
||||
JSObject *obj = NewObject(cx, clasp, type, parent, kind);
|
||||
JSObject *obj = NewObject(cx, clasp, type, parent, allocKind, newKind);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
if (entry != -1 && !obj->hasDynamicSlots())
|
||||
cache.fillGlobal(entry, clasp, &parent->asGlobal(), kind, obj);
|
||||
cache.fillGlobal(entry, clasp, &parent->asGlobal(), allocKind, obj);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
JSObject *
|
||||
js::NewObjectWithType(JSContext *cx, HandleTypeObject type, JSObject *parent, gc::AllocKind kind)
|
||||
js::NewObjectWithType(JSContext *cx, HandleTypeObject type, JSObject *parent, gc::AllocKind allocKind,
|
||||
NewObjectKind newKind /* = GenericObject */)
|
||||
{
|
||||
JS_ASSERT(type->proto->hasNewType(&ObjectClass, type));
|
||||
JS_ASSERT(parent);
|
||||
|
||||
JS_ASSERT(kind <= gc::FINALIZE_OBJECT_LAST);
|
||||
if (CanBeFinalizedInBackground(kind, &ObjectClass))
|
||||
kind = GetBackgroundAllocKind(kind);
|
||||
JS_ASSERT(allocKind <= gc::FINALIZE_OBJECT_LAST);
|
||||
if (CanBeFinalizedInBackground(allocKind, &ObjectClass))
|
||||
allocKind = GetBackgroundAllocKind(allocKind);
|
||||
|
||||
NewObjectCache &cache = cx->runtime->newObjectCache;
|
||||
|
||||
NewObjectCache::EntryIndex entry = -1;
|
||||
if (parent == type->proto->getParent()) {
|
||||
if (cache.lookupType(&ObjectClass, type, kind, &entry)) {
|
||||
JSObject *obj = cache.newObjectFromHit(cx, entry);
|
||||
if (parent == type->proto->getParent() && newKind != SingletonObject) {
|
||||
if (cache.lookupType(&ObjectClass, type, allocKind, &entry)) {
|
||||
JSObject *obj = cache.newObjectFromHit(cx, entry, InitialHeapForNewKind(newKind));
|
||||
if (obj)
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
JSObject *obj = NewObject(cx, &ObjectClass, type, parent, kind);
|
||||
JSObject *obj = NewObject(cx, &ObjectClass, type, parent, allocKind, newKind);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
if (entry != -1 && !obj->hasDynamicSlots())
|
||||
cache.fillType(entry, &ObjectClass, type, kind, obj);
|
||||
cache.fillType(entry, &ObjectClass, type, allocKind, obj);
|
||||
|
||||
return obj;
|
||||
}
|
||||
@ -1348,16 +1359,19 @@ js::NewObjectWithType(JSContext *cx, HandleTypeObject type, JSObject *parent, gc
|
||||
bool
|
||||
js::NewObjectScriptedCall(JSContext *cx, MutableHandleObject pobj)
|
||||
{
|
||||
gc::AllocKind kind = NewObjectGCKind(&ObjectClass);
|
||||
RootedObject obj(cx, NewBuiltinClassInstance(cx, &ObjectClass, kind));
|
||||
jsbytecode *pc;
|
||||
RootedScript script(cx, cx->stack.currentScript(&pc));
|
||||
gc::AllocKind allocKind = NewObjectGCKind(&ObjectClass);
|
||||
NewObjectKind newKind = script
|
||||
? UseNewTypeForInitializer(cx, script, pc, &ObjectClass)
|
||||
: GenericObject;
|
||||
RootedObject obj(cx, NewBuiltinClassInstance(cx, &ObjectClass, allocKind, newKind));
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
jsbytecode *pc;
|
||||
RootedScript script(cx, cx->stack.currentScript(&pc));
|
||||
if (script) {
|
||||
/* Try to specialize the type of the object to the scripted call site. */
|
||||
if (!types::SetInitializerObjectType(cx, script, pc, obj))
|
||||
if (!types::SetInitializerObjectType(cx, script, pc, obj, newKind))
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1406,7 +1420,7 @@ js::NewReshapedObject(JSContext *cx, HandleTypeObject type, JSObject *parent,
|
||||
}
|
||||
|
||||
JSObject*
|
||||
js_CreateThis(JSContext *cx, Class *newclasp, HandleObject callee)
|
||||
js::CreateThis(JSContext *cx, Class *newclasp, HandleObject callee)
|
||||
{
|
||||
RootedValue protov(cx);
|
||||
if (!JSObject::getProperty(cx, callee, callee, cx->names().classPrototype, &protov))
|
||||
@ -1419,7 +1433,8 @@ js_CreateThis(JSContext *cx, Class *newclasp, HandleObject callee)
|
||||
}
|
||||
|
||||
static inline JSObject *
|
||||
CreateThisForFunctionWithType(JSContext *cx, HandleTypeObject type, JSObject *parent)
|
||||
CreateThisForFunctionWithType(JSContext *cx, HandleTypeObject type, JSObject *parent,
|
||||
NewObjectKind newKind)
|
||||
{
|
||||
if (type->newScript) {
|
||||
/*
|
||||
@ -1436,12 +1451,13 @@ CreateThisForFunctionWithType(JSContext *cx, HandleTypeObject type, JSObject *pa
|
||||
return res;
|
||||
}
|
||||
|
||||
gc::AllocKind kind = NewObjectGCKind(&ObjectClass);
|
||||
return NewObjectWithType(cx, type, parent, kind);
|
||||
gc::AllocKind allocKind = NewObjectGCKind(&ObjectClass);
|
||||
return NewObjectWithType(cx, type, parent, allocKind, newKind);
|
||||
}
|
||||
|
||||
JSObject *
|
||||
js_CreateThisForFunctionWithProto(JSContext *cx, HandleObject callee, JSObject *proto)
|
||||
js::CreateThisForFunctionWithProto(JSContext *cx, HandleObject callee, JSObject *proto,
|
||||
NewObjectKind newKind /* = GenericObject */)
|
||||
{
|
||||
JSObject *res;
|
||||
|
||||
@ -1449,10 +1465,10 @@ js_CreateThisForFunctionWithProto(JSContext *cx, HandleObject callee, JSObject *
|
||||
RootedTypeObject type(cx, proto->getNewType(cx, &ObjectClass, callee->toFunction()));
|
||||
if (!type)
|
||||
return NULL;
|
||||
res = CreateThisForFunctionWithType(cx, type, callee->getParent());
|
||||
res = CreateThisForFunctionWithType(cx, type, callee->getParent(), newKind);
|
||||
} else {
|
||||
gc::AllocKind kind = NewObjectGCKind(&ObjectClass);
|
||||
res = NewObjectWithClassProto(cx, &ObjectClass, proto, callee->getParent(), kind);
|
||||
gc::AllocKind allocKind = NewObjectGCKind(&ObjectClass);
|
||||
res = NewObjectWithClassProto(cx, &ObjectClass, proto, callee->getParent(), allocKind, newKind);
|
||||
}
|
||||
|
||||
if (res && cx->typeInferenceEnabled()) {
|
||||
@ -1464,7 +1480,7 @@ js_CreateThisForFunctionWithProto(JSContext *cx, HandleObject callee, JSObject *
|
||||
}
|
||||
|
||||
JSObject *
|
||||
js_CreateThisForFunction(JSContext *cx, HandleObject callee, bool newType)
|
||||
js::CreateThisForFunction(JSContext *cx, HandleObject callee, bool newType)
|
||||
{
|
||||
RootedValue protov(cx);
|
||||
if (!JSObject::getProperty(cx, callee, callee, cx->names().classPrototype, &protov))
|
||||
@ -1474,18 +1490,14 @@ js_CreateThisForFunction(JSContext *cx, HandleObject callee, bool newType)
|
||||
proto = &protov.toObject();
|
||||
else
|
||||
proto = NULL;
|
||||
JSObject *obj = js_CreateThisForFunctionWithProto(cx, callee, proto);
|
||||
NewObjectKind newKind = newType ? SingletonObject : GenericObject;
|
||||
JSObject *obj = CreateThisForFunctionWithProto(cx, callee, proto, newKind);
|
||||
|
||||
if (obj && newType) {
|
||||
RootedObject nobj(cx, obj);
|
||||
|
||||
/*
|
||||
* Reshape the object and give it a (lazily instantiated) singleton
|
||||
* type before passing it as the 'this' value for the call.
|
||||
*/
|
||||
/* Reshape the singleton before passing it as the 'this' value. */
|
||||
JSObject::clear(cx, nobj);
|
||||
if (!JSObject::setSingletonType(cx, nobj))
|
||||
return NULL;
|
||||
|
||||
RootedScript calleeScript(cx, callee->toFunction()->nonLazyScript());
|
||||
TypeScript::SetThis(cx, calleeScript, types::Type::ObjectType(nobj));
|
||||
@ -1690,8 +1702,7 @@ js::CloneObject(JSContext *cx, HandleObject obj, Handle<js::TaggedProto> proto,
|
||||
JSMSG_CANT_CLONE_OBJECT);
|
||||
return NULL;
|
||||
}
|
||||
RootedObject clone(cx, NewObjectWithGivenProto(cx, obj->getClass(),
|
||||
proto, parent, obj->getAllocKind()));
|
||||
RootedObject clone(cx, NewObjectWithGivenProto(cx, obj->getClass(), proto, parent));
|
||||
if (!clone)
|
||||
return NULL;
|
||||
if (obj->isNative()) {
|
||||
@ -2117,13 +2128,10 @@ js::DefineConstructorAndPrototype(JSContext *cx, HandleObject obj, JSProtoKey ke
|
||||
* [which already needs to happen for bug 638316], figure out nicer
|
||||
* semantics for null-protoProto, and use createBlankPrototype.)
|
||||
*/
|
||||
RootedObject proto(cx, NewObjectWithClassProto(cx, clasp, protoProto, obj));
|
||||
RootedObject proto(cx, NewObjectWithClassProto(cx, clasp, protoProto, obj, SingletonObject));
|
||||
if (!proto)
|
||||
return NULL;
|
||||
|
||||
if (!JSObject::setSingletonType(cx, proto))
|
||||
return NULL;
|
||||
|
||||
/* After this point, control must exit via label bad or out. */
|
||||
RootedObject ctor(cx);
|
||||
bool named = false;
|
||||
@ -2152,8 +2160,8 @@ js::DefineConstructorAndPrototype(JSContext *cx, HandleObject obj, JSProtoKey ke
|
||||
* (FIXME: remove this dependency on the exact identity of the parent,
|
||||
* perhaps as part of bug 638316.)
|
||||
*/
|
||||
RootedFunction fun(cx, js_NewFunction(cx, NullPtr(), constructor, nargs,
|
||||
JSFunction::NATIVE_CTOR, obj, atom, ctorKind));
|
||||
RootedFunction fun(cx, NewFunction(cx, NullPtr(), constructor, nargs,
|
||||
JSFunction::NATIVE_CTOR, obj, atom, ctorKind));
|
||||
if (!fun)
|
||||
goto bad;
|
||||
|
||||
|
@ -20,7 +20,6 @@
|
||||
#include "jsatom.h"
|
||||
#include "jsclass.h"
|
||||
#include "jsfriendapi.h"
|
||||
#include "jsinfer.h"
|
||||
|
||||
#include "gc/Barrier.h"
|
||||
#include "gc/Heap.h"
|
||||
@ -300,6 +299,7 @@ class JSObject : public js::ObjectImpl
|
||||
/* Make a non-array object with the specified initial state. */
|
||||
static inline JSObject *create(JSContext *cx,
|
||||
js::gc::AllocKind kind,
|
||||
js::gc::InitialHeap heap,
|
||||
js::HandleShape shape,
|
||||
js::HandleTypeObject type,
|
||||
js::HeapSlot *slots);
|
||||
@ -307,6 +307,7 @@ class JSObject : public js::ObjectImpl
|
||||
/* Make an array object with the specified initial state. */
|
||||
static inline JSObject *createArray(JSContext *cx,
|
||||
js::gc::AllocKind kind,
|
||||
js::gc::InitialHeap heap,
|
||||
js::HandleShape shape,
|
||||
js::HandleTypeObject type,
|
||||
uint32_t length);
|
||||
@ -1160,19 +1161,6 @@ bool
|
||||
js_FindClassObject(JSContext *cx, JSProtoKey protoKey, js::MutableHandleValue vp,
|
||||
js::Class *clasp = NULL);
|
||||
|
||||
// Specialized call for constructing |this| with a known function callee,
|
||||
// and a known prototype.
|
||||
extern JSObject *
|
||||
js_CreateThisForFunctionWithProto(JSContext *cx, js::HandleObject callee, JSObject *proto);
|
||||
|
||||
// Specialized call for constructing |this| with a known function callee.
|
||||
extern JSObject *
|
||||
js_CreateThisForFunction(JSContext *cx, js::HandleObject callee, bool newType);
|
||||
|
||||
// Generic call for constructing |this|.
|
||||
extern JSObject *
|
||||
js_CreateThis(JSContext *cx, js::Class *clasp, js::HandleObject callee);
|
||||
|
||||
/*
|
||||
* Find or create a property named by id in obj's scope, with the given getter
|
||||
* and setter, slot, attributes, and other members.
|
||||
@ -1188,7 +1176,50 @@ js_DefineOwnProperty(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
|
||||
|
||||
namespace js {
|
||||
|
||||
JSObject *
|
||||
/*
|
||||
* The NewObjectKind allows an allocation site to specify the type properties
|
||||
* and lifetime requirements that must be fixed at allocation time.
|
||||
*/
|
||||
enum NewObjectKind {
|
||||
/* This is the default. Most objects are generic. */
|
||||
GenericObject,
|
||||
|
||||
/*
|
||||
* Singleton objects are treated specially by the type system. This flag
|
||||
* ensures that the new object is automatically set up correctly as a
|
||||
* singleton and is allocated in the correct heap.
|
||||
*/
|
||||
SingletonObject,
|
||||
|
||||
/*
|
||||
* Objects which may be marked as a singleton after allocation must still
|
||||
* be allocated on the correct heap, but are not automatically setup as a
|
||||
* singleton after allocation.
|
||||
*/
|
||||
MaybeSingletonObject
|
||||
};
|
||||
|
||||
inline gc::InitialHeap
|
||||
InitialHeapForNewKind(NewObjectKind newKind)
|
||||
{
|
||||
return newKind == GenericObject ? gc::DefaultHeap : gc::TenuredHeap;
|
||||
}
|
||||
|
||||
// Specialized call for constructing |this| with a known function callee,
|
||||
// and a known prototype.
|
||||
extern JSObject *
|
||||
CreateThisForFunctionWithProto(JSContext *cx, js::HandleObject callee, JSObject *proto,
|
||||
NewObjectKind newKind = GenericObject);
|
||||
|
||||
// Specialized call for constructing |this| with a known function callee.
|
||||
extern JSObject *
|
||||
CreateThisForFunction(JSContext *cx, js::HandleObject callee, bool newType);
|
||||
|
||||
// Generic call for constructing |this|.
|
||||
extern JSObject *
|
||||
CreateThis(JSContext *cx, js::Class *clasp, js::HandleObject callee);
|
||||
|
||||
extern JSObject *
|
||||
CloneObject(JSContext *cx, HandleObject obj, Handle<js::TaggedProto> proto, HandleObject parent);
|
||||
|
||||
/*
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user