Merge mozilla-inbound to mozilla-central

This commit is contained in:
Ed Morley 2013-02-06 14:26:36 +00:00
commit d524aacc84
159 changed files with 5593 additions and 3690 deletions

View File

@ -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);

View File

@ -1,2 +0,0 @@
Components.utils.import('resource://gre/modules/UserAgentOverrides.jsm');
UserAgentOverrides.init();

View File

@ -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

View File

@ -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');
}
}
}
},
};

View File

@ -4,5 +4,11 @@
"digest": "e0b98a75831313171781d91ab4c3b8ae66e3af7fcec433a33d75fbc647cb3bba311f790ccb9cd9c8be8c5549210b759d6b85afe7395ada74c2c319a29556fd8e",
"algorithm": "sha512",
"filename": "gonk.tar.xz"
},
{
"size": 2116507,
"digest": "be67a012963a5c162834f9fcb989bcebd2d047dcb4e17ee23031b694dcf7cdfd6d7a6545d7a1f5e7293b6d24415403972f4ea1ab8c6c78fefcabfaf3f6875214",
"algorithm": "sha512",
"filename": "download-panda.tar.bz2"
}
]

View File

@ -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

View File

@ -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">

View File

@ -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");

View File

@ -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 ?

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -665,7 +665,6 @@ html[dir='rtl'] .dropdownToolbarButton {
}
.dropdownToolbarButton {
min-width: 120px;
max-width: 120px;
padding: 3px 2px 2px;
overflow: hidden;

View File

@ -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">

View File

@ -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();
});
})();

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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"

View File

@ -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;

View File

@ -106,7 +106,7 @@ TextComposition::CompositionEventDispatcher::CompositionEventDispatcher(
mPresContext(aPresContext), mEventTarget(aEventTarget),
mEventMessage(aEventMessage), mData(aData)
{
mWidget = mPresContext->GetNearestWidget();
mWidget = mPresContext->GetRootWidget();
}
NS_IMETHODIMP

View File

@ -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.
}

View File

@ -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;
}

View File

@ -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;
};
/**

View File

@ -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)

View File

@ -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

View File

@ -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);
};

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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);

View File

@ -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]),

View File

@ -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
View 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
View 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__ */

View File

@ -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;
}

View File

@ -108,6 +108,8 @@ MOCHITEST_FILES = \
errorwarning_worker.js \
test_contentWorker.html \
content_worker.js \
test_url.html \
url_worker.js \
$(NULL)
_SUBDIRMOCHITEST_FILES = \

View 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>

View 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' });
}

View File

@ -12,6 +12,7 @@ TransGaming Inc.
3DLabs Inc. Ltd.
Adobe Systems Inc.
Apple Inc.
Autodesk, Inc.
Cloud Party, Inc.
Intel Corporation

View File

@ -56,6 +56,7 @@ DEFINES += -DCOMPILER_IMPLEMENTATION
VPATH += $(srcdir)/src/compiler
# src/compiler:
CPPSRCS += \
ArrayBoundsClamper.cpp \
BuiltInFunctionEmulator.cpp \
Compiler.cpp \
compiler_debug.cpp \

View File

@ -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
View 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 \

View File

@ -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;
//

View File

@ -59,6 +59,8 @@
'COMPILER_IMPLEMENTATION',
],
'sources': [
'compiler/ArrayBoundsClamper.cpp',
'compiler/ArrayBoundsClamper.h',
'compiler/BaseTypes.h',
'compiler/BuiltInFunctionEmulator.cpp',
'compiler/BuiltInFunctionEmulator.h',

View 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();
}
}

View 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_

View File

@ -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;
}

View File

@ -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)
{

View File

@ -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.

View File

@ -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);

View File

@ -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);

View File

@ -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)

View File

@ -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;
};
//

View File

@ -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>

View File

@ -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
View 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
View 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

File diff suppressed because it is too large Load Diff

View File

@ -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)

View File

@ -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));

View File

@ -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 ||

View File

@ -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) {

View File

@ -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,

View File

@ -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).
#

View File

@ -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)

View File

@ -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);

View File

@ -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;

View File

@ -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"

View File

@ -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;

View File

@ -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"
/*

View File

@ -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.

File diff suppressed because it is too large Load Diff

View File

@ -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)

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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 *)

View File

@ -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;

View File

@ -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

View File

@ -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___ */

View File

@ -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;

View File

@ -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.

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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),

View File

@ -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;

View File

@ -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;

View File

@ -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