author | Wes Kocher <wkocher@mozilla.com> |
Fri, 07 Nov 2014 17:48:37 -0800 | |
changeset 214713 | eb0d3b3c0b22f3c8e1601e47e8f1e90a218b5fed |
parent 214679 | b7f2bf6856a2f15916c44fc094e9415045a84f8d (current diff) |
parent 214712 | 970e11385295170eb53d18b37db21bd9968a2f66 (diff) |
child 214714 | 80a0087967e64bd7adc9b90188cf690c55ebe229 |
child 214731 | bc6087adc259410c765a5f9acd7c3538e89dc1e3 |
child 214764 | 09731edabab5a9b259a0b13f12f3bc4590118f3e |
child 214840 | de3ee8e6554ca640a8e0748470e1cb30629f1354 |
push id | 27792 |
push user | kwierso@gmail.com |
push date | Sat, 08 Nov 2014 01:50:17 +0000 |
treeherder | autoland@eb0d3b3c0b22 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | merge |
milestone | 36.0a1 |
first release with | nightly linux32
eb0d3b3c0b22
/
36.0a1
/
20141108030205
/
files
nightly linux64
eb0d3b3c0b22
/
36.0a1
/
20141108030205
/
files
nightly mac
eb0d3b3c0b22
/
36.0a1
/
20141108030205
/
files
nightly win32
eb0d3b3c0b22
/
36.0a1
/
20141108030205
/
files
nightly win64
eb0d3b3c0b22
/
36.0a1
/
20141108030205
/
files
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
releases | nightly linux32
36.0a1
/
20141108030205
/
pushlog to previous
nightly linux64
36.0a1
/
20141108030205
/
pushlog to previous
nightly mac
36.0a1
/
20141108030205
/
pushlog to previous
nightly win32
36.0a1
/
20141108030205
/
pushlog to previous
nightly win64
36.0a1
/
20141108030205
/
pushlog to previous
|
js/src/tests/ecma_6/TypedObject/Bug914137.js | file | annotate | diff | comparison | revisions | |
js/src/tests/ecma_6/TypedObject/handle_unsized.js | file | annotate | diff | comparison | revisions | |
js/src/tests/ecma_6/TypedObject/unsizedarrays.js | file | annotate | diff | comparison | revisions | |
js/src/tests/ecma_6/TypedObject/unsizedarraysanddim.js | file | annotate | diff | comparison | revisions | |
js/src/tests/ecma_6/TypedObject/unsizedarraysembedded.js | file | annotate | diff | comparison | revisions | |
modules/libpref/init/all.js | file | annotate | diff | comparison | revisions |
--- a/accessible/base/nsAccessibilityService.h +++ b/accessible/base/nsAccessibilityService.h @@ -249,17 +249,17 @@ GetAccService() * Return true if we're in a content process and not B2G. */ inline bool IPCAccessibilityActive() { #ifdef MOZ_B2G return false; #else - return XRE_GetProcessType() != GeckoProcessType_Default; + return XRE_GetProcessType() == GeckoProcessType_Content; #endif } /** * Map nsIAccessibleEvents constants to strings. Used by * nsIAccessibleRetrieval::getStringEventType() method. */ static const char kEventTypeNames[][40] = {
--- a/accessible/windows/msaa/XULListboxAccessibleWrap.cpp +++ b/accessible/windows/msaa/XULListboxAccessibleWrap.cpp @@ -10,17 +10,18 @@ using namespace mozilla::a11y; //////////////////////////////////////////////////////////////////////////////// // XULListboxAccessibleWrap //////////////////////////////////////////////////////////////////////////////// NS_IMPL_ISUPPORTS_INHERITED0(XULListboxAccessibleWrap, XULListboxAccessible) IMPL_IUNKNOWN_QUERY_HEAD(XULListboxAccessibleWrap) -IMPL_IUNKNOWN_QUERY_CLASS_COND(ia2AccessibleTable, IsMulticolumn()); +IMPL_IUNKNOWN_QUERY_CLASS_COND(ia2AccessibleTable, + !IsDefunct() && IsMulticolumn()); IMPL_IUNKNOWN_QUERY_CLASS(AccessibleWrap) IMPL_IUNKNOWN_QUERY_TAIL void XULListboxAccessibleWrap::Shutdown() { ia2AccessibleTable::mTable = nullptr; XULListboxAccessible::Shutdown();
--- a/addon-sdk/mach_commands.py +++ b/addon-sdk/mach_commands.py @@ -98,17 +98,18 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] != "gonk dir_path = '' else: # Ensure that we don't have things like: # EXTRA_JS_MODULES.commonjs.sdk.private-browsing # which would be a Python syntax error. path = d.split('/') module_path = ''.join('.' + p if p.find('-') == -1 else "['%s']" % p for p in path) dir_path = d + '/' - filelist = ["'source/lib/%s%s'" % (dir_path, f) for f in sorted(files)] + filelist = ["'source/lib/%s%s'" % (dir_path, f) + for f in sorted(files, key=lambda x: x.lower())] js_modules.append("EXTRA_JS_MODULES.commonjs%s += [\n %s,\n]\n" % (module_path, ',\n '.join(filelist))) stringified = '\n'.join(js_modules) # This isn't the same thing as |js_modules|, since |js_modules| had # embedded newlines. lines = stringified.split('\n') # Indent lines while avoiding trailing whitespace. lines = [indent + line if line else line for line in lines]
--- a/b2g/app/b2g.js +++ b/b2g/app/b2g.js @@ -107,25 +107,17 @@ pref("browser.sessionstore.max_tabs_undo /* these should help performance */ pref("mozilla.widget.force-24bpp", true); pref("mozilla.widget.use-buffer-pixmap", true); pref("mozilla.widget.disable-native-theme", true); pref("layout.reflow.synthMouseMove", false); pref("layers.enable-tiles", true); pref("layers.low-precision-buffer", true); pref("layers.low-precision-opacity", "0.5"); -/* - Cross Process Mutex is not supported on Mac OS X so progressive - paint cannot be enabled for B2G on Mac OS X desktop -*/ -#ifdef MOZ_WIDGET_COCOA -pref("layers.progressive-paint", false); -#else pref("layers.progressive-paint", true); -#endif /* download manager (don't show the window or alert) */ pref("browser.download.useDownloadDir", true); pref("browser.download.folderList", 1); // Default to ~/Downloads pref("browser.download.manager.showAlertOnComplete", false); pref("browser.download.manager.showAlertInterval", 2000); pref("browser.download.manager.retention", 2); pref("browser.download.manager.showWhenStarting", false);
--- a/browser/devtools/debugger/test/browser.ini +++ b/browser/devtools/debugger/test/browser.ini @@ -501,47 +501,47 @@ skip-if = e10s || buildapp == 'mulet' skip-if = e10s [browser_dbg_variables-view-large-array-buffer.js] skip-if = e10s [browser_dbg_variables-view-override-01.js] skip-if = e10s [browser_dbg_variables-view-override-02.js] skip-if = e10s [browser_dbg_variables-view-popup-01.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_variables-view-popup-02.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_variables-view-popup-03.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_variables-view-popup-04.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_variables-view-popup-05.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_variables-view-popup-06.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_variables-view-popup-07.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_variables-view-popup-08.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_variables-view-popup-09.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_variables-view-popup-10.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_variables-view-popup-11.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_variables-view-popup-12.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_variables-view-popup-13.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_variables-view-popup-14.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_variables-view-popup-15.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_variables-view-popup-16.js] -skip-if = e10s +skip-if = e10s && debug [browser_dbg_variables-view-reexpand-01.js] skip-if = e10s [browser_dbg_variables-view-reexpand-02.js] skip-if = e10s [browser_dbg_variables-view-reexpand-03.js] skip-if = e10s [browser_dbg_variables-view-webidl.js] skip-if = e10s
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-01.js +++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-01.js @@ -5,17 +5,17 @@ * Tests opening the variable inspection popup on a variable which has a * simple literal as the value. */ const TAB_URL = EXAMPLE_URL + "doc_frame-parameters.html"; function test() { Task.spawn(function() { - let [tab, debuggee, panel] = yield initDebugger(TAB_URL); + let [tab,, panel] = yield initDebugger(TAB_URL); let win = panel.panelWin; let bubble = win.DebuggerView.VariableBubble; let tooltip = bubble._tooltip.panel; bubble._ignoreLiterals = false; function verifyContents(textContent, className) { is(tooltip.querySelectorAll(".variables-view-container").length, 0, @@ -24,18 +24,17 @@ function test() { "There should be a simple text node added to the tooltip instead."); is(tooltip.querySelector(".devtools-tooltip-simple-text").textContent, textContent, "The inspected property's value is correct."); ok(tooltip.querySelector(".devtools-tooltip-simple-text").className.contains(className), "The inspected property's value is colorized correctly."); } - // Allow this generator function to yield first. - executeSoon(() => debuggee.start()); + callInTab(tab, "start"); yield waitForSourceAndCaretAndScopes(panel, ".html", 24); // Inspect variables. yield openVarPopup(panel, { line: 15, ch: 12 }); verifyContents("1", "token-number"); yield reopenVarPopup(panel, { line: 16, ch: 21 }); verifyContents("1", "token-number");
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-02.js +++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-02.js @@ -5,35 +5,34 @@ * Tests opening the variable inspection popup on a variable which has a * a property accessible via getters and setters. */ const TAB_URL = EXAMPLE_URL + "doc_frame-parameters.html"; function test() { Task.spawn(function() { - let [tab, debuggee, panel] = yield initDebugger(TAB_URL); + let [tab,, panel] = yield initDebugger(TAB_URL); let win = panel.panelWin; let bubble = win.DebuggerView.VariableBubble; let tooltip = bubble._tooltip.panel; function verifyContents(textContent, className) { is(tooltip.querySelectorAll(".variables-view-container").length, 0, "There should be no variables view containers added to the tooltip."); is(tooltip.querySelectorAll(".devtools-tooltip-simple-text").length, 1, "There should be a simple text node added to the tooltip instead."); is(tooltip.querySelector(".devtools-tooltip-simple-text").textContent, textContent, "The inspected property's value is correct."); ok(tooltip.querySelector(".devtools-tooltip-simple-text").className.contains(className), "The inspected property's value is colorized correctly."); } - // Allow this generator function to yield first. - executeSoon(() => debuggee.start()); + callInTab(tab, "start"); yield waitForSourceAndCaretAndScopes(panel, ".html", 24); // Inspect properties. yield openVarPopup(panel, { line: 19, ch: 10 }); verifyContents("42", "token-number"); yield reopenVarPopup(panel, { line: 20, ch: 14 }); verifyContents("42", "token-number");
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-03.js +++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-03.js @@ -4,22 +4,21 @@ /** * Tests that the inspected indentifier is highlighted. */ const TAB_URL = EXAMPLE_URL + "doc_frame-parameters.html"; function test() { Task.spawn(function() { - let [tab, debuggee, panel] = yield initDebugger(TAB_URL); + let [tab,, panel] = yield initDebugger(TAB_URL); let win = panel.panelWin; let bubble = win.DebuggerView.VariableBubble; - // Allow this generator function to yield first. - executeSoon(() => debuggee.start()); + callInTab(tab, "start"); yield waitForSourceAndCaretAndScopes(panel, ".html", 24); // Inspect variable. yield openVarPopup(panel, { line: 15, ch: 12 }); ok(bubble.contentsShown(), "The variable should register as being shown."); ok(!bubble._tooltip.isEmpty(),
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-04.js +++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-04.js @@ -4,22 +4,21 @@ /** * Tests that the variable inspection popup is hidden when the editor scrolls. */ const TAB_URL = EXAMPLE_URL + "doc_frame-parameters.html"; function test() { Task.spawn(function() { - let [tab, debuggee, panel] = yield initDebugger(TAB_URL); + let [tab,, panel] = yield initDebugger(TAB_URL); let win = panel.panelWin; let bubble = win.DebuggerView.VariableBubble; - // Allow this generator function to yield first. - executeSoon(() => debuggee.start()); + callInTab(tab, "start"); yield waitForSourceAndCaretAndScopes(panel, ".html", 24); // Inspect variable. yield openVarPopup(panel, { line: 15, ch: 12 }); yield hideVarPopupByScrollingEditor(panel); ok(true, "The variable inspection popup was hidden."); ok(bubble._tooltip.isEmpty(),
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-05.js +++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-05.js @@ -5,17 +5,17 @@ * Tests opening the variable inspection popup on a variable which has a * simple object as the value. */ const TAB_URL = EXAMPLE_URL + "doc_frame-parameters.html"; function test() { Task.spawn(function() { - let [tab, debuggee, panel] = yield initDebugger(TAB_URL); + let [tab,, panel] = yield initDebugger(TAB_URL); let win = panel.panelWin; let bubble = win.DebuggerView.VariableBubble; let tooltip = bubble._tooltip.panel; function verifyContents() { is(tooltip.querySelectorAll(".variables-view-container").length, 1, "There should be one variables view container added to the tooltip."); @@ -33,18 +33,17 @@ function test() { "The first property's value is correct."); is(tooltip.querySelectorAll(".variables-view-property .name")[1].getAttribute("value"), "__proto__", "The second property's name is correct."); is(tooltip.querySelectorAll(".variables-view-property .value")[1].getAttribute("value"), "Object", "The second property's value is correct."); } - // Allow this generator function to yield first. - executeSoon(() => debuggee.start()); + callInTab(tab, "start"); yield waitForSourceAndCaretAndScopes(panel, ".html", 24); // Inspect variable. yield openVarPopup(panel, { line: 16, ch: 12 }, true); verifyContents(); yield resumeDebuggerThenCloseAndFinish(panel); });
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-06.js +++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-06.js @@ -6,17 +6,17 @@ * complext object as the value. */ const TAB_URL = EXAMPLE_URL + "doc_frame-parameters.html"; function test() { requestLongerTimeout(2); Task.spawn(function() { - let [tab, debuggee, panel] = yield initDebugger(TAB_URL); + let [tab,, panel] = yield initDebugger(TAB_URL); let win = panel.panelWin; let bubble = win.DebuggerView.VariableBubble; let tooltip = bubble._tooltip.panel; function verifyContents() { is(tooltip.querySelectorAll(".variables-view-container").length, 1, "There should be one variables view container added to the tooltip."); @@ -59,18 +59,17 @@ function test() { "The sixth property's value is correct."); is(tooltip.querySelectorAll(".variables-view-property .name")[6].getAttribute("value"), "__proto__", "The seventh property's name is correct."); is(tooltip.querySelectorAll(".variables-view-property .value")[6].getAttribute("value"), "Object", "The seventh property's value is correct."); } - // Allow this generator function to yield first. - executeSoon(() => debuggee.start()); + callInTab(tab, "start"); yield waitForSourceAndCaretAndScopes(panel, ".html", 24); // Inspect variable. yield openVarPopup(panel, { line: 17, ch: 12 }, true); verifyContents(); yield resumeDebuggerThenCloseAndFinish(panel); });
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-07.js +++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-07.js @@ -5,17 +5,17 @@ * Tests the variable inspection popup behaves correctly when switching * between simple and complex objects. */ const TAB_URL = EXAMPLE_URL + "doc_frame-parameters.html"; function test() { Task.spawn(function() { - let [tab, debuggee, panel] = yield initDebugger(TAB_URL); + let [tab,, panel] = yield initDebugger(TAB_URL); let win = panel.panelWin; let bubble = win.DebuggerView.VariableBubble; let tooltip = bubble._tooltip.panel; function verifySimpleContents(textContent, className) { is(tooltip.querySelectorAll(".variables-view-container").length, 0, "There should be no variables view container added to the tooltip."); is(tooltip.querySelectorAll(".devtools-tooltip-simple-text").length, 1, @@ -37,18 +37,17 @@ function test() { "There should be one scope with no header displayed."); is(tooltip.querySelectorAll(".variables-view-variable[untitled]").length, 1, "There should be one variable with no header displayed."); ok(tooltip.querySelectorAll(".variables-view-property").length >= propertyCount, "There should be some properties displayed."); } - // Allow this generator function to yield first. - executeSoon(() => debuggee.start()); + callInTab(tab, "start"); yield waitForSourceAndCaretAndScopes(panel, ".html", 24); // Inspect variables. yield openVarPopup(panel, { line: 15, ch: 12 }); verifySimpleContents("1", "token-number"); yield reopenVarPopup(panel, { line: 16, ch: 12 }, true); verifyComplexContents(2);
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-08.js +++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-08.js @@ -4,17 +4,17 @@ /** * Tests opening inspecting variables works across scopes. */ const TAB_URL = EXAMPLE_URL + "doc_scope-variable.html"; function test() { Task.spawn(function() { - let [tab, debuggee, panel] = yield initDebugger(TAB_URL); + let [tab,, panel] = yield initDebugger(TAB_URL); let win = panel.panelWin; let events = win.EVENTS; let editor = win.DebuggerView.editor; let frames = win.DebuggerView.StackFrames; let bubble = win.DebuggerView.VariableBubble; let tooltip = bubble._tooltip.panel; function verifyContents(textContent, className) { @@ -35,18 +35,17 @@ function test() { is(frames.itemCount, 2, "Should have two frames."); is(frames.selectedDepth, selectedFrame, "The correct frame is selected in the widget."); ok(isCaretPos(panel, caretLine), "Editor caret location is correct."); } - // Allow this generator function to yield first. - executeSoon(() => debuggee.test()); + callInTab(tab, "test"); yield waitForSourceAndCaretAndScopes(panel, ".html", 20); checkView(0, 20); // Inspect variable in topmost frame. yield openVarPopup(panel, { line: 18, ch: 12 }); verifyContents("\"second scope\"", "token-string"); checkView(0, 20);
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-09.js +++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-09.js @@ -4,23 +4,22 @@ /** * Tests opening inspecting variables works across scopes. */ const TAB_URL = EXAMPLE_URL + "doc_scope-variable-3.html"; function test() { Task.spawn(function() { - let [tab, debuggee, panel] = yield initDebugger(TAB_URL); + let [tab,, panel] = yield initDebugger(TAB_URL); let win = panel.panelWin; let bubble = win.DebuggerView.VariableBubble; let tooltip = bubble._tooltip.panel; - // Allow this generator function to yield first. - executeSoon(() => debuggee.test()); + callInTab(tab, "test"); yield waitForSourceAndCaretAndScopes(panel, ".html", 15); yield openVarPopup(panel, { line: 12, ch: 10 }); ok(true, "The variable inspection popup was shown for the real variable."); once(tooltip, "popupshown").then(() => { ok(false, "The variable inspection popup shouldn't have been opened."); });
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-10.js +++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-10.js @@ -6,27 +6,26 @@ * a variable inspection popup is opened and a watch expression is * also evaluated at the same time. */ const TAB_URL = EXAMPLE_URL + "doc_frame-parameters.html"; function test() { Task.spawn(function() { - let [tab, debuggee, panel] = yield initDebugger(TAB_URL); + let [tab,, panel] = yield initDebugger(TAB_URL); let win = panel.panelWin; let events = win.EVENTS; let editor = win.DebuggerView.editor; let editorContainer = win.document.getElementById("editor"); let bubble = win.DebuggerView.VariableBubble; let expressions = win.DebuggerView.WatchExpressions; let tooltip = bubble._tooltip.panel; - // Allow this generator function to yield first. - executeSoon(() => debuggee.start()); + callInTab(tab, "start"); yield waitForSourceAndCaretAndScopes(panel, ".html", 24); let expressionsEvaluated = waitForDebuggerEvents(panel, events.FETCHED_WATCH_EXPRESSIONS); expressions.addExpression("this"); editor.focus(); yield expressionsEvaluated; // Scroll to the top of the editor and inspect variables.
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-11.js +++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-11.js @@ -4,17 +4,17 @@ /** * Tests that the watch expression button is added in variable view popup. */ const TAB_URL = EXAMPLE_URL + "doc_watch-expression-button.html"; function test() { Task.spawn(function() { - let [tab, debuggee, panel] = yield initDebugger(TAB_URL); + let [tab,, panel] = yield initDebugger(TAB_URL); let win = panel.panelWin; let events = win.EVENTS; let watch = win.DebuggerView.WatchExpressions; let bubble = win.DebuggerView.VariableBubble; let tooltip = bubble._tooltip.panel; let label = win.L10N.getStr("addWatchExpressionButton"); let className = "dbg-expression-button"; @@ -32,18 +32,17 @@ function test() { ok(!tooltip.querySelector("button"), "There should be no button available in variable view popup."); ok(watch.getItemAtIndex(0), "The expression at index 0 should be available."); is(watch.getItemAtIndex(0).attachment.initialExpression, aExpression, "The expression at index 0 is correct."); } - // Allow this generator function to yield first. - executeSoon(() => debuggee.start()); + callInTab(tab, "start"); yield waitForSourceAndCaretAndScopes(panel, ".html", 19); // Inspect primitive value variable. yield openVarPopup(panel, { line: 15, ch: 12 }); let popupHiding = once(tooltip, "popuphiding"); let expressionsEvaluated = waitForDebuggerEvents(panel, events.FETCHED_WATCH_EXPRESSIONS); testExpressionButton(label, className, "a"); yield promise.all([popupHiding, expressionsEvaluated]);
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-12.js +++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-12.js @@ -5,35 +5,34 @@ * Tests that the clicking "Watch" button twice, for the same expression, only adds it * once. */ const TAB_URL = EXAMPLE_URL + "doc_watch-expression-button.html"; function test() { Task.spawn(function() { - let [tab, debuggee, panel] = yield initDebugger(TAB_URL); + let [tab,, panel] = yield initDebugger(TAB_URL); let win = panel.panelWin; let events = win.EVENTS; let watch = win.DebuggerView.WatchExpressions; let bubble = win.DebuggerView.VariableBubble; let tooltip = bubble._tooltip.panel; function verifyContent(aExpression, aItemCount) { ok(watch.getItemAtIndex(0), "The expression at index 0 should be available."); is(watch.getItemAtIndex(0).attachment.initialExpression, aExpression, "The expression at index 0 is correct."); is(watch.itemCount, aItemCount, "The expression count is correct."); } - // Allow this generator function to yield first. - executeSoon(() => debuggee.start()); + callInTab(tab, "start"); yield waitForSourceAndCaretAndScopes(panel, ".html", 19); // Inspect primitive value variable. yield openVarPopup(panel, { line: 15, ch: 12 }); let popupHiding = once(tooltip, "popuphiding"); let expressionsEvaluated = waitForDebuggerEvents(panel, events.FETCHED_WATCH_EXPRESSIONS); tooltip.querySelector("button").click(); verifyContent("a", 1);
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-13.js +++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-13.js @@ -5,17 +5,17 @@ * Tests that the variable inspection popup has inspector links for DOMNode * properties and that the popup closes when the link is clicked */ const TAB_URL = EXAMPLE_URL + "doc_domnode-variables.html"; function test() { Task.spawn(function() { - let [tab, debuggee, panel] = yield initDebugger(TAB_URL); + let [tab,, panel] = yield initDebugger(TAB_URL); let win = panel.panelWin; let bubble = win.DebuggerView.VariableBubble; let tooltip = bubble._tooltip.panel; let toolbox = gDevTools.getToolbox(panel.target); function getDomNodeInTooltip(propertyName) { let domNodeProperties = tooltip.querySelectorAll(".token-domnode"); for (let prop of domNodeProperties) { @@ -23,18 +23,17 @@ function test() { if (propName.getAttribute("value") === propertyName) { ok(true, "DOMNode " + propertyName + " was found in the tooltip"); return prop; } } ok(false, "DOMNode " + propertyName + " wasn't found in the tooltip"); } - // Allow this generator function to yield first. - executeSoon(() => debuggee.start()); + callInTab(tab, "start"); yield waitForSourceAndCaretAndScopes(panel, ".html", 19); // Inspect the div DOM variable. yield openVarPopup(panel, { line: 17, ch: 38 }, true); let property = getDomNodeInTooltip("firstElementChild"); // Simulate mouseover on the property value let highlighted = once(toolbox, "node-highlight");
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-14.js +++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-14.js @@ -5,22 +5,21 @@ * Tests that the variable inspection popup is hidden when * selecting text in the editor. */ const TAB_URL = EXAMPLE_URL + "doc_frame-parameters.html"; function test() { Task.spawn(function*() { - let [tab, debuggee, panel] = yield initDebugger(TAB_URL); + let [tab,, panel] = yield initDebugger(TAB_URL); let win = panel.panelWin; let bubble = win.DebuggerView.VariableBubble; - // Allow this generator function to yield first. - executeSoon(() => debuggee.start()); + callInTab(tab, "start"); yield waitForSourceAndCaretAndScopes(panel, ".html", 24); // Select some text. let cursor = win.DebuggerView.editor.getOffset({ line: 15, ch: 12 }); let [ anchor, head ] = win.DebuggerView.editor.getPosition( cursor, cursor + 3 );
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-15.js +++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-15.js @@ -4,23 +4,22 @@ /** * Tests opening the variable inspection popup directly on literals. */ const TAB_URL = EXAMPLE_URL + "doc_frame-parameters.html"; function test() { Task.spawn(function() { - let [tab, debuggee, panel] = yield initDebugger(TAB_URL); + let [tab,, panel] = yield initDebugger(TAB_URL); let win = panel.panelWin; let bubble = win.DebuggerView.VariableBubble; let tooltip = bubble._tooltip.panel; - // Allow this generator function to yield first. - executeSoon(() => debuggee.start()); + callInTab(tab, "start"); yield waitForSourceAndCaretAndScopes(panel, ".html", 24); yield openVarPopup(panel, { line: 15, ch: 12 }); ok(true, "The variable inspection popup was shown for the real variable."); once(tooltip, "popupshown").then(() => { ok(false, "The variable inspection popup shouldn't have been opened."); });
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-16.js +++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-16.js @@ -5,17 +5,17 @@ * Tests if opening the variables inspection popup preserves the highlighting * associated with the currently debugged line. */ const TAB_URL = EXAMPLE_URL + "doc_recursion-stack.html"; function test() { Task.spawn(function() { - let [tab, debuggee, panel] = yield initDebugger(TAB_URL); + let [tab,, panel] = yield initDebugger(TAB_URL); let win = panel.panelWin; let events = win.EVENTS; let editor = win.DebuggerView.editor; let frames = win.DebuggerView.StackFrames; let variables = win.DebuggerView.Variables; let bubble = win.DebuggerView.VariableBubble; let tooltip = bubble._tooltip.panel; @@ -46,18 +46,17 @@ function test() { is(globalScope.expanded, false, "The globalScope should not be expanded yet."); let finished = waitForDebuggerEvents(panel, events.FETCHED_VARIABLES); globalScope.expand(); return finished; } - // Allow this generator function to yield first. - executeSoon(() => debuggee.recurse()); + callInTab(tab, "recurse"); yield waitForSourceAndCaretAndScopes(panel, ".html", 26); yield checkView(0, 26); yield expandGlobalScope(); yield checkView(0, 26); // Inspect variable in topmost frame. yield openVarPopup(panel, { line: 26, ch: 11 });
--- a/dom/base/DOMException.cpp +++ b/dom/base/DOMException.cpp @@ -153,16 +153,18 @@ NS_GetNameAndMessageForDOMNSResult(nsres namespace mozilla { namespace dom { bool Exception::sEverMadeOneFromFactory = false; NS_IMPL_CLASSINFO(Exception, nullptr, nsIClassInfo::DOM_OBJECT, NS_XPCEXCEPTION_CID) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Exception) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY + NS_INTERFACE_MAP_ENTRY(Exception) NS_INTERFACE_MAP_ENTRY(nsIException) NS_INTERFACE_MAP_ENTRY(nsIXPCException) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIException) NS_IMPL_QUERY_CLASSINFO(Exception) NS_INTERFACE_MAP_END NS_IMPL_CYCLE_COLLECTING_ADDREF(Exception) NS_IMPL_CYCLE_COLLECTING_RELEASE(Exception)
--- a/dom/media/MediaPermissionGonk.cpp +++ b/dom/media/MediaPermissionGonk.cpp @@ -391,20 +391,19 @@ private: }; NS_IMPL_ISUPPORTS(MediaDeviceErrorCallback, nsIDOMGetUserMediaErrorCallback) // nsIDOMGetUserMediaErrorCallback method NS_IMETHODIMP MediaDeviceErrorCallback::OnError(nsISupports* aError) { - MediaStreamError *error = nullptr; - nsresult rv = CallQueryInterface(aError, &error); - if (NS_FAILED(rv)) { - return rv; + nsRefPtr<MediaStreamError> error = do_QueryObject(aError); + if (!error) { + return NS_ERROR_NO_INTERFACE; } nsString name; error->GetName(name); return NotifyPermissionDeny(mCallID, name); } } // namespace anonymous
--- a/dom/media/PeerConnection.js +++ b/dom/media/PeerConnection.js @@ -830,23 +830,28 @@ RTCPeerConnection.prototype = { this.logWarning( "addIceCandidate called without success/failure callbacks. This is deprecated, and will be an error in the future.", null, 0); } if (!cand.candidate && !cand.sdpMLineIndex) { throw new this._win.DOMError("", "Invalid candidate passed to addIceCandidate!"); } + + this._queueOrRun({ + func: this._addIceCandidate, + args: [cand, onSuccess, onError], + wait: false + }); + }, + + _addIceCandidate: function(cand, onSuccess, onError) { this._onAddIceCandidateSuccess = onSuccess || null; this._onAddIceCandidateError = onError || null; - this._queueOrRun({ func: this._addIceCandidate, args: [cand], wait: false }); - }, - - _addIceCandidate: function(cand) { this._impl.addIceCandidate(cand.candidate, cand.sdpMid || "", (cand.sdpMLineIndex === null) ? 0 : cand.sdpMLineIndex + 1); }, addStream: function(stream) { stream.getTracks().forEach(track => this.addTrack(track, stream)); },
--- a/dom/webidl/WorkerGlobalScope.webidl +++ b/dom/webidl/WorkerGlobalScope.webidl @@ -45,10 +45,11 @@ WorkerGlobalScope implements GlobalFetch // Mozilla extensions partial interface WorkerGlobalScope { attribute EventHandler onclose; void dump(optional DOMString str); // XXXbz no spec for this yet, because the webperf WG is a bit dysfunctional + [Constant, Cached] readonly attribute Performance performance; };
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp +++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp @@ -3043,31 +3043,31 @@ ScrollableLayerGuid AsyncPanZoomControll void AsyncPanZoomController::UpdateSharedCompositorFrameMetrics() { mMonitor.AssertCurrentThreadIn(); FrameMetrics* frame = mSharedFrameMetricsBuffer ? static_cast<FrameMetrics*>(mSharedFrameMetricsBuffer->memory()) : nullptr; - if (frame && mSharedLock && gfxPrefs::UseProgressiveTilePainting()) { + if (frame && mSharedLock && gfxPlatform::GetPlatform()->UseProgressivePaint()) { mSharedLock->Lock(); *frame = mFrameMetrics.MakePODObject(); mSharedLock->Unlock(); } } void AsyncPanZoomController::ShareCompositorFrameMetrics() { PCompositorParent* compositor = GetSharedFrameMetricsCompositor(); // Only create the shared memory buffer if it hasn't already been created, // we are using progressive tile painting, and we have a // compositor to pass the shared memory back to the content process/thread. - if (!mSharedFrameMetricsBuffer && compositor && gfxPrefs::UseProgressiveTilePainting()) { + if (!mSharedFrameMetricsBuffer && compositor && gfxPlatform::GetPlatform()->UseProgressivePaint()) { // Create shared memory and initialize it with the current FrameMetrics value mSharedFrameMetricsBuffer = new ipc::SharedMemoryBasic; FrameMetrics* frame = nullptr; mSharedFrameMetricsBuffer->Create(sizeof(FrameMetrics)); mSharedFrameMetricsBuffer->Map(sizeof(FrameMetrics)); frame = static_cast<FrameMetrics*>(mSharedFrameMetricsBuffer->memory());
--- a/gfx/layers/client/ClientTiledPaintedLayer.cpp +++ b/gfx/layers/client/ClientTiledPaintedLayer.cpp @@ -188,17 +188,17 @@ ClientTiledPaintedLayer::UseFastPath() { LayerMetricsWrapper scrollAncestor; GetAncestorLayers(&scrollAncestor, nullptr); if (!scrollAncestor) { return true; } const FrameMetrics& parentMetrics = scrollAncestor.Metrics(); - bool multipleTransactionsNeeded = gfxPrefs::UseProgressiveTilePainting() + bool multipleTransactionsNeeded = gfxPlatform::GetPlatform()->UseProgressivePaint() || gfxPrefs::UseLowPrecisionBuffer() || !parentMetrics.mCriticalDisplayPort.IsEmpty(); bool isFixed = GetIsFixedPosition() || GetParent()->GetIsFixedPosition(); return !multipleTransactionsNeeded || isFixed || parentMetrics.mDisplayPort.IsEmpty(); } bool ClientTiledPaintedLayer::RenderHighPrecision(nsIntRegion& aInvalidRegion, @@ -209,17 +209,17 @@ ClientTiledPaintedLayer::RenderHighPreci // If we have no high-precision stuff to draw, or we have started drawing low-precision // already, then we shouldn't do anything there. if (aInvalidRegion.IsEmpty() || mPaintData.mLowPrecisionPaintCount != 0) { return false; } // Only draw progressively when the resolution is unchanged, and we're not // in a reftest scenario (that's what the HasShadowManager() check is for). - if (gfxPrefs::UseProgressiveTilePainting() && + if (gfxPlatform::GetPlatform()->UseProgressivePaint() && !ClientManager()->HasShadowTarget() && mContentClient->mTiledBuffer.GetFrameResolution() == mPaintData.mResolution) { // Store the old valid region, then clear it before painting. // We clip the old valid region to the visible region, as it only gets // used to decide stale content (currently valid and previously visible) nsIntRegion oldValidRegion = mContentClient->mTiledBuffer.GetValidRegion(); oldValidRegion.And(oldValidRegion, aVisibleRegion); if (!mPaintData.mCriticalDisplayPort.IsEmpty()) {
--- a/gfx/layers/composite/LayerManagerComposite.cpp +++ b/gfx/layers/composite/LayerManagerComposite.cpp @@ -871,17 +871,17 @@ GetDisplayportCoverage(const CSSRect& aD } #endif // MOZ_WIDGET_ANDROID float LayerManagerComposite::ComputeRenderIntegrity() { // We only ever have incomplete rendering when progressive tiles are enabled. Layer* root = GetRoot(); - if (!gfxPrefs::UseProgressiveTilePainting() || !root) { + if (!gfxPlatform::GetPlatform()->UseProgressivePaint() || !root) { return 1.f; } FrameMetrics rootMetrics = LayerMetricsWrapper::TopmostScrollableMetrics(root); if (!rootMetrics.IsScrollable()) { // The root may not have any scrollable metrics, in which case rootMetrics // will just be an empty FrameMetrics. Instead use the actual metrics from // the root layer.
--- a/gfx/thebes/gfxPlatform.h +++ b/gfx/thebes/gfxPlatform.h @@ -258,19 +258,20 @@ public: bool SupportsAzureContentForType(mozilla::gfx::BackendType aType) { return BackendTypeBit(aType) & mContentBackendBitmask; } virtual bool UseAcceleratedSkiaCanvas(); virtual void InitializeSkiaCacheLimits(); - /// This should be used instead of directly accessing the preference, + /// These should be used instead of directly accessing the preference, /// as different platforms may override the behaviour. virtual bool UseTiling() { return gfxPrefs::LayersTilesEnabledDoNotUseDirectly(); } + virtual bool UseProgressivePaint() { return gfxPrefs::ProgressivePaintDoNotUseDirectly(); } void GetAzureBackendInfo(mozilla::widget::InfoObject &aObj) { aObj.DefineProperty("AzureCanvasBackend", GetBackendName(mPreferredCanvasBackend)); aObj.DefineProperty("AzureSkiaAccelerated", UseAcceleratedSkiaCanvas()); aObj.DefineProperty("AzureFallbackCanvasBackend", GetBackendName(mFallbackCanvasBackend)); aObj.DefineProperty("AzureContentBackend", GetBackendName(mContentBackend)); }
--- a/gfx/thebes/gfxPlatformMac.cpp +++ b/gfx/thebes/gfxPlatformMac.cpp @@ -406,16 +406,24 @@ gfxPlatformMac::UseTiling() { if (gfxPrefs::LayersTilesForceEnabled()) { return true; } // Tiling seems to be slow on 10.6 so disable it until we figure it out return nsCocoaFeatures::OnLionOrLater() && gfxPlatform::UseTiling(); } +bool +gfxPlatformMac::UseProgressivePaint() +{ + // Progressive painting requires cross-process mutexes, which don't work so + // well on OS X 10.6 so we disable there. + return nsCocoaFeatures::OnLionOrLater() && gfxPlatform::UseProgressivePaint(); +} + void gfxPlatformMac::GetPlatformCMSOutputProfile(void* &mem, size_t &size) { mem = nullptr; size = 0; CGColorSpaceRef cspace = ::CGDisplayCopyColorSpace(::CGMainDisplayID()); if (!cspace) {
--- a/gfx/thebes/gfxPlatformMac.h +++ b/gfx/thebes/gfxPlatformMac.h @@ -66,16 +66,17 @@ public: virtual bool CanRenderContentToDataSurface() const MOZ_OVERRIDE { return true; } bool UseAcceleratedCanvas(); virtual bool UseTiling() MOZ_OVERRIDE; + virtual bool UseProgressivePaint() MOZ_OVERRIDE; // lower threshold on font anti-aliasing uint32_t GetAntiAliasingThreshold() { return mFontAntiAliasingThreshold; } private: virtual void GetPlatformCMSOutputProfile(void* &mem, size_t &size); // read in the pref value for the lower threshold on font anti-aliasing
--- a/gfx/thebes/gfxPrefs.h +++ b/gfx/thebes/gfxPrefs.h @@ -288,17 +288,17 @@ private: DECL_GFX_PREF(Once, "layers.offmainthreadcomposition.enabled", LayersOffMainThreadCompositionEnabled, bool, false); DECL_GFX_PREF(Live, "layers.offmainthreadcomposition.frame-rate", LayersCompositionFrameRate, int32_t,-1); DECL_GFX_PREF(Once, "layers.offmainthreadcomposition.force-enabled", LayersOffMainThreadCompositionForceEnabled, bool, false); DECL_GFX_PREF(Once, "layers.offmainthreadcomposition.testing.enabled", LayersOffMainThreadCompositionTestingEnabled, bool, false); DECL_GFX_PREF(Once, "layers.use-image-offscreen-surfaces", UseImageOffscreenSurfaces, bool, false); DECL_GFX_PREF(Live, "layers.orientation.sync.timeout", OrientationSyncMillis, uint32_t, (uint32_t)0); DECL_GFX_PREF(Once, "layers.prefer-d3d9", LayersPreferD3D9, bool, false); DECL_GFX_PREF(Once, "layers.prefer-opengl", LayersPreferOpenGL, bool, false); - DECL_GFX_PREF(Once, "layers.progressive-paint", UseProgressiveTilePainting, bool, false); + DECL_GFX_PREF(Once, "layers.progressive-paint", ProgressivePaintDoNotUseDirectly, bool, false); DECL_GFX_PREF(Once, "layers.uniformity-info", UniformityInfo, bool, false); DECL_GFX_PREF(Once, "layers.gralloc.disable", DisableGralloc, bool, false); DECL_GFX_PREF(Live, "layout.css.scroll-behavior.damping-ratio", ScrollBehaviorDampingRatio, float, 1.0f); DECL_GFX_PREF(Live, "layout.css.scroll-behavior.enabled", ScrollBehaviorEnabled, bool, false); DECL_GFX_PREF(Live, "layout.css.scroll-behavior.spring-constant", ScrollBehaviorSpringConstant, float, 250.0f); DECL_GFX_PREF(Once, "layout.css.touch_action.enabled", TouchActionEnabled, bool, false); DECL_GFX_PREF(Once, "layout.frame_rate", LayoutFrameRate, int32_t, -1);
--- a/ipc/glue/CrossProcessMutex.h +++ b/ipc/glue/CrossProcessMutex.h @@ -4,17 +4,17 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef mozilla_CrossProcessMutex_h #define mozilla_CrossProcessMutex_h #include "base/process.h" #include "mozilla/Mutex.h" -#if defined(OS_LINUX) +#if defined(OS_POSIX) #include <pthread.h> #include "SharedMemoryBasic.h" #include "mozilla/Atomics.h" #include "nsAutoPtr.h" #endif namespace IPC { template<typename T> @@ -27,19 +27,19 @@ struct ParamTraits; // - CrossProcessMutex, a non-recursive mutex that can be shared across processes // - CrossProcessMutexAutoLock, an RAII class for ensuring that Mutexes are // properly locked and unlocked // // Using CrossProcessMutexAutoLock/CrossProcessMutexAutoUnlock is MUCH // preferred to making bare calls to CrossProcessMutex.Lock and Unlock. // namespace mozilla { -#ifdef XP_WIN +#if defined(OS_WIN) typedef HANDLE CrossProcessMutexHandle; -#elif defined(OS_LINUX) +#elif defined(OS_POSIX) typedef mozilla::ipc::SharedMemoryBasic::Handle CrossProcessMutexHandle; #else // Stub for other platforms. We can't use uintptr_t here since different // processes could disagree on its size. typedef uintptr_t CrossProcessMutexHandle; #endif class CrossProcessMutex @@ -93,19 +93,19 @@ public: private: friend struct IPC::ParamTraits<CrossProcessMutex>; CrossProcessMutex(); CrossProcessMutex(const CrossProcessMutex&); CrossProcessMutex &operator=(const CrossProcessMutex&); -#ifdef XP_WIN +#if defined(OS_WIN) HANDLE mMutex; -#elif defined(OS_LINUX) +#elif defined(OS_POSIX) nsRefPtr<mozilla::ipc::SharedMemoryBasic> mSharedBuffer; pthread_mutex_t* mMutex; mozilla::Atomic<int32_t>* mCount; #endif }; typedef BaseAutoLock<CrossProcessMutex> CrossProcessMutexAutoLock; typedef BaseAutoUnlock<CrossProcessMutex> CrossProcessMutexAutoUnlock;
--- a/ipc/glue/CrossProcessMutex_posix.cpp +++ b/ipc/glue/CrossProcessMutex_posix.cpp @@ -3,16 +3,20 @@ * 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 "CrossProcessMutex.h" #include "mozilla/unused.h" #include "nsDebug.h" #include "nsISupportsImpl.h" +#ifdef OS_MACOSX +#include "nsCocoaFeatures.h" +#endif + namespace { struct MutexData { pthread_mutex_t mMutex; mozilla::Atomic<int32_t> mCount; }; } @@ -36,16 +40,25 @@ InitMutex(pthread_mutex_t* mMutex) MOZ_CRASH(); } } CrossProcessMutex::CrossProcessMutex(const char*) : mMutex(nullptr) , mCount(nullptr) { +#ifdef OS_MACOSX + if (!nsCocoaFeatures::OnLionOrLater()) { + // Don't allow using the cross-process mutex before OS X 10.7 because it + // probably doesn't work very well. See discussion in bug 1072093 for more + // details. + MOZ_CRASH(); + } +#endif + mSharedBuffer = new ipc::SharedMemoryBasic; if (!mSharedBuffer->Create(sizeof(MutexData))) { MOZ_CRASH(); } if (!mSharedBuffer->Map(sizeof(MutexData))) { MOZ_CRASH(); }
--- a/ipc/glue/moz.build +++ b/ipc/glue/moz.build @@ -54,17 +54,17 @@ else: 'SharedMemory_posix.cpp', 'Transport_posix.cpp', ] if CONFIG['OS_ARCH'] == 'WINNT': SOURCES += [ 'CrossProcessMutex_windows.cpp', ] -elif CONFIG['OS_ARCH'] == 'Linux': +elif CONFIG['OS_ARCH'] in ('Linux', 'Darwin'): UNIFIED_SOURCES += [ 'CrossProcessMutex_posix.cpp', ] else: UNIFIED_SOURCES += [ 'CrossProcessMutex_unimplemented.cpp', ]
--- a/js/src/asmjs/AsmJSValidate.cpp +++ b/js/src/asmjs/AsmJSValidate.cpp @@ -8387,16 +8387,17 @@ GenerateAsyncInterruptExit(ModuleCompile // This will restore stack to the address before the call. masm.movePtr(s0, StackPointer); masm.PopRegsInMask(AllRegsExceptSP); // Pop resumePC into PC. Clobber HeapReg to make the jump and restore it // during jump delay slot. masm.pop(HeapReg); masm.as_jr(HeapReg); + masm.loadAsmJSHeapRegisterFromGlobalData(); #elif defined(JS_CODEGEN_ARM) masm.setFramePushed(0); // set to zero so we can use masm.framePushed() below masm.PushRegsInMask(RegisterSet(GeneralRegisterSet(Registers::AllMask & ~(1<<Registers::sp)), FloatRegisterSet(uint32_t(0)))); // save all GP registers,excep sp // Save both the APSR and FPSCR in non-volatile registers. masm.as_mrs(r4); masm.as_vmrs(r5); // Save the stack pointer in a non-volatile register.
--- a/js/src/builtin/Eval.cpp +++ b/js/src/builtin/Eval.cpp @@ -7,16 +7,17 @@ #include "builtin/Eval.h" #include "mozilla/HashFunctions.h" #include "mozilla/Range.h" #include "jscntxt.h" #include "frontend/BytecodeCompiler.h" +#include "vm/Debugger.h" #include "vm/GlobalObject.h" #include "vm/JSONParser.h" #include "vm/Interpreter-inl.h" using namespace js; using mozilla::AddToHash; @@ -475,16 +476,19 @@ js::ExecuteInGlobalAndReturnScope(JSCont assertSameCompartment(cx, global); MOZ_ASSERT(global->is<GlobalObject>()); RootedScript script(cx, scriptArg); if (script->compartment() != cx->compartment()) { script = CloneScript(cx, NullPtr(), NullPtr(), script); if (!script) return false; + + Rooted<GlobalObject *> global(cx, script->compileAndGo() ? &script->global() : nullptr); + Debugger::onNewScript(cx, script, global); } RootedObject scope(cx, JS_NewObject(cx, nullptr, JS::NullPtr(), JS::NullPtr())); if (!scope) return false; if (!scope->setQualifiedVarObj(cx)) return false;
--- a/js/src/builtin/TestingFunctions.cpp +++ b/js/src/builtin/TestingFunctions.cpp @@ -2012,17 +2012,18 @@ FindPath(JSContext *cx, unsigned argc, j } static bool EvalReturningScope(JSContext *cx, unsigned argc, jsval *vp) { CallArgs args = CallArgsFromVp(argc, vp); RootedString str(cx); - if (!JS_ConvertArguments(cx, args, "S", str.address())) + RootedObject global(cx); + if (!JS_ConvertArguments(cx, args, "S/o", str.address(), global.address())) return false; AutoStableStringChars strChars(cx); if (!strChars.initTwoByte(cx, str)) return false; mozilla::Range<const char16_t> chars = strChars.twoByteRange(); size_t srclen = chars.length(); @@ -2038,26 +2039,102 @@ EvalReturningScope(JSContext *cx, unsign options.setNoScriptRval(true); options.setCompileAndGo(false); JS::SourceBufferHolder srcBuf(src, srclen, JS::SourceBufferHolder::NoOwnership); RootedScript script(cx); if (!JS::Compile(cx, JS::NullPtr(), options, srcBuf, &script)) return false; - RootedObject global(cx, JS::CurrentGlobalOrNull(cx)); + if (global) { + global = CheckedUnwrap(global); + if (!global) { + JS_ReportError(cx, "Permission denied to access global"); + return false; + } + if (!global->is<GlobalObject>()) { + JS_ReportError(cx, "Argument must be a global object"); + return false; + } + } else { + global = JS::CurrentGlobalOrNull(cx); + } + RootedObject scope(cx); - if (!js::ExecuteInGlobalAndReturnScope(cx, global, script, &scope)) + + { + // If we're switching globals here, ExecuteInGlobalAndReturnScope will + // take care of cloning the script into that compartment before + // executing it. + AutoCompartment ac(cx, global); + + if (!js::ExecuteInGlobalAndReturnScope(cx, global, script, &scope)) + return false; + } + + if (!cx->compartment()->wrap(cx, &scope)) return false; args.rval().setObject(*scope); return true; } static bool +ShellCloneAndExecuteScript(JSContext *cx, unsigned argc, Value *vp) +{ + CallArgs args = CallArgsFromVp(argc, vp); + + RootedString str(cx); + RootedObject global(cx); + if (!JS_ConvertArguments(cx, args, "So", str.address(), global.address())) + return false; + + AutoStableStringChars strChars(cx); + if (!strChars.initTwoByte(cx, str)) + return false; + + mozilla::Range<const char16_t> chars = strChars.twoByteRange(); + size_t srclen = chars.length(); + const char16_t *src = chars.start().get(); + + JS::AutoFilename filename; + unsigned lineno; + + DescribeScriptedCaller(cx, &filename, &lineno); + + JS::CompileOptions options(cx); + options.setFileAndLine(filename.get(), lineno); + options.setNoScriptRval(true); + options.setCompileAndGo(false); + + JS::SourceBufferHolder srcBuf(src, srclen, JS::SourceBufferHolder::NoOwnership); + RootedScript script(cx); + if (!JS::Compile(cx, JS::NullPtr(), options, srcBuf, &script)) + return false; + + global = CheckedUnwrap(global); + if (!global) { + JS_ReportError(cx, "Permission denied to access global"); + return false; + } + if (!global->is<GlobalObject>()) { + JS_ReportError(cx, "Argument must be a global object"); + return false; + } + + AutoCompartment ac(cx, global); + + if (!JS::CloneAndExecuteScript(cx, global, script)) + return false; + + args.rval().setUndefined(); + return true; +} + +static bool IsSimdAvailable(JSContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); #ifdef JS_CODEGEN_NONE bool available = false; #else bool available = cx->jitSupportsSimd(); #endif @@ -2394,18 +2471,24 @@ gc::ZealModeHelpText), #ifdef NIGHTLY_BUILD JS_FN_HELP("objectAddress", ObjectAddress, 1, 0, "objectAddress(obj)", " Return the current address of the object. For debugging only--this\n" " address may change during a moving GC."), #endif JS_FN_HELP("evalReturningScope", EvalReturningScope, 1, 0, -"evalReturningScope(scriptStr)", -" Evaluate the script in a new scope and return the scope."), +"evalReturningScope(scriptStr, [global])", +" Evaluate the script in a new scope and return the scope.\n" +" If |global| is present, clone the script to |global| before executing."), + + JS_FN_HELP("cloneAndExecuteScript", ShellCloneAndExecuteScript, 2, 0, +"cloneAndExecuteScript(source, global)", +" Compile |source| in the current compartment, clone it into |global|'s\n" +" compartment, and run it there."), JS_FN_HELP("backtrace", DumpBacktrace, 1, 0, "backtrace()", " Dump out a brief backtrace."), JS_FN_HELP("getBacktrace", GetBacktrace, 1, 0, "getBacktrace([options])", " Return the current stack as a string. Takes an optional options object,\n"
--- a/js/src/builtin/TypedObject.cpp +++ b/js/src/builtin/TypedObject.cpp @@ -500,57 +500,39 @@ CreatePrototypeObjectForComplexTypeInsta TenuredObject); if (!result) return nullptr; result->initTypeDescrSlot(*descr); return result; } -const Class UnsizedArrayTypeDescr::class_ = { +const Class ArrayTypeDescr::class_ = { "ArrayType", JSCLASS_HAS_RESERVED_SLOTS(JS_DESCR_SLOTS), JS_PropertyStub, JS_DeletePropertyStub, JS_PropertyStub, JS_StrictPropertyStub, JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, nullptr, nullptr, nullptr, - OutlineTypedObject::constructUnsized, - nullptr -}; - -const Class SizedArrayTypeDescr::class_ = { - "ArrayType", - JSCLASS_HAS_RESERVED_SLOTS(JS_DESCR_SLOTS), - JS_PropertyStub, - JS_DeletePropertyStub, - JS_PropertyStub, - JS_StrictPropertyStub, - JS_EnumerateStub, - JS_ResolveStub, - JS_ConvertStub, - nullptr, - nullptr, - nullptr, - TypedObject::constructSized, + TypedObject::construct, nullptr }; const JSPropertySpec ArrayMetaTypeDescr::typeObjectProperties[] = { JS_PS_END }; const JSFunctionSpec ArrayMetaTypeDescr::typeObjectMethods[] = { {"array", {nullptr, nullptr}, 1, 0, "ArrayShorthand"}, - JS_FN("dimension", UnsizedArrayTypeDescr::dimension, 1, 0), JS_SELF_HOSTED_FN("toSource", "DescrToSource", 0, 0), {"equivalent", {nullptr, nullptr}, 1, 0, "TypeDescrEquivalent"}, JS_SELF_HOSTED_FN("build", "TypedObjectArrayTypeBuild", 3, 0), JS_SELF_HOSTED_FN("buildPar", "TypedObjectArrayTypeBuildPar", 3, 0), JS_SELF_HOSTED_FN("from", "TypedObjectArrayTypeFrom", 3, 0), JS_SELF_HOSTED_FN("fromPar", "TypedObjectArrayTypeFromPar", 3, 0), JS_FS_END }; @@ -572,31 +554,29 @@ const JSFunctionSpec ArrayMetaTypeDescr: JS_SELF_HOSTED_FN("filterPar", "TypedArrayFilterPar", 1, 0), JS_FS_END }; bool js::CreateUserSizeAndAlignmentProperties(JSContext *cx, HandleTypeDescr descr) { // If data is transparent, also store the public slots. - if (descr->transparent() && descr->is<SizedTypeDescr>()) { - Rooted<SizedTypeDescr*> sizedDescr(cx, &descr->as<SizedTypeDescr>()); - + if (descr->transparent()) { // byteLength - RootedValue typeByteLength(cx, Int32Value(sizedDescr->size())); + RootedValue typeByteLength(cx, Int32Value(descr->size())); if (!JSObject::defineProperty(cx, descr, cx->names().byteLength, typeByteLength, nullptr, nullptr, JSPROP_READONLY | JSPROP_PERMANENT)) { return false; } // byteAlignment - RootedValue typeByteAlignment(cx, Int32Value(sizedDescr->alignment())); + RootedValue typeByteAlignment(cx, Int32Value(descr->alignment())); if (!JSObject::defineProperty(cx, descr, cx->names().byteAlignment, typeByteAlignment, nullptr, nullptr, JSPROP_READONLY | JSPROP_PERMANENT)) { return false; } } else { @@ -614,55 +594,52 @@ js::CreateUserSizeAndAlignmentProperties UndefinedHandleValue, nullptr, nullptr, JSPROP_READONLY | JSPROP_PERMANENT)) { return false; } } - // variable -- true for unsized arrays - RootedValue variable(cx, BooleanValue(!descr->is<SizedTypeDescr>())); - if (!JSObject::defineProperty(cx, descr, cx->names().variable, - variable, - nullptr, nullptr, - JSPROP_READONLY | JSPROP_PERMANENT)) - { - return false; - } - return true; } -template<class T> -T * +ArrayTypeDescr * ArrayMetaTypeDescr::create(JSContext *cx, HandleObject arrayTypePrototype, - HandleSizedTypeDescr elementType, + HandleTypeDescr elementType, HandleAtom stringRepr, - int32_t size) + int32_t size, + int32_t length) { - Rooted<T*> obj(cx); - obj = NewObjectWithProto<T>(cx, arrayTypePrototype, nullptr, SingletonObject); + Rooted<ArrayTypeDescr*> obj(cx); + obj = NewObjectWithProto<ArrayTypeDescr>(cx, arrayTypePrototype, nullptr, SingletonObject); if (!obj) return nullptr; - obj->initReservedSlot(JS_DESCR_SLOT_KIND, Int32Value(T::Kind)); + obj->initReservedSlot(JS_DESCR_SLOT_KIND, Int32Value(ArrayTypeDescr::Kind)); obj->initReservedSlot(JS_DESCR_SLOT_STRING_REPR, StringValue(stringRepr)); obj->initReservedSlot(JS_DESCR_SLOT_ALIGNMENT, Int32Value(elementType->alignment())); obj->initReservedSlot(JS_DESCR_SLOT_SIZE, Int32Value(size)); obj->initReservedSlot(JS_DESCR_SLOT_OPAQUE, BooleanValue(elementType->opaque())); obj->initReservedSlot(JS_DESCR_SLOT_ARRAY_ELEM_TYPE, ObjectValue(*elementType)); + obj->initReservedSlot(JS_DESCR_SLOT_ARRAY_LENGTH, Int32Value(length)); RootedValue elementTypeVal(cx, ObjectValue(*elementType)); if (!JSObject::defineProperty(cx, obj, cx->names().elementType, elementTypeVal, nullptr, nullptr, JSPROP_READONLY | JSPROP_PERMANENT)) return nullptr; + RootedValue lengthValue(cx, NumberValue(length)); + if (!JSObject::defineProperty(cx, obj, cx->names().length, + lengthValue, nullptr, nullptr, + JSPROP_READONLY | JSPROP_PERMANENT)) + return nullptr; + if (!CreateUserSizeAndAlignmentProperties(cx, obj)) return nullptr; Rooted<TypedProto*> prototypeObj(cx); prototypeObj = CreatePrototypeObjectForComplexTypeInstance(cx, obj, arrayTypePrototype); if (!prototypeObj) return nullptr; @@ -682,142 +659,79 @@ ArrayMetaTypeDescr::construct(JSContext if (!args.isConstructing()) { JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_NOT_FUNCTION, "ArrayType"); return false; } RootedObject arrayTypeGlobal(cx, &args.callee()); - // Expect one argument which is a sized type object - if (args.length() < 1) { + // Expect two arguments. The first is a type object, the second is a length. + if (args.length() < 2) { JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_MORE_ARGS_NEEDED, - "ArrayType", "0", ""); + "ArrayType", "1", ""); return false; } - if (!args[0].isObject() || !args[0].toObject().is<SizedTypeDescr>()) { + if (!args[0].isObject() || !args[0].toObject().is<TypeDescr>()) { ReportCannotConvertTo(cx, args[0], "ArrayType element specifier"); return false; } - Rooted<SizedTypeDescr*> elementType(cx); - elementType = &args[0].toObject().as<SizedTypeDescr>(); - - // Construct a canonical string `new ArrayType(<elementType>)`: + if (!args[1].isInt32() || args[1].toInt32() < 0) { + ReportCannotConvertTo(cx, args[1], "ArrayType length specifier"); + return false; + } + + Rooted<TypeDescr*> elementType(cx, &args[0].toObject().as<TypeDescr>()); + + int32_t length = args[1].toInt32(); + + // Compute the byte size. + CheckedInt32 size = CheckedInt32(elementType->size()) * length; + if (!size.isValid()) { + JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, + JSMSG_TYPEDOBJECT_TOO_BIG); + return false; + } + + // Construct a canonical string `new ArrayType(<elementType>, N)`: StringBuffer contents(cx); contents.append("new ArrayType("); contents.append(&elementType->stringRepr()); + contents.append(", "); + if (!NumberValueToStringBuffer(cx, NumberValue(length), contents)) + return false; contents.append(")"); RootedAtom stringRepr(cx, contents.finishAtom()); if (!stringRepr) return false; // Extract ArrayType.prototype RootedObject arrayTypePrototype(cx, GetPrototype(cx, arrayTypeGlobal)); if (!arrayTypePrototype) return false; // Create the instance of ArrayType - Rooted<UnsizedArrayTypeDescr *> obj(cx); - obj = create<UnsizedArrayTypeDescr>(cx, arrayTypePrototype, elementType, - stringRepr, 0); + Rooted<ArrayTypeDescr *> obj(cx); + obj = create(cx, arrayTypePrototype, elementType, stringRepr, size.value(), length); if (!obj) return false; - // Add `length` property, which is undefined for an unsized array. - if (!JSObject::defineProperty(cx, obj, cx->names().length, - UndefinedHandleValue, nullptr, nullptr, - JSPROP_READONLY | JSPROP_PERMANENT)) - return false; - - args.rval().setObject(*obj); - return true; -} - -/*static*/ bool -UnsizedArrayTypeDescr::dimension(JSContext *cx, unsigned int argc, jsval *vp) -{ - // Expect that the `this` pointer is an unsized array type - // and the first argument is an integer size. - CallArgs args = CallArgsFromVp(argc, vp); - if (args.length() != 1 || - !args.thisv().isObject() || - !args.thisv().toObject().is<UnsizedArrayTypeDescr>() || - !args[0].isInt32() || - args[0].toInt32() < 0) - { - JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, - JSMSG_TYPEDOBJECT_ARRAYTYPE_BAD_ARGS); - return false; - } - - // Extract arguments. - Rooted<UnsizedArrayTypeDescr*> unsizedTypeDescr(cx); - unsizedTypeDescr = &args.thisv().toObject().as<UnsizedArrayTypeDescr>(); - int32_t length = args[0].toInt32(); - Rooted<SizedTypeDescr*> elementType(cx, &unsizedTypeDescr->elementType()); - - // Compute the size. - CheckedInt32 size = CheckedInt32(elementType->size()) * length; - if (!size.isValid()) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, - JSMSG_TYPEDOBJECT_TOO_BIG); - return false; - } - - // Construct a canonical string `new ArrayType(<elementType>).dimension(N)`: - StringBuffer contents(cx); - contents.append("new ArrayType("); - contents.append(&elementType->stringRepr()); - contents.append(").dimension("); - if (!NumberValueToStringBuffer(cx, NumberValue(length), contents)) - return false; - contents.append(")"); - RootedAtom stringRepr(cx, contents.finishAtom()); - if (!stringRepr) - return false; - - // Create the sized type object. - Rooted<SizedArrayTypeDescr*> obj(cx); - obj = ArrayMetaTypeDescr::create<SizedArrayTypeDescr>(cx, unsizedTypeDescr, - elementType, - stringRepr, size.value()); - if (!obj) - return false; - - obj->initReservedSlot(JS_DESCR_SLOT_SIZED_ARRAY_LENGTH, - Int32Value(length)); - - // Add `length` property. - RootedValue lengthVal(cx, Int32Value(length)); - if (!JSObject::defineProperty(cx, obj, cx->names().length, - lengthVal, nullptr, nullptr, - JSPROP_READONLY | JSPROP_PERMANENT)) - return false; - - // Add `unsized` property, which is a link from the sized - // array to the unsized array. - RootedValue unsizedTypeDescrValue(cx, ObjectValue(*unsizedTypeDescr)); - if (!JSObject::defineProperty(cx, obj, cx->names().unsized, - unsizedTypeDescrValue, nullptr, nullptr, - JSPROP_READONLY | JSPROP_PERMANENT)) - return false; - args.rval().setObject(*obj); return true; } bool js::IsTypedObjectArray(JSObject &obj) { if (!obj.is<TypedObject>()) return false; TypeDescr& d = obj.as<TypedObject>().typeDescr(); - return d.is<SizedArrayTypeDescr>() || d.is<UnsizedArrayTypeDescr>(); + return d.is<ArrayTypeDescr>(); } /********************************* * StructType class */ const Class StructTypeDescr::class_ = { "StructType", @@ -827,17 +741,17 @@ const Class StructTypeDescr::class_ = { JS_PropertyStub, JS_StrictPropertyStub, JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, nullptr, /* finalize */ nullptr, /* call */ nullptr, /* hasInstance */ - TypedObject::constructSized, + TypedObject::construct, nullptr /* trace */ }; const JSPropertySpec StructMetaTypeDescr::typeObjectProperties[] = { JS_PS_END }; const JSFunctionSpec StructMetaTypeDescr::typeObjectMethods[] = { @@ -888,33 +802,33 @@ StructMetaTypeDescr::create(JSContext *c if (!stringBuffer.append("new StructType({")) { js_ReportOutOfMemory(cx); return nullptr; } RootedValue fieldTypeVal(cx); RootedId id(cx); - Rooted<SizedTypeDescr*> fieldType(cx); + Rooted<TypeDescr*> fieldType(cx); for (unsigned int i = 0; i < ids.length(); i++) { id = ids[i]; // Check that all the property names are non-numeric strings. uint32_t unused; if (!JSID_IS_ATOM(id) || JSID_TO_ATOM(id)->isIndex(&unused)) { RootedValue idValue(cx, IdToValue(id)); ReportCannotConvertTo(cx, idValue, "StructType field name"); return nullptr; } // Load the value for the current field from the `fields` object. // The value should be a type descriptor. if (!JSObject::getGeneric(cx, fields, fields, id, &fieldTypeVal)) return nullptr; - fieldType = ToObjectIf<SizedTypeDescr>(fieldTypeVal); + fieldType = ToObjectIf<TypeDescr>(fieldTypeVal); if (!fieldType) { ReportCannotConvertTo(cx, fieldTypeVal, "StructType field specifier"); return nullptr; } // Collect field name and type object RootedValue fieldName(cx, IdToValue(id)); if (!fieldNames.append(fieldName)) { @@ -1163,32 +1077,32 @@ StructTypeDescr::fieldOffset(size_t inde size_t StructTypeDescr::maybeForwardedFieldOffset(size_t index) const { NativeObject &fieldOffsets = maybeForwardedFieldInfoObject(JS_DESCR_SLOT_STRUCT_FIELD_OFFSETS); MOZ_ASSERT(index < fieldOffsets.getDenseInitializedLength()); return AssertedCast<size_t>(fieldOffsets.getDenseElement(index).toInt32()); } -SizedTypeDescr& +TypeDescr& StructTypeDescr::fieldDescr(size_t index) const { NativeObject &fieldDescrs = fieldInfoObject(JS_DESCR_SLOT_STRUCT_FIELD_TYPES); MOZ_ASSERT(index < fieldDescrs.getDenseInitializedLength()); - return fieldDescrs.getDenseElement(index).toObject().as<SizedTypeDescr>(); + return fieldDescrs.getDenseElement(index).toObject().as<TypeDescr>(); } -SizedTypeDescr& +TypeDescr& StructTypeDescr::maybeForwardedFieldDescr(size_t index) const { NativeObject &fieldDescrs = maybeForwardedFieldInfoObject(JS_DESCR_SLOT_STRUCT_FIELD_TYPES); MOZ_ASSERT(index < fieldDescrs.getDenseInitializedLength()); JSObject &descr = *MaybeForwarded(&fieldDescrs.getDenseElement(index).toObject()); - return descr.as<SizedTypeDescr>(); + return descr.as<TypeDescr>(); } /****************************************************************************** * Creating the TypedObject "module" * * We create one global, `TypedObject`, which contains the following * members: * @@ -1463,19 +1377,17 @@ TypedObject::offset() const if (is<InlineTypedObject>()) return 0; return typedMem() - typedMemBase(); } int32_t TypedObject::length() const { - if (typeDescr().is<SizedArrayTypeDescr>()) - return typeDescr().as<SizedArrayTypeDescr>().length(); - return as<OutlineTypedObject>().unsizedLength(); + return typeDescr().as<ArrayTypeDescr>().length(); } uint8_t * TypedObject::typedMem() const { MOZ_ASSERT(isAttached()); if (is<InlineTypedObject>()) @@ -1612,28 +1524,24 @@ OutlineTypedObject::createUnattachedWith { MOZ_ASSERT(clasp == &OutlineTransparentTypedObject::class_ || clasp == &OutlineOpaqueTypedObject::class_); RootedObject proto(cx, PrototypeForTypeDescr(cx, type)); if (!proto) return nullptr; - gc::AllocKind allocKind = allocKindForTypeDescriptor(type); NewObjectKind newKind = (heap == gc::TenuredHeap) ? MaybeSingletonObject : GenericObject; - JSObject *obj = NewObjectWithClassProto(cx, clasp, proto, nullptr, allocKind, newKind); + JSObject *obj = NewObjectWithClassProto(cx, clasp, proto, nullptr, gc::FINALIZE_OBJECT0, newKind); if (!obj) return nullptr; OutlineTypedObject *typedObj = &obj->as<OutlineTypedObject>(); typedObj->setOwnerAndData(nullptr, nullptr); - if (type->kind() == type::UnsizedArray) - typedObj->setUnsizedLength(length); - return typedObj; } void OutlineTypedObject::attach(JSContext *cx, ArrayBufferObject &buffer, int32_t offset) { MOZ_ASSERT(!isAttached()); MOZ_ASSERT(offset >= 0); @@ -1663,38 +1571,35 @@ OutlineTypedObject::attach(JSContext *cx attach(cx, owner->as<ArrayBufferObject>(), offset); } else { MOZ_ASSERT(owner->is<InlineTypedObject>()); setOwnerAndData(owner, owner->as<InlineTypedObject>().inlineTypedMem() + offset); } } // Returns a suitable JS_TYPEDOBJ_SLOT_LENGTH value for an instance of -// the type `type`. `type` must not be an unsized array. +// the type `type`. static int32_t TypedObjLengthFromType(TypeDescr &descr) { switch (descr.kind()) { case type::Scalar: case type::Reference: case type::Struct: case type::Simd: return 0; - case type::SizedArray: - return descr.as<SizedArrayTypeDescr>().length(); - - case type::UnsizedArray: - MOZ_CRASH("TypedObjLengthFromType() invoked on unsized type"); + case type::Array: + return descr.as<ArrayTypeDescr>().length(); } MOZ_CRASH("Invalid kind"); } /*static*/ OutlineTypedObject * -OutlineTypedObject::createDerived(JSContext *cx, HandleSizedTypeDescr type, +OutlineTypedObject::createDerived(JSContext *cx, HandleTypeDescr type, HandleTypedObject typedObj, int32_t offset) { MOZ_ASSERT(offset <= typedObj->size()); MOZ_ASSERT(offset + type->size() <= typedObj->size()); int32_t length = TypedObjLengthFromType(*type); const js::Class *clasp = typedObj->opaque() @@ -1708,73 +1613,36 @@ OutlineTypedObject::createDerived(JSCont obj->attach(cx, *typedObj, offset); return obj; } /*static*/ TypedObject * TypedObject::createZeroed(JSContext *cx, HandleTypeDescr descr, int32_t length, gc::InitialHeap heap) { // If possible, create an object with inline data. - if (descr->is<SizedTypeDescr>() && - (size_t) descr->as<SizedTypeDescr>().size() <= InlineTypedObject::MaximumSize) - { + if ((size_t) descr->size() <= InlineTypedObject::MaximumSize) { InlineTypedObject *obj = InlineTypedObject::create(cx, descr, heap); - descr->as<SizedTypeDescr>().initInstances(cx->runtime(), obj->inlineTypedMem(), 1); + descr->initInstances(cx->runtime(), obj->inlineTypedMem(), 1); return obj; } // Create unattached wrapper object. Rooted<OutlineTypedObject*> obj(cx, OutlineTypedObject::createUnattached(cx, descr, length, heap)); if (!obj) return nullptr; // Allocate and initialize the memory for this instance. - // Also initialize the JS_TYPEDOBJ_SLOT_LENGTH slot. - switch (descr->kind()) { - case type::Scalar: - case type::Reference: - case type::Struct: - case type::Simd: - case type::SizedArray: - { - size_t totalSize = descr->as<SizedTypeDescr>().size(); - Rooted<ArrayBufferObject*> buffer(cx); - buffer = ArrayBufferObject::create(cx, totalSize); - if (!buffer) - return nullptr; - descr->as<SizedTypeDescr>().initInstances(cx->runtime(), buffer->dataPointer(), 1); - obj->attach(cx, *buffer, 0); - return obj; - } - - case type::UnsizedArray: - { - Rooted<SizedTypeDescr*> elementTypeRepr(cx); - elementTypeRepr = &descr->as<UnsizedArrayTypeDescr>().elementType(); - - CheckedInt32 totalSize = CheckedInt32(elementTypeRepr->size()) * length; - if (!totalSize.isValid()) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, - JSMSG_TYPEDOBJECT_TOO_BIG); - return nullptr; - } - - Rooted<ArrayBufferObject*> buffer(cx); - buffer = ArrayBufferObject::create(cx, totalSize.value()); - if (!buffer) - return nullptr; - - if (length) - elementTypeRepr->initInstances(cx->runtime(), buffer->dataPointer(), length); - obj->attach(cx, *buffer, 0); - return obj; - } - } - - MOZ_CRASH("Bad TypeRepresentation Kind"); + size_t totalSize = descr->size(); + Rooted<ArrayBufferObject*> buffer(cx); + buffer = ArrayBufferObject::create(cx, totalSize); + if (!buffer) + return nullptr; + descr->initInstances(cx->runtime(), buffer->dataPointer(), 1); + obj->attach(cx, *buffer, 0); + return obj; } static bool ReportTypedObjTypeError(JSContext *cx, const unsigned errorNumber, HandleTypedObject obj) { // Serialize type string of obj @@ -1818,49 +1686,33 @@ OutlineTypedObject::obj_trace(JSTracer * { mem += reinterpret_cast<uint8_t *>(owner) - reinterpret_cast<uint8_t *>(oldOwner); typedObj.setData(mem); } if (!descr.opaque() || !typedObj.maybeForwardedIsAttached()) return; - switch (descr.kind()) { - case type::Scalar: - case type::Reference: - case type::Struct: - case type::SizedArray: - case type::Simd: - descr.as<SizedTypeDescr>().traceInstances(trc, mem, 1); - break; - - case type::UnsizedArray: - { - SizedTypeDescr &elemType = descr.as<UnsizedArrayTypeDescr>().maybeForwardedElementType(); - elemType.traceInstances(trc, mem, typedObj.unsizedLength()); - break; - } - } + descr.traceInstances(trc, mem, 1); } bool TypedObject::obj_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id, MutableHandleObject objp, MutableHandleShape propp) { MOZ_ASSERT(obj->is<TypedObject>()); Rooted<TypeDescr*> descr(cx, &obj->as<TypedObject>().typeDescr()); switch (descr->kind()) { case type::Scalar: case type::Reference: case type::Simd: break; - case type::SizedArray: - case type::UnsizedArray: + case type::Array: { uint32_t index; if (js_IdIsIndex(id, &index)) return obj_lookupElement(cx, obj, index, objp, propp); if (JSID_IS_ATOM(id, cx->names().length)) { MarkNonNativePropertyFound(propp); objp.set(obj); @@ -1977,18 +1829,17 @@ TypedObject::obj_getGeneric(JSContext *c switch (typedObj->typeDescr().kind()) { case type::Scalar: case type::Reference: break; case type::Simd: break; - case type::SizedArray: - case type::UnsizedArray: + case type::Array: if (JSID_IS_ATOM(id, cx->names().length)) { if (!typedObj->isAttached()) { JS_ReportErrorNumber( cx, js_GetErrorMessage, nullptr, JSMSG_TYPEDOBJECT_HANDLE_UNATTACHED); return false; } @@ -2000,17 +1851,17 @@ TypedObject::obj_getGeneric(JSContext *c case type::Struct: { Rooted<StructTypeDescr*> descr(cx, &typedObj->typeDescr().as<StructTypeDescr>()); size_t fieldIndex; if (!descr->fieldIndex(id, &fieldIndex)) break; size_t offset = descr->fieldOffset(fieldIndex); - Rooted<SizedTypeDescr*> fieldType(cx, &descr->fieldDescr(fieldIndex)); + Rooted<TypeDescr*> fieldType(cx, &descr->fieldDescr(fieldIndex)); return Reify(cx, fieldType, typedObj, offset, vp); } } RootedObject proto(cx, obj->getProto()); if (!proto) { vp.setUndefined(); return true; @@ -2037,50 +1888,42 @@ TypedObject::obj_getElement(JSContext *c switch (descr->kind()) { case type::Scalar: case type::Reference: case type::Simd: case type::Struct: break; - case type::SizedArray: - return obj_getArrayElement<SizedArrayTypeDescr>(cx, typedObj, descr, - index, vp); - - case type::UnsizedArray: - return obj_getArrayElement<UnsizedArrayTypeDescr>(cx, typedObj, descr, - index, vp); + case type::Array: + return obj_getArrayElement(cx, typedObj, descr, index, vp); } RootedObject proto(cx, obj->getProto()); if (!proto) { vp.setUndefined(); return true; } return JSObject::getElement(cx, proto, receiver, index, vp); } -template<class T> /*static*/ bool TypedObject::obj_getArrayElement(JSContext *cx, Handle<TypedObject*> typedObj, Handle<TypeDescr*> typeDescr, uint32_t index, MutableHandleValue vp) { - MOZ_ASSERT(typeDescr->is<T>()); - if (index >= (size_t) typedObj->length()) { vp.setUndefined(); return true; } - Rooted<SizedTypeDescr*> elementType(cx, &typeDescr->as<T>().elementType()); + Rooted<TypeDescr*> elementType(cx, &typeDescr->as<ArrayTypeDescr>().elementType()); size_t offset = elementType->size() * index; return Reify(cx, elementType, typedObj, offset, vp); } bool TypedObject::obj_setGeneric(JSContext *cx, HandleObject obj, HandleId id, MutableHandleValue vp, bool strict) { @@ -2094,34 +1937,33 @@ TypedObject::obj_setGeneric(JSContext *c switch (typedObj->typeDescr().kind()) { case type::Scalar: case type::Reference: break; case type::Simd: break; - case type::SizedArray: - case type::UnsizedArray: + case type::Array: if (JSID_IS_ATOM(id, cx->names().length)) { JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_CANT_REDEFINE_ARRAY_LENGTH); return false; } break; case type::Struct: { Rooted<StructTypeDescr*> descr(cx, &typedObj->typeDescr().as<StructTypeDescr>()); size_t fieldIndex; if (!descr->fieldIndex(id, &fieldIndex)) break; size_t offset = descr->fieldOffset(fieldIndex); - Rooted<SizedTypeDescr*> fieldType(cx, &descr->fieldDescr(fieldIndex)); + Rooted<TypeDescr*> fieldType(cx, &descr->fieldDescr(fieldIndex)); return ConvertAndCopyTo(cx, fieldType, typedObj, offset, vp); } } return ReportTypedObjTypeError(cx, JSMSG_OBJECT_NOT_EXTENSIBLE, typedObj); } bool @@ -2143,44 +1985,38 @@ TypedObject::obj_setElement(JSContext *c switch (descr->kind()) { case type::Scalar: case type::Reference: case type::Simd: case type::Struct: break; - case type::SizedArray: - return obj_setArrayElement<SizedArrayTypeDescr>(cx, typedObj, descr, index, vp); - - case type::UnsizedArray: - return obj_setArrayElement<UnsizedArrayTypeDescr>(cx, typedObj, descr, index, vp); + case type::Array: + return obj_setArrayElement(cx, typedObj, descr, index, vp); } return ReportTypedObjTypeError(cx, JSMSG_OBJECT_NOT_EXTENSIBLE, typedObj); } -template<class T> /*static*/ bool TypedObject::obj_setArrayElement(JSContext *cx, Handle<TypedObject*> typedObj, Handle<TypeDescr*> descr, uint32_t index, MutableHandleValue vp) { - MOZ_ASSERT(descr->is<T>()); - if (index >= (size_t) typedObj->length()) { JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_TYPEDOBJECT_BINARYARRAY_BAD_INDEX); return false; } - Rooted<SizedTypeDescr*> elementType(cx); - elementType = &descr->as<T>().elementType(); + Rooted<TypeDescr*> elementType(cx); + elementType = &descr->as<ArrayTypeDescr>().elementType(); size_t offset = elementType->size() * index; return ConvertAndCopyTo(cx, elementType, typedObj, offset, vp); } bool TypedObject::obj_getGenericAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp) { @@ -2189,18 +2025,17 @@ TypedObject::obj_getGenericAttributes(JS switch (typedObj->typeDescr().kind()) { case type::Scalar: case type::Reference: break; case type::Simd: break; - case type::SizedArray: - case type::UnsizedArray: + case type::Array: if (js_IdIsIndex(id, &index)) { *attrsp = JSPROP_ENUMERATE | JSPROP_PERMANENT; return true; } if (JSID_IS_ATOM(id, cx->names().length)) { *attrsp = JSPROP_READONLY | JSPROP_PERMANENT; return true; } @@ -2230,18 +2065,17 @@ IsOwnId(JSContext *cx, HandleObject obj, uint32_t index; Rooted<TypedObject *> typedObj(cx, &obj->as<TypedObject>()); switch (typedObj->typeDescr().kind()) { case type::Scalar: case type::Reference: case type::Simd: return false; - case type::SizedArray: - case type::UnsizedArray: + case type::Array: return js_IdIsIndex(id, &index) || JSID_IS_ATOM(id, cx->names().length); case type::Struct: size_t index; if (typedObj->typeDescr().as<StructTypeDescr>().fieldIndex(id, &index)) return true; } @@ -2300,18 +2134,17 @@ TypedObject::obj_enumerate(JSContext *cx case JSENUMERATE_NEXT: case JSENUMERATE_DESTROY: statep.setNull(); break; } break; - case type::SizedArray: - case type::UnsizedArray: + case type::Array: switch (enum_op) { case JSENUMERATE_INIT_ALL: case JSENUMERATE_INIT: statep.setInt32(0); idp.set(INT_TO_JSID(typedObj->length())); break; case JSENUMERATE_NEXT: @@ -2361,18 +2194,16 @@ TypedObject::obj_enumerate(JSContext *cx } return true; } void OutlineTypedObject::neuter(void *newData) { - if (typeDescr().kind() == type::UnsizedArray) - setUnsizedLength(0); setData(reinterpret_cast<uint8_t *>(newData)); } /****************************************************************************** * Inline typed objects */ /* static */ InlineTypedObject * @@ -2413,17 +2244,17 @@ InlineTypedObject::createCopy(JSContext InlineTypedObject::obj_trace(JSTracer *trc, JSObject *object) { InlineTypedObject &typedObj = object->as<InlineTypedObject>(); // When this is called for compacting GC, the related objects we touch here // may not have had their slots updated yet. TypeDescr &descr = typedObj.maybeForwardedTypeDescr(); - descr.as<SizedTypeDescr>().traceInstances(trc, typedObj.inlineTypedMem(), 1); + descr.traceInstances(trc, typedObj.inlineTypedMem(), 1); } ArrayBufferObject * InlineTransparentTypedObject::getOrCreateBuffer(JSContext *cx) { LazyArrayBufferTable *&table = cx->compartment()->lazyArrayBuffers; if (!table) { table = cx->new_<LazyArrayBufferTable>(cx); @@ -2432,17 +2263,17 @@ InlineTransparentTypedObject::getOrCreat } ArrayBufferObject *buffer = table->maybeBuffer(this); if (buffer) return buffer; ArrayBufferObject::BufferContents contents = ArrayBufferObject::BufferContents::createPlain(inlineTypedMem()); - size_t nbytes = typeDescr().as<SizedTypeDescr>().size(); + size_t nbytes = typeDescr().size(); // Prevent GC under ArrayBufferObject::create, which might move this object // and its contents. gc::AutoSuppressGC suppress(cx); buffer = ArrayBufferObject::create(cx, nbytes, contents, ArrayBufferObject::DoesntOwnData); if (!buffer) return nullptr; @@ -2589,21 +2420,18 @@ LengthForType(TypeDescr &descr) { switch (descr.kind()) { case type::Scalar: case type::Reference: case type::Struct: case type::Simd: return 0; - case type::SizedArray: - return descr.as<SizedArrayTypeDescr>().length(); - - case type::UnsizedArray: - return 0; + case type::Array: + return descr.as<ArrayTypeDescr>().length(); } MOZ_CRASH("Invalid kind"); } static bool CheckOffset(int32_t offset, int32_t size, @@ -2628,25 +2456,25 @@ CheckOffset(int32_t offset, // Offset must be aligned. if ((offset % alignment) != 0) return false; return true; } /*static*/ bool -TypedObject::constructSized(JSContext *cx, unsigned int argc, Value *vp) +TypedObject::construct(JSContext *cx, unsigned int argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); - MOZ_ASSERT(args.callee().is<SizedTypeDescr>()); - Rooted<SizedTypeDescr*> callee(cx, &args.callee().as<SizedTypeDescr>()); - - // Typed object constructors for sized types are overloaded in - // three ways, in order of precedence: + MOZ_ASSERT(args.callee().is<TypeDescr>()); + Rooted<TypeDescr*> callee(cx, &args.callee().as<TypeDescr>()); + + // Typed object constructors are overloaded in three ways, in order of + // precedence: // // new TypeObj() // new TypeObj(buffer, [offset]) // new TypeObj(data) // Zero argument constructor: if (args.length() == 0) { int32_t length = LengthForType(*callee); @@ -2721,203 +2549,47 @@ TypedObject::constructSized(JSContext *c } // Something bogus. JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_TYPEDOBJECT_BAD_ARGS); return false; } -/*static*/ bool -TypedObject::constructUnsized(JSContext *cx, unsigned int argc, Value *vp) -{ - CallArgs args = CallArgsFromVp(argc, vp); - - MOZ_ASSERT(args.callee().is<TypeDescr>()); - Rooted<UnsizedArrayTypeDescr*> callee(cx); - callee = &args.callee().as<UnsizedArrayTypeDescr>(); - - // Typed object constructors for unsized arrays are overloaded in - // four ways, in order of precedence: - // - // new TypeObj(buffer, [offset, [length]]) // [1] - // new TypeObj(length) // [1] - // new TypeObj(data) - // new TypeObj() - // - // [1] Explicit lengths only available for unsized arrays. - - // Zero argument constructor: - if (args.length() == 0) { - Rooted<TypedObject*> obj(cx, createZeroed(cx, callee, 0)); - if (!obj) - return false; - args.rval().setObject(*obj); - return true; - } - - // Length constructor. - if (args[0].isInt32()) { - int32_t length = args[0].toInt32(); - if (length < 0) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, - nullptr, JSMSG_TYPEDOBJECT_BAD_ARGS); - return false; - } - Rooted<TypedObject*> obj(cx, createZeroed(cx, callee, length)); - if (!obj) - return false; - args.rval().setObject(*obj); - return true; - } - - // Buffer constructor. - if (args[0].isObject() && args[0].toObject().is<ArrayBufferObject>()) { - Rooted<ArrayBufferObject*> buffer(cx); - buffer = &args[0].toObject().as<ArrayBufferObject>(); - - if (callee->opaque()) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, - nullptr, JSMSG_TYPEDOBJECT_BAD_ARGS); - return false; - } - - int32_t offset; - if (args.length() >= 2 && !args[1].isUndefined()) { - if (!args[1].isInt32()) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, - nullptr, JSMSG_TYPEDOBJECT_BAD_ARGS); - return false; - } - - offset = args[1].toInt32(); - } else { - offset = 0; - } - - if (!CheckOffset(offset, 0, callee->alignment(), buffer->byteLength())) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, - nullptr, JSMSG_TYPEDOBJECT_BAD_ARGS); - return false; - } - - int32_t elemSize = callee->elementType().size(); - int32_t bytesRemaining = buffer->byteLength() - offset; - int32_t maximumLength = bytesRemaining / elemSize; - - int32_t length; - if (args.length() >= 3 && !args[2].isUndefined()) { - if (!args[2].isInt32()) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, - nullptr, JSMSG_TYPEDOBJECT_BAD_ARGS); - return false; - } - length = args[2].toInt32(); - - if (length < 0 || length > maximumLength) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, - nullptr, JSMSG_TYPEDOBJECT_BAD_ARGS); - return false; - } - } else { - if ((bytesRemaining % elemSize) != 0) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, - nullptr, JSMSG_TYPEDOBJECT_BAD_ARGS); - return false; - } - - length = maximumLength; - } - - if (buffer->isNeutered()) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, - nullptr, JSMSG_TYPEDOBJECT_BAD_ARGS); - return false; - } - - Rooted<OutlineTypedObject*> obj(cx); - obj = OutlineTypedObject::createUnattached(cx, callee, length); - if (!obj) - return false; - - obj->attach(cx, args[0].toObject().as<ArrayBufferObject>(), offset); - } - - // Data constructor for unsized values - if (args[0].isObject()) { - // Read length out of the object. - RootedObject arg(cx, &args[0].toObject()); - RootedValue lengthVal(cx); - if (!JSObject::getProperty(cx, arg, arg, cx->names().length, &lengthVal)) - return false; - if (!lengthVal.isInt32()) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, - nullptr, JSMSG_TYPEDOBJECT_BAD_ARGS); - return false; - } - int32_t length = lengthVal.toInt32(); - - // Check that length * elementSize does not overflow. - int32_t elementSize = callee->elementType().size(); - int32_t byteLength; - if (!SafeMul(elementSize, length, &byteLength)) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, - nullptr, JSMSG_TYPEDOBJECT_BAD_ARGS); - return false; - } - - // Create the unsized array. - Rooted<TypedObject*> obj(cx, createZeroed(cx, callee, length)); - if (!obj) - return false; - - // Initialize from `arg` - if (!ConvertAndCopyTo(cx, obj, args[0])) - return false; - args.rval().setObject(*obj); - return true; - } - - // Something bogus. - JS_ReportErrorNumber(cx, js_GetErrorMessage, - nullptr, JSMSG_TYPEDOBJECT_BAD_ARGS); - return false; -} - /****************************************************************************** * Intrinsics */ bool js::NewOpaqueTypedObject(JSContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); MOZ_ASSERT(args.length() == 1); - MOZ_ASSERT(args[0].isObject() && args[0].toObject().is<SizedTypeDescr>()); - - Rooted<SizedTypeDescr*> descr(cx, &args[0].toObject().as<SizedTypeDescr>()); + MOZ_ASSERT(args[0].isObject() && args[0].toObject().is<TypeDescr>()); + + Rooted<TypeDescr*> descr(cx, &args[0].toObject().as<TypeDescr>()); int32_t length = TypedObjLengthFromType(*descr); Rooted<OutlineTypedObject*> obj(cx); obj = OutlineTypedObject::createUnattachedWithClass(cx, &OutlineOpaqueTypedObject::class_, descr, length); if (!obj) return false; args.rval().setObject(*obj); return true; } bool js::NewDerivedTypedObject(JSContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); MOZ_ASSERT(args.length() == 3); - MOZ_ASSERT(args[0].isObject() && args[0].toObject().is<SizedTypeDescr>()); + MOZ_ASSERT(args[0].isObject() && args[0].toObject().is<TypeDescr>()); MOZ_ASSERT(args[1].isObject() && args[1].toObject().is<TypedObject>()); MOZ_ASSERT(args[2].isInt32()); - Rooted<SizedTypeDescr*> descr(cx, &args[0].toObject().as<SizedTypeDescr>()); + Rooted<TypeDescr*> descr(cx, &args[0].toObject().as<TypeDescr>()); Rooted<TypedObject*> typedObj(cx, &args[1].toObject().as<TypedObject>()); int32_t offset = args[2].toInt32(); Rooted<TypedObject*> obj(cx); obj = OutlineTypedObject::createDerived(cx, descr, typedObj, offset); if (!obj) return false; @@ -3052,56 +2724,25 @@ JS_JITINFO_NATIVE_PARALLEL_THREADSAFE(js bool js::TypeDescrIsArrayType(ThreadSafeContext *, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); MOZ_ASSERT(args.length() == 1); MOZ_ASSERT(args[0].isObject()); MOZ_ASSERT(args[0].toObject().is<js::TypeDescr>()); JSObject& obj = args[0].toObject(); - args.rval().setBoolean(obj.is<js::SizedArrayTypeDescr>() || - obj.is<js::UnsizedArrayTypeDescr>()); + args.rval().setBoolean(obj.is<js::ArrayTypeDescr>()); return true; } JS_JITINFO_NATIVE_PARALLEL_THREADSAFE(js::TypeDescrIsArrayTypeJitInfo, TypeDescrIsArrayTypeJitInfo, js::TypeDescrIsArrayType); bool -js::TypeDescrIsSizedArrayType(ThreadSafeContext *, unsigned argc, Value *vp) -{ - CallArgs args = CallArgsFromVp(argc, vp); - MOZ_ASSERT(args.length() == 1); - MOZ_ASSERT(args[0].isObject()); - MOZ_ASSERT(args[0].toObject().is<js::TypeDescr>()); - args.rval().setBoolean(args[0].toObject().is<js::SizedArrayTypeDescr>()); - return true; -} - -JS_JITINFO_NATIVE_PARALLEL_THREADSAFE(js::TypeDescrIsSizedArrayTypeJitInfo, - TypeDescrIsSizedArrayTypeJitInfo, - js::TypeDescrIsSizedArrayType); - -bool -js::TypeDescrIsUnsizedArrayType(ThreadSafeContext *, unsigned argc, Value *vp) -{ - CallArgs args = CallArgsFromVp(argc, vp); - MOZ_ASSERT(args.length() == 1); - MOZ_ASSERT(args[0].isObject()); - MOZ_ASSERT(args[0].toObject().is<js::TypeDescr>()); - args.rval().setBoolean(args[0].toObject().is<js::UnsizedArrayTypeDescr>()); - return true; -} - -JS_JITINFO_NATIVE_PARALLEL_THREADSAFE(js::TypeDescrIsUnsizedArrayTypeJitInfo, - TypeDescrIsUnsizedArrayTypeJitInfo, - js::TypeDescrIsUnsizedArrayType); - -bool js::TypedObjectIsAttached(ThreadSafeContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); TypedObject &typedObj = args[0].toObject().as<TypedObject>(); args.rval().setBoolean(typedObj.isAttached()); return true; } @@ -3306,53 +2947,48 @@ JS_FOR_EACH_UNIQUE_SCALAR_TYPE_REPR_CTYP JS_FOR_EACH_REFERENCE_TYPE_REPR(JS_STORE_REFERENCE_CLASS_IMPL) JS_FOR_EACH_REFERENCE_TYPE_REPR(JS_LOAD_REFERENCE_CLASS_IMPL) /////////////////////////////////////////////////////////////////////////// // Walking memory template<typename V> static void -visitReferences(SizedTypeDescr &descr, +visitReferences(TypeDescr &descr, uint8_t *mem, V& visitor) { if (descr.transparent()) return; switch (descr.kind()) { case type::Scalar: case type::Simd: return; case type::Reference: visitor.visitReference(descr.as<ReferenceTypeDescr>(), mem); return; - case type::SizedArray: + case type::Array: { - SizedArrayTypeDescr &arrayDescr = descr.as<SizedArrayTypeDescr>(); - SizedTypeDescr &elementDescr = arrayDescr.maybeForwardedElementType(); + ArrayTypeDescr &arrayDescr = descr.as<ArrayTypeDescr>(); + TypeDescr &elementDescr = arrayDescr.maybeForwardedElementType(); for (int32_t i = 0; i < arrayDescr.length(); i++) { visitReferences(elementDescr, mem, visitor); mem += elementDescr.size(); } return; } - case type::UnsizedArray: - { - MOZ_CRASH("Only Sized Type representations"); - } - case type::Struct: { StructTypeDescr &structDescr = descr.as<StructTypeDescr>(); for (size_t i = 0; i < structDescr.maybeForwardedFieldCount(); i++) { - SizedTypeDescr &descr = structDescr.maybeForwardedFieldDescr(i); + TypeDescr &descr = structDescr.maybeForwardedFieldDescr(i); size_t offset = structDescr.maybeForwardedFieldOffset(i); visitReferences(descr, mem + offset, visitor); } return; } } MOZ_CRASH("Invalid type repr kind"); @@ -3401,17 +3037,17 @@ js::MemoryInitVisitor::visitReference(Re return; } } MOZ_CRASH("Invalid kind"); } void -SizedTypeDescr::initInstances(const JSRuntime *rt, uint8_t *mem, size_t length) +TypeDescr::initInstances(const JSRuntime *rt, uint8_t *mem, size_t length) { MOZ_ASSERT(length >= 1); MemoryInitVisitor visitor(rt); // Initialize the 0th instance memset(mem, 0, size()); if (opaque()) @@ -3471,17 +3107,17 @@ js::MemoryTracingVisitor::visitReference return; } } MOZ_CRASH("Invalid kind"); } void -SizedTypeDescr::traceInstances(JSTracer *trace, uint8_t *mem, size_t length) +TypeDescr::traceInstances(JSTracer *trace, uint8_t *mem, size_t length) { MemoryTracingVisitor visitor(trace); for (size_t i = 0; i < length; i++) { visitReferences(*this, mem, visitor); mem += size(); } }
--- a/js/src/builtin/TypedObject.h +++ b/js/src/builtin/TypedObject.h @@ -114,35 +114,29 @@ static T ConvertScalar(double d) namespace type { enum Kind { Scalar = JS_TYPEREPR_SCALAR_KIND, Reference = JS_TYPEREPR_REFERENCE_KIND, Simd = JS_TYPEREPR_SIMD_KIND, Struct = JS_TYPEREPR_STRUCT_KIND, - SizedArray = JS_TYPEREPR_SIZED_ARRAY_KIND, - UnsizedArray = JS_TYPEREPR_UNSIZED_ARRAY_KIND, + Array = JS_TYPEREPR_ARRAY_KIND }; -static inline bool isSized(type::Kind kind) { - return kind > JS_TYPEREPR_MAX_UNSIZED_KIND; -} - } /////////////////////////////////////////////////////////////////////////// // Typed Prototypes -class SizedTypeDescr; class SimpleTypeDescr; class ComplexTypeDescr; class SimdTypeDescr; class StructTypeDescr; -class SizedTypedProto; +class TypedProto; /* * The prototype for a typed object. Currently, carries a link to the * type descriptor. Eventually will carry most of the type information * we want. */ class TypedProto : public NativeObject { @@ -169,20 +163,16 @@ class TypeDescr : public NativeObject // errors if a is<FooTypeDescr>() etc goes wrong. Otherwise, the // default implementation resolves this to a reference to // FooTypeDescr::class_ which resolves to // JSObject::class_. Debugging the resulting errors leads to much // fun and rejoicing. static const Class class_; public: - static bool isSized(type::Kind kind) { - return kind > JS_TYPEREPR_MAX_UNSIZED_KIND; - } - TypedProto &typedProto() const { return getReservedSlot(JS_DESCR_SLOT_TYPROTO).toObject().as<TypedProto>(); } JSAtom &stringRepr() const { return getReservedSlot(JS_DESCR_SLOT_STRING_REPR).toString()->asAtom(); } @@ -196,34 +186,28 @@ class TypeDescr : public NativeObject bool transparent() const { return !opaque(); } int32_t alignment() const { return getReservedSlot(JS_DESCR_SLOT_ALIGNMENT).toInt32(); } -}; -typedef Handle<TypeDescr*> HandleTypeDescr; - -class SizedTypeDescr : public TypeDescr -{ - public: int32_t size() const { return getReservedSlot(JS_DESCR_SLOT_SIZE).toInt32(); } void initInstances(const JSRuntime *rt, uint8_t *mem, size_t length); void traceInstances(JSTracer *trace, uint8_t *mem, size_t length); }; -typedef Handle<SizedTypeDescr*> HandleSizedTypeDescr; +typedef Handle<TypeDescr*> HandleTypeDescr; -class SimpleTypeDescr : public SizedTypeDescr +class SimpleTypeDescr : public TypeDescr { }; // Type for scalar type constructors like `uint8`. All such type // constructors share a common js::Class and JSFunctionSpec. Scalar // types are non-opaque (their storage is visible unless combined with // an opaque reference type.) class ScalarTypeDescr : public SimpleTypeDescr @@ -323,17 +307,17 @@ class ReferenceTypeDescr : public Simple #define JS_FOR_EACH_REFERENCE_TYPE_REPR(macro_) \ macro_(ReferenceTypeDescr::TYPE_ANY, HeapValue, Any) \ macro_(ReferenceTypeDescr::TYPE_OBJECT, HeapPtrObject, Object) \ macro_(ReferenceTypeDescr::TYPE_STRING, HeapPtrString, string) // Type descriptors whose instances are objects and hence which have // an associated `prototype` property. -class ComplexTypeDescr : public SizedTypeDescr +class ComplexTypeDescr : public TypeDescr { public: // Returns the prototype that instances of this type descriptor // will have. TypedProto &instancePrototype() const { return getReservedSlot(JS_DESCR_SLOT_TYPROTO).toObject().as<TypedProto>(); } }; @@ -367,43 +351,38 @@ class SimdTypeDescr : public ComplexType macro_(SimdTypeDescr::TYPE_INT32, int32_t, int32) \ macro_(SimdTypeDescr::TYPE_FLOAT32, float, float32) bool IsTypedObjectClass(const Class *clasp); // Defined below bool IsTypedObjectArray(JSObject& obj); bool CreateUserSizeAndAlignmentProperties(JSContext *cx, HandleTypeDescr obj); +class ArrayTypeDescr; + /* * Properties and methods of the `ArrayType` meta type object. There * is no `class_` field because `ArrayType` is just a native * constructor function. */ class ArrayMetaTypeDescr : public JSObject { private: - friend class UnsizedArrayTypeDescr; - - // Helper for creating a new ArrayType object, either sized or unsized. - // The template parameter `T` should be either `UnsizedArrayTypeDescr` - // or `SizedArrayTypeDescr`. + // Helper for creating a new ArrayType object. // - // - `arrayTypePrototype` - prototype for the new object to be created, - // either ArrayType.prototype or - // unsizedArrayType.__proto__ depending on - // whether this is a sized or unsized array + // - `arrayTypePrototype` - prototype for the new object to be created // - `elementType` - type object for the elements in the array // - `stringRepr` - canonical string representation for the array - // - `size` - length of the array (0 if unsized) - template<class T> - static T *create(JSContext *cx, - HandleObject arrayTypePrototype, - HandleSizedTypeDescr elementType, - HandleAtom stringRepr, - int32_t size); + // - `size` - length of the array + static ArrayTypeDescr *create(JSContext *cx, + HandleObject arrayTypePrototype, + HandleTypeDescr elementType, + HandleAtom stringRepr, + int32_t size, + int32_t length); public: // Properties and methods to be installed on ArrayType.prototype, // and hence inherited by all array type objects: static const JSPropertySpec typeObjectProperties[]; static const JSFunctionSpec typeObjectMethods[]; // Properties and methods to be installed on ArrayType.prototype.prototype, @@ -412,64 +391,35 @@ class ArrayMetaTypeDescr : public JSObje static const JSFunctionSpec typedObjectMethods[]; // This is the function that gets called when the user // does `new ArrayType(elem)`. It produces an array type object. static bool construct(JSContext *cx, unsigned argc, Value *vp); }; /* - * Type descriptor created by `new ArrayType(typeObj)` - * - * These have a prototype, and hence *could* be a subclass of - * `ComplexTypeDescr`, but it would require some reshuffling of the - * hierarchy, and it's not worth the trouble since they will be going - * away as part of bug 973238. + * Type descriptor created by `new ArrayType(type, n)` */ -class UnsizedArrayTypeDescr : public TypeDescr +class ArrayTypeDescr : public ComplexTypeDescr { public: static const Class class_; - static const type::Kind Kind = type::UnsizedArray; + static const type::Kind Kind = type::Array; - // This is the sized method on unsized array type objects. It - // produces a sized variant. - static bool dimension(JSContext *cx, unsigned int argc, jsval *vp); - - SizedTypeDescr &elementType() const { - return getReservedSlot(JS_DESCR_SLOT_ARRAY_ELEM_TYPE).toObject().as<SizedTypeDescr>(); + TypeDescr &elementType() const { + return getReservedSlot(JS_DESCR_SLOT_ARRAY_ELEM_TYPE).toObject().as<TypeDescr>(); } - SizedTypeDescr &maybeForwardedElementType() const { - JSObject *elemType = - MaybeForwarded(&getReservedSlot(JS_DESCR_SLOT_ARRAY_ELEM_TYPE).toObject()); - return elemType->as<SizedTypeDescr>(); - } -}; - -/* - * Type descriptor created by `unsizedArrayTypeObj.dimension()` - */ -class SizedArrayTypeDescr : public ComplexTypeDescr -{ - public: - static const Class class_; - static const type::Kind Kind = type::SizedArray; - - SizedTypeDescr &elementType() const { - return getReservedSlot(JS_DESCR_SLOT_ARRAY_ELEM_TYPE).toObject().as<SizedTypeDescr>(); - } - - SizedTypeDescr &maybeForwardedElementType() const { + TypeDescr &maybeForwardedElementType() const { JSObject *elemType = &getReservedSlot(JS_DESCR_SLOT_ARRAY_ELEM_TYPE).toObject(); - return MaybeForwarded(elemType)->as<SizedTypeDescr>(); + return MaybeForwarded(elemType)->as<TypeDescr>(); } int32_t length() const { - return getReservedSlot(JS_DESCR_SLOT_SIZED_ARRAY_LENGTH).toInt32(); + return getReservedSlot(JS_DESCR_SLOT_ARRAY_LENGTH).toInt32(); } }; /* * Properties and methods of the `StructType` meta type object. There * is no `class_` field because `StructType` is just a native * constructor function. */ @@ -507,18 +457,18 @@ class StructTypeDescr : public ComplexTy // Set `*out` to the index of the field named `id` and returns true, // or return false if no such field exists. bool fieldIndex(jsid id, size_t *out) const; // Return the name of the field at index `index`. JSAtom &fieldName(size_t index) const; // Return the type descr of the field at index `index`. - SizedTypeDescr &fieldDescr(size_t index) const; - SizedTypeDescr &maybeForwardedFieldDescr(size_t index) const; + TypeDescr &fieldDescr(size_t index) const; + TypeDescr &maybeForwardedFieldDescr(size_t index) const; // Return the offset of the field at index `index`. size_t fieldOffset(size_t index) const; size_t maybeForwardedFieldOffset(size_t index) const; private: NativeObject &fieldInfoObject(size_t slot) const { return getReservedSlot(slot).toObject().as<NativeObject>(); @@ -548,24 +498,22 @@ class TypedObjectModuleObject : public N }; /* Base type for transparent and opaque typed objects. */ class TypedObject : public JSObject { private: static const bool IsTypedObjectClass = true; - template<class T> static bool obj_getArrayElement(JSContext *cx, Handle<TypedObject*> typedObj, Handle<TypeDescr*> typeDescr, uint32_t index, MutableHandleValue vp); - template<class T> static bool obj_setArrayElement(JSContext *cx, Handle<TypedObject*> typedObj, Handle<TypeDescr*> typeDescr, uint32_t index, MutableHandleValue vp); protected: static bool obj_lookupGeneric(JSContext *cx, HandleObject obj, @@ -595,19 +543,16 @@ class TypedObject : public JSObject HandleId id, MutableHandleValue vp); static bool obj_getProperty(JSContext *cx, HandleObject obj, HandleObject receiver, HandlePropertyName name, MutableHandleValue vp); static bool obj_getElement(JSContext *cx, HandleObject obj, HandleObject receiver, uint32_t index, MutableHandleValue vp); - static bool obj_getUnsizedArrayElement(JSContext *cx, HandleObject obj, HandleObject receiver, - uint32_t index, MutableHandleValue vp); - static bool obj_setGeneric(JSContext *cx, HandleObject obj, HandleId id, MutableHandleValue vp, bool strict); static bool obj_setProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, MutableHandleValue vp, bool strict); static bool obj_setElement(JSContext *cx, HandleObject obj, uint32_t index, MutableHandleValue vp, bool strict); static bool obj_getGenericAttributes(JSContext *cx, HandleObject obj, @@ -640,30 +585,17 @@ class TypedObject : public JSObject int32_t offset() const; int32_t length() const; uint8_t *typedMem() const; uint8_t *typedMemBase() const; bool isAttached() const; bool maybeForwardedIsAttached() const; int32_t size() const { - switch (typeDescr().kind()) { - case type::Scalar: - case type::Simd: - case type::Reference: - case type::Struct: - case type::SizedArray: - return typeDescr().as<SizedTypeDescr>().size(); - - case type::UnsizedArray: { - SizedTypeDescr &elementType = typeDescr().as<UnsizedArrayTypeDescr>().elementType(); - return elementType.size() * length(); - } - } - MOZ_CRASH("unhandled typerepresentation kind"); + return typeDescr().size(); } uint8_t *typedMem(size_t offset) const { // It seems a bit surprising that one might request an offset // == size(), but it can happen when taking the "address of" a // 0-sized value. (In other words, we maintain the invariant // that `offset + size <= size()` -- this is always checked in // the caller's side.) @@ -674,22 +606,19 @@ class TypedObject : public JSObject inline bool opaque() const; // Creates a new typed object whose memory is freshly allocated and // initialized with zeroes (or, in the case of references, an appropriate // default value). static TypedObject *createZeroed(JSContext *cx, HandleTypeDescr typeObj, int32_t length, gc::InitialHeap heap = gc::DefaultHeap); - // User-accessible constructor (`new TypeDescriptor(...)`) used for sized - // types. Note that the callee here is the type descriptor. - static bool constructSized(JSContext *cx, unsigned argc, Value *vp); - - // As `constructSized`, but for unsized array types. - static bool constructUnsized(JSContext *cx, unsigned argc, Value *vp); + // User-accessible constructor (`new TypeDescriptor(...)`). Note that the + // callee here is the type descriptor. + static bool construct(JSContext *cx, unsigned argc, Value *vp); /* Accessors for self hosted code. */ static bool GetBuffer(JSContext *cx, unsigned argc, Value *vp); static bool GetByteOffset(JSContext *cx, unsigned argc, Value *vp); }; typedef Handle<TypedObject*> HandleTypedObject; @@ -698,59 +627,36 @@ class OutlineTypedObject : public TypedO // The object which owns the data this object points to. Because this // pointer is managed in tandem with |data|, this is not a HeapPtr and // barriers are managed directly. JSObject *owner_; // Data pointer to some offset in the owner's contents. uint8_t *data_; - // The length for unsized array objects. For other outline objects the - // space for this field is not allocated and cannot be accessed. - uint32_t unsizedLength_; - void setOwnerAndData(JSObject *owner, uint8_t *data); - void setUnsizedLength(uint32_t length) { - MOZ_ASSERT(typeDescr().is<UnsizedArrayTypeDescr>()); - unsizedLength_ = length; - } - public: - static gc::AllocKind allocKindForTypeDescriptor(TypeDescr *descr) { - // Use a larger allocation kind for unsized arrays, to accommodate the - // unsized length. - if (descr->is<UnsizedArrayTypeDescr>()) - return gc::FINALIZE_OBJECT2; - return gc::FINALIZE_OBJECT0; - } - // JIT accessors. static size_t offsetOfData() { return offsetof(OutlineTypedObject, data_); } static size_t offsetOfOwner() { return offsetof(OutlineTypedObject, owner_); } - static size_t offsetOfUnsizedLength() { return offsetof(OutlineTypedObject, unsizedLength_); } JSObject &owner() const { MOZ_ASSERT(owner_); return *owner_; } JSObject *maybeOwner() const { return owner_; } uint8_t *outOfLineTypedMem() const { return data_; } - int32_t unsizedLength() const { - MOZ_ASSERT(typeDescr().is<UnsizedArrayTypeDescr>()); - return unsizedLength_; - } - void setData(uint8_t *data) { data_ = data; } // Helper for createUnattached() static OutlineTypedObject *createUnattachedWithClass(JSContext *cx, const Class *clasp, HandleTypeDescr type, @@ -767,17 +673,17 @@ class OutlineTypedObject : public TypedO // - length: 0 unless this is an array, otherwise the length static OutlineTypedObject *createUnattached(JSContext *cx, HandleTypeDescr type, int32_t length, gc::InitialHeap heap = gc::DefaultHeap); // Creates a typedObj that aliases the memory pointed at by `owner` // at the given offset. The typedObj will be a handle iff type is a // handle and a typed object otherwise. static OutlineTypedObject *createDerived(JSContext *cx, - HandleSizedTypeDescr type, + HandleTypeDescr type, Handle<TypedObject*> typedContents, int32_t offset); // Use this method when `buffer` is the owner of the memory. void attach(JSContext *cx, ArrayBufferObject &buffer, int32_t offset); // Otherwise, use this to attach to memory referenced by another typedObj. void attach(JSContext *cx, TypedObject &typedObj, int32_t offset); @@ -811,17 +717,17 @@ class InlineTypedObject : public TypedOb // Start of the inline data, which immediately follows the shape and type. uint8_t data_[1]; public: static const size_t MaximumSize = sizeof(NativeObject) - sizeof(TypedObject) + NativeObject::MAX_FIXED_SLOTS * sizeof(Value); static gc::AllocKind allocKindForTypeDescriptor(TypeDescr *descr) { - size_t nbytes = descr->as<SizedTypeDescr>().size(); + size_t nbytes = descr->size(); MOZ_ASSERT(nbytes <= MaximumSize); size_t dataSlots = AlignBytes(nbytes, sizeof(Value) / sizeof(Value)); MOZ_ASSERT(nbytes <= dataSlots * sizeof(Value)); return gc::GetGCObjectKind(dataSlots); } uint8_t *inlineTypedMem() const { @@ -927,22 +833,16 @@ extern const JSJitInfo ObjectIsTranspare /* Predicates on type descriptor objects. In all cases, 'obj' must be a type descriptor. */ bool TypeDescrIsSimpleType(ThreadSafeContext *, unsigned argc, Value *vp); extern const JSJitInfo TypeDescrIsSimpleTypeJitInfo; bool TypeDescrIsArrayType(ThreadSafeContext *, unsigned argc, Value *vp); extern const JSJitInfo TypeDescrIsArrayTypeJitInfo; -bool TypeDescrIsSizedArrayType(ThreadSafeContext *, unsigned argc, Value *vp); -extern const JSJitInfo TypeDescrIsSizedArrayTypeJitInfo; - -bool TypeDescrIsUnsizedArrayType(ThreadSafeContext *, unsigned argc, Value *vp); -extern const JSJitInfo TypeDescrIsUnsizedArrayTypeJitInfo; - /* * Usage: TypedObjectIsAttached(obj) * * Given a TypedObject `obj`, returns true if `obj` is * "attached" (i.e., its data pointer is nullptr). */ bool TypedObjectIsAttached(ThreadSafeContext *cx, unsigned argc, Value *vp); extern const JSJitInfo TypedObjectIsAttachedJitInfo; @@ -1096,32 +996,25 @@ IsSimpleTypeDescrClass(const Class* clas return clasp == &ScalarTypeDescr::class_ || clasp == &ReferenceTypeDescr::class_; } inline bool IsComplexTypeDescrClass(const Class* clasp) { return clasp == &StructTypeDescr::class_ || - clasp == &SizedArrayTypeDescr::class_ || + clasp == &ArrayTypeDescr::class_ || clasp == &SimdTypeDescr::class_; } inline bool -IsSizedTypeDescrClass(const Class* clasp) -{ - return IsSimpleTypeDescrClass(clasp) || - IsComplexTypeDescrClass(clasp); -} - -inline bool IsTypeDescrClass(const Class* clasp) { - return IsSizedTypeDescrClass(clasp) || - clasp == &UnsizedArrayTypeDescr::class_; + return IsSimpleTypeDescrClass(clasp) || + IsComplexTypeDescrClass(clasp); } inline bool TypedObject::opaque() const { return IsOpaqueTypedObjectClass(getClass()); } @@ -1158,23 +1051,16 @@ template <> inline bool JSObject::is<js::SimpleTypeDescr>() const { return IsSimpleTypeDescrClass(getClass()); } template <> inline bool -JSObject::is<js::SizedTypeDescr>() const -{ - return IsSizedTypeDescrClass(getClass()); -} - -template <> -inline bool JSObject::is<js::ComplexTypeDescr>() const { return IsComplexTypeDescrClass(getClass()); } template <> inline bool JSObject::is<js::TypeDescr>() const
--- a/js/src/builtin/TypedObject.js +++ b/js/src/builtin/TypedObject.js @@ -14,18 +14,18 @@ #define DESCR_SIZE(obj) \ UnsafeGetReservedSlot(obj, JS_DESCR_SLOT_SIZE) #define DESCR_OPAQUE(obj) \ UnsafeGetReservedSlot(obj, JS_DESCR_SLOT_OPAQUE) #define DESCR_TYPE(obj) \ UnsafeGetReservedSlot(obj, JS_DESCR_SLOT_TYPE) #define DESCR_ARRAY_ELEMENT_TYPE(obj) \ UnsafeGetReservedSlot(obj, JS_DESCR_SLOT_ARRAY_ELEM_TYPE) -#define DESCR_SIZED_ARRAY_LENGTH(obj) \ - TO_INT32(UnsafeGetReservedSlot(obj, JS_DESCR_SLOT_SIZED_ARRAY_LENGTH)) +#define DESCR_ARRAY_LENGTH(obj) \ + TO_INT32(UnsafeGetReservedSlot(obj, JS_DESCR_SLOT_ARRAY_LENGTH)) #define DESCR_STRUCT_FIELD_NAMES(obj) \ UnsafeGetReservedSlot(obj, JS_DESCR_SLOT_STRUCT_FIELD_NAMES) #define DESCR_STRUCT_FIELD_TYPES(obj) \ UnsafeGetReservedSlot(obj, JS_DESCR_SLOT_STRUCT_FIELD_TYPES) #define DESCR_STRUCT_FIELD_OFFSETS(obj) \ UnsafeGetReservedSlot(obj, JS_DESCR_SLOT_STRUCT_FIELD_OFFSETS) // Typed prototype slots @@ -65,22 +65,19 @@ function TypedObjectGet(descr, typedObj, return TypedObjectGetScalar(descr, typedObj, offset); case JS_TYPEREPR_REFERENCE_KIND: return TypedObjectGetReference(descr, typedObj, offset); case JS_TYPEREPR_SIMD_KIND: return TypedObjectGetSimd(descr, typedObj, offset); - case JS_TYPEREPR_SIZED_ARRAY_KIND: + case JS_TYPEREPR_ARRAY_KIND: case JS_TYPEREPR_STRUCT_KIND: return TypedObjectGetDerived(descr, typedObj, offset); - - case JS_TYPEREPR_UNSIZED_ARRAY_KIND: - assert(false, "Unhandled repr kind: " + DESCR_KIND(descr)); } assert(false, "Unhandled kind: " + DESCR_KIND(descr)); return undefined; } function TypedObjectGetDerived(descr, typedObj, offset) { assert(!TypeDescrIsSimpleType(descr), @@ -196,24 +193,18 @@ function TypedObjectSet(descr, typedObj, case JS_TYPEREPR_REFERENCE_KIND: TypedObjectSetReference(descr, typedObj, offset, fromValue); return; case JS_TYPEREPR_SIMD_KIND: TypedObjectSetSimd(descr, typedObj, offset, fromValue); return; - case JS_TYPEREPR_SIZED_ARRAY_KIND: - var length = DESCR_SIZED_ARRAY_LENGTH(descr); - if (TypedObjectSetArray(descr, length, typedObj, offset, fromValue)) - return; - break; - - case JS_TYPEREPR_UNSIZED_ARRAY_KIND: - var length = typedObj.length; + case JS_TYPEREPR_ARRAY_KIND: + var length = DESCR_ARRAY_LENGTH(descr); if (TypedObjectSetArray(descr, length, typedObj, offset, fromValue)) return; break; case JS_TYPEREPR_STRUCT_KIND: if (!IsObject(fromValue)) break; @@ -422,41 +413,32 @@ function TypedArrayRedimension(newArrayT ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS); if (!IsObject(newArrayType) || !ObjectIsTypeDescr(newArrayType)) ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS); // Peel away the outermost array layers from the type of `this` to find // the core element type. In the process, count the number of elements. var oldArrayType = TypedObjectTypeDescr(this); - var oldArrayReprKind = DESCR_KIND(oldArrayType); var oldElementType = oldArrayType; var oldElementCount = 1; - switch (oldArrayReprKind) { - case JS_TYPEREPR_UNSIZED_ARRAY_KIND: - oldElementCount *= this.length; - oldElementType = oldElementType.elementType; - break; - case JS_TYPEREPR_SIZED_ARRAY_KIND: - break; + if (DESCR_KIND(oldArrayType) != JS_TYPEREPR_ARRAY_KIND) + ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS); - default: - ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS); - } - while (DESCR_KIND(oldElementType) === JS_TYPEREPR_SIZED_ARRAY_KIND) { + while (DESCR_KIND(oldElementType) === JS_TYPEREPR_ARRAY_KIND) { oldElementCount *= oldElementType.length; oldElementType = oldElementType.elementType; } // Peel away the outermost array layers from `newArrayType`. In the // process, count the number of elements. var newElementType = newArrayType; var newElementCount = 1; - while (DESCR_KIND(newElementType) == JS_TYPEREPR_SIZED_ARRAY_KIND) { + while (DESCR_KIND(newElementType) == JS_TYPEREPR_ARRAY_KIND) { newElementCount *= newElementType.length; newElementType = newElementType.elementType; } // Check that the total number of elements does not change. if (oldElementCount !== newElementCount) { ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS); } @@ -531,21 +513,21 @@ function DescrToSource() { // Warning: user exposed! function ArrayShorthand(...dims) { if (!IsObject(this) || !ObjectIsTypeDescr(this)) ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS); var T = GetTypedObjectModule(); if (dims.length == 0) - return new T.ArrayType(this); + ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS); var accum = this; for (var i = dims.length - 1; i >= 0; i--) - accum = new T.ArrayType(accum).dimension(dims[i]); + accum = new T.ArrayType(accum, dims[i]); return accum; } // This is the `storage()` function defined in the spec. When // provided with a *transparent* typed object, it returns an object // containing buffer, byteOffset, byteLength. When given an opaque // typed object, it returns null. Otherwise it throws. // @@ -555,21 +537,17 @@ function StorageOfTypedObject(obj) { if (ObjectIsOpaqueTypedObject(obj)) return null; if (ObjectIsTransparentTypedObject(obj)) { if (!TypedObjectIsAttached(obj)) ThrowError(JSMSG_TYPEDOBJECT_HANDLE_UNATTACHED); var descr = TypedObjectTypeDescr(obj); - var byteLength; - if (DESCR_KIND(descr) == JS_TYPEREPR_UNSIZED_ARRAY_KIND) - byteLength = DESCR_SIZE(descr.elementType) * obj.length; - else - byteLength = DESCR_SIZE(descr); + var byteLength = DESCR_SIZE(descr); return { buffer: TypedObjectBuffer(obj), byteLength: byteLength, byteOffset: TypedObjectByteOffset(obj) }; } } ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS); @@ -600,42 +578,31 @@ function TypeOfTypedObject(obj) { } } /////////////////////////////////////////////////////////////////////////// // TypedObject surface API methods (sequential implementations). // Warning: user exposed! function TypedObjectArrayTypeBuild(a,b,c) { - // Arguments (this sized) : [depth], func - // Arguments (this unsized) : length, [depth], func + // Arguments : [depth], func if (!IsObject(this) || !ObjectIsTypeDescr(this)) ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS); var kind = DESCR_KIND(this); switch (kind) { - case JS_TYPEREPR_SIZED_ARRAY_KIND: + case JS_TYPEREPR_ARRAY_KIND: if (typeof a === "function") // XXX here and elsewhere: these type dispatches are fragile at best. return BuildTypedSeqImpl(this, this.length, 1, a); else if (typeof a === "number" && typeof b === "function") return BuildTypedSeqImpl(this, this.length, a, b); else if (typeof a === "number") ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS); else ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS); - case JS_TYPEREPR_UNSIZED_ARRAY_KIND: - var len = a; - if (typeof b === "function") - return BuildTypedSeqImpl(this, len, 1, b); - else if (typeof b === "number" && typeof c === "function") - return BuildTypedSeqImpl(this, len, b, c); - else if (typeof b === "number") - ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS); - else - ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS); default: ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS); } } // Warning: user exposed! function TypedObjectArrayTypeFrom(a, b, c) { // Arguments: arrayLike, [depth], func @@ -726,17 +693,17 @@ function TypedArrayReduce(a, b) { function TypedArrayScatter(a, b, c, d) { // Arguments: outputArrayType, indices, defaultValue, conflictFunction if (!IsObject(this) || !ObjectIsTypedObject(this)) ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS); var thisType = TypedObjectTypeDescr(this); if (!TypeDescrIsArrayType(thisType)) ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS); - if (!IsObject(a) || !ObjectIsTypeDescr(a) || !TypeDescrIsSizedArrayType(a)) + if (!IsObject(a) || !ObjectIsTypeDescr(a) || !TypeDescrIsArrayType(a)) ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS); if (d !== undefined && typeof d !== "function") ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS); return ScatterTypedSeqImpl(this, a, b, c, d); } @@ -823,17 +790,17 @@ function BuildTypedSeqImpl(arrayType, le // ArrayType(ArrayType(T, 4), 5) // and a depth of 2, we get // grainType = T // iterationSpace = [5, 4] var [iterationSpace, grainType, totalLength] = ComputeIterationSpace(arrayType, depth, len); // Create a zeroed instance with no data - var result = arrayType.variable ? new arrayType(len) : new arrayType(); + var result = new arrayType(); var indices = NewDenseArray(depth); for (var i = 0; i < depth; i++) { indices[i] = 0; } var grainTypeIsComplex = !TypeDescrIsSimpleType(grainType); var size = DESCR_SIZE(grainType); @@ -916,21 +883,21 @@ function MapUntypedSeqImpl(inArray, outp if (!IsCallable(maybeFunc)) ThrowError(JSMSG_NOT_FUNCTION, DecompileArg(0, maybeFunc)); var func = maybeFunc; // Skip check for compatible iteration spaces; any normal JS array // is trivially compatible with any iteration space of depth 1. - var outLength = outputType.variable ? inArray.length : outputType.length; + var outLength = outputType.length; var outGrainType = outputType.elementType; // Create a zeroed instance with no data - var result = outputType.variable ? new outputType(inArray.length) : new outputType(); + var result = new outputType(); var outUnitSize = DESCR_SIZE(outGrainType); var outGrainTypeIsComplex = !TypeDescrIsSimpleType(outGrainType); var outOffset = 0; // Core of map computation starts here (comparable to // DoMapTypedSeqDepth1 and DoMapTypedSeqDepthN below). @@ -970,24 +937,24 @@ function MapTypedSeqImpl(inArray, depth, // Compute iteration space for input and output and check for compatibility. var inputType = TypeOfTypedObject(inArray); var [inIterationSpace, inGrainType, _] = ComputeIterationSpace(inputType, depth, inArray.length); if (!IsObject(inGrainType) || !ObjectIsTypeDescr(inGrainType)) ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS); var [iterationSpace, outGrainType, totalLength] = - ComputeIterationSpace(outputType, depth, outputType.variable ? inArray.length : outputType.length); + ComputeIterationSpace(outputType, depth, outputType.length); for (var i = 0; i < depth; i++) if (inIterationSpace[i] !== iterationSpace[i]) // TypeError("Incompatible iteration space in input and output type"); ThrowError(JSMSG_TYPEDOBJECT_ARRAYTYPE_BAD_ARGS); // Create a zeroed instance with no data - var result = outputType.variable ? new outputType(inArray.length) : new outputType(); + var result = new outputType(); var inGrainTypeIsComplex = !TypeDescrIsSimpleType(inGrainType); var outGrainTypeIsComplex = !TypeDescrIsSimpleType(outGrainType); var inOffset = 0; var outOffset = 0; var isDepth1Simple = depth == 1 && !(inGrainTypeIsComplex || outGrainTypeIsComplex); @@ -1078,17 +1045,17 @@ function MapTypedParImpl(inArray, depth, "Map/From called on something not callable"); var inArrayType = TypeOfTypedObject(inArray); if (ShouldForceSequential() || depth <= 0 || TO_INT32(depth) !== depth || !TypeDescrIsArrayType(inArrayType) || - !TypeDescrIsUnsizedArrayType(outputType)) + !TypeDescrIsArrayType(outputType)) { // defer error cases to seq implementation: return MapTypedSeqImpl(inArray, depth, outputType, func); } switch (depth) { case 1: return MapTypedParImplDepth1(inArray, inArrayType, outputType, func); @@ -1156,17 +1123,17 @@ function MapTypedParImplDepth1(inArray, const inGrainTypeSize = DESCR_SIZE(inGrainType); const outGrainTypeSize = DESCR_SIZE(outGrainType); const inGrainTypeIsComplex = !TypeDescrIsSimpleType(inGrainType); const outGrainTypeIsComplex = !TypeDescrIsSimpleType(outGrainType); const length = inArray.length; const mode = undefined; - const outArray = new outArrayType(length); + const outArray = new outArrayType(); if (length === 0) return outArray; const outGrainTypeIsTransparent = ObjectIsTransparentTypedObject(outArray); // Construct the slices and initial pointers for each worker: const slicesInfo = ComputeSlicesInfo(length); const numWorkers = ForkJoinNumWorkers(); @@ -1302,17 +1269,17 @@ function ReduceTypedSeqImpl(array, outpu } return value; } function ScatterTypedSeqImpl(array, outputType, indices, defaultValue, conflictFunc) { assert(IsObject(array) && ObjectIsTypedObject(array), "Scatter called on non-object or untyped input array."); assert(IsObject(outputType) && ObjectIsTypeDescr(outputType), "Scatter called on non-type-object outputType"); - assert(TypeDescrIsSizedArrayType(outputType), "Scatter called on non-sized array type"); + assert(TypeDescrIsArrayType(outputType), "Scatter called on non-array type"); assert(conflictFunc === undefined || typeof conflictFunc === "function", "Scatter called with invalid conflictFunc"); var result = new outputType(); var bitvec = new Uint8Array(result.length); var elemType = outputType.elementType; var i, j; if (defaultValue !== elemType(undefined)) { for (i = 0; i < result.length; i++) { @@ -1351,16 +1318,18 @@ function FilterTypedSeqImpl(array, func) var v = TypedObjectGet(elementType, array, inOffset); if (func(v, i, array)) { SET_BIT(flags, i); count++; } inOffset += size; } - var resultType = (arrayType.variable ? arrayType : arrayType.unsized); - var result = new resultType(count); + var T = GetTypedObjectModule(); + + var resultType = new T.ArrayType(elementType, count); + var result = new resultType(); for (var i = 0, j = 0; i < array.length; i++) { if (GET_BIT(flags, i)) result[j++] = array[i]; } return result; }
--- a/js/src/builtin/TypedObjectConstants.h +++ b/js/src/builtin/TypedObjectConstants.h @@ -22,46 +22,44 @@ // particular kinds of type objects. For simplicity we use the same // number of slots no matter what kind of type descriptor we are // working with, even though this is mildly wasteful. // Slots on all type objects #define JS_DESCR_SLOT_KIND 0 // Atomized string representation #define JS_DESCR_SLOT_STRING_REPR 1 // Atomized string representation #define JS_DESCR_SLOT_ALIGNMENT 2 // Alignment in bytes -#define JS_DESCR_SLOT_SIZE 3 // Size in bytes, if sized, else 0 +#define JS_DESCR_SLOT_SIZE 3 // Size in bytes, else 0 #define JS_DESCR_SLOT_OPAQUE 4 // Atomized string representation #define JS_DESCR_SLOT_TYPROTO 5 // Prototype for instances, if any // Slots on scalars, references, and x4s #define JS_DESCR_SLOT_TYPE 6 // Type code // Slots on all array descriptors #define JS_DESCR_SLOT_ARRAY_ELEM_TYPE 6 -// Slots on sized array descriptors -#define JS_DESCR_SLOT_SIZED_ARRAY_LENGTH 7 +// Slots on array descriptors +#define JS_DESCR_SLOT_ARRAY_LENGTH 7 // Slots on struct type objects #define JS_DESCR_SLOT_STRUCT_FIELD_NAMES 6 #define JS_DESCR_SLOT_STRUCT_FIELD_TYPES 7 #define JS_DESCR_SLOT_STRUCT_FIELD_OFFSETS 8 // Maximum number of slots for any descriptor #define JS_DESCR_SLOTS 9 // These constants are for use exclusively in JS code. In C++ code, // prefer TypeRepresentation::Scalar etc, which allows you to // write a switch which will receive a warning if you omit a case. -#define JS_TYPEREPR_UNSIZED_ARRAY_KIND 0 -#define JS_TYPEREPR_MAX_UNSIZED_KIND 0 // Unsized kinds go above here #define JS_TYPEREPR_SCALAR_KIND 1 #define JS_TYPEREPR_REFERENCE_KIND 2 #define JS_TYPEREPR_STRUCT_KIND 3 -#define JS_TYPEREPR_SIZED_ARRAY_KIND 4 +#define JS_TYPEREPR_ARRAY_KIND 4 #define JS_TYPEREPR_SIMD_KIND 5 // These constants are for use exclusively in JS code. In C++ code, // prefer Scalar::Int8 etc, which allows you to write a switch which will // receive a warning if you omit a case. #define JS_SCALARTYPEREPR_INT8 0 #define JS_SCALARTYPEREPR_UINT8 1 #define JS_SCALARTYPEREPR_INT16 2
--- a/js/src/frontend/BytecodeCompiler.cpp +++ b/js/src/frontend/BytecodeCompiler.cpp @@ -270,18 +270,17 @@ frontend::CompileScript(ExclusiveContext /* foldConstants = */ true, canLazilyParse ? syntaxParser.ptr() : nullptr, nullptr); parser.sct = sct; parser.ss = ss; Directives directives(options.strictOption); GlobalSharedContext globalsc(cx, scopeChain, directives, options.extraWarningsOption); - bool savedCallerFun = options.compileAndGo && - evalCaller && evalCaller->functionOrCallerFunction(); + bool savedCallerFun = evalCaller && evalCaller->functionOrCallerFunction(); Rooted<JSScript*> script(cx, JSScript::Create(cx, NullPtr(), savedCallerFun, options, staticLevel, sourceObject, 0, srcBuf.length())); if (!script) return nullptr; // We can specialize a bit for the given scope chain if that scope chain is the global object. JSObject *globalScope = @@ -307,17 +306,17 @@ frontend::CompileScript(ExclusiveContext /* blockScopeDepth = */ 0); if (!pc->init(parser.tokenStream)) return nullptr; /* If this is a direct call to eval, inherit the caller's strictness. */ if (evalCaller && evalCaller->strict()) globalsc.strict = true; - if (options.compileAndGo && evalCaller && evalCaller->functionOrCallerFunction()) { + if (savedCallerFun) { /* * An eval script in a caller frame needs to have its enclosing * function captured in case it refers to an upvar, and someone * wishes to decompile it while it's running. */ JSFunction *fun = evalCaller->functionOrCallerFunction(); Directives directives(/* strict = */ fun->strict()); ObjectBox *funbox = parser.newFunctionBox(/* fn = */ nullptr, fun, pc.ptr(),
--- a/js/src/gc/Nursery.cpp +++ b/js/src/gc/Nursery.cpp @@ -399,21 +399,19 @@ GetObjectAllocKindForCopy(const Nursery // Figure out the size of this object, from the prototype's TypeDescr. // The objects we are traversing here are all tenured, so we don't need // to check forwarding pointers. TypeDescr *descr = &obj->as<InlineTypedObject>().typeDescr(); MOZ_ASSERT(!IsInsideNursery(descr)); return InlineTypedObject::allocKindForTypeDescriptor(descr); } - // Outline typed objects have special requirements for their allocation kind. - if (obj->is<OutlineTypedObject>()) { - TypeDescr *descr = &obj->as<OutlineTypedObject>().typeDescr(); - return OutlineTypedObject::allocKindForTypeDescriptor(descr); - } + // Outline typed objects use the minimum allocation kind. + if (obj->is<OutlineTypedObject>()) + return FINALIZE_OBJECT0; // The only non-native objects in existence are proxies and typed objects. MOZ_ASSERT(obj->isNative()); AllocKind kind = GetGCObjectFixedSlotsKind(obj->as<NativeObject>().numFixedSlots()); MOZ_ASSERT(!IsBackgroundFinalized(kind)); MOZ_ASSERT(CanBeFinalizedInBackground(kind, obj->getClass())); return GetBackgroundAllocKind(kind);
--- a/js/src/jit-test/tests/TypedObject/Bug981650.js +++ b/js/src/jit-test/tests/TypedObject/Bug981650.js @@ -1,10 +1,9 @@ -// Fuzz bug 981650: Test creating an unsized array type based on an instance of +// Fuzz bug 981650: Test creating an array type based on an instance of // that same type. if (typeof TypedObject === "undefined") quit(); var T = TypedObject; -var AT = new T.ArrayType(T.int32); -var v = new AT(10); -new AT(v); +var v = new T.ArrayType(T.int32, 10); +new v(v);
--- a/js/src/jit-test/tests/TypedObject/atopneuteredbuffer.js +++ b/js/src/jit-test/tests/TypedObject/atopneuteredbuffer.js @@ -4,21 +4,21 @@ if (typeof TypedObject === "undefined") quit(); load(libdir + "asserts.js") var {StructType, uint32, Object, Any, storage, objectType} = TypedObject; function main(variant) { // once a C programmer, always a C programmer. - var Uints = uint32.array(); + var Uints = uint32.array(0); var Unit = new StructType({}); // Empty struct type var buffer = new ArrayBuffer(0); // Empty buffer var p = new Unit(buffer); // OK neuter(buffer, variant); assertThrowsInstanceOf(() => new Unit(buffer), TypeError, "Able to instantiate atop neutered buffer"); - assertThrowsInstanceOf(() => new Uints(buffer, 0), TypeError, + assertThrowsInstanceOf(() => new Uints(buffer), TypeError, "Able to instantiate atop neutered buffer"); } main("same-data"); main("change-data");
--- a/js/src/jit-test/tests/TypedObject/bug950458.js +++ b/js/src/jit-test/tests/TypedObject/bug950458.js @@ -8,16 +8,16 @@ if (!this.hasOwnProperty("TypedObject")) // with an empty type set, which would then fail sanity // checking assertions. // // Public domain. var N = 100; var T = TypedObject; var Point = new T.StructType({x: T.uint32, y: T.uint32, z: T.uint32}); -var PointArray = Point.array(); +var PointArray = Point.array(N); function foo(arr) { var sum = 0; for (var i = 0; i < N; i++) { sum += arr[i].x + arr[i].y + arr[i].z; } } -foo(new PointArray(N)); +foo(new PointArray());
--- a/js/src/jit-test/tests/TypedObject/bug953111.js +++ b/js/src/jit-test/tests/TypedObject/bug953111.js @@ -3,16 +3,16 @@ * http://creativecommons.org/licenses/publicdomain/ */ if (!this.hasOwnProperty("TypedObject")) quit(); // bug 953111 -var A = TypedObject.uint8.array(); -var a = new A(0); +var A = TypedObject.uint8.array(0); +var a = new A(); a.forEach(function(val, i) {}); // bug 951356 (dup, but a dup that is more likely to crash) -var AA = TypedObject.uint8.array(2147483647).array(); -var aa = new AA(0); +var AA = TypedObject.uint8.array(2147483647).array(0); +var aa = new AA();
--- a/js/src/jit-test/tests/TypedObject/jit-read-unsized.js +++ b/js/src/jit-test/tests/TypedObject/jit-read-unsized.js @@ -6,26 +6,26 @@ if (!this.hasOwnProperty("TypedObject")) quit(); setJitCompilerOption("ion.warmup.trigger", 30); var N = 100; var T = TypedObject; var Point = new T.StructType({x: T.uint32, y: T.uint32, z: T.uint32}); -var PointArray = Point.array(); +var PointArray = Point.array(N); function bar(array, i, x, y, z) { assertEq(array[i].x, x); assertEq(array[i].y, y); assertEq(array[i].z, z); } function foo() { - var array = new PointArray(N); + var array = new PointArray(); for (var i = 0; i < N; i++) { array[i].x = i + 0; array[i].y = i + 1; array[i].z = i + 2; } // get it primed up.. for (var i = 0; i < N; i++)
--- a/js/src/jit-test/tests/TypedObject/neutertypedobjunsizedarray.js +++ b/js/src/jit-test/tests/TypedObject/neutertypedobjunsizedarray.js @@ -1,24 +1,24 @@ // Test the case where we neuter an instance of a variable-length array. // Here we can fold the neuter check into the bounds check. if (!this.hasOwnProperty("TypedObject")) quit(); var {StructType, uint32, storage} = TypedObject; var S = new StructType({f: uint32, g: uint32}); -var A = S.array(); +var A = S.array(10); function readFrom(a) { return a[2].f + a[2].g; } function main(variant) { - var a = new A(10); + var a = new A(); a[2].f = 22; a[2].g = 44; for (var i = 0; i < 10; i++) assertEq(readFrom(a), 66); neuter(storage(a).buffer, variant);
--- a/js/src/jit-test/tests/TypedObject/opaqueatopbuffer.js +++ b/js/src/jit-test/tests/TypedObject/opaqueatopbuffer.js @@ -9,16 +9,11 @@ var {StructType, ArrayType, uint32, Obje var anArray = new Uint32Array(100); anArray[0] = 22; var buffer = anArray.buffer; var Unit = new StructType(({ f : Object, } )); assertThrowsInstanceOf(() => new Unit(buffer), TypeError, "Able to instantiate opaque type atop buffer"); -var Units = new ArrayType(Unit); +var Units = new ArrayType(Unit, 2); assertThrowsInstanceOf(() => new Units(buffer), TypeError, "Able to instantiate opaque type atop buffer"); - -var Units2 = Units.dimension(2); -assertThrowsInstanceOf(() => new Units2(buffer), TypeError, - "Able to instantiate opaque type atop buffer"); -
new file mode 100644 --- /dev/null +++ b/js/src/jit-test/tests/debug/onNewScript-CloneAndExecuteScript.js @@ -0,0 +1,28 @@ +// Debugger should be notified of scripts created with cloneAndExecuteScript. + +var g = newGlobal(); +var g2 = newGlobal(); +var dbg = new Debugger(g, g2); +var log = ''; + +dbg.onNewScript = function (evalScript) { + log += 'e'; + + dbg.onNewScript = function (clonedScript) { + log += 'c'; + clonedScript.setBreakpoint(0, { + hit(frame) { + log += 'b'; + assertEq(frame.script, clonedScript); + } + }); + }; +}; + +dbg.onDebuggerStatement = function (frame) { + log += 'd'; +}; + +assertEq(log, ''); +g.cloneAndExecuteScript("debugger; // nee", g2); +assertEq(log, 'ecbd');
new file mode 100644 --- /dev/null +++ b/js/src/jit-test/tests/debug/onNewScript-ExecuteInGlobalAndReturnScope.js @@ -0,0 +1,28 @@ +// Debugger should be notified of scripts created with ExecuteInGlobalAndReturnScope. + +var g = newGlobal(); +var g2 = newGlobal(); +var dbg = new Debugger(g, g2); +var log = ''; + +dbg.onNewScript = function (evalScript) { + log += 'e'; + + dbg.onNewScript = function (clonedScript) { + log += 'c'; + clonedScript.setBreakpoint(0, { + hit(frame) { + log += 'b'; + assertEq(frame.script, clonedScript); + } + }); + }; +}; + +dbg.onDebuggerStatement = function (frame) { + log += 'd'; +}; + +assertEq(log, ''); +var evalScope = g.evalReturningScope("debugger; // nee", g2); +assertEq(log, 'ecbd');
--- a/js/src/jit-test/tests/gc/bug-948423.js +++ b/js/src/jit-test/tests/gc/bug-948423.js @@ -3,22 +3,21 @@ if (!this.hasOwnProperty("TypedObject")) var ArrayType = TypedObject.ArrayType; var StructType = TypedObject.StructType; var uint8 = TypedObject.uint8; var uint32 = TypedObject.uint32; var ObjectType = TypedObject.Object; function runTests() { (function DimensionLinkedToUndimension() { - var UintsA = uint32.array(); - var FiveUintsA = UintsA.dimension(5); + var FiveUintsA = uint32.array(5); var FiveUintsB = uint32.array(5); assertEq(true, FiveUintsA.equivalent(FiveUintsB) ); })(); (function PrototypeHierarchy() { schedulegc(3); - var Uint8s = uint8.array(); + var Uint8s = uint8.array(5); })(); } runTests();
--- a/js/src/jit-test/tests/ion/inlining/TypedObject-TypeDescrIsArrayType-unknown.js +++ b/js/src/jit-test/tests/ion/inlining/TypedObject-TypeDescrIsArrayType-unknown.js @@ -24,24 +24,24 @@ */ if (!this.TypedObject) { print("No TypedObject, skipping"); quit(); } var T = TypedObject; -var AT = new T.ArrayType(T.int32); +var AT = new T.ArrayType(T.int32, 100); function check(v) { return v.map(x => x+1); } function test() { - var w1 = AT.build(100, x => x+1); + var w1 = AT.build(x => x+1); var w2 = Array.build(100, x => x+1); w2.map = w1.map; var a = [ w1, w2 ]; for ( var i=0 ; i < 2000 ; i++ ) try { a[i%2] = check(a[i%2]); } catch (e) { assertEq( i%2, 1 ); } return a[0]; }
--- a/js/src/jit-test/tests/ion/inlining/TypedObject-TypeDescrIsArrayType.js +++ b/js/src/jit-test/tests/ion/inlining/TypedObject-TypeDescrIsArrayType.js @@ -20,24 +20,24 @@ */ if (!this.TypedObject) { print("No TypedObject, skipping"); quit(); } var T = TypedObject; -var AT = new T.ArrayType(T.int32); +var AT = new T.ArrayType(T.int32, 100); function check(v) { return v.map(x => x+1); } function test() { - var w = new AT(100); + var w = new AT(); for ( var i=0 ; i < 1000 ; i++ ) w = check(w); return w; } var w = test(); assertEq(w.length, 100); assertEq(w[99], 1000);
--- a/js/src/jit-test/tests/ion/inlining/TypedObject-TypeDescrIsSimpleType.js +++ b/js/src/jit-test/tests/ion/inlining/TypedObject-TypeDescrIsSimpleType.js @@ -18,20 +18,20 @@ */ if (!this.TypedObject) { print("No TypedObject, skipping"); quit(); } var T = TypedObject; -var AT = new T.ArrayType(T.uint32); +var AT = new T.ArrayType(T.uint32, 100); function check() { - return AT.build(100, x => x+1); + return AT.build(x => x+1); } function test() { var w; for ( var i=0 ; i < 100 ; i++ ) w = check(); return w; }
--- a/js/src/jit-test/tests/ion/inlining/TypedObject-TypeDescrIsSizedArrayType.js +++ b/js/src/jit-test/tests/ion/inlining/TypedObject-TypeDescrIsSizedArrayType.js @@ -16,27 +16,26 @@ */ if (!this.TypedObject) { print("No TypedObject, skipping"); quit(); } var T = TypedObject; -var AT = new T.ArrayType(T.int32); -var IT = AT.dimension(100); -var ix = AT.build(100, x => x == 0 ? 99 : x-1); // [99, 0, 1, ..., 98] +var IT = new T.ArrayType(T.int32, 100); +var ix = IT.build(x => x == 0 ? 99 : x-1); // [99, 0, 1, ..., 98] // This is a left-rotate by one place function check(v) { return v.scatter(IT, ix); } function test() { - var w = AT.build(100, x => x); + var w = IT.build(x => x); for ( var i=0 ; i < 77 ; i++ ) w = check(w); return w; } w = test(); assertEq(w.length, 100); assertEq(w[0], 77);
--- a/js/src/jit-test/tests/ion/inlining/TypedObject-storage-opaque.js +++ b/js/src/jit-test/tests/ion/inlining/TypedObject-storage-opaque.js @@ -22,15 +22,15 @@ if (!this.TypedObject) var T = TypedObject; function check(v) { return T.storage(v); } function test() { var AT = new T.ArrayType(T.Any,10); - var v = new AT(10); + var v = new AT(); for ( var i=0 ; i < 1000 ; i++ ) check(v); return check(v); } test();
--- a/js/src/jit-test/tests/ion/inlining/TypedObject-storage-transparent.js +++ b/js/src/jit-test/tests/ion/inlining/TypedObject-storage-transparent.js @@ -21,16 +21,16 @@ if (!this.TypedObject) var T = TypedObject; function check(v) { return T.storage(v); } function test() { - var AT = new T.ArrayType(T.int32,10); - var v = new AT(10); + var AT = new T.ArrayType(T.int32, 10); + var v = new AT(); for ( var i=0 ; i < 1000 ; i++ ) check(v); return check(v); } test();
--- a/js/src/jit-test/tests/ion/inlining/TypedObject-storage-unknown.js +++ b/js/src/jit-test/tests/ion/inlining/TypedObject-storage-unknown.js @@ -24,16 +24,16 @@ var T = TypedObject; function check(v) { return T.storage(v); } function test() { var AT = new T.ArrayType(T.int32,10); var v = new Object; // Not actually a typed object - var w = new AT(10); // Actually a typed object + var w = new AT(); // Actually a typed object var a = [v,w]; for ( var i=0 ; i < 1000 ; i++ ) try { check(a[i%2]); } catch (e) {} try { return check(a[1]); } catch (e) {} } test();
--- a/js/src/jit-test/tests/parallel/TypedObj-fromPar-outpointer-struct.js +++ b/js/src/jit-test/tests/parallel/TypedObj-fromPar-outpointer-struct.js @@ -12,17 +12,17 @@ function test() { var L = minItemsTestingThreshold; var Matrix = uint32.array(L, 2); var matrix = new Matrix(); for (var i = 0; i < L; i++) matrix[i][0] = i; var Point = new StructType({x: uint32, y: uint32}); - var Points = Point.array(); + var Points = Point.array(L); assertParallelExecSucceeds( // FIXME Bug 983692 -- no where to pass `m` to function(m) Points.fromPar(matrix, function(p, i, c, out) { out.y = p[0]; }), function(points) { for (var i = 0; i < L; i++) { assertEq(matrix[i][0], i); assertEq(matrix[i][1], 0);
--- a/js/src/jit-test/tests/parallel/TypedObj-fromPar-return-scalar.js +++ b/js/src/jit-test/tests/parallel/TypedObj-fromPar-return-scalar.js @@ -5,17 +5,17 @@ if (!getBuildConfiguration().parallelJS) load(libdir + "parallelarray-helpers.js") var { uint8, uint32 } = TypedObject; function test() { var L = minItemsTestingThreshold; var Uints = uint32.array(L); - var Uint8s = uint8.array(); + var Uint8s = uint8.array(L); var uint32s = new Uints(); assertParallelExecSucceeds( // FIXME Bug 983692 -- no where to pass `m` to function(m) Uint8s.fromPar(uint32s, function(e) e + 1), function(uint8s) { for (var i = 0; i < L; i++)
--- a/js/src/jit-test/tests/parallel/TypedObj-mapPar-outpointer-struct.js +++ b/js/src/jit-test/tests/parallel/TypedObj-mapPar-outpointer-struct.js @@ -6,18 +6,18 @@ if (!this.hasOwnProperty("TypedObject")) load(libdir + "parallelarray-helpers.js") var { ArrayType, StructType, uint32 } = TypedObject; function test() { var L = minItemsTestingThreshold; var Point = new StructType({x: uint32, y: uint32}); - var Points = Point.array(); - var points = new Points(L); + var Points = Point.array(L); + var points = new Points(); for (var i = 0; i < L; i++) points[i].x = i; assertParallelExecSucceeds( // FIXME Bug 983692 -- no where to pass `m` to function(m) points.mapPar(function(p, i, c, out) { out.y = p.x; }), function(points2) { for (var i = 0; i < L; i++) {
--- a/js/src/jit-test/tests/parallel/bug977647.js +++ b/js/src/jit-test/tests/parallel/bug977647.js @@ -1,12 +1,12 @@ // Check for mapPar() applied to an empty array. // Public domain. if (!this.hasOwnProperty("TypedObject")) quit(); var { ArrayType, StructType, uint32 } = TypedObject; var Point = new StructType({x: uint32, y: uint32}); -var Points = Point.array(); +var Points = Point.array(0); var points = new Points(); points.mapPar(function() {});
--- a/js/src/jit/BaselineIC.cpp +++ b/js/src/jit/BaselineIC.cpp @@ -8602,17 +8602,17 @@ GetTemplateObjectForNative(JSContext *cx return true; } static bool GetTemplateObjectForClassHook(JSContext *cx, JSNative hook, CallArgs &args, MutableHandleObject templateObject) { - if (hook == TypedObject::constructSized) { + if (hook == TypedObject::construct) { Rooted<TypeDescr *> descr(cx, &args.callee().as<TypeDescr>()); JSObject *obj = TypedObject::createZeroed(cx, descr, 1, gc::TenuredHeap); if (!obj) return false; templateObject.set(obj); return true; }
--- a/js/src/jit/CodeGenerator.cpp +++ b/js/src/jit/CodeGenerator.cpp @@ -5093,26 +5093,16 @@ CodeGenerator::visitTypedObjectProto(LTy const Register tempReg = ToRegister(lir->temp()); masm.setupUnalignedABICall(1, tempReg); masm.passABIArg(obj); masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, TypedObjectProto)); return true; } bool -CodeGenerator::visitTypedObjectUnsizedLength(LTypedObjectUnsizedLength *lir) -{ - Register obj = ToRegister(lir->object()); - Register out = ToRegister(lir->output()); - - masm.load32(Address(obj, OutlineTypedObject::offsetOfUnsizedLength()), out); - return true; -} - -bool CodeGenerator::visitTypedObjectElements(LTypedObjectElements *lir) { Register obj = ToRegister(lir->object()); Register out = ToRegister(lir->output()); Label inlineObject, done; masm.loadObjClass(obj, out); masm.branchPtr(Assembler::Equal, out, ImmPtr(&InlineOpaqueTypedObject::class_), &inlineObject);
--- a/js/src/jit/CodeGenerator.h +++ b/js/src/jit/CodeGenerator.h @@ -181,17 +181,16 @@ class CodeGenerator : public CodeGenerat bool visitLoadArrowThis(LLoadArrowThis *lir); bool visitArrayLength(LArrayLength *lir); bool visitSetArrayLength(LSetArrayLength *lir); bool visitTypedArrayLength(LTypedArrayLength *lir); bool visitTypedArrayElements(LTypedArrayElements *lir); bool visitTypedObjectElements(LTypedObjectElements *lir); bool visitSetTypedObjectOffset(LSetTypedObjectOffset *lir); bool visitTypedObjectProto(LTypedObjectProto *ins); - bool visitTypedObjectUnsizedLength(LTypedObjectUnsizedLength *ins); bool visitStringLength(LStringLength *lir); bool visitInitializedLength(LInitializedLength *lir); bool visitSetInitializedLength(LSetInitializedLength *lir); bool visitNotO(LNotO *ins); bool visitNotV(LNotV *ins); bool visitBoundsCheck(LBoundsCheck *lir); bool visitBoundsCheckRange(LBoundsCheckRange *lir); bool visitBoundsCheckLower(LBoundsCheckLower *lir);
--- a/js/src/jit/IonBuilder.cpp +++ b/js/src/jit/IonBuilder.cpp @@ -7230,29 +7230,27 @@ IonBuilder::getElemTryTypedObject(bool * if (!objPrediction.ofArrayKind()) return true; TypedObjectPrediction elemPrediction = objPrediction.arrayElementType(); if (elemPrediction.isUseless()) return true; - MOZ_ASSERT(TypeDescr::isSized(elemPrediction.kind())); - int32_t elemSize; if (!elemPrediction.hasKnownSize(&elemSize)) return true; switch (elemPrediction.kind()) { case type::Simd: // FIXME (bug 894105): load into a MIRType_float32x4 etc return true; case type::Struct: - case type::SizedArray: + case type::Array: return getElemTryComplexElemOfTypedObject(emitted, obj, index, objPrediction, elemPrediction, elemSize); case type::Scalar: return getElemTryScalarElemOfTypedObject(emitted, @@ -7263,19 +7261,16 @@ IonBuilder::getElemTryTypedObject(bool * elemSize); case type::Reference: return getElemTryReferenceElemOfTypedObject(emitted, obj, index, objPrediction, elemPrediction); - - case type::UnsizedArray: - MOZ_CRASH("Unsized arrays cannot be element types"); } MOZ_CRASH("Bad kind"); } static MIRType MIRTypeForTypedArrayRead(Scalar::Type arrayType, bool observedDouble); @@ -7299,22 +7294,16 @@ IonBuilder::checkTypedObjectIndexInBound if (objPrediction.hasKnownArrayLength(&lenOfAll)) { length = constantInt(lenOfAll); // If we are not loading the length from the object itself, only // optimize if the array buffer can't have been neutered. types::TypeObjectKey *globalType = types::TypeObjectKey::get(&script()->global()); if (globalType->hasFlags(constraints(), types::OBJECT_FLAG_TYPED_OBJECT_NEUTERED)) return false; - } else if (objPrediction.kind() == type::UnsizedArray) { - // Note: unsized arrays will have their length set to zero if they are - // neutered, so we don't need to make sure that no neutering has - // occurred which affects this object. - length = MTypedObjectUnsizedLength::New(alloc(), obj); - current->add(length->toInstruction()); } else { return false; } index = addBoundsCheck(idInt32, length); // Since we passed the bounds check, it is impossible for the // result of multiplication to overflow; so enable imul path. @@ -8197,18 +8186,16 @@ IonBuilder::setElemTryTypedObject(bool * if (!objPrediction.ofArrayKind()) return true; TypedObjectPrediction elemPrediction = objPrediction.arrayElementType(); if (elemPrediction.isUseless()) return true; - MOZ_ASSERT(TypeDescr::isSized(elemPrediction.kind())); - int32_t elemSize; if (!elemPrediction.hasKnownSize(&elemSize)) return true; switch (elemPrediction.kind()) { case type::Simd: // FIXME (bug 894105): store a MIRType_float32x4 etc return true; @@ -8222,18 +8209,17 @@ IonBuilder::setElemTryTypedObject(bool * obj, index, objPrediction, value, elemPrediction, elemSize); case type::Struct: - case type::SizedArray: - case type::UnsizedArray: + case type::Array: // Not yet optimized. return true; } MOZ_CRASH("Bad kind"); } bool @@ -8715,18 +8701,16 @@ IonBuilder::jsop_length_fastPath() if (globalType->hasFlags(constraints(), types::OBJECT_FLAG_TYPED_OBJECT_NEUTERED)) return false; MInstruction *length; int32_t sizedLength; if (prediction.hasKnownArrayLength(&sizedLength)) { obj->setImplicitlyUsedUnchecked(); length = MConstant::New(alloc(), Int32Value(sizedLength)); - } else if (prediction.kind() == type::UnsizedArray) { - length = MTypedObjectUnsizedLength::New(alloc(), obj); } else { return false; } current->pop(); current->add(length); current->push(length); return true; @@ -9444,17 +9428,17 @@ IonBuilder::getPropTryTypedObject(bool * return true; switch (fieldPrediction.kind()) { case type::Simd: // FIXME (bug 894104): load into a MIRType_float32x4 etc return true; case type::Struct: - case type::SizedArray: + case type::Array: return getPropTryComplexPropOfTypedObject(emitted, obj, fieldOffset, fieldPrediction, fieldIndex, resultTypes); case type::Reference: @@ -9465,19 +9449,16 @@ IonBuilder::getPropTryTypedObject(bool * resultTypes); case type::Scalar: return getPropTryScalarPropOfTypedObject(emitted, obj, fieldOffset, fieldPrediction, resultTypes); - - case type::UnsizedArray: - MOZ_CRASH("Field of unsized array type"); } MOZ_CRASH("Bad kind"); } bool IonBuilder::getPropTryScalarPropOfTypedObject(bool *emitted, MDefinition *typedObj, int32_t fieldOffset, @@ -10161,18 +10142,17 @@ IonBuilder::setPropTryTypedObject(bool * return setPropTryReferencePropOfTypedObject(emitted, obj, fieldOffset, value, fieldPrediction); case type::Scalar: return setPropTryScalarPropOfTypedObject(emitted, obj, fieldOffset, value, fieldPrediction); case type::Struct: - case type::SizedArray: - case type::UnsizedArray: + case type::Array: return true; } MOZ_CRASH("Unknown kind"); } bool IonBuilder::setPropTryReferencePropOfTypedObject(bool *emitted,
--- a/js/src/jit/IonBuilder.h +++ b/js/src/jit/IonBuilder.h @@ -772,17 +772,17 @@ class IonBuilder // ForkJoin intrinsics InliningStatus inlineForkJoinGetSlice(CallInfo &callInfo); // TypedObject intrinsics and natives. InliningStatus inlineObjectIsTypeDescr(CallInfo &callInfo); InliningStatus inlineSetTypedObjectOffset(CallInfo &callInfo); bool elementAccessIsTypedObjectArrayOfScalarType(MDefinition* obj, MDefinition* id, ScalarTypeDescr::Type *arrayType); - InliningStatus inlineConstructTypedObject(CallInfo &callInfo, SizedTypeDescr *target); + InliningStatus inlineConstructTypedObject(CallInfo &callInfo, TypeDescr *target); // Utility intrinsics. InliningStatus inlineIsCallable(CallInfo &callInfo); InliningStatus inlineIsObject(CallInfo &callInfo); InliningStatus inlineHaveSameClass(CallInfo &callInfo); InliningStatus inlineToObject(CallInfo &callInfo); InliningStatus inlineToInteger(CallInfo &callInfo); InliningStatus inlineToString(CallInfo &callInfo);
--- a/js/src/jit/LIR-Common.h +++ b/js/src/jit/LIR-Common.h @@ -4226,30 +4226,16 @@ class LTypedObjectProto : public LCallIn const LAllocation *object() { return getOperand(0); } const LDefinition *temp() { return getTemp(0); } }; -// Load an unsized typed object's length. -class LTypedObjectUnsizedLength : public LInstructionHelper<1, 1, 0> -{ - public: - LIR_HEADER(TypedObjectUnsizedLength) - - explicit LTypedObjectUnsizedLength(const LAllocation &object) { - setOperand(0, object); - } - const LAllocation *object() { - return getOperand(0); - } -}; - // Load a typed object's elements vector. class LTypedObjectElements : public LInstructionHelper<1, 1, 0> { public: LIR_HEADER(TypedObjectElements) explicit LTypedObjectElements(const LAllocation &object) { setOperand(0, object);
--- a/js/src/jit/LOpcodes.h +++ b/js/src/jit/LOpcodes.h @@ -279,17 +279,16 @@ _(IteratorMore) \ _(IsNoIterAndBranch) \ _(IteratorEnd) \ _(ArrayLength) \ _(SetArrayLength) \ _(TypedArrayLength) \ _(TypedArrayElements) \ _(TypedObjectProto) \ - _(TypedObjectUnsizedLength) \ _(TypedObjectElements) \ _(SetTypedObjectOffset) \ _(StringLength) \ _(ArgumentsLength) \ _(GetFrameArgument) \ _(SetFrameArgumentT) \ _(SetFrameArgumentC) \ _(SetFrameArgumentV) \
--- a/js/src/jit/Lowering.cpp +++ b/js/src/jit/Lowering.cpp @@ -2518,23 +2518,16 @@ LIRGenerator::visitTypedObjectProto(MTyp MOZ_ASSERT(ins->type() == MIRType_Object); return defineReturn(new(alloc()) LTypedObjectProto( useFixed(ins->object(), CallTempReg0), tempFixed(CallTempReg1)), ins); } bool -LIRGenerator::visitTypedObjectUnsizedLength(MTypedObjectUnsizedLength *ins) -{ - MOZ_ASSERT(ins->type() == MIRType_Int32); - return define(new(alloc()) LTypedObjectUnsizedLength(useRegisterAtStart(ins->object())), ins); -} - -bool LIRGenerator::visitTypedObjectElements(MTypedObjectElements *ins) { MOZ_ASSERT(ins->type() == MIRType_Elements); return define(new(alloc()) LTypedObjectElements(useRegister(ins->object())), ins); } bool LIRGenerator::visitSetTypedObjectOffset(MSetTypedObjectOffset *ins)
--- a/js/src/jit/Lowering.h +++ b/js/src/jit/Lowering.h @@ -187,17 +187,16 @@ class LIRGenerator : public LIRGenerator bool visitPostWriteBarrier(MPostWriteBarrier *ins); bool visitArrayLength(MArrayLength *ins); bool visitSetArrayLength(MSetArrayLength *ins); bool visitTypedArrayLength(MTypedArrayLength *ins); bool visitTypedArrayElements(MTypedArrayElements *ins); bool visitTypedObjectElements(MTypedObjectElements *ins); bool visitSetTypedObjectOffset(MSetTypedObjectOffset *ins); bool visitTypedObjectProto(MTypedObjectProto *ins); - bool visitTypedObjectUnsizedLength(MTypedObjectUnsizedLength *ins); bool visitInitializedLength(MInitializedLength *ins); bool visitSetInitializedLength(MSetInitializedLength *ins); bool visitNot(MNot *ins); bool visitBoundsCheck(MBoundsCheck *ins); bool visitBoundsCheckLower(MBoundsCheckLower *ins); bool visitLoadElement(MLoadElement *ins); bool visitLoadElementHole(MLoadElementHole *ins); bool visitLoadUnboxedObjectOrNull(MLoadUnboxedObjectOrNull *ins);
--- a/js/src/jit/MCallOptimize.cpp +++ b/js/src/jit/MCallOptimize.cpp @@ -214,22 +214,17 @@ IonBuilder::inlineNativeCall(CallInfo &c &OutlineOpaqueTypedObject::class_, &InlineOpaqueTypedObject::class_); if (native == intrinsic_ObjectIsTypeDescr) return inlineObjectIsTypeDescr(callInfo); if (native == intrinsic_TypeDescrIsSimpleType) return inlineHasClass(callInfo, &ScalarTypeDescr::class_, &ReferenceTypeDescr::class_); if (native == intrinsic_TypeDescrIsArrayType) - return inlineHasClass(callInfo, - &SizedArrayTypeDescr::class_, &UnsizedArrayTypeDescr::class_); - if (native == intrinsic_TypeDescrIsSizedArrayType) - return inlineHasClass(callInfo, &SizedArrayTypeDescr::class_); - if (native == intrinsic_TypeDescrIsUnsizedArrayType) - return inlineHasClass(callInfo, &UnsizedArrayTypeDescr::class_); + return inlineHasClass(callInfo, &ArrayTypeDescr::class_); if (native == intrinsic_SetTypedObjectOffset) return inlineSetTypedObjectOffset(callInfo); // Testing Functions if (native == testingFunc_inParallelSection) return inlineForceSequentialOrInParallelSection(callInfo); if (native == testingFunc_bailout) return inlineBailout(callInfo); @@ -281,18 +276,18 @@ IonBuilder::inlineNativeGetter(CallInfo } IonBuilder::InliningStatus IonBuilder::inlineNonFunctionCall(CallInfo &callInfo, JSObject *target) { // Inline a call to a non-function object, invoking the object's call or // construct hook. - if (callInfo.constructing() && target->constructHook() == TypedObject::constructSized) - return inlineConstructTypedObject(callInfo, &target->as<SizedTypeDescr>()); + if (callInfo.constructing() && target->constructHook() == TypedObject::construct) + return inlineConstructTypedObject(callInfo, &target->as<TypeDescr>()); return InliningStatus_NotInlined; } types::TemporaryTypeSet * IonBuilder::getInlineReturnTypeSet() { return bytecodeTypes(pc); @@ -1647,17 +1642,16 @@ IonBuilder::elementAccessIsTypedObjectAr TypedObjectPrediction prediction = typedObjectPrediction(obj); if (prediction.isUseless() || !prediction.ofArrayKind()) return false; TypedObjectPrediction elemPrediction = prediction.arrayElementType(); if (elemPrediction.isUseless() || elemPrediction.kind() != type::Scalar) return false; - MOZ_ASSERT(type::isSized(elemPrediction.kind())); *arrayType = elemPrediction.scalarType(); return true; } bool IonBuilder::inlineUnsafeSetDenseArrayElement(CallInfo &callInfo, uint32_t base) { // Note: we do not check the conditions that are asserted as true @@ -2514,17 +2508,17 @@ IonBuilder::inlineIsConstructing(CallInf } bool constructing = inlineCallInfo_->constructing(); pushConstant(BooleanValue(constructing)); return InliningStatus_Inlined; } IonBuilder::InliningStatus -IonBuilder::inlineConstructTypedObject(CallInfo &callInfo, SizedTypeDescr *descr) +IonBuilder::inlineConstructTypedObject(CallInfo &callInfo, TypeDescr *descr) { // Only inline default constructors for now. if (callInfo.argc() != 0) return InliningStatus_NotInlined; if (size_t(descr->size()) > InlineTypedObject::MaximumSize) return InliningStatus_NotInlined;
--- a/js/src/jit/MIR.h +++ b/js/src/jit/MIR.h @@ -2802,46 +2802,16 @@ class MTypedObjectProto bool congruentTo(const MDefinition *ins) const { return congruentIfOperandsEqual(ins); } AliasSet getAliasSet() const { return AliasSet::Load(AliasSet::ObjectFields); } }; -class MTypedObjectUnsizedLength - : public MUnaryInstruction, - public SingleObjectPolicy::Data -{ - private: - explicit MTypedObjectUnsizedLength(MDefinition *object) - : MUnaryInstruction(object) - { - setResultType(MIRType_Int32); - setMovable(); - } - - public: - INSTRUCTION_HEADER(TypedObjectUnsizedLength) - - static MTypedObjectUnsizedLength *New(TempAllocator &alloc, MDefinition *object) { - return new(alloc) MTypedObjectUnsizedLength(object); - } - - MDefinition *object() const { - return getOperand(0); - } - bool congruentTo(const MDefinition *ins) const { - return congruentIfOperandsEqual(ins); - } - AliasSet getAliasSet() const { - return AliasSet::Load(AliasSet::ObjectFields); - } -}; - // Creates a new derived type object. At runtime, this is just a call // to `BinaryBlock::createDerived()`. That is, the MIR itself does not // compile to particularly optimized code. However, using a distinct // MIR for creating derived type objects allows the compiler to // optimize ephemeral typed objects as would be created for a // reference like `a.b.c` -- here, the `a.b` will create an ephemeral // derived type object that aliases the memory of `a` itself. The // specific nature of `a.b` is revealed by using
--- a/js/src/jit/MOpcodes.h +++ b/js/src/jit/MOpcodes.h @@ -158,17 +158,16 @@ namespace jit { _(GuardObjectType) \ _(GuardObjectIdentity) \ _(GuardClass) \ _(ArrayLength) \ _(SetArrayLength) \ _(TypedArrayLength) \ _(TypedArrayElements) \ _(TypedObjectProto) \ - _(TypedObjectUnsizedLength) \ _(TypedObjectElements) \ _(SetTypedObjectOffset) \ _(InitializedLength) \ _(SetInitializedLength) \ _(Not) \ _(BoundsCheck) \ _(BoundsCheckLower) \ _(InArray) \
--- a/js/src/jit/ParallelSafetyAnalysis.cpp +++ b/js/src/jit/ParallelSafetyAnalysis.cpp @@ -244,17 +244,16 @@ class ParallelSafetyVisitor : public MDe SAFE_OP(GuardObjectIdentity) SAFE_OP(GuardClass) SAFE_OP(AssertRange) SAFE_OP(ArrayLength) WRITE_GUARDED_OP(SetArrayLength, elements) SAFE_OP(TypedArrayLength) SAFE_OP(TypedArrayElements) SAFE_OP(TypedObjectProto) - SAFE_OP(TypedObjectUnsizedLength) SAFE_OP(TypedObjectElements) SAFE_OP(SetTypedObjectOffset) SAFE_OP(InitializedLength) WRITE_GUARDED_OP(SetInitializedLength, elements) SAFE_OP(Not) SAFE_OP(BoundsCheck) SAFE_OP(BoundsCheckLower) SAFE_OP(LoadElement)
--- a/js/src/jit/Recover.cpp +++ b/js/src/jit/Recover.cpp @@ -1108,17 +1108,17 @@ MNewDerivedTypedObject::writeRecoverData } RNewDerivedTypedObject::RNewDerivedTypedObject(CompactBufferReader &reader) { } bool RNewDerivedTypedObject::recover(JSContext *cx, SnapshotIterator &iter) const { - Rooted<SizedTypeDescr *> descr(cx, &iter.read().toObject().as<SizedTypeDescr>()); + Rooted<TypeDescr *> descr(cx, &iter.read().toObject().as<TypeDescr>()); Rooted<TypedObject *> owner(cx, &iter.read().toObject().as<TypedObject>()); int32_t offset = iter.read().toInt32(); JSObject *obj = OutlineTypedObject::createDerived(cx, descr, owner, offset); if (!obj) return false; RootedValue result(cx, ObjectValue(*obj));
--- a/js/src/jit/TypedObjectPrediction.cpp +++ b/js/src/jit/TypedObjectPrediction.cpp @@ -118,44 +118,34 @@ TypedObjectPrediction::ofArrayKind() con { switch (kind()) { case type::Scalar: case type::Reference: case type::Simd: case type::Struct: return false; - case type::SizedArray: - case type::UnsizedArray: + case type::Array: return true; } MOZ_CRASH("Bad kind"); } -static bool -DescrHasKnownSize(const TypeDescr &descr, int32_t *out) -{ - if (!descr.is<SizedTypeDescr>()) - return false; - - *out = descr.as<SizedTypeDescr>().size(); - return true; -} - bool TypedObjectPrediction::hasKnownSize(int32_t *out) const { switch (predictionKind()) { case TypedObjectPrediction::Empty: case TypedObjectPrediction::Inconsistent: break; case TypedObjectPrediction::Descr: - return DescrHasKnownSize(descr(), out); + *out = descr().size(); + return true; case TypedObjectPrediction::Prefix: // We only know a prefix of the struct fields, hence we do not // know its complete size. return false; } MOZ_CRASH("Bad prediction kind"); @@ -228,46 +218,39 @@ TypedObjectPrediction::hasKnownArrayLeng switch (predictionKind()) { case TypedObjectPrediction::Empty: case TypedObjectPrediction::Inconsistent: break; case TypedObjectPrediction::Descr: // In later patches, this condition will always be true // so long as this represents an array - if (descr().is<SizedArrayTypeDescr>()) { - *length = descr().as<SizedArrayTypeDescr>().length(); + if (descr().is<ArrayTypeDescr>()) { + *length = descr().as<ArrayTypeDescr>().length(); return true; } return false; case TypedObjectPrediction::Prefix: break; // Prefixes are always structs, never arrays } MOZ_CRASH("Bad prediction kind"); } -static TypeDescr & -DescrArrayElementType(const TypeDescr &descr) { - return (descr.is<SizedArrayTypeDescr>() - ? descr.as<SizedArrayTypeDescr>().elementType() - : descr.as<UnsizedArrayTypeDescr>().elementType()); -} - TypedObjectPrediction TypedObjectPrediction::arrayElementType() const { MOZ_ASSERT(ofArrayKind()); switch (predictionKind()) { case TypedObjectPrediction::Empty: case TypedObjectPrediction::Inconsistent: break; case TypedObjectPrediction::Descr: - return TypedObjectPrediction(DescrArrayElementType(descr())); + return TypedObjectPrediction(descr().as<ArrayTypeDescr>().elementType()); case TypedObjectPrediction::Prefix: break; // Prefixes are always structs, never arrays } MOZ_CRASH("Bad prediction kind"); } bool
--- a/js/src/jit/VMFunctions.cpp +++ b/js/src/jit/VMFunctions.cpp @@ -1009,19 +1009,19 @@ InitBaselineFrameForOsr(BaselineFrame *f { return frame->initForOsr(interpFrame, numStackValues); } JSObject * CreateDerivedTypedObj(JSContext *cx, HandleObject descr, HandleObject owner, int32_t offset) { - MOZ_ASSERT(descr->is<SizedTypeDescr>()); + MOZ_ASSERT(descr->is<TypeDescr>()); MOZ_ASSERT(owner->is<TypedObject>()); - Rooted<SizedTypeDescr*> descr1(cx, &descr->as<SizedTypeDescr>()); + Rooted<TypeDescr*> descr1(cx, &descr->as<TypeDescr>()); Rooted<TypedObject*> owner1(cx, &owner->as<TypedObject>()); return OutlineTypedObject::createDerived(cx, descr1, owner1, offset); } JSString * RegExpReplace(JSContext *cx, HandleString string, HandleObject regexp, HandleString repl) { MOZ_ASSERT(string);
--- a/js/src/jit/mips/MacroAssembler-mips.cpp +++ b/js/src/jit/mips/MacroAssembler-mips.cpp @@ -834,16 +834,22 @@ MacroAssemblerMIPS::ma_sw(Imm32 imm, Add ma_li(SecondScratchReg, Imm32(address.offset)); as_addu(SecondScratchReg, address.base, SecondScratchReg); as_sw(ScratchRegister, SecondScratchReg, 0); } } void +MacroAssemblerMIPS::ma_sw(Register data, BaseIndex &address) +{ + ma_store(data, address, SizeWord); +} + +void MacroAssemblerMIPS::ma_pop(Register r) { as_lw(r, StackPointer, 0); as_addiu(StackPointer, StackPointer, sizeof(intptr_t)); } void MacroAssemblerMIPS::ma_push(Register r) @@ -2531,16 +2537,29 @@ MacroAssemblerMIPSCompat::branchTestValu // Load payload ma_lw(ScratchRegister, Address(valaddr.base, valaddr.offset + PAYLOAD_OFFSET)); branchPtr(cond, ScratchRegister, value.payloadReg(), label); } // unboxing code void +MacroAssemblerMIPSCompat::unboxNonDouble(const ValueOperand &operand, Register dest) +{ + if (operand.payloadReg() != dest) + ma_move(dest, operand.payloadReg()); +} + +void +MacroAssemblerMIPSCompat::unboxNonDouble(const Address &src, Register dest) +{ + ma_lw(dest, Address(src.base, src.offset + PAYLOAD_OFFSET)); +} + +void MacroAssemblerMIPSCompat::unboxInt32(const ValueOperand &operand, Register dest) { ma_move(dest, operand.payloadReg()); } void MacroAssemblerMIPSCompat::unboxInt32(const Address &src, Register dest) {
--- a/js/src/jit/mips/MacroAssembler-mips.h +++ b/js/src/jit/mips/MacroAssembler-mips.h @@ -211,16 +211,17 @@ class MacroAssemblerMIPS : public Assemb int32_t shift, Label *negZero = nullptr); // memory // shortcut for when we know we're transferring 32 bits of data void ma_lw(Register data, Address address); void ma_sw(Register data, Address address); void ma_sw(Imm32 imm, Address address); + void ma_sw(Register data, BaseIndex &address); void ma_pop(Register r); void ma_push(Register r); // branches when done from within mips-specific code void ma_b(Register lhs, Register rhs, Label *l, Condition c, JumpKind jumpKind = LongJump); void ma_b(Register lhs, Imm32 imm, Label *l, Condition c, JumpKind jumpKind = LongJump); void ma_b(Register lhs, ImmPtr imm, Label *l, Condition c, JumpKind jumpKind = LongJump) { @@ -544,16 +545,18 @@ class MacroAssemblerMIPSCompat : public void branchTestPrimitive(Condition cond, const ValueOperand &value, Label *label); void branchTestPrimitive(Condition cond, Register tag, Label *label); void branchTestValue(Condition cond, const ValueOperand &value, const Value &v, Label *label); void branchTestValue(Condition cond, const Address &valaddr, const ValueOperand &value, Label *label); // unboxing code + void unboxNonDouble(const ValueOperand &operand, Register dest); + void unboxNonDouble(const Address &src, Register dest); void unboxInt32(const ValueOperand &operand, Register dest); void unboxInt32(const Address &src, Register dest); void unboxBoolean(const ValueOperand &operand, Register dest); void unboxBoolean(const Address &src, Register dest); void unboxDouble(const ValueOperand &operand, FloatRegister dest); void unboxDouble(const Address &src, FloatRegister dest); void unboxString(const ValueOperand &operand, Register dest); void unboxString(const Address &src, Register dest);
--- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -4748,16 +4748,19 @@ JS::CloneAndExecuteScript(JSContext *cx, { CHECK_REQUEST(cx); assertSameCompartment(cx, obj); RootedScript script(cx, scriptArg); if (script->compartment() != cx->compartment()) { script = CloneScript(cx, NullPtr(), NullPtr(), script); if (!script) return false; + + Rooted<GlobalObject *> global(cx, script->compileAndGo() ? &script->global() : nullptr); + js::Debugger::onNewScript(cx, script, global); } return ExecuteScript(cx, obj, script, nullptr); } JS_PUBLIC_API(bool) JS_ExecuteScriptVersion(JSContext *cx, HandleObject obj, HandleScript script, MutableHandleValue rval, JSVersion version) {
--- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -991,18 +991,16 @@ bool intrinsic_ForkJoinGetSlice(JSContex bool intrinsic_InParallelSection(JSContext *cx, unsigned argc, Value *vp); bool intrinsic_ObjectIsTypedObject(JSContext *cx, unsigned argc, Value *vp); bool intrinsic_ObjectIsTransparentTypedObject(JSContext *cx, unsigned argc, Value *vp); bool intrinsic_ObjectIsOpaqueTypedObject(JSContext *cx, unsigned argc, Value *vp); bool intrinsic_ObjectIsTypeDescr(JSContext *cx, unsigned argc, Value *vp); bool intrinsic_TypeDescrIsSimpleType(JSContext *cx, unsigned argc, Value *vp); bool intrinsic_TypeDescrIsArrayType(JSContext *cx, unsigned argc, Value *vp); -bool intrinsic_TypeDescrIsUnsizedArrayType(JSContext *cx, unsigned argc, Value *vp); -bool intrinsic_TypeDescrIsSizedArrayType(JSContext *cx, unsigned argc, Value *vp); class AutoLockForExclusiveAccess { JSRuntime *runtime; void init(JSRuntime *rt) { runtime = rt; if (runtime->numExclusiveThreads) {
--- a/js/src/jsnum.cpp +++ b/js/src/jsnum.cpp @@ -1447,34 +1447,43 @@ CharsToNumber(ThreadSafeContext *cx, con else *result = GenericNaN(); return true; } const CharT *end = chars + length; const CharT *bp = SkipSpace(chars, end); - /* ECMA doesn't allow signed hex numbers (bug 273467). */ - if (end - bp >= 2 && bp[0] == '0' && (bp[1] == 'x' || bp[1] == 'X')) { - /* - * It's probably a hex number. Accept if there's at least one hex - * digit after the 0x, and if no non-whitespace characters follow all - * the hex digits. - */ - const CharT *endptr; - double d; - if (!GetPrefixInteger(cx, bp + 2, end, 16, &endptr, &d) || - endptr == bp + 2 || - SkipSpace(endptr, end) != end) - { - *result = GenericNaN(); - } else { - *result = d; + /* ECMA doesn't allow signed non-decimal numbers (bug 273467). */ + if (end - bp >= 2 && bp[0] == '0') { + int radix = 0; + if (bp[1] == 'b' || bp[1] == 'B') + radix = 2; + else if (bp[1] == 'o' || bp[1] == 'O') + radix = 8; + else if (bp[1] == 'x' || bp[1] == 'X') + radix = 16; + + if (radix != 0) { + /* + * It's probably a non-decimal number. Accept if there's at least one digit after + * the 0b|0o|0x, and if no non-whitespace characters follow all the digits. + */ + const CharT *endptr; + double d; + if (!GetPrefixInteger(cx, bp + 2, end, radix, &endptr, &d) || + endptr == bp + 2 || + SkipSpace(endptr, end) != end) + { + *result = GenericNaN(); + } else { + *result = d; + } + return true; } - return true; } /* * Note that ECMA doesn't treat a string beginning with a '0' as * an octal number here. This works because all such numbers will * be interpreted as decimal by js_strtod. Also, any hex numbers * that have made it here (which can only be negative ones) will * be treated as 0 without consuming the 'x' by js_strtod.
new file mode 100644 --- /dev/null +++ b/js/src/tests/ecma_6/Number/ToNumber.js @@ -0,0 +1,26 @@ +/* + * Any copyright is dedicated to the Public Domain. + * https://creativecommons.org/publicdomain/zero/1.0/ + */ + +assertEq(Number("0b11"), 3); +assertEq(Number("0B11"), 3); +assertEq(Number(" 0b11 "), 3); +assertEq(Number("0b12"), NaN); +assertEq(Number("-0b11"), NaN); +assertEq(+"0b11", 3); + +assertEq(Number("0o66"), 54); +assertEq(Number("0O66"), 54); +assertEq(Number(" 0o66 "), 54); +assertEq(Number("0o88"), NaN); +assertEq(Number("-0o66"), NaN); +assertEq(+"0o66", 54); + +if(typeof getSelfHostedValue === "function"){ + assertEq(getSelfHostedValue("ToNumber")("0b11"), 3); + assertEq(getSelfHostedValue("ToNumber")("0o66"), 54); +} + +if (typeof reportCompare === "function") + reportCompare(true, true);
deleted file mode 100644 --- a/js/src/tests/ecma_6/TypedObject/Bug914137.js +++ /dev/null @@ -1,15 +0,0 @@ -// |reftest| skip-if(!this.hasOwnProperty("TypedObject")||(Android)) -var BUGNUMBER = 914137; -var summary = 'Fuzz bug'; - -function test() { - var A = new TypedObject.ArrayType(TypedObject.uint8, 2147483647); - var a = new A(); - assertEq(arguments[5], a); -} - -print(BUGNUMBER + ": " + summary); -assertThrows(test); -if (typeof reportCompare === "function") - reportCompare(true, true); -print("Tests complete");
--- a/js/src/tests/ecma_6/TypedObject/arrayofstructs.js +++ b/js/src/tests/ecma_6/TypedObject/arrayofstructs.js @@ -2,19 +2,19 @@ var BUGNUMBER = 578700; var summary = 'TypedObjects StructType prototype chains'; var ArrayType = TypedObject.ArrayType; var StructType = TypedObject.StructType; var float32 = TypedObject.float32; function runTests() { - var Point = new ArrayType(float32).dimension(3); + var Point = new ArrayType(float32, 3); var Line = new StructType({from: Point, to: Point}); - var Lines = new ArrayType(Line).dimension(3); + var Lines = new ArrayType(Line, 3); var lines = new Lines([ {from: [1, 2, 3], to: [4, 5, 6]}, {from: [7, 8, 9], to: [10, 11, 12]}, {from: [13, 14, 15], to: [16, 17, 18]} ]); assertEq(lines[1].to[1], 11);
--- a/js/src/tests/ecma_6/TypedObject/arraytype.js +++ b/js/src/tests/ecma_6/TypedObject/arraytype.js @@ -23,24 +23,24 @@ function runTests() { assertEq(typeof ArrayType.prototype.prototype.forEach == "function", true); assertThrows(function() ArrayType(uint8, 10)); assertThrows(function() new ArrayType()); assertThrows(function() new ArrayType("")); assertThrows(function() new ArrayType(5)); assertThrows(function() new ArrayType(uint8).dimension(-1)); - var A = new ArrayType(uint8).dimension(10); - assertEq(A.__proto__.__proto__, ArrayType.prototype); + var A = new ArrayType(uint8, 10); + //assertEq(A.__proto__.__proto__, ArrayType.prototype); assertEq(A.length, 10); assertEq(A.elementType, uint8); assertEq(A.byteLength, 10); - assertEq(A.toSource(), "new ArrayType(uint8).dimension(10)"); + assertEq(A.toSource(), "new ArrayType(uint8, 10)"); - assertEq(A.prototype.__proto__.__proto__, ArrayType.prototype.prototype); + //assertEq(A.prototype.__proto__.__proto__, ArrayType.prototype.prototype); var a = new A(); assertEq(a.__proto__, A.prototype); assertEq(a.length, 10); assertThrows(function() a.length = 2); for (var i = 0; i < a.length; i++) @@ -69,18 +69,18 @@ function runTests() { for (var i = 0; i < b.length; i++) assertEq(b[i], i%2); assertThrows(function() new A(5)); assertThrows(function() new A(/fail/)); // Length different assertThrows(function() new A([0, 1, 0, 1, 0, 1, 0, 1, 0])); - var Vec3 = new ArrayType(float32).dimension(3); - var Sprite = new ArrayType(Vec3).dimension(3); // say for position, velocity, and direction + var Vec3 = new ArrayType(float32, 3); + var Sprite = new ArrayType(Vec3, 3); // say for position, velocity, and direction assertEq(Sprite.elementType, Vec3); assertEq(Sprite.elementType.elementType, float32); var mario = new Sprite(); // setting using binary data mario[0] = new Vec3([1, 0, 0]); // setting using JS array conversion @@ -91,17 +91,17 @@ function runTests() { assertEq(mario[0][1], 0); assertEq(mario[0][2], 0); assertThrows(function() mario[1] = 5); mario[1][1] = {}; assertEq(Number.isNaN(mario[1][1]), true); // ok this is just for kicks - var AllSprites = new ArrayType(Sprite).dimension(65536); + var AllSprites = new ArrayType(Sprite, 65536); var as = new AllSprites(); assertEq(as.length, 65536); var indexPropDesc = Object.getOwnPropertyDescriptor(as, '0'); assertEq(typeof indexPropDesc == "undefined", false); assertEq(indexPropDesc.configurable, false); assertEq(indexPropDesc.enumerable, true); assertEq(indexPropDesc.writable, true);
deleted file mode 100644 --- a/js/src/tests/ecma_6/TypedObject/handle_unsized.js +++ /dev/null @@ -1,25 +0,0 @@ -// |reftest| skip-if(!this.hasOwnProperty("TypedObject")) - -/* - * Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/licenses/publicdomain/ - */ - -var BUGNUMBER = 922115; -var summary = 'check we cannot create handles to unsized arrays'; - -var T = TypedObject; - -function runTests() { - var Line = new T.StructType({from: T.uint8, to: T.uint8}); - var Lines = Line.array(); - assertThrowsInstanceOf(function() Lines.handle(), TypeError, - "was able to create handle to unsized array"); - - reportCompare(true, true); - print("Tests complete"); -} - -runTests(); - -
--- a/js/src/tests/ecma_6/TypedObject/method_filter.js +++ b/js/src/tests/ecma_6/TypedObject/method_filter.js @@ -16,50 +16,32 @@ var uint8Clamped = TypedObject.uint8Clam var int8 = TypedObject.int8; var int16 = TypedObject.int16; var int32 = TypedObject.int32; var float32 = TypedObject.float32; var float64 = TypedObject.float64; var objectType = TypedObject.objectType; -function filterOddsFromVariable() { +function filterOdds() { var length = 100; - var Uint32s = uint32.array(); - var uint32s = new Uint32s(100); - for (var i = 0; i < length; i++) - uint32s[i] = i; - - var odds = uint32s.filter(i => (i % 2) != 0); - assertEq(true, objectType(odds) == Uint32s); - assertEq(true, Uint32s.variable); - assertEq(50, odds.length); - for (var i = 0, j = 1; j < length; i++, j += 2) - assertEq(odds[i], j); -} - -function filterOddsFromSized() { - var length = 100; - var Uint32s = uint32.array(100); + var Uint32s = new ArrayType(uint32, 100); var uint32s = new Uint32s(); for (var i = 0; i < length; i++) uint32s[i] = i; var odds = uint32s.filter(i => (i % 2) != 0); - assertEq(true, objectType(odds) == Uint32s.unsized); - assertEq(true, objectType(odds).variable); assertEq(50, odds.length); for (var i = 0, j = 1; j < length; i++, j += 2) assertEq(odds[i], j); } function runTests() { print(BUGNUMBER + ": " + summary); - filterOddsFromVariable(); - filterOddsFromSized(); + filterOdds(); if (typeof reportCompare === "function") reportCompare(true, true); print("Tests complete"); } runTests();
--- a/js/src/tests/ecma_6/TypedObject/referencetypecoercions.js +++ b/js/src/tests/ecma_6/TypedObject/referencetypecoercions.js @@ -22,17 +22,17 @@ function TestValues(type, values) { } for (var i = 0; i < values.length; i++) { var struct = new Struct(); struct.f = values[i].input; compare(struct.f, values[i]); } - var Array = new ArrayType(type).dimension(1); + var Array = new ArrayType(type, 1); for (var i = 0; i < values.length; i++) { var array = new Array(); array[0] = values[i].input; compare(array[0], values[i]); } function compare(v, spec) { if (spec.source)
--- a/js/src/tests/ecma_6/TypedObject/referencetypetrace.js +++ b/js/src/tests/ecma_6/TypedObject/referencetypetrace.js @@ -34,36 +34,27 @@ function TestStructFields(RefType) { var s1 = new S1({f: rabbit}); assertCanReach(s1, rabbit); s1.f = null; assertCannotReach(s1, rabbit); } function TestArrayElements(RefType) { var rabbit = {}; - var S1 = new ArrayType(RefType).dimension(1); - var s1 = new S1([rabbit]); - assertCanReach(s1, rabbit); - s1[0] = null; - assertCannotReach(s1, rabbit); -} - -function TestUnsizedArrayElements(RefType) { - var rabbit = {}; - var S1 = new ArrayType(RefType); + var S1 = new ArrayType(RefType, 1); var s1 = new S1([rabbit]); assertCanReach(s1, rabbit); s1[0] = null; assertCannotReach(s1, rabbit); } function TestStructInArray(RefType) { var rabbit = {}; var S2 = new StructType({f: RefType, g: RefType}); - var S1 = new ArrayType(S2).dimension(1); + var S1 = new ArrayType(S2, 1); var s1 = new S1([{f: rabbit, g: {}}]); assertCanReach(s1, rabbit); s1[0].f = null; assertCannotReach(s1, rabbit); } function TestStringInStruct() { // Rather subtle hair-pullingly maddening testing phenomena: If you @@ -86,19 +77,16 @@ function runTests() printStatus(summary); TestStructFields(Object); TestStructFields(Any); TestArrayElements(Object); TestArrayElements(Any); - TestUnsizedArrayElements(Object); - TestUnsizedArrayElements(Any); - TestStructInArray(Object); TestStructInArray(Any); TestStringInStruct(); reportCompare(true, true, "TypedObjects trace tests"); }
--- a/js/src/tests/ecma_6/TypedObject/size_and_alignment.js +++ b/js/src/tests/ecma_6/TypedObject/size_and_alignment.js @@ -34,19 +34,19 @@ function runTests() { {type: float32, size: 4, alignment: 4}, {type: float64, size: 8, alignment: 8}, {type: new StructType({a: uint8, b: uint16, c: uint8}), size: 6, alignment: 2}, {type: new StructType({a: uint8, b: uint8, c: uint16}), size: 4, alignment: 2}, - {type: new ArrayType(uint8).dimension(32), size: 32, alignment: 1}, - {type: new ArrayType(uint16).dimension(16), size: 32, alignment: 2}, - {type: new ArrayType(uint32).dimension(8), size: 32, alignment: 4}, + {type: new ArrayType(uint8, 32), size: 32, alignment: 1}, + {type: new ArrayType(uint16, 16), size: 32, alignment: 2}, + {type: new ArrayType(uint32, 8), size: 32, alignment: 4}, ]; for (var i = 0; i < typesAndAlignments.length; i++) { var test = typesAndAlignments[i]; print("Type:", test.type.toSource(), "Size:", test.type.byteLength, "Alignment:", test.type.byteAlignment); assertEq(test.type.byteLength, test.size);
--- a/js/src/tests/ecma_6/TypedObject/structtypereflection.js +++ b/js/src/tests/ecma_6/TypedObject/structtypereflection.js @@ -16,17 +16,16 @@ var float64 = TypedObject.float64; function runTests() { print(BUGNUMBER + ": " + summary); var S = new StructType({x: int32, y: uint8, z: float64}); assertEq(S.__proto__, StructType.prototype); assertEq(S.prototype.__proto__, StructType.prototype.prototype); assertEq(S.toSource(), "new StructType({x: int32, y: uint8, z: float64})"); - assertEq(S.variable, false); assertEq(S.byteLength, 16); assertEq(S.byteAlignment, 8); var fieldNames = Object.getOwnPropertyNames(S.fieldTypes); assertEq(fieldNames[0], "x"); assertEq(fieldNames[1], "y"); assertEq(fieldNames[2], "z"); assertEq(fieldNames.length, 3); assertEq(S.fieldTypes.x, int32);
deleted file mode 100644 --- a/js/src/tests/ecma_6/TypedObject/unsizedarrays.js +++ /dev/null @@ -1,54 +0,0 @@ -// |reftest| skip-if(!this.hasOwnProperty("TypedObject")) -var BUGNUMBER = 922115; -var summary = 'TypedObjects ArrayType implementation'; - -/* - * Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/licenses/publicdomain/ - */ - -var { ArrayType, StructType, uint8, float32, uint32 } = TypedObject; -var ObjectType = TypedObject.Object; - -function runTests() { - print(BUGNUMBER + ": " + summary); - - (function SimpleArrayOfTwoObjects() { - print("SimpleArrayOfTwoObjects"); - var Objects = new ArrayType(ObjectType); - var objects2 = new Objects([{f: "Hello"}, - {f: "World"}]); - assertEq(objects2[0].f, "Hello"); - assertEq(objects2[1].f, "World"); - assertEq(objects2.length, 2); - })(); - - (function EmbedUnsizedArraysBad() { - print("EmbedUnsizedArraysBad"); - var Objects = new ArrayType(ObjectType); - assertThrows(() => new ArrayType(Objects)); - assertThrows(() => new StructType({f: Objects})); - })(); - - (function MultipleSizes() { - print("MultipleSizes"); - var Uints = new ArrayType(uint32); - var Point = new StructType({values: new ArrayType(uint32).dimension(3)}); - - var uints = new Uints([0, 1, 2]); - var point = new Point({values: uints}); - - assertEq(uints.length, point.values.length); - for (var i = 0; i < uints.length; i++) { - assertEq(uints[i], i); - assertEq(uints[i], point.values[i]); - } - })(); - - if (typeof reportCompare === "function") - reportCompare(true, true); - print("Tests complete"); -} - -runTests(); -
deleted file mode 100644 --- a/js/src/tests/ecma_6/TypedObject/unsizedarraysanddim.js +++ /dev/null @@ -1,47 +0,0 @@ -// |reftest| skip-if(!this.hasOwnProperty("TypedObject")) -var BUGNUMBER = 922115; -var summary = 'TypedObjects ArrayType implementation'; - -var ArrayType = TypedObject.ArrayType; -var StructType = TypedObject.StructType; -var uint8 = TypedObject.uint8; -var float32 = TypedObject.float32; -var uint32 = TypedObject.uint32; -var ObjectType = TypedObject.Object; - -function runTests() { - (function DimensionLinkedToUndimension() { - var UintsA = uint32.array(); - var FiveUintsA = UintsA.dimension(5); - var FiveUintsB = uint32.array(5); - - assertEq(true, FiveUintsA.equivalent(FiveUintsB)); - assertEq(true, FiveUintsA.unsized === UintsA); - assertEq(true, FiveUintsB.unsized !== UintsA); - })(); - - (function PrototypeHierarchy() { - var Uint8s = uint8.array(); - assertEq(Uint8s.prototype.__proto__, ArrayType.prototype.prototype); - Uint8s.prototype.sum = function() { - var r = 0; - for (var i = 0; i < this.length; i++) - r = uint8(r + this[i]); - return r; - }; - - var FiveUint8s = Uint8s.dimension(5); - assertEq(FiveUint8s.__proto__, Uint8s); - - var fiveUint8s = new FiveUint8s([128, 128, 128, 128, 128]); - assertEq(128, fiveUint8s.sum()); - })(); - - if (typeof reportCompare === "function") - reportCompare(true, true); - - print("Tests complete"); -} - -runTests(); -
deleted file mode 100644 --- a/js/src/tests/ecma_6/TypedObject/unsizedarraysembedded.js +++ /dev/null @@ -1,23 +0,0 @@ -// |reftest| skip-if(!this.hasOwnProperty("TypedObject")) -var BUGNUMBER = 922115; -var summary = 'cannot embed unsized array in a struct'; - -/* - * Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/licenses/publicdomain/ - */ - -var T = TypedObject; - -function runTests() { - print(BUGNUMBER + ": " + summary); - - var Uints = T.uint32.array(); - assertThrowsInstanceOf(() => { new T.StructType({f: Uints}) }, TypeError); - assertThrowsInstanceOf(() => { Uints.array() }, TypeError); - - reportCompare(true, true); - print("Tests complete"); -} - -runTests();
--- a/js/src/vm/Debugger.cpp +++ b/js/src/vm/Debugger.cpp @@ -4827,18 +4827,21 @@ DebuggerArguments_getArg(JSContext *cx, * Since getters can be extracted and applied to other objects, * there is no guarantee this object has an ith argument. */ MOZ_ASSERT(i >= 0); RootedValue arg(cx); RootedScript script(cx); if (unsigned(i) < frame.numActualArgs()) { script = frame.script(); - if (!script->ensureHasAnalyzedArgsUsage(cx)) - return false; + { + AutoCompartment ac(cx, script->compartment()); + if (!script->ensureHasAnalyzedArgsUsage(cx)) + return false; + } if (unsigned(i) < frame.numFormalArgs() && script->formalIsAliased(i)) { for (AliasedFormalIter fi(script); ; fi++) { if (fi.frameIndex() == unsigned(i)) { arg = frame.callObj().aliasedVar(fi); break; } } } else if (script->argsObjAliasesFormals() && frame.hasArgsObj()) {
--- a/js/src/vm/SelfHosting.cpp +++ b/js/src/vm/SelfHosting.cpp @@ -909,28 +909,16 @@ js::intrinsic_TypeDescrIsSimpleType(JSCo } bool js::intrinsic_TypeDescrIsArrayType(JSContext *cx, unsigned argc, Value *vp) { return js::TypeDescrIsArrayType(cx, argc, vp); } -bool -js::intrinsic_TypeDescrIsUnsizedArrayType(JSContext *cx, unsigned argc, Value *vp) -{ - return js::TypeDescrIsUnsizedArrayType(cx, argc, vp); -} - -bool -js::intrinsic_TypeDescrIsSizedArrayType(JSContext *cx, unsigned argc, Value *vp) -{ - return js::TypeDescrIsSizedArrayType(cx, argc, vp); -} - /** * Returns the default locale as a well-formed, but not necessarily canonicalized, * BCP-47 language tag. */ static bool intrinsic_RuntimeDefaultLocale(JSContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -1126,22 +1114,16 @@ static const JSFunctionSpec intrinsic_fu JSNativeThreadSafeWrapper<js::TypedObjectIsAttached>, &js::TypedObjectIsAttachedJitInfo, 1, 0), JS_FNINFO("ObjectIsOpaqueTypedObject", intrinsic_ObjectIsOpaqueTypedObject, &js::ObjectIsOpaqueTypedObjectJitInfo, 1, 0), JS_FNINFO("TypeDescrIsArrayType", intrinsic_TypeDescrIsArrayType, &js::TypeDescrIsArrayTypeJitInfo, 1, 0), - JS_FNINFO("TypeDescrIsUnsizedArrayType", - intrinsic_TypeDescrIsUnsizedArrayType, - &js::TypeDescrIsUnsizedArrayTypeJitInfo, 1, 0), - JS_FNINFO("TypeDescrIsSizedArrayType", - intrinsic_TypeDescrIsSizedArrayType, - &js::TypeDescrIsSizedArrayTypeJitInfo, 1, 0), JS_FNINFO("TypeDescrIsSimpleType", intrinsic_TypeDescrIsSimpleType, &js::TypeDescrIsSimpleTypeJitInfo, 1, 0), JS_FNINFO("ClampToUint8", JSNativeThreadSafeWrapper<js::ClampToUint8>, &js::ClampToUint8JitInfo, 1, 0), JS_FN("GetTypedObjectModule", js::GetTypedObjectModule, 0, 0), JS_FN("GetFloat32x4TypeDescr", js::GetFloat32x4TypeDescr, 0, 0),
--- a/media/libvpx/moz.build +++ b/media/libvpx/moz.build @@ -46,28 +46,31 @@ if CONFIG['VPX_X86_ASM']: SOURCES += files['AVX2'] #postproc is only enabled on x86 with asm SOURCES += files['VP8_POSTPROC'] arm_asm_files = [] if CONFIG['VPX_ARM_ASM']: arm_asm_files += files['ARM_ASM'] - CFLAGS += ['-mfpu=neon'] if CONFIG['VPX_AS_CONVERSION']: GENERATED_SOURCES += [ "%s.%s" % (f, CONFIG['VPX_ASM_SUFFIX']) for f in sorted(arm_asm_files) if f.endswith('.asm') ] SOURCES += [ f for f in sorted(arm_asm_files) if not f.endswith('.asm') ] else: SOURCES += sorted(arm_asm_files) + for f in SOURCES: + if f.endswith('.c') and 'neon' in f: + SOURCES[f].flags += ['-march=armv7-a', '-mthumb', '-mfloat-abi=softfp', '-mfpu=neon'] + # boolhuff_armv5te.asm defines the same functions as boolhuff.c instead of # using RTCD, so we have to make sure we only add one of the two. if 'vp8/encoder/arm/armv5te/boolhuff_armv5te.asm' not in arm_asm_files: SOURCES += [ 'vp8/encoder/boolhuff.c', ] MSVC_ENABLE_PGO = True
--- a/media/mtransport/third_party/nICEr/src/stun/turn_client_ctx.c +++ b/media/mtransport/third_party/nICEr/src/stun/turn_client_ctx.c @@ -58,16 +58,21 @@ int NR_LOG_TURN = 0; #define TURN_USECS_PER_S 1000000 #define TURN_REFRESH_SLACK_SECONDS 10 /* How long before expiry to refresh allocations/permissions. The RFC 5766 Section 7 recommendation if 60 seconds, but this is silly since the transaction times out after about 5. */ #define TURN_PERMISSION_LIFETIME_SECONDS 300 /* 5 minutes. From RFC 5766 2.3 */ +// Set to enable a temporary fix that will run the TURN reservation keep-alive +// logic when data is received via a TURN relayed path: a DATA_INDICATION packet is received. +// TODO(pkerr@mozilla.com) This should be replace/removed when bug 935806 is implemented. +#define REFRESH_RESERVATION_ON_RECV 1 + static int nr_turn_stun_ctx_create(nr_turn_client_ctx *tctx, int type, NR_async_cb success_cb, NR_async_cb failure_cb, nr_turn_stun_ctx **ctxp); static int nr_turn_stun_ctx_destroy(nr_turn_stun_ctx **ctxp); static void nr_turn_stun_ctx_cb(NR_SOCKET s, int how, void *arg); static int nr_turn_stun_set_auth_params(nr_turn_stun_ctx *ctx, char *realm, char *nonce); @@ -785,16 +790,22 @@ int nr_turn_client_parse_data_indication } ABORT(r); } if ((r=nr_transport_addr_copy(remote_addr, &attr->u.xor_mapped_address.unmasked))) ABORT(r); +#if REFRESH_RESERVATION_ON_RECV + if ((r=nr_turn_client_ensure_perm(ctx, remote_addr))) { + ABORT(r); + } +#endif + if (!nr_stun_message_has_attribute(ind, NR_STUN_ATTR_DATA, &attr)) { ABORT(R_BAD_DATA); } assert(newsize >= attr->u.data.length); if (newsize < attr->u.data.length) ABORT(R_BAD_ARGS);
--- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -3901,16 +3901,17 @@ pref("layers.acceleration.draw-fps", fal pref("layers.dump", false); pref("layers.draw-borders", false); pref("layers.draw-tile-borders", false); pref("layers.draw-bigimage-borders", false); pref("layers.frame-counter", false); pref("layers.enable-tiles", false); pref("layers.tiled-drawtarget.enabled", false); pref("layers.low-precision-buffer", false); +pref("layers.progressive-paint", false); pref("layers.tile-width", 256); pref("layers.tile-height", 256); // Max number of layers per container. See Overwrite in mobile prefs. pref("layers.max-active", -1); // Set the default values, and then override per-platform as needed pref("layers.offmainthreadcomposition.enabled", false); // Compositor target frame rate. NOTE: If vsync is enabled the compositor
--- a/netwerk/base/src/BackgroundFileSaver.cpp +++ b/netwerk/base/src/BackgroundFileSaver.cpp @@ -613,20 +613,25 @@ BackgroundFileSaver::ProcessStateChange( int32_t creationIoFlags; if (isContinuation) { creationIoFlags = PR_APPEND; } else { creationIoFlags = (append ? PR_APPEND : PR_TRUNCATE) | PR_CREATE_FILE; } // Create the target file, or append to it if we already started writing it. + // The 0600 permissions are used while the file is being downloaded, and for + // interrupted downloads. Those may be located in the system temporary + // directory, as well as the target directory, and generally have a ".part" + // extension. Those part files should never be group or world-writable even + // if the umask allows it. nsCOMPtr<nsIOutputStream> outputStream; rv = NS_NewLocalFileOutputStream(getter_AddRefs(outputStream), mActualTarget, - PR_WRONLY | creationIoFlags, 0644); + PR_WRONLY | creationIoFlags, 0600); NS_ENSURE_SUCCESS(rv, rv); outputStream = NS_BufferOutputStream(outputStream, BUFFERED_IO_SIZE); if (!outputStream) { return NS_ERROR_FAILURE; } // Wrap the output stream so that it feeds the digest context if needed.
--- a/netwerk/protocol/http/Http2Session.cpp +++ b/netwerk/protocol/http/Http2Session.cpp @@ -2578,28 +2578,30 @@ Http2Session::WriteSegments(nsAHttpSegme if (mDownstreamState == PROCESSING_CONTROL_RST_STREAM) { nsresult streamCleanupCode; // There is no bounds checking on the error code.. we provide special // handling for a couple of cases and all others (including unknown) are // equivalent to cancel. if (mDownstreamRstReason == REFUSED_STREAM_ERROR) { streamCleanupCode = NS_ERROR_NET_RESET; // can retry this 100% safely + mInputFrameDataStream->Transaction()->ReuseConnectionOnRestartOK(true); } else if (mDownstreamRstReason == HTTP_1_1_REQUIRED) { streamCleanupCode = NS_ERROR_NET_RESET; mInputFrameDataStream->Transaction()->ReuseConnectionOnRestartOK(true); mInputFrameDataStream->Transaction()->DisableSpdy(); } else { streamCleanupCode = mInputFrameDataStream->RecvdData() ? NS_ERROR_NET_PARTIAL_TRANSFER : NS_ERROR_NET_INTERRUPT; } - if (mDownstreamRstReason == COMPRESSION_ERROR) + if (mDownstreamRstReason == COMPRESSION_ERROR) { mShouldGoAway = true; + } // mInputFrameDataStream is reset by ChangeDownstreamState Http2Stream *stream = mInputFrameDataStream; ResetDownstreamState(); LOG3(("Http2Session::WriteSegments cleanup stream on recv of rst " "session=%p stream=%p 0x%X\n", this, stream, stream ? stream->StreamID() : 0)); CleanupStream(stream, streamCleanupCode, CANCEL_ERROR);
--- a/netwerk/test/unit/test_http2.js +++ b/netwerk/test/unit/test_http2.js @@ -497,16 +497,22 @@ H11RequiredSessionListener.prototype.onS function test_http2_h11required_session() { var chan = makeChan("https://localhost:6944/h11required_session"); var listener = new H11RequiredSessionListener(); listener.shouldBeHttp2 = false; chan.asyncOpen(listener, null); } +function test_http2_retry_rst() { + var chan = makeChan("https://localhost:6944/rstonce"); + var listener = new Http2CheckListener(); + chan.asyncOpen(listener, null); +} + // hack - the header test resets the multiplex object on the server, // so make sure header is always run before the multiplex test. // // make sure post_big runs first to test race condition in restarting // a stalled stream when a SETTINGS frame arrives var tests = [ test_http2_post_big , test_http2_basic , test_http2_nospdy @@ -521,16 +527,17 @@ var tests = [ test_http2_post_big , test_http2_cookie_crumbling , test_http2_multiplex , test_http2_big , test_http2_post , test_http2_pushapi_1 // These next two must always come in this order , test_http2_h11required_stream , test_http2_h11required_session + , test_http2_retry_rst ]; var current_test = 0; function run_next_test() { if (current_test < tests.length) { tests[current_test](); current_test++; do_test_pending();
--- a/security/manager/tools/PreloadedHPKPins.json +++ b/security/manager/tools/PreloadedHPKPins.json @@ -207,17 +207,17 @@ "pins": "mozilla_services", "test_mode": false, "id": 5 }, { "name": "cdn.mozilla.net", "include_subdomains": true, "pins": "mozilla", "test_mode": false }, { "name": "cdn.mozilla.org", "include_subdomains": true, "pins": "mozilla", "test_mode": false }, { "name": "media.mozilla.com", "include_subdomains": true, "pins": "mozilla", "test_mode": false }, { "name": "services.mozilla.com", "include_subdomains": true, - "pins": "mozilla_services", "test_mode": true, "id": 6 }, + "pins": "mozilla_services", "test_mode": false, "id": 6 }, { "name": "include-subdomains.pinning.example.com", "include_subdomains": true, "pins": "mozilla_test", "test_mode": false }, // Example domain to collect per-host stats for telemetry tests. { "name": "exclude-subdomains.pinning.example.com", "include_subdomains": false, "pins": "mozilla_test", "test_mode": false, "id": 0 }, { "name": "test-mode.pinning.example.com", "include_subdomains": true,
--- a/testing/marionette/client/marionette/marionette.py +++ b/testing/marionette/client/marionette/marionette.py @@ -8,16 +8,17 @@ import datetime import json import os import socket import StringIO import time import traceback import warnings +from contextlib import contextmanager from application_cache import ApplicationCache from decorators import do_crash_check from keys import Keys from marionette_transport import MarionetteTransport from mozrunner import B2GEmulatorRunner @@ -951,30 +952,51 @@ class Marionette(object): """ response = self._send_message("close", "ok") return response def set_context(self, context): ''' - Sets the context that marionette commands are running in. + Sets the context that Marionette commands are running in. :param context: Context, may be one of the class properties `CONTEXT_CHROME` or `CONTEXT_CONTENT`. - Usage example: - - :: + Usage example:: marionette.set_context(marionette.CONTEXT_CHROME) ''' assert(context == self.CONTEXT_CHROME or context == self.CONTEXT_CONTENT) return self._send_message('setContext', 'ok', value=context) + @contextmanager + def using_context(self, context): + ''' + Sets the context that Marionette commands are running in using + a `with` statement. The state of the context on the server is + saved before entering the block, and restored upon exiting it. + + :param context: Context, may be one of the class properties + `CONTEXT_CHROME` or `CONTEXT_CONTENT`. + + Usage example:: + + with marionette.using_context(marionette.CONTEXT_CHROME): + # chrome scope + ... do stuff ... + ''' + scope = self._send_message('getContext', 'value') + self.set_context(context) + try: + yield + finally: + self.set_context(scope) + def switch_to_window(self, window_id): ''' Switch to the specified window; subsequent commands will be directed at the new window. :param window_id: The id or name of the window to switch to. ''' response = self._send_message('switchToWindow', 'ok', name=window_id) self.window = window_id
new file mode 100644 --- /dev/null +++ b/testing/marionette/client/marionette/tests/unit/test_with_using_context.py @@ -0,0 +1,54 @@ +# 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/. + +from marionette_test import MarionetteTestCase +from errors import MarionetteException + + +class TestSetContext(MarionetteTestCase): + def setUp(self): + MarionetteTestCase.setUp(self) + + # shortcuts to improve readability of these tests + self.chrome = self.marionette.CONTEXT_CHROME + self.content = self.marionette.CONTEXT_CONTENT + + test_url = self.marionette.absolute_url('empty.html') + self.marionette.navigate(test_url) + self.marionette.set_context(self.content) + self.assertEquals(self.get_context(), self.content) + + def get_context(self): + return self.marionette._send_message('getContext', 'value') + + def test_set_different_context_using_with_block(self): + with self.marionette.using_context(self.chrome): + self.assertEquals(self.get_context(), self.chrome) + self.assertEquals(self.get_context(), self.content) + + def test_set_same_context_using_with_block(self): + with self.marionette.using_context(self.content): + self.assertEquals(self.get_context(), self.content) + self.assertEquals(self.get_context(), self.content) + + def test_nested_with_blocks(self): + with self.marionette.using_context(self.chrome): + self.assertEquals(self.get_context(), self.chrome) + with self.marionette.using_context(self.content): + self.assertEquals(self.get_context(), self.content) + self.assertEquals(self.get_context(), self.chrome) + self.assertEquals(self.get_context(), self.content) + + def test_set_scope_while_in_with_block(self): + with self.marionette.using_context(self.chrome): + self.assertEquals(self.get_context(), self.chrome) + self.marionette.set_context(self.content) + self.assertEquals(self.get_context(), self.content) + self.assertEquals(self.get_context(), self.content) + + def test_exception_raised_while_in_with_block_is_propagated(self): + with self.assertRaises(MarionetteException): + with self.marionette.using_context(self.chrome): + raise MarionetteException + self.assertEquals(self.get_context(), self.content)
--- a/testing/marionette/client/marionette/tests/unit/unit-tests.ini +++ b/testing/marionette/client/marionette/tests/unit/unit-tests.ini @@ -128,8 +128,9 @@ browser = false [test_execute_isolate.py] [test_click_scrolling.py] [test_profile_management.py] b2g = false [test_set_window_size.py] b2g = false skip-if = os == "linux" # Bug 1085717 +[test_with_using_context.py]
--- a/testing/marionette/marionette-server.js +++ b/testing/marionette/marionette-server.js @@ -694,16 +694,24 @@ MarionetteServerConnection.prototype = { } else { this.context = context; this.sendOk(this.command_id); } }, /** + * Gets the context of the server, either 'chrome' or 'content'. + */ + getContext: function MDA_getContext() { + this.command_id = this.getCommandId(); + this.sendResponse(this.context, this.command_id); + }, + + /** * Returns a chrome sandbox that can be used by the execute_foo functions. * * @param nsIDOMWindow aWindow * Window in which we will execute code * @param Marionette marionette * Marionette test instance * @param object args * Client given args @@ -2730,16 +2738,17 @@ MarionetteServerConnection.prototype = { MarionetteServerConnection.prototype.requestTypes = { "getMarionetteID": MarionetteServerConnection.prototype.getMarionetteID, "sayHello": MarionetteServerConnection.prototype.sayHello, "newSession": MarionetteServerConnection.prototype.newSession, "getSessionCapabilities": MarionetteServerConnection.prototype.getSessionCapabilities, "log": MarionetteServerConnection.prototype.log, "getLogs": MarionetteServerConnection.prototype.getLogs, "setContext": MarionetteServerConnection.prototype.setContext, + "getContext": MarionetteServerConnection.prototype.getContext, "executeScript": MarionetteServerConnection.prototype.execute, "setScriptTimeout": MarionetteServerConnection.prototype.setScriptTimeout, "timeouts": MarionetteServerConnection.prototype.timeouts, "singleTap": MarionetteServerConnection.prototype.singleTap, "actionChain": MarionetteServerConnection.prototype.actionChain, "multiAction": MarionetteServerConnection.prototype.multiAction, "executeAsyncScript": MarionetteServerConnection.prototype.executeWithCallback, "executeJSScript": MarionetteServerConnection.prototype.executeJSScript,
--- a/testing/xpcshell/moz-http2/moz-http2.js +++ b/testing/xpcshell/moz-http2/moz-http2.js @@ -80,16 +80,18 @@ var m = { } else { res.end(); } } }; var h11required_conn = null; var h11required_header = "yes"; +var didRst = false; +var rstConnection = null; function handleRequest(req, res) { var u = url.parse(req.url); var content = getHttpContent(u.pathname); var push, push1, push1a, push2, push3; if (req.httpVersionMajor === 2) { res.setHeader('X-Connection-Http2', 'yes'); @@ -257,16 +259,36 @@ function handleRequest(req, res) { } res.stream.connection.close('HTTP_1_1_REQUIRED', res.stream.id - 2); return; } else { res.setHeader('X-H11Required-Stream-Ok', h11required_header); } } + else if (u.pathname === "/rstonce") { + if (!didRst) { + didRst = true; + rstConnection = req.stream.connection; + req.stream.reset('REFUSED_STREAM'); + return; + } + + if (rstConnection === null || + rstConnection !== req.stream.connection) { + res.writeHead(400); + res.end("WRONG CONNECTION, HOMIE!"); + return; + } + + res.writeHead(200); + res.end("It's all good."); + return; + } + res.setHeader('Content-Type', 'text/html'); res.writeHead(200); res.end(content); } // Set up the SSL certs for our server var options = { key: fs.readFileSync(__dirname + '/../moz-spdy/spdy-key.pem'),
--- a/toolkit/components/downloads/nsDownloadManager.cpp +++ b/toolkit/components/downloads/nsDownloadManager.cpp @@ -3321,33 +3321,55 @@ nsDownload::ExecuteDesiredAction() // Assume an unknown action is save to disk nsHandlerInfoAction action = nsIMIMEInfo::saveToDisk; if (mMIMEInfo) { nsresult rv = mMIMEInfo->GetPreferredAction(&action); NS_ENSURE_SUCCESS(rv, rv); } - nsresult retVal = NS_OK; + nsresult rv = NS_OK; switch (action) { case nsIMIMEInfo::saveToDisk: // Move the file to the proper location - retVal = MoveTempToTarget(); + rv = MoveTempToTarget(); + if (NS_SUCCEEDED(rv)) { + rv = FixTargetPermissions(); + } break; case nsIMIMEInfo::useHelperApp: case nsIMIMEInfo::useSystemDefault: // For these cases we have to move the file to the target location and // open with the appropriate application - retVal = OpenWithApplication(); + rv = OpenWithApplication(); break; default: break; } - return retVal; + return rv; +} + +nsresult +nsDownload::FixTargetPermissions() +{ + nsCOMPtr<nsIFile> target; + nsresult rv = GetTargetFile(getter_AddRefs(target)); + NS_ENSURE_SUCCESS(rv, rv); + + // Set perms according to umask. + nsCOMPtr<nsIPropertyBag2> infoService = + do_GetService("@mozilla.org/system-info;1"); + uint32_t gUserUmask = 0; + rv = infoService->GetPropertyAsUint32(NS_LITERAL_STRING("umask"), + &gUserUmask); + if (NS_SUCCEEDED(rv)) { + rv = target->SetPermissions(0666 & ~gUserUmask); + } + return rv; } nsresult nsDownload::MoveTempToTarget() { nsCOMPtr<nsIFile> target; nsresult rv = GetTargetFile(getter_AddRefs(target)); NS_ENSURE_SUCCESS(rv, rv); @@ -3363,39 +3385,31 @@ nsDownload::MoveTempToTarget() // Extract the new leaf name from the file location nsAutoString fileName; rv = target->GetLeafName(fileName); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIFile> dir; rv = target->GetParent(getter_AddRefs(dir)); NS_ENSURE_SUCCESS(rv, rv); rv = mTempFile->MoveTo(dir, fileName); - NS_ENSURE_SUCCESS(rv, rv); - - return NS_OK; + return rv; } nsresult nsDownload::OpenWithApplication() { // First move the temporary file to the target location nsCOMPtr<nsIFile> target; nsresult rv = GetTargetFile(getter_AddRefs(target)); NS_ENSURE_SUCCESS(rv, rv); // Move the temporary file to the target location rv = MoveTempToTarget(); NS_ENSURE_SUCCESS(rv, rv); - // We do not verify the return value here because, irrespective of success - // or failure of the method, the deletion of temp file has to take place, as - // per the corresponding preference. But we store this separately as this is - // what we ultimately return from this function. - nsresult retVal = mMIMEInfo->LaunchWithFile(target); - bool deleteTempFileOnExit; nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID)); if (!prefs || NS_FAILED(prefs->GetBoolPref(PREF_BH_DELETETEMPFILEONEXIT, &deleteTempFileOnExit))) { // No prefservice or no pref set; use default value #if !defined(XP_MACOSX) // Mac users have been very verbal about temp files being deleted on // app exit - they don't like it - but we'll continue to do this on @@ -3404,33 +3418,37 @@ nsDownload::OpenWithApplication() #else deleteTempFileOnExit = false; #endif } // Always schedule files to be deleted at the end of the private browsing // mode, regardless of the value of the pref. if (deleteTempFileOnExit || mPrivate) { + + // Make the tmp file readonly so users won't lose changes. + target->SetPermissions(0400); + // Use the ExternalHelperAppService to push the temporary file to the list // of files to be deleted on exit. nsCOMPtr<nsPIExternalAppLauncher> appLauncher(do_GetService (NS_EXTERNALHELPERAPPSERVICE_CONTRACTID)); // Even if we are unable to get this service we return the result // of LaunchWithFile() which makes more sense. if (appLauncher) { if (mPrivate) { (void)appLauncher->DeleteTemporaryPrivateFileWhenPossible(target); } else { (void)appLauncher->DeleteTemporaryFileOnExit(target); } } } - return retVal; + return mMIMEInfo->LaunchWithFile(target); } void nsDownload::SetStartTime(int64_t aStartTime) { mStartTime = aStartTime; mLastUpdate = aStartTime; }
--- a/toolkit/components/downloads/nsDownloadManager.h +++ b/toolkit/components/downloads/nsDownloadManager.h @@ -303,16 +303,21 @@ protected: /** * Move the temporary file to the final destination by removing the existing * dummy target and renaming the temporary. */ nsresult MoveTempToTarget(); /** + * Set the target file permissions to be appropriate. + */ + nsresult FixTargetPermissions(); + + /** * Update the start time which also implies the last update time is the same. */ void SetStartTime(int64_t aStartTime); /** * Update the amount of bytes transferred and max bytes; and recalculate the * download percent. */
--- a/toolkit/components/jsdownloads/src/DownloadIntegration.jsm +++ b/toolkit/components/jsdownloads/src/DownloadIntegration.jsm @@ -607,25 +607,39 @@ this.DownloadIntegration = { // specific error. if (!(ex instanceof OS.File.Error) || ex.winLastError != 123) { Cu.reportError(ex); } } } #endif - // Now that the file is completely downloaded, make it accessible by other - // users on this system. On Unix, the umask of the process is respected. - // This call has no effect on Windows. + // The file with the partially downloaded data has restrictive permissions + // that don't allow other users on the system to access it. Now that the + // download is completed, we need to adjust permissions based on whether + // this is a permanently downloaded file or a temporary download to be + // opened read-only with an external application. try { - yield OS.File.setPermissions(aDownload.target.path, - { unixMode: 0o666 }); + // The following logic to determine whether this is a temporary download + // is due to the fact that "deleteTempFileOnExit" is false on Mac, where + // downloads to be opened with external applications are preserved in + // the "Downloads" folder like normal downloads. + let isTemporaryDownload = + aDownload.launchWhenSucceeded && (aDownload.source.isPrivate || + Services.prefs.getBoolPref("browser.helperApps.deleteTempFileOnExit")); + // Permanently downloaded files are made accessible by other users on + // this system, while temporary downloads are marked as read-only. + let unixMode = isTemporaryDownload ? 0o400 : 0o666; + // On Unix, the umask of the process is respected. This call has no + // effect on Windows. + yield OS.File.setPermissions(aDownload.target.path, { unixMode }); } catch (ex) { - // Errors with making the permissions less restrictive should be - // reported, but should not prevent the download from completing. + // We should report errors with making the permissions less restrictive + // or marking the file as read-only on Unix and Mac, but this should not + // prevent the download from completing. Cu.reportError(ex); } gDownloadPlatform.downloadDone(NetUtil.newURI(aDownload.source.url), new FileUtils.File(aDownload.target.path), aDownload.contentType, aDownload.source.isPrivate); this.downloadDoneCalled = true;
--- a/toolkit/components/jsdownloads/test/unit/common_test_Download.js +++ b/toolkit/components/jsdownloads/test/unit/common_test_Download.js @@ -9,16 +9,18 @@ * the "copy" and "legacy" saver implementations. */ "use strict"; //////////////////////////////////////////////////////////////////////////////// //// Globals +const kDeleteTempFileOnExit = "browser.helperApps.deleteTempFileOnExit"; + /** * Creates and starts a new download, using either DownloadCopySaver or * DownloadLegacySaver based on the current test run. * * @return {Promise} * @resolves The newly created Download object. The download may be in progress * or already finished. The promiseDownloadStopped function can be * used to wait for completion. @@ -165,31 +167,65 @@ add_task(function test_basic_tryToKeepPa TEST_DATA_SHORT + TEST_DATA_SHORT); do_check_false(yield OS.File.exists(download.target.partFilePath)); do_check_eq(32, download.saver.getSha256Hash().length); }); /** * Tests the permissions of the final target file once the download finished. */ -add_task(function test_basic_unix_permissions() +add_task(function test_unix_permissions() { // This test is only executed on Linux and Mac. if (Services.appinfo.OS != "Darwin" && Services.appinfo.OS != "Linux") { - do_print("Skipping test_basic_unix_permissions"); + do_print("Skipping test."); return; } - let download = yield promiseStartDownload(httpUrl("source.txt")); - yield promiseDownloadStopped(download); + let launcherPath = getTempFile("app-launcher").path; + + for (let autoDelete of [false, true]) { + for (let isPrivate of [false, true]) { + for (let launchWhenSucceeded of [false, true]) { + do_print("Checking " + JSON.stringify({ autoDelete, + isPrivate, + launchWhenSucceeded })); + + Services.prefs.setBoolPref(kDeleteTempFileOnExit, autoDelete); - // The file should readable and writable by everyone, but the restrictions - // from the umask of the process should still apply. - do_check_eq((yield OS.File.stat(download.target.path)).unixMode, - 0o666 & ~OS.Constants.Sys.umask); + let download; + if (!gUseLegacySaver) { + download = yield Downloads.createDownload({ + source: { url: httpUrl("source.txt"), isPrivate }, + target: getTempFile(TEST_TARGET_FILE_NAME).path, + launchWhenSucceeded, + launcherPath, + }); + yield download.start(); + } else { + download = yield promiseStartLegacyDownload(httpUrl("source.txt"), { + isPrivate, + launchWhenSucceeded, + launcherPath: launchWhenSucceeded && launcherPath, + }); + yield promiseDownloadStopped(download); + } + + // Temporary downloads should be read-only and not accessible to other + // users, while permanently downloaded files should be readable and + // writable as specified by the system umask. + let isTemporary = launchWhenSucceeded && (autoDelete || isPrivate); + do_check_eq((yield OS.File.stat(download.target.path)).unixMode, + isTemporary ? 0o400 : (0o666 & ~OS.Constants.Sys.umask)); + } + } + } + + // Clean up the changes to the preference. + Services.prefs.clearUserPref(kDeleteTempFileOnExit); }); /** * Checks the referrer for downloads. */ add_task(function test_referrer() { let sourcePath = "/test_referrer.txt"; @@ -769,16 +805,23 @@ add_task(function test_cancel_midway_res yield promiseDownloadMidway(download); yield promisePartFileReady(download); // While the download is in progress, we should still have a ".part" file. do_check_false(download.hasPartialData); do_check_true(yield OS.File.exists(download.target.partFilePath)); + // On Unix, verify that the file with the partially downloaded data is not + // accessible by other users on the system. + if (Services.appinfo.OS == "Darwin" || Services.appinfo.OS == "Linux") { + do_check_eq((yield OS.File.stat(download.target.partFilePath)).unixMode, + 0o600); + } + yield download.cancel(); // The ".part" file should be deleted now that the download is canceled. do_check_false(download.hasPartialData); do_check_false(yield OS.File.exists(download.target.partFilePath)); // The third time, we'll request and obtain the entire response again. continueResponses();
--- a/uriloader/exthandler/nsExternalHelperAppService.cpp +++ b/uriloader/exthandler/nsExternalHelperAppService.cpp @@ -1449,17 +1449,17 @@ nsresult nsExternalAppHandler::SetUpTemp // Add an additional .part to prevent the OS from running this file in the // default application. tempLeafName.AppendLiteral(".part"); rv = mTempFile->Append(NS_ConvertUTF8toUTF16(tempLeafName)); // make this file unique!!! NS_ENSURE_SUCCESS(rv, rv); - rv = mTempFile->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0644); + rv = mTempFile->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0600); NS_ENSURE_SUCCESS(rv, rv); // Now save the temp leaf name, minus the ".part" bit, so we can use it later. // This is a bit broken in the case when createUnique actually had to append // some numbers, because then we now have a filename like foo.bar-1.part and // we'll end up with foo.bar-1.bar as our final filename if we end up using // this. But the other options are all bad too.... Ideally we'd have a way // to tell createUnique to put its unique marker before the extension that @@ -2396,17 +2396,17 @@ NS_IMETHODIMP nsExternalAppHandler::Laun } #ifdef XP_WIN fileToUse->Append(mSuggestedFileName + mTempFileExtension); #else fileToUse->Append(mSuggestedFileName); #endif - nsresult rv = fileToUse->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0644); + nsresult rv = fileToUse->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0600); if(NS_SUCCEEDED(rv)) { mFinalFileDestination = do_QueryInterface(fileToUse); // launch the progress window now that the user has picked the desired action. rv = CreateTransfer(); if (NS_FAILED(rv)) { Cancel(rv); } } else {
--- a/widget/cocoa/nsChildView.h +++ b/widget/cocoa/nsChildView.h @@ -578,17 +578,16 @@ public: NS_IMETHOD ReparentNativeWidget(nsIWidget* aNewParent); mozilla::widget::TextInputHandler* GetTextInputHandler() { return mTextInputHandler; } - void NotifyDirtyRegion(const nsIntRegion& aDirtyRegion); void ClearVibrantAreas(); NSColor* VibrancyFillColorForWidgetType(uint8_t aWidgetType); NSColor* VibrancyFontSmoothingBackgroundColorForWidgetType(uint8_t aWidgetType); // unit conversion convenience functions int32_t CocoaPointsToDevPixels(CGFloat aPts) const { return nsCocoaUtils::CocoaPointsToDevPixels(aPts, BackingScaleFactor()); }
--- a/widget/cocoa/nsChildView.mm +++ b/widget/cocoa/nsChildView.mm @@ -2116,25 +2116,16 @@ nsChildView::NewCompositorParent(int aSu [EventThreadRunner start]; } gNumberOfWidgetsNeedingEventThread++; } return compositor; } -void -nsChildView::NotifyDirtyRegion(const nsIntRegion& aDirtyRegion) -{ - if ([(ChildView*)mView isCoveringTitlebar]) { - // We store the dirty region so that we know what to repaint in the titlebar. - mDirtyTitlebarRegion.Or(mDirtyTitlebarRegion, aDirtyRegion); - } -} - nsIntRect nsChildView::RectContainingTitlebarControls() { // Start with a thin strip at the top of the window for the highlight line. NSRect rect = NSMakeRect(0, 0, [mView bounds].size.width, [(ChildView*)mView cornerRadius]); // Add the rects of the titlebar controls. @@ -2338,57 +2329,50 @@ CreateCGContext(const nsIntSize& aSize) return ctx; } // When this method is entered, mEffectsLock is already being held. void nsChildView::UpdateTitlebarCGContext() { - nsIntRegion dirtyTitlebarRegion; - dirtyTitlebarRegion.And(mDirtyTitlebarRegion, mTitlebarRect); - mDirtyTitlebarRegion.SetEmpty(); - if (mTitlebarRect.IsEmpty()) { ReleaseTitlebarCGContext(); return; } + NSRect titlebarRect = DevPixelsToCocoaPoints(mTitlebarRect); + NSRect dirtyRect = [mView convertRect:[(BaseWindow*)[mView window] getAndResetNativeDirtyRect] fromView:nil]; + NSRect dirtyTitlebarRect = NSIntersectionRect(titlebarRect, dirtyRect); + nsIntSize texSize = RectTextureImage::TextureSizeForSize(mTitlebarRect.Size()); if (!mTitlebarCGContext || CGBitmapContextGetWidth(mTitlebarCGContext) != size_t(texSize.width) || CGBitmapContextGetHeight(mTitlebarCGContext) != size_t(texSize.height)) { - dirtyTitlebarRegion = mTitlebarRect; + dirtyTitlebarRect = titlebarRect; ReleaseTitlebarCGContext(); mTitlebarCGContext = CreateCGContext(texSize); } - if (dirtyTitlebarRegion.IsEmpty()) + if (NSIsEmptyRect(dirtyTitlebarRect)) { return; + } CGContextRef ctx = mTitlebarCGContext; CGContextSaveGState(ctx); - nsTArray<CGRect> rects; - nsIntRegionRectIterator iter(dirtyTitlebarRegion); - for (;;) { - const nsIntRect* r = iter.Next(); - if (!r) - break; - rects.AppendElement(CGRectMake(r->x, r->y, r->width, r->height)); - } - CGContextClipToRects(ctx, rects.Elements(), rects.Length()); - - CGContextClearRect(ctx, CGRectMake(0, 0, texSize.width, texSize.height)); - double scale = BackingScaleFactor(); CGContextScaleCTM(ctx, scale, scale); + + CGContextClipToRect(ctx, NSRectToCGRect(dirtyTitlebarRect)); + CGContextClearRect(ctx, NSRectToCGRect(dirtyTitlebarRect)); + NSGraphicsContext* oldContext = [NSGraphicsContext currentContext]; CGContextSaveGState(ctx); BaseWindow* window = (BaseWindow*)[mView window]; NSView* frameView = [[window contentView] superview]; if (![frameView isFlipped]) { CGContextTranslateCTM(ctx, 0, [frameView bounds].size.height); @@ -2400,18 +2384,18 @@ nsChildView::UpdateTitlebarCGContext() // Draw the title string. if ([window wantsTitleDrawn] && [frameView respondsToSelector:@selector(_drawTitleBar:)]) { [frameView _drawTitleBar:[frameView bounds]]; } // Draw the titlebar controls into the titlebar image. for (id view in [window titlebarControls]) { NSRect viewFrame = [view frame]; - nsIntRect viewRect = CocoaPointsToDevPixels([mView convertRect:viewFrame fromView:frameView]); - if (!dirtyTitlebarRegion.Intersects(viewRect)) { + NSRect viewRect = [mView convertRect:viewFrame fromView:frameView]; + if (!NSIntersectsRect(dirtyTitlebarRect, viewRect)) { continue; } // All of the titlebar controls we're interested in are subclasses of // NSButton. if (![view isKindOfClass:[NSButton class]]) { continue; } NSButton *button = (NSButton *) view; @@ -2461,17 +2445,17 @@ nsChildView::UpdateTitlebarCGContext() DrawTitlebarHighlight([frameView bounds].size, [(ChildView*)mView cornerRadius], DevPixelsToCocoaPoints(1)); [NSGraphicsContext setCurrentContext:oldContext]; CGContextRestoreGState(ctx); - mUpdatedTitlebarRegion.Or(mUpdatedTitlebarRegion, dirtyTitlebarRegion); + mUpdatedTitlebarRegion.OrWith(CocoaPointsToDevPixels(dirtyTitlebarRect)); } // This method draws an overlay in the top of the window which contains the // titlebar controls (e.g. close, min, zoom, fullscreen) and the titlebar // highlight effect. // This is necessary because the real titlebar controls are covered by our // OpenGL context. Note that in terms of the NSView hierarchy, our ChildView // is actually below the titlebar controls - that's why hovering and clicking @@ -4097,21 +4081,16 @@ NSEvent* gLastDragMouseDownEvent = nil; NS_ADDREF(mGeckoChild); [widgetArray addObject:[NSNumber numberWithUnsignedInteger:(NSUInteger)mGeckoChild]]; [self performSelector:@selector(releaseWidgets:) withObject:widgetArray afterDelay:0]; } if ([self isUsingOpenGL]) { - // When our view covers the titlebar, we need to repaint the titlebar - // texture buffer when, for example, the window buttons are hovered. - // So we notify our nsChildView about any areas needing repainting. - mGeckoChild->NotifyDirtyRegion([self nativeDirtyRegionWithBoundingRect:[self bounds]]); - if (mGeckoChild->GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_CLIENT) { ClientLayerManager *manager = static_cast<ClientLayerManager*>(mGeckoChild->GetLayerManager()); manager->AsShadowForwarder()->WindowOverlayChanged(); } } mGeckoChild->WillPaintWindow(); }
--- a/widget/cocoa/nsCocoaWindow.h +++ b/widget/cocoa/nsCocoaWindow.h @@ -72,16 +72,18 @@ typedef struct _nsCocoaWindowList { // DPI cache. Getting the physical screen size (CGDisplayScreenSize) // is ridiculously slow, so we cache it in the toplevel window for all // descendants to use. float mDPI; NSTrackingArea* mTrackingArea; + NSRect mDirtyRect; + BOOL mBeingShown; BOOL mDrawTitle; BOOL mBrightTitlebarForeground; } - (void)importState:(NSDictionary*)aState; - (NSMutableDictionary*)exportState; - (void)setDrawsContentsIntoWindowFrame:(BOOL)aState; @@ -111,16 +113,18 @@ typedef struct _nsCocoaWindowList { - (BOOL)wantsTitleDrawn; - (void)setUseBrightTitlebarForeground:(BOOL)aBrightForeground; - (BOOL)useBrightTitlebarForeground; - (void)disableSetNeedsDisplay; - (void)enableSetNeedsDisplay; +- (NSRect)getAndResetNativeDirtyRect; + @end @interface NSWindow (Undocumented) // If a window has been explicitly removed from the "window cache" (to // deactivate it), it's sometimes necessary to "reset" it to reactivate it // (and put it back in the "window cache"). One way to do this, which Apple // often uses, is to set the "window number" to '-1' and then back to its
--- a/widget/cocoa/nsCocoaWindow.mm +++ b/widget/cocoa/nsCocoaWindow.mm @@ -2645,16 +2645,17 @@ static NSMutableSet *gSwizzledFrameViewC [super initWithContentRect:aContentRect styleMask:aStyle backing:aBufferingType defer:aFlag]; mState = nil; mActiveTitlebarColor = nil; mInactiveTitlebarColor = nil; mScheduledShadowInvalidation = NO; mDisabledNeedsDisplay = NO; mDPI = GetDPI(self); mTrackingArea = nil; + mDirtyRect = NSZeroRect; mBeingShown = NO; mDrawTitle = NO; mBrightTitlebarForeground = NO; [self updateTrackingArea]; return self; } @@ -2866,19 +2867,27 @@ static const NSString* kStateShowsToolba - (void)_setNeedsDisplayInRect:(NSRect)aRect { // Prevent unnecessary invalidations due to moving NSViews (e.g. for plugins) if (!mDisabledNeedsDisplay) { // This method is only called by Cocoa, so when we're here, we know that // it's available and don't need to check whether our superclass responds // to the selector. [super _setNeedsDisplayInRect:aRect]; + mDirtyRect = NSUnionRect(mDirtyRect, aRect); } } +- (NSRect)getAndResetNativeDirtyRect +{ + NSRect dirtyRect = mDirtyRect; + mDirtyRect = NSZeroRect; + return dirtyRect; +} + - (void)updateContentViewSize { NSRect rect = [self contentRectForFrameRect:[self frame]]; [[self contentView] setFrameSize:rect.size]; } // Possibly move the titlebar buttons. - (void)reflowTitlebarElements
--- a/xpfe/components/autocomplete/resources/content/autocomplete.xml +++ b/xpfe/components/autocomplete/resources/content/autocomplete.xml @@ -1326,17 +1326,17 @@ <handler event="mousedown" phase="capturing" action="if ( !this.mMenuOpen ) this.finishAutoComplete(false, false, event);"/> </handlers> </binding> <binding id="autocomplete-result-popup" extends="chrome://global/content/bindings/popup.xml#popup"> <resources> - <stylesheet src="chrome://global/content/autocomplete.css"/> + <stylesheet src="chrome://communicator/content/autocomplete.css"/> <stylesheet src="chrome://global/skin/autocomplete.css"/> </resources> <content ignorekeys="true" level="top"> <xul:tree anonid="tree" class="autocomplete-tree plain" flex="1"> <xul:treecols anonid="treecols"> <xul:treecol class="autocomplete-treecol" id="treecolAutoCompleteValue" flex="2"/> <xul:treecol class="autocomplete-treecol" id="treecolAutoCompleteComment" flex="1" hidden="true"/> @@ -1593,17 +1593,17 @@ } ]]></handler> </handlers> </binding> <binding id="autocomplete-history-popup" extends="chrome://global/content/bindings/popup.xml#popup-scrollbars"> <resources> - <stylesheet src="chrome://global/content/autocomplete.css"/> + <stylesheet src="chrome://communicator/content/autocomplete.css"/> <stylesheet src="chrome://global/skin/autocomplete.css"/> </resources> <implementation> <method name="removeOpenAttribute"> <parameter name="parentNode"/> <body><![CDATA[ parentNode.removeAttribute("open");