merge mozilla-inbound to mozilla-central. r=merge a=merge

This commit is contained in:
Sebastian Hengst 2017-11-09 00:00:16 +02:00
commit a353221537
166 changed files with 1510 additions and 1556 deletions

View file

@ -4,7 +4,28 @@ const TEST_URL = "data:text/html,a test page";
const DRAG_URL = "http://www.example.com/"; const DRAG_URL = "http://www.example.com/";
const DRAG_FORBIDDEN_URL = "chrome://browser/content/aboutDialog.xul"; const DRAG_FORBIDDEN_URL = "chrome://browser/content/aboutDialog.xul";
const DRAG_TEXT = "Firefox is awesome"; const DRAG_TEXT = "Firefox is awesome";
const DRAG_TEXT_URL = "http://example.com/?q=Firefox+is+awesome";
const DRAG_WORD = "Firefox"; const DRAG_WORD = "Firefox";
const DRAG_WORD_URL = "http://example.com/?q=Firefox";
registerCleanupFunction(async function cleanup() {
while (gBrowser.tabs.length > 1) {
await BrowserTestUtils.removeTab(gBrowser.tabs[gBrowser.tabs.length - 1]);
}
Services.search.currentEngine = originalEngine;
let engine = Services.search.getEngineByName("MozSearch");
Services.search.removeEngine(engine);
});
let originalEngine;
add_task(async function test_setup() {
// Stop search-engine loads from hitting the network
Services.search.addEngineWithDetails("MozSearch", "", "", "", "GET",
"http://example.com/?q={searchTerms}");
let engine = Services.search.getEngineByName("MozSearch");
originalEngine = Services.search.currentEngine;
Services.search.currentEngine = engine;
});
add_task(async function checkDragURL() { add_task(async function checkDragURL() {
await BrowserTestUtils.withNewTab(TEST_URL, function(browser) { await BrowserTestUtils.withNewTab(TEST_URL, function(browser) {
@ -26,13 +47,15 @@ add_task(async function checkDragForbiddenURL() {
}); });
add_task(async function checkDragText() { add_task(async function checkDragText() {
await BrowserTestUtils.withNewTab(TEST_URL, function(browser) { await BrowserTestUtils.withNewTab(TEST_URL, async browser => {
let promiseLoad = BrowserTestUtils.browserLoaded(browser, false, DRAG_TEXT_URL);
EventUtils.synthesizeDrop(document.getElementById("home-button"), gURLBar, EventUtils.synthesizeDrop(document.getElementById("home-button"), gURLBar,
[[{type: "text/plain", data: DRAG_TEXT}]], "copy", window); [[{type: "text/plain", data: DRAG_TEXT}]], "copy", window);
is(gURLBar.value, DRAG_TEXT, "Dragging normal text should replace the URL bar value"); await promiseLoad;
promiseLoad = BrowserTestUtils.browserLoaded(browser, false, DRAG_WORD_URL);
EventUtils.synthesizeDrop(document.getElementById("home-button"), gURLBar, EventUtils.synthesizeDrop(document.getElementById("home-button"), gURLBar,
[[{type: "text/plain", data: DRAG_WORD}]], "copy", window); [[{type: "text/plain", data: DRAG_WORD}]], "copy", window);
is(gURLBar.value, DRAG_WORD, "Dragging a single word should replace the URL bar value"); await promiseLoad;
}); });
}); });

View file

@ -951,12 +951,10 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
this.value = droppedItem instanceof URL ? droppedItem.href : droppedItem; this.value = droppedItem instanceof URL ? droppedItem.href : droppedItem;
SetPageProxyState("invalid"); SetPageProxyState("invalid");
this.focus(); this.focus();
if (droppedItem instanceof URL) { this.handleCommand();
this.handleCommand(); // Force not showing the dropped URI immediately.
// Force not showing the dropped URI immediately. gBrowser.userTypedValue = null;
gBrowser.userTypedValue = null; URLBarSetURI();
URLBarSetURI();
}
} }
]]></body> ]]></body>
</method> </method>

View file

@ -315,7 +315,6 @@
@RESPATH@/components/txtsvc.xpt @RESPATH@/components/txtsvc.xpt
@RESPATH@/components/txmgr.xpt @RESPATH@/components/txmgr.xpt
@RESPATH@/components/uconv.xpt @RESPATH@/components/uconv.xpt
@RESPATH@/components/unicharutil.xpt
@RESPATH@/components/update.xpt @RESPATH@/components/update.xpt
@RESPATH@/components/uriloader.xpt @RESPATH@/components/uriloader.xpt
@RESPATH@/components/urlformatter.xpt @RESPATH@/components/urlformatter.xpt

View file

@ -69,6 +69,7 @@ included_inclnames_to_ignore = set([
'jscustomallocator.h', # provided by embedders; allowed to be missing 'jscustomallocator.h', # provided by embedders; allowed to be missing
'js-config.h', # generated in $OBJDIR 'js-config.h', # generated in $OBJDIR
'fdlibm.h', # fdlibm 'fdlibm.h', # fdlibm
'mozmemory.h', # included without a path
'pratom.h', # NSPR 'pratom.h', # NSPR
'prcvar.h', # NSPR 'prcvar.h', # NSPR
'prerror.h', # NSPR 'prerror.h', # NSPR

View file

@ -13,6 +13,7 @@
#include "mozilla/Maybe.h" #include "mozilla/Maybe.h"
#include "mozilla/NotNull.h" #include "mozilla/NotNull.h"
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
#include "nsIURI.h"
class nsPresContext; class nsPresContext;
class nsIPresShell; class nsIPresShell;
namespace mozilla { namespace mozilla {

View file

@ -5,6 +5,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "AbortSignal.h" #include "AbortSignal.h"
#include "AbortController.h"
#include "mozilla/dom/Event.h" #include "mozilla/dom/Event.h"
#include "mozilla/dom/AbortSignalBinding.h" #include "mozilla/dom/AbortSignalBinding.h"

View file

@ -6,6 +6,8 @@
#include "mozilla/dom/AnimationEffectReadOnly.h" #include "mozilla/dom/AnimationEffectReadOnly.h"
#include "mozilla/dom/AnimationEffectReadOnlyBinding.h" #include "mozilla/dom/AnimationEffectReadOnlyBinding.h"
#include "mozilla/dom/Animation.h"
#include "mozilla/AnimationUtils.h" #include "mozilla/AnimationUtils.h"
#include "mozilla/FloatingPoint.h" #include "mozilla/FloatingPoint.h"

View file

@ -7,6 +7,7 @@
#include "mozilla/dom/CSSPseudoElement.h" #include "mozilla/dom/CSSPseudoElement.h"
#include "mozilla/dom/CSSPseudoElementBinding.h" #include "mozilla/dom/CSSPseudoElementBinding.h"
#include "mozilla/dom/Element.h" #include "mozilla/dom/Element.h"
#include "mozilla/dom/KeyframeEffectBinding.h"
#include "mozilla/AnimationComparator.h" #include "mozilla/AnimationComparator.h"
namespace mozilla { namespace mozilla {

View file

@ -13,6 +13,7 @@
#include "mozilla/BasePrincipal.h" #include "mozilla/BasePrincipal.h"
#include "mozilla/TimeStamp.h" #include "mozilla/TimeStamp.h"
#include "mozilla/dom/IdleDeadline.h" #include "mozilla/dom/IdleDeadline.h"
#include "mozilla/dom/UnionTypes.h"
#include "mozilla/dom/WindowBinding.h" // For IdleRequestCallback/Options #include "mozilla/dom/WindowBinding.h" // For IdleRequestCallback/Options
#include "nsThreadUtils.h" #include "nsThreadUtils.h"

View file

@ -9,6 +9,7 @@
#include "mozilla/CycleCollectedJSContext.h" #include "mozilla/CycleCollectedJSContext.h"
#include "mozilla/dom/CustomElementRegistryBinding.h" #include "mozilla/dom/CustomElementRegistryBinding.h"
#include "mozilla/dom/HTMLElementBinding.h" #include "mozilla/dom/HTMLElementBinding.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/WebComponentsBinding.h" #include "mozilla/dom/WebComponentsBinding.h"
#include "mozilla/dom/DocGroup.h" #include "mozilla/dom/DocGroup.h"
#include "nsHTMLTags.h" #include "nsHTMLTags.h"

View file

@ -8,6 +8,7 @@
#include "mozilla/dom/DOMErrorBinding.h" #include "mozilla/dom/DOMErrorBinding.h"
#include "mozilla/dom/DOMException.h" #include "mozilla/dom/DOMException.h"
#include "mozilla/UseCounter.h" #include "mozilla/UseCounter.h"
#include "nsIDocument.h"
#include "nsPIDOMWindow.h" #include "nsPIDOMWindow.h"
namespace mozilla { namespace mozilla {

View file

@ -7736,6 +7736,31 @@ nsIDocument::SetDir(const nsAString& aDirection)
} }
} }
/* static */
bool
nsIDocument::MatchNameAttribute(Element* aElement, int32_t aNamespaceID,
nsAtom* aAtom, void* aData)
{
NS_PRECONDITION(aElement, "Must have element to work with!");
if (!aElement->HasName()) {
return false;
}
nsString* elementName = static_cast<nsString*>(aData);
return
aElement->GetNameSpaceID() == kNameSpaceID_XHTML &&
aElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
*elementName, eCaseMatters);
}
/* static */
void*
nsIDocument::UseExistingNameString(nsINode* aRootNode, const nsString* aName)
{
return const_cast<nsString*>(aName);
}
NS_IMETHODIMP NS_IMETHODIMP
nsDocument::GetInputEncoding(nsAString& aInputEncoding) nsDocument::GetInputEncoding(nsAString& aInputEncoding)
{ {

View file

@ -57,6 +57,7 @@ class ElementCreationOptionsOrString;
class gfxUserFontSet; class gfxUserFontSet;
class imgIRequest; class imgIRequest;
class nsBindingManager; class nsBindingManager;
class nsCachableElementsByNameNodeList;
class nsIDocShell; class nsIDocShell;
class nsDocShell; class nsDocShell;
class nsDOMNavigationTiming; class nsDOMNavigationTiming;
@ -2941,6 +2942,14 @@ public:
virtual void SetTitle(const nsAString& aTitle, mozilla::ErrorResult& rv) = 0; virtual void SetTitle(const nsAString& aTitle, mozilla::ErrorResult& rv) = 0;
void GetDir(nsAString& aDirection) const; void GetDir(nsAString& aDirection) const;
void SetDir(const nsAString& aDirection); void SetDir(const nsAString& aDirection);
already_AddRefed<nsContentList> GetElementsByName(const nsAString& aName)
{
return GetFuncStringContentList<nsCachableElementsByNameNodeList>(this,
MatchNameAttribute,
nullptr,
UseExistingNameString,
aName);
}
nsPIDOMWindowOuter* GetDefaultView() const nsPIDOMWindowOuter* GetDefaultView() const
{ {
return GetWindow(); return GetWindow();
@ -3321,6 +3330,12 @@ protected:
// Helper for GetScrollingElement/IsScrollingElement. // Helper for GetScrollingElement/IsScrollingElement.
bool IsPotentiallyScrollable(mozilla::dom::HTMLBodyElement* aBody); bool IsPotentiallyScrollable(mozilla::dom::HTMLBodyElement* aBody);
// Helpers for GetElementsByName.
static bool MatchNameAttribute(mozilla::dom::Element* aElement,
int32_t aNamespaceID,
nsAtom* aAtom, void* aData);
static void* UseExistingNameString(nsINode* aRootNode, const nsString* aName);
nsCString mReferrer; nsCString mReferrer;
nsString mLastModified; nsString mLastModified;

View file

@ -6,14 +6,18 @@
#include "WebIDLGlobalNameHash.h" #include "WebIDLGlobalNameHash.h"
#include "js/GCAPI.h" #include "js/GCAPI.h"
#include "jswrapper.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/HashFunctions.h" #include "mozilla/HashFunctions.h"
#include "mozilla/Maybe.h" #include "mozilla/Maybe.h"
#include "mozilla/dom/DOMJSClass.h" #include "mozilla/dom/DOMJSClass.h"
#include "mozilla/dom/DOMJSProxyHandler.h" #include "mozilla/dom/DOMJSProxyHandler.h"
#include "mozilla/dom/PrototypeList.h" #include "mozilla/dom/PrototypeList.h"
#include "mozilla/dom/RegisterBindings.h" #include "mozilla/dom/RegisterBindings.h"
#include "nsGlobalWindow.h"
#include "nsIMemoryReporter.h" #include "nsIMemoryReporter.h"
#include "nsTHashtable.h" #include "nsTHashtable.h"
#include "WrapperFactory.h"
namespace mozilla { namespace mozilla {
namespace dom { namespace dom {

View file

@ -12,6 +12,7 @@
#include "jsprf.h" #include "jsprf.h"
#include "MainThreadUtils.h" #include "MainThreadUtils.h"
#include "mozilla/Assertions.h" #include "mozilla/Assertions.h"
#include "nsContentUtils.h"
#include "nsGlobalWindow.h" #include "nsGlobalWindow.h"
#include "nsNetUtil.h" #include "nsNetUtil.h"
#include "nsPIDOMWindow.h" #include "nsPIDOMWindow.h"

View file

@ -14,6 +14,8 @@
#include "jsapi.h" #include "jsapi.h"
#include "js/RootingAPI.h" #include "js/RootingAPI.h"
#include "nsCOMArray.h"
#include "nsCycleCollectionParticipant.h"
#include "nsIScriptError.h" #include "nsIScriptError.h"
#include "nsString.h" #include "nsString.h"

View file

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html>
<head>
<script>
function boom()
{
var canvas = document.createElement("canvas");
canvas.setAttribute("width", "7623");
canvas.setAttribute("height", "14064");
canvas.getContext("experimental-webgl");
}
</script>
</head>
<body onload="boom();"></body>
</html>

View file

@ -16,6 +16,7 @@ skip-if(Android) load 780392-1.html
skip-if(Android) skip-if(gtkWidget&&isDebugBuild) load 789933-1.html # bug 1155252 for linux skip-if(Android) skip-if(gtkWidget&&isDebugBuild) load 789933-1.html # bug 1155252 for linux
load 794463-1.html load 794463-1.html
load 802926-1.html load 802926-1.html
skip-if(winWidget&&isDebugBuild&&/^Windows\x20NT\x206\.1/.test(http.oscpu)) load 844280.html # intermittent OOMs on Win7 debug
load 896047-1.html load 896047-1.html
load 916128-1.html load 916128-1.html
load 934939-1.html load 934939-1.html

View file

@ -6,6 +6,8 @@
#include "ClientState.h" #include "ClientState.h"
#include "mozilla/dom/ClientIPCTypes.h"
namespace mozilla { namespace mozilla {
namespace dom { namespace dom {

View file

@ -7,6 +7,9 @@
#ifndef _mozilla_dom_ClientState_h #ifndef _mozilla_dom_ClientState_h
#define _mozilla_dom_ClientState_h #define _mozilla_dom_ClientState_h
#include "mozilla/dom/DocumentBinding.h"
#include "mozilla/Maybe.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/UniquePtr.h" #include "mozilla/UniquePtr.h"
namespace mozilla { namespace mozilla {

View file

@ -6,9 +6,11 @@
#include "mozilla/dom/WebCryptoThreadPool.h" #include "mozilla/dom/WebCryptoThreadPool.h"
#include "MainThreadUtils.h"
#include "mozilla/Services.h" #include "mozilla/Services.h"
#include "mozilla/StaticPtr.h" #include "mozilla/StaticPtr.h"
#include "nsComponentManagerUtils.h" #include "nsComponentManagerUtils.h"
#include "nsNSSComponent.h"
#include "nsXPCOMCIDInternal.h" #include "nsXPCOMCIDInternal.h"
#include "nsXPCOMPrivate.h" #include "nsXPCOMPrivate.h"
#include "nsIObserverService.h" #include "nsIObserverService.h"

View file

@ -7,6 +7,8 @@
#ifndef mozilla_dom_WebCryptoThreadPool_h #ifndef mozilla_dom_WebCryptoThreadPool_h
#define mozilla_dom_WebCryptoThreadPool_h #define mozilla_dom_WebCryptoThreadPool_h
#include "mozilla/Mutex.h"
#include "nsIObserver.h"
#include "nsIObserverService.h" #include "nsIObserverService.h"
#include "nsIThreadPool.h" #include "nsIThreadPool.h"

View file

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html>
<head>
<script>
function boom()
{
function f() {
document.removeEventListener("DOMSubtreeModified", f, true);
document.documentElement.setAttributeNS(null, "contenteditable", "false");
}
document.addEventListener("DOMSubtreeModified", f, true);
document.documentElement.contentEditable = "true";
}
</script>
</head>
<body onload="boom();"></body>
</html>

View file

@ -53,6 +53,7 @@ load 682460.html
load 738744.xhtml load 738744.xhtml
load 741218.json load 741218.json
load 741250.xhtml load 741250.xhtml
load 768344.html
load 795221-1.html load 795221-1.html
load 795221-2.html load 795221-2.html
load 795221-3.html load 795221-3.html

View file

@ -2063,38 +2063,6 @@ nsHTMLDocument::Writeln(JSContext* cx, const Sequence<nsString>& aText,
WriteCommon(cx, aText, true, rv); WriteCommon(cx, aText, true, rv);
} }
bool
nsHTMLDocument::MatchNameAttribute(Element* aElement, int32_t aNamespaceID,
nsAtom* aAtom, void* aData)
{
NS_PRECONDITION(aElement, "Must have element to work with!");
if (!aElement->HasName()) {
return false;
}
nsString* elementName = static_cast<nsString*>(aData);
return
aElement->GetNameSpaceID() == kNameSpaceID_XHTML &&
aElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
*elementName, eCaseMatters);
}
/* static */
void*
nsHTMLDocument::UseExistingNameString(nsINode* aRootNode, const nsString* aName)
{
return const_cast<nsString*>(aName);
}
NS_IMETHODIMP
nsHTMLDocument::GetElementsByName(const nsAString& aElementName,
nsIDOMNodeList** aReturn)
{
*aReturn = GetElementsByName(aElementName).take();
return NS_OK;
}
void void
nsHTMLDocument::AddedForm() nsHTMLDocument::AddedForm()
{ {

View file

@ -193,14 +193,6 @@ public:
return nsHTMLDocument::GetForms(); return nsHTMLDocument::GetForms();
} }
nsIHTMLCollection* Scripts(); nsIHTMLCollection* Scripts();
already_AddRefed<nsContentList> GetElementsByName(const nsAString & aName)
{
return GetFuncStringContentList<nsCachableElementsByNameNodeList>(this,
MatchNameAttribute,
nullptr,
UseExistingNameString,
aName);
}
already_AddRefed<nsIDocument> Open(JSContext* cx, already_AddRefed<nsIDocument> Open(JSContext* cx,
const nsAString& aType, const nsAString& aType,
const nsAString& aReplace, const nsAString& aReplace,
@ -280,10 +272,6 @@ protected:
nsAtom* aAtom, void* aData); nsAtom* aAtom, void* aData);
static bool MatchAnchors(mozilla::dom::Element* aElement, int32_t aNamespaceID, static bool MatchAnchors(mozilla::dom::Element* aElement, int32_t aNamespaceID,
nsAtom* aAtom, void* aData); nsAtom* aAtom, void* aData);
static bool MatchNameAttribute(mozilla::dom::Element* aElement,
int32_t aNamespaceID,
nsAtom* aAtom, void* aData);
static void* UseExistingNameString(nsINode* aRootNode, const nsString* aName);
static void DocumentWriteTerminationFunc(nsISupports *aRef); static void DocumentWriteTerminationFunc(nsISupports *aRef);

View file

@ -29,7 +29,6 @@ interface nsIDOMHTMLDocument : nsIDOMDocument
readonly attribute nsIDOMHTMLCollection links; readonly attribute nsIDOMHTMLCollection links;
readonly attribute nsIDOMHTMLCollection forms; readonly attribute nsIDOMHTMLCollection forms;
readonly attribute nsIDOMHTMLCollection scripts; readonly attribute nsIDOMHTMLCollection scripts;
nsIDOMNodeList getElementsByName(in DOMString elementName);
// If aContentType is not something supported by nsHTMLDocument and // If aContentType is not something supported by nsHTMLDocument and
// the HTML content sink, trying to write to the document will // the HTML content sink, trying to write to the document will

View file

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script>
function boom()
{
vid.setMediaKeys(null);
vid.fastSeek(111);
}
</script>
</head>
<body onload="boom();">
<video id="vid" src="../../../../layout/reftests/webm-video/frames.webm"></video>
</body>
</html>

View file

@ -0,0 +1,32 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Media test: Negative duration.</title>
</head>
<body>
<video id="v" controls src="1389304.mp4">
</video>
<p id="msg"></p>
<script type="text/javascript">
function log(x) {
msg.innerHTML = x + "<br>";
}
v.play();
v.onended = function() {
log("endded!");
let seekable = v.seekable;
for (let i = 0; i < seekable.length; ++i) {
let start = seekable.start(i);
let end = seekable.end(i);
log(`[${i}]: start=${start} end=${end}`);
}
}
</script>
</body>
</html>

Binary file not shown.

View file

@ -86,6 +86,7 @@ load 1158427.html
load 1185176.html load 1185176.html
load 1185192.html load 1185192.html
load 1257700.html load 1257700.html
load 1267263.html
load 1270303.html load 1270303.html
load 1304948.html load 1304948.html
load 1319486.html load 1319486.html
@ -93,6 +94,7 @@ load 1368490.html
load 1291702.html load 1291702.html
load 1378826.html load 1378826.html
load 1384248.html load 1384248.html
load 1389304.html
load 1393272.webm load 1393272.webm
load disconnect-wrong-destination.html load disconnect-wrong-destination.html
load analyser-channels-1.html load analyser-channels-1.html

View file

@ -123,7 +123,8 @@ partial interface Document {
//(HTML only)readonly attribute HTMLCollection links; //(HTML only)readonly attribute HTMLCollection links;
//(HTML only)readonly attribute HTMLCollection forms; //(HTML only)readonly attribute HTMLCollection forms;
//(HTML only)readonly attribute HTMLCollection scripts; //(HTML only)readonly attribute HTMLCollection scripts;
//(HTML only)NodeList getElementsByName(DOMString elementName); [Pure]
NodeList getElementsByName(DOMString elementName);
//(Not implemented)readonly attribute DOMElementMap cssElementMap; //(Not implemented)readonly attribute DOMElementMap cssElementMap;
// dynamic markup insertion // dynamic markup insertion

View file

@ -29,7 +29,6 @@ interface HTMLDocument : Document {
readonly attribute HTMLCollection forms; readonly attribute HTMLCollection forms;
[Pure] [Pure]
readonly attribute HTMLCollection scripts; readonly attribute HTMLCollection scripts;
NodeList getElementsByName(DOMString elementName);
// dynamic markup insertion // dynamic markup insertion
[CEReactions, Throws] [CEReactions, Throws]

View file

@ -0,0 +1,6 @@
<!DOCTYPE html>
<html style="-moz-perspective: 1000px; -moz-transform: skewY(277deg); overflow: -moz-hidden-unscrollable;">
<body style="-moz-transform: skewY(127deg);">
<div style="height: 20px; background: lightgreen;"></div>
</body>
</html>

View file

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<head>
<script>
function boom()
{
var ctx = document.getElementById("c").getContext('2d');
ctx.stroke();
}
</script>
</head>
<body onload="boom();">
<canvas id="c" width="800" style="overflow: -moz-hidden-unscrollable; transform: skewY(30rad);"></canvas>
</body>
</html>

View file

@ -0,0 +1,7 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<body style="display: flex; position: absolute; transform: matrix3d(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); overflow-y: hidden;">
<video></video><video></video><video></video><track style="transform: rotate(45deg) scale(2, 1); position: absolute;"><video></video></track>
</body>
</html>

View file

@ -114,6 +114,8 @@ load 746849.html
load 746866.html load 746866.html
load 747132.html load 747132.html
load 747302.html load 747302.html
load 766422-1.html
load 766422-2.html
load 766452-1.html load 766452-1.html
load 766452-2.html load 766452-2.html
load 768079-1.html load 768079-1.html
@ -136,6 +138,7 @@ pref(layers.force-active,true) load 914457-1.html
load 944579.svg load 944579.svg
load 944579.html load 944579.html
pref(security.fileuri.strict_origin_policy,false) load 950000.html pref(security.fileuri.strict_origin_policy,false) load 950000.html
load 951893.xhtml
load 1011218.html load 1011218.html
load 1034403-1.html load 1034403-1.html
load 1056516.html load 1056516.html

View file

@ -10,9 +10,6 @@
#include "nsJISx4051LineBreaker.h" #include "nsJISx4051LineBreaker.h"
#include "nsSampleWordBreaker.h" #include "nsSampleWordBreaker.h"
// unicharutil
#include "nsUnicodeNormalizer.h"
// string bundles (intl) // string bundles (intl)
#include "nsStringBundleService.h" #include "nsStringBundleService.h"
#include "nsStringBundleTextOverride.h" #include "nsStringBundleTextOverride.h"
@ -28,13 +25,10 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsSampleWordBreaker)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsStringBundleService, Init) NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsStringBundleService, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsStringBundleTextOverride, Init) NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsStringBundleTextOverride, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsUnicodeNormalizer)
NS_DEFINE_NAMED_CID(MOZ_LOCALESERVICE_CID); NS_DEFINE_NAMED_CID(MOZ_LOCALESERVICE_CID);
NS_DEFINE_NAMED_CID(MOZ_OSPREFERENCES_CID); NS_DEFINE_NAMED_CID(MOZ_OSPREFERENCES_CID);
NS_DEFINE_NAMED_CID(NS_LBRK_CID); NS_DEFINE_NAMED_CID(NS_LBRK_CID);
NS_DEFINE_NAMED_CID(NS_WBRK_CID); NS_DEFINE_NAMED_CID(NS_WBRK_CID);
NS_DEFINE_NAMED_CID(NS_UNICODE_NORMALIZER_CID);
NS_DEFINE_NAMED_CID(NS_STRINGBUNDLESERVICE_CID); NS_DEFINE_NAMED_CID(NS_STRINGBUNDLESERVICE_CID);
NS_DEFINE_NAMED_CID(NS_STRINGBUNDLETEXTOVERRIDE_CID); NS_DEFINE_NAMED_CID(NS_STRINGBUNDLETEXTOVERRIDE_CID);
NS_DEFINE_NAMED_CID(NS_COLLATIONFACTORY_CID); NS_DEFINE_NAMED_CID(NS_COLLATIONFACTORY_CID);
@ -46,7 +40,6 @@ static const mozilla::Module::CIDEntry kIntlCIDs[] = {
{ &kMOZ_OSPREFERENCES_CID, false, nullptr, mozilla::intl::OSPreferencesConstructor }, { &kMOZ_OSPREFERENCES_CID, false, nullptr, mozilla::intl::OSPreferencesConstructor },
{ &kNS_LBRK_CID, false, nullptr, nsJISx4051LineBreakerConstructor }, { &kNS_LBRK_CID, false, nullptr, nsJISx4051LineBreakerConstructor },
{ &kNS_WBRK_CID, false, nullptr, nsSampleWordBreakerConstructor }, { &kNS_WBRK_CID, false, nullptr, nsSampleWordBreakerConstructor },
{ &kNS_UNICODE_NORMALIZER_CID, false, nullptr, nsUnicodeNormalizerConstructor },
{ &kNS_STRINGBUNDLESERVICE_CID, false, nullptr, nsStringBundleServiceConstructor }, { &kNS_STRINGBUNDLESERVICE_CID, false, nullptr, nsStringBundleServiceConstructor },
{ &kNS_STRINGBUNDLETEXTOVERRIDE_CID, false, nullptr, nsStringBundleTextOverrideConstructor }, { &kNS_STRINGBUNDLETEXTOVERRIDE_CID, false, nullptr, nsStringBundleTextOverrideConstructor },
{ &kNS_COLLATIONFACTORY_CID, false, nullptr, nsCollationFactoryConstructor }, { &kNS_COLLATIONFACTORY_CID, false, nullptr, nsCollationFactoryConstructor },
@ -60,7 +53,6 @@ static const mozilla::Module::ContractIDEntry kIntlContracts[] = {
{ MOZ_OSPREFERENCES_CONTRACTID, &kMOZ_OSPREFERENCES_CID }, { MOZ_OSPREFERENCES_CONTRACTID, &kMOZ_OSPREFERENCES_CID },
{ NS_LBRK_CONTRACTID, &kNS_LBRK_CID }, { NS_LBRK_CONTRACTID, &kNS_LBRK_CID },
{ NS_WBRK_CONTRACTID, &kNS_WBRK_CID }, { NS_WBRK_CONTRACTID, &kNS_WBRK_CID },
{ NS_UNICODE_NORMALIZER_CONTRACTID, &kNS_UNICODE_NORMALIZER_CID },
{ NS_STRINGBUNDLE_CONTRACTID, &kNS_STRINGBUNDLESERVICE_CID }, { NS_STRINGBUNDLE_CONTRACTID, &kNS_STRINGBUNDLESERVICE_CID },
{ NS_STRINGBUNDLETEXTOVERRIDE_CONTRACTID, &kNS_STRINGBUNDLETEXTOVERRIDE_CID }, { NS_STRINGBUNDLETEXTOVERRIDE_CONTRACTID, &kNS_STRINGBUNDLETEXTOVERRIDE_CID },
{ NS_COLLATIONFACTORY_CONTRACTID, &kNS_COLLATIONFACTORY_CID }, { NS_COLLATIONFACTORY_CONTRACTID, &kNS_COLLATIONFACTORY_CID },

View file

@ -5,24 +5,9 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/. # file, You can obtain one at http://mozilla.org/MPL/2.0/.
DIRS += ['util'] DIRS += ['util']
TEST_DIRS += ['tests']
XPIDL_SOURCES += [
'nsIUnicodeNormalizer.idl',
]
XPIDL_MODULE = 'unicharutil'
EXPORTS += [ EXPORTS += [
'nsUGenCategory.h', 'nsUGenCategory.h',
'nsUnicodeNormalizer.h',
]
UNIFIED_SOURCES += [
'nsUnicodeNormalizer.cpp',
] ]
FINAL_LIBRARY = 'xul' FINAL_LIBRARY = 'xul'
if CONFIG['GNU_CXX']:
CXXFLAGS += ['-Wno-error=shadow']

View file

@ -1,33 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsISupports.idl"
%{C++
#define NS_UNICODE_NORMALIZER_CID { 0xa665e49a, 0xf3e6, 0x4fed, { 0x9f, 0x31, 0xf7, 0xc5, 0x68, 0xa2, 0x98, 0x99 } }
#define NS_UNICODE_NORMALIZER_CONTRACTID "@mozilla.org/intl/unicodenormalizer;1"
%}
[scriptable, uuid(B43A461F-1BCF-4329-820B-66E48C979E14)]
interface nsIUnicodeNormalizer : nsISupports
{
/**
* Normalize Unicode (NFD, NFC, NFKD, NFKC).
*
* NFD: Canonical Decomposition
* NFC: Canonical Decomposition, followed by Canonical Composition
* NFKD: Compatibility Decomposition
* NFKC: Compatibility Decomposition, followed by Canonical Composition
* Reference: Unicode Standard, TR15, Unicode Normalization Forms
*
* @param aSrc [IN] nsAString which contains an input UTF-16 string.
* @param aDest [OUT] A pointer to an output buffer provided by a callee.
* @return NS_OK for success,
*/
void NormalizeUnicodeNFD(in AString aSrc, out AString aDest);
void NormalizeUnicodeNFC(in AString aSrc, out AString aDest);
void NormalizeUnicodeNFKD(in AString aSrc, out AString aDest);
void NormalizeUnicodeNFKC(in AString aSrc, out AString aDest);
};

View file

@ -1,91 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsUnicodeNormalizer.h"
#include "ICUUtils.h"
#include "unicode/unorm2.h"
#include "unicode/utext.h"
NS_IMPL_ISUPPORTS(nsUnicodeNormalizer, nsIUnicodeNormalizer)
static nsresult
DoNormalization(const UNormalizer2* aNorm, const nsAString& aSrc,
nsAString& aDest)
{
UErrorCode errorCode = U_ZERO_ERROR;
const int32_t length = aSrc.Length();
const UChar* src = reinterpret_cast<const UChar*>(aSrc.BeginReading());
// Initial guess for a capacity that is likely to be enough for most cases.
int32_t capacity = length + (length >> 8) + 8;
while (true) {
aDest.SetLength(capacity);
UChar* dest = reinterpret_cast<UChar*>(aDest.BeginWriting());
int32_t len = unorm2_normalize(aNorm, src, aSrc.Length(), dest, capacity,
&errorCode);
if (U_SUCCESS(errorCode)) {
aDest.SetLength(len);
break;
}
if (errorCode != U_BUFFER_OVERFLOW_ERROR) {
// Some other error that we don't handle
break;
}
// Buffer wasn't big enough; adjust to the reported size and try again.
capacity = len;
errorCode = U_ZERO_ERROR;
}
return ICUUtils::UErrorToNsResult(errorCode);
}
nsresult
nsUnicodeNormalizer::NormalizeUnicodeNFD(const nsAString& aSrc,
nsAString& aDest)
{
// The unorm2_getNF*Instance functions return static singletons that should
// not be deleted, so we just get them once on first use.
static UErrorCode errorCode = U_ZERO_ERROR;
static const UNormalizer2* norm = unorm2_getNFDInstance(&errorCode);
if (U_SUCCESS(errorCode)) {
return DoNormalization(norm, aSrc, aDest);
}
return ICUUtils::UErrorToNsResult(errorCode);
}
nsresult
nsUnicodeNormalizer::NormalizeUnicodeNFC(const nsAString& aSrc,
nsAString& aDest)
{
static UErrorCode errorCode = U_ZERO_ERROR;
static const UNormalizer2* norm = unorm2_getNFCInstance(&errorCode);
if (U_SUCCESS(errorCode)) {
return DoNormalization(norm, aSrc, aDest);
}
return ICUUtils::UErrorToNsResult(errorCode);
}
nsresult
nsUnicodeNormalizer::NormalizeUnicodeNFKD(const nsAString& aSrc,
nsAString& aDest)
{
static UErrorCode errorCode = U_ZERO_ERROR;
static const UNormalizer2* norm = unorm2_getNFKDInstance(&errorCode);
if (U_SUCCESS(errorCode)) {
return DoNormalization(norm, aSrc, aDest);
}
return ICUUtils::UErrorToNsResult(errorCode);
}
nsresult
nsUnicodeNormalizer::NormalizeUnicodeNFKC(const nsAString& aSrc,
nsAString& aDest)
{
static UErrorCode errorCode = U_ZERO_ERROR;
static const UNormalizer2* norm = unorm2_getNFKCInstance(&errorCode);
if (U_SUCCESS(errorCode)) {
return DoNormalization(norm, aSrc, aDest);
}
return ICUUtils::UErrorToNsResult(errorCode);
}

View file

@ -1,33 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsUnicodeNormalizer_h__
#define nsUnicodeNormalizer_h__
#include "nscore.h"
#include "nsISupports.h"
#include "nsIUnicodeNormalizer.h"
nsresult NS_NewUnicodeNormalizer(nsISupports** oResult);
class nsUnicodeNormalizer : public nsIUnicodeNormalizer {
public:
nsUnicodeNormalizer() { }
NS_DECL_ISUPPORTS
NS_IMETHOD NormalizeUnicodeNFD( const nsAString& aSrc, nsAString& aDest) override;
NS_IMETHOD NormalizeUnicodeNFC( const nsAString& aSrc, nsAString& aDest) override;
NS_IMETHOD NormalizeUnicodeNFKD( const nsAString& aSrc, nsAString& aDest) override;
NS_IMETHOD NormalizeUnicodeNFKC( const nsAString& aSrc, nsAString& aDest) override;
private:
virtual ~nsUnicodeNormalizer() { }
};
#endif //nsUnicodeNormalizer_h__

View file

@ -1,12 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* dummy test data will be overwritten by generator */
static char versionText[] = "\0";
static testcaseLine Part0TestData[1];
static testcaseLine Part1TestData[1];
static testcaseLine Part2TestData[1];
static testcaseLine Part3TestData[1];

View file

@ -1,282 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <stdio.h>
#include "gtest/gtest.h"
#include "nsXPCOM.h"
#include "nsIUnicodeNormalizer.h"
#include "nsString.h"
#include "nsCharTraits.h"
#include "nsServiceManagerUtils.h"
#include "mozilla/Sprintf.h"
struct testcaseLine {
wchar_t* c1;
wchar_t* c2;
wchar_t* c3;
wchar_t* c4;
wchar_t* c5;
char* description;
};
#ifdef DEBUG_smontagu
#define DEBUG_NAMED_TESTCASE(t, s) \
printf(t ": "); \
for (uint32_t i = 0; i < s.Length(); ++i) \
printf("%x ", s.CharAt(i)); \
printf("\n")
#else
#define DEBUG_NAMED_TESTCASE(t, s)
#endif
#define DEBUG_TESTCASE(x) DEBUG_NAMED_TESTCASE(#x, x)
#define NORMALIZE_AND_COMPARE(base, comparison, form, description) \
normalized.Truncate();\
normalizer->NormalizeUnicode##form(comparison, normalized);\
DEBUG_NAMED_TESTCASE(#form "(" #comparison ")", normalized);\
if (!base.Equals(normalized)) {\
rv = false;\
showError(description, #base " != " #form "(" #comparison ")\n");\
}
NS_DEFINE_CID(kUnicodeNormalizerCID, NS_UNICODE_NORMALIZER_CID);
nsIUnicodeNormalizer *normalizer;
#include "NormalizationData.h"
void showError(const char* description, const char* errorText)
{
printf("%s failed: %s", description, errorText);
}
bool TestInvariants(testcaseLine* testLine)
{
nsAutoString c1, c2, c3, c4, c5, normalized;
c1 = nsDependentString((char16_t*)testLine->c1);
c2 = nsDependentString((char16_t*)testLine->c2);
c3 = nsDependentString((char16_t*)testLine->c3);
c4 = nsDependentString((char16_t*)testLine->c4);
c5 = nsDependentString((char16_t*)testLine->c5);
bool rv = true;
/*
1. The following invariants must be true for all conformant implementations
NFC
c2 == NFC(c1) == NFC(c2) == NFC(c3)
*/
DEBUG_TESTCASE(c2);
NORMALIZE_AND_COMPARE(c2, c1, NFC, testLine->description);
NORMALIZE_AND_COMPARE(c2, c2, NFC, testLine->description);
NORMALIZE_AND_COMPARE(c2, c3, NFC, testLine->description);
/*
c4 == NFC(c4) == NFC(c5)
*/
DEBUG_TESTCASE(c4);
NORMALIZE_AND_COMPARE(c4, c4, NFC, testLine->description);
NORMALIZE_AND_COMPARE(c4, c5, NFC, testLine->description);
/*
NFD
c3 == NFD(c1) == NFD(c2) == NFD(c3)
*/
DEBUG_TESTCASE(c3);
NORMALIZE_AND_COMPARE(c3, c1, NFD, testLine->description);
NORMALIZE_AND_COMPARE(c3, c2, NFD, testLine->description);
NORMALIZE_AND_COMPARE(c3, c3, NFD, testLine->description);
/*
c5 == NFD(c4) == NFD(c5)
*/
DEBUG_TESTCASE(c5);
NORMALIZE_AND_COMPARE(c5, c4, NFD, testLine->description);
NORMALIZE_AND_COMPARE(c5, c5, NFD, testLine->description);
/*
NFKC
c4 == NFKC(c1) == NFKC(c2) == NFKC(c3) == NFKC(c4) == NFKC(c5)
*/
DEBUG_TESTCASE(c4);
NORMALIZE_AND_COMPARE(c4, c1, NFKC, testLine->description);
NORMALIZE_AND_COMPARE(c4, c2, NFKC, testLine->description);
NORMALIZE_AND_COMPARE(c4, c3, NFKC, testLine->description);
NORMALIZE_AND_COMPARE(c4, c4, NFKC, testLine->description);
NORMALIZE_AND_COMPARE(c4, c5, NFKC, testLine->description);
/*
NFKD
c5 == NFKD(c1) == NFKD(c2) == NFKD(c3) == NFKD(c4) == NFKD(c5)
*/
DEBUG_TESTCASE(c5);
NORMALIZE_AND_COMPARE(c5, c1, NFKD, testLine->description);
NORMALIZE_AND_COMPARE(c5, c2, NFKD, testLine->description);
NORMALIZE_AND_COMPARE(c5, c3, NFKD, testLine->description);
NORMALIZE_AND_COMPARE(c5, c4, NFKD, testLine->description);
NORMALIZE_AND_COMPARE(c5, c5, NFKD, testLine->description);
return rv;
}
uint32_t UTF32CodepointFromTestcase(testcaseLine* testLine)
{
if (!IS_SURROGATE(testLine->c1[0]))
return testLine->c1[0];
NS_ASSERTION(NS_IS_HIGH_SURROGATE(testLine->c1[0]) &&
NS_IS_LOW_SURROGATE(testLine->c1[1]),
"Test data neither in BMP nor legal surrogate pair");
return SURROGATE_TO_UCS4(testLine->c1[0], testLine->c1[1]);
}
bool TestUnspecifiedCodepoint(uint32_t codepoint)
{
bool rv = true;
char16_t unicharArray[3];
nsAutoString X, normalized;
if (IS_IN_BMP(codepoint)) {
unicharArray[0] = codepoint;
unicharArray[1] = 0;
X = nsDependentString(unicharArray);
}
else {
unicharArray[0] = H_SURROGATE(codepoint);
unicharArray[1] = L_SURROGATE(codepoint);
unicharArray[2] = 0;
X = nsDependentString(unicharArray);
}
/*
2. For every code point X assigned in this version of Unicode that is not specifically
listed in Part 1, the following invariants must be true for all conformant
implementations:
X == NFC(X) == NFD(X) == NFKC(X) == NFKD(X)
*/
static const size_t len = 9;
char description[len];
DEBUG_TESTCASE(X);
snprintf(description, len, "U+%04X", codepoint);
NORMALIZE_AND_COMPARE(X, X, NFC, description);
NORMALIZE_AND_COMPARE(X, X, NFD, description);
NORMALIZE_AND_COMPARE(X, X, NFKC, description);
NORMALIZE_AND_COMPARE(X, X, NFKD, description);
return rv;
}
void TestPart0()
{
printf("Test Part0: Specific cases\n");
uint32_t i = 0;
uint32_t numFailed = 0;
uint32_t numPassed = 0;
while (Part0TestData[i].c1[0] != 0) {
if (TestInvariants(&Part0TestData[i++]))
++numPassed;
else
++numFailed;
}
printf(" %d cases passed, %d failed\n\n", numPassed, numFailed);
EXPECT_EQ(0u, numFailed);
}
void TestPart1()
{
printf("Test Part1: Character by character test\n");
uint32_t i = 0;
uint32_t numFailed = 0;
uint32_t numPassed = 0;
uint32_t codepoint;
uint32_t testDataCodepoint = UTF32CodepointFromTestcase(&Part1TestData[i]);
for (codepoint = 1; codepoint < 0x110000; ++codepoint) {
if (testDataCodepoint == codepoint) {
if (TestInvariants(&Part1TestData[i]))
++numPassed;
else
++numFailed;
testDataCodepoint = UTF32CodepointFromTestcase(&Part1TestData[++i]);
} else {
if (TestUnspecifiedCodepoint(codepoint))
++numPassed;
else
++numFailed;
}
}
printf(" %d cases passed, %d failed\n\n", numPassed, numFailed);
EXPECT_EQ(0u, numFailed);
}
void TestPart2()
{
printf("Test Part2: Canonical Order Test\n");
uint32_t i = 0;
uint32_t numFailed = 0;
uint32_t numPassed = 0;
while (Part2TestData[i].c1[0] != 0) {
if (TestInvariants(&Part2TestData[i++]))
++numPassed;
else
++numFailed;
}
printf(" %d cases passed, %d failed\n\n", numPassed, numFailed);
EXPECT_EQ(0u, numFailed);
}
void TestPart3()
{
printf("Test Part3: PRI #29 Test\n");
uint32_t i = 0;
uint32_t numFailed = 0;
uint32_t numPassed = 0;
while (Part3TestData[i].c1[0] != 0) {
if (TestInvariants(&Part3TestData[i++]))
++numPassed;
else
++numFailed;
}
printf(" %d cases passed, %d failed\n\n", numPassed, numFailed);
EXPECT_EQ(0u, numFailed);
}
TEST(NormalizationTest, Main) {
if (sizeof(wchar_t) != 2) {
printf("This test can only be run where sizeof(wchar_t) == 2\n");
return;
}
if (strlen(versionText) == 0) {
printf("No testcases: to run the tests generate the header file using\n");
printf(" perl genNormalizationData.pl\n");
printf("in intl/unichar/tools and rebuild\n");
return;
}
printf("NormalizationTest: test nsIUnicodeNormalizer. UCD version: %s\n",
versionText);
normalizer = nullptr;
nsresult res;
res = CallGetService(kUnicodeNormalizerCID, &normalizer);
ASSERT_FALSE(NS_FAILED(res)) << "GetService failed";
ASSERT_NE(nullptr, normalizer);
TestPart0();
TestPart1();
TestPart2();
TestPart3();
NS_RELEASE(normalizer);
}

View file

@ -1,93 +0,0 @@
#!/usr/bin/perl
#
# 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/.
open ( TEXTFILE , "< NormalizationTest.txt")
|| die "Cannot find NormalizationTest.txt. The latest version should be available from\n http://www.unicode.org/Public/UNIDATA/NormalizationTest.txt\n";
open ( OUT , "> NormalizationData.h")
#open ( OUT , "> test.txt")
|| die "Cannot create output file NormalizationData.h\n";
$mpl = <<END_OF_MPL;
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
DO NOT EDIT THIS DOCUMENT !!! THIS DOCUMENT IS GENERATED BY
mozilla/intl/unicharutil/tools/genNormalizationData.pl
*/
END_OF_MPL
print OUT $mpl;
# XXX This code assumes that wchar_t is 16-bit unsigned, which is currently
# true on Windows, Linux and Mac (with |g++ -fshort-wchar|).
# To make it work where that assumption doesn't hold, one could generate
# one huge array containing all the strings as 16-bit units (including
# the 0 terminator) and initialize the array of testcaseLine with pointers
# into the huge array.
while(<TEXTFILE>) {
chop;
if (/^# NormalizationTest-(.+)\.txt/) {
print OUT "static char versionText[] = \"$1\";\n";
} elsif (/^\@Part(.)/) {
if ($1 != "0") {
print OUT " {\n";
print OUT " L\"\",\n";
print OUT " L\"\",\n";
print OUT " L\"\",\n";
print OUT " L\"\",\n";
print OUT " L\"\",\n";
print OUT " \"\",\n";
print OUT " },\n";
print OUT "};\n";
}
print OUT "\n";
print OUT "static testcaseLine Part$1TestData[] = \n";
print OUT "{\n";
} else {
unless (/^\#/) {
@cases = split(/;/ , $_);
print OUT " {\n";
for ($case = 0; $case < 5; ++$case) {
$c = $cases[$case];
print OUT " L\"";
@codepoints = split(/ / , $c);
foreach (@codepoints) {
$cp = hex($_);
if ($cp < 0x10000) {
# BMP codepoint
printf OUT "\\x%04X", $cp;
} else {
# non-BMP codepoint, convert to surrogate pair
printf OUT "\\x%04X\\x%04X",
($cp >> 10) + 0xD7C0,
($cp & 0x03FF) | 0xDC00;
}
}
print OUT "\",\n";
}
$description = $cases[10];
$description =~ s/^ \) //;
print OUT " \"$description\"\n";
print OUT " },\n";
}
}
}
print OUT " {\n";
print OUT " L\"\",\n";
print OUT " L\"\",\n";
print OUT " L\"\",\n";
print OUT " L\"\",\n";
print OUT " L\"\",\n";
print OUT " \"\",\n";
print OUT " },\n";
print OUT "};\n";
close (OUT);
close (TEXTFILE);

View file

@ -1,11 +0,0 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
SOURCES += [
'NormalizationTest.cpp',
]
FINAL_LIBRARY = 'xul-gtest'

View file

@ -1,2 +0,0 @@
[DEFAULT]
head =

View file

@ -26,6 +26,8 @@
#include "jstypes.h" #include "jstypes.h"
#include "mozmemory.h"
/* The public JS engine namespace. */ /* The public JS engine namespace. */
namespace JS {} namespace JS {}
@ -364,22 +366,33 @@ struct MOZ_RAII JS_PUBLIC_DATA(AutoEnterOOMUnsafeRegion)
} /* namespace js */ } /* namespace js */
// Malloc allocation.
namespace js {
extern JS_PUBLIC_DATA(arena_id_t) MallocArena;
extern void InitMallocAllocator();
extern void ShutDownMallocAllocator();
} /* namespace js */
static inline void* js_malloc(size_t bytes) static inline void* js_malloc(size_t bytes)
{ {
JS_OOM_POSSIBLY_FAIL(); JS_OOM_POSSIBLY_FAIL();
return malloc(bytes); return moz_arena_malloc(js::MallocArena, bytes);
} }
static inline void* js_calloc(size_t bytes) static inline void* js_calloc(size_t bytes)
{ {
JS_OOM_POSSIBLY_FAIL(); JS_OOM_POSSIBLY_FAIL();
return calloc(bytes, 1); return moz_arena_calloc(js::MallocArena, bytes, 1);
} }
static inline void* js_calloc(size_t nmemb, size_t size) static inline void* js_calloc(size_t nmemb, size_t size)
{ {
JS_OOM_POSSIBLY_FAIL(); JS_OOM_POSSIBLY_FAIL();
return calloc(nmemb, size); return moz_arena_calloc(js::MallocArena, nmemb, size);
} }
static inline void* js_realloc(void* p, size_t bytes) static inline void* js_realloc(void* p, size_t bytes)
@ -390,19 +403,18 @@ static inline void* js_realloc(void* p, size_t bytes)
MOZ_ASSERT(bytes != 0); MOZ_ASSERT(bytes != 0);
JS_OOM_POSSIBLY_FAIL(); JS_OOM_POSSIBLY_FAIL();
return realloc(p, bytes); return moz_arena_realloc(js::MallocArena, p, bytes);
} }
static inline void js_free(void* p) static inline void js_free(void* p)
{ {
// TODO: This should call |moz_arena_free(js::MallocArena, p)| but we
// currently can't enforce that all memory freed here was allocated by
// js_malloc().
free(p); free(p);
} }
static inline char* js_strdup(const char* s) JS_PUBLIC_API(char*) js_strdup(const char* s);
{
JS_OOM_POSSIBLY_FAIL();
return strdup(s);
}
#endif/* JS_USE_CUSTOM_ALLOCATOR */ #endif/* JS_USE_CUSTOM_ALLOCATOR */
#include <new> #include <new>

View file

@ -2272,6 +2272,7 @@ PerformPromiseRace(JSContext *cx, JS::ForOfIterator& iterator, HandleObject C,
MOZ_ASSERT_UNREACHABLE("Shouldn't reach the end of PerformPromiseRace"); MOZ_ASSERT_UNREACHABLE("Shouldn't reach the end of PerformPromiseRace");
} }
// ES2016, Sub-steps of 25.4.4.4 and 25.4.4.5. // ES2016, Sub-steps of 25.4.4.4 and 25.4.4.5.
static MOZ_MUST_USE JSObject* static MOZ_MUST_USE JSObject*
CommonStaticResolveRejectImpl(JSContext* cx, HandleValue thisVal, HandleValue argVal, CommonStaticResolveRejectImpl(JSContext* cx, HandleValue thisVal, HandleValue argVal,
@ -2332,6 +2333,13 @@ CommonStaticResolveRejectImpl(JSContext* cx, HandleValue thisVal, HandleValue ar
return promise; return promise;
} }
MOZ_MUST_USE JSObject*
js::PromiseResolve(JSContext* cx, HandleObject constructor, HandleValue value)
{
RootedValue C(cx, ObjectValue(*constructor));
return CommonStaticResolveRejectImpl(cx, C, value, ResolveMode);
}
/** /**
* ES2016, 25.4.4.4, Promise.reject. * ES2016, 25.4.4.4, Promise.reject.
*/ */
@ -3680,6 +3688,7 @@ CreatePromisePrototype(JSContext* cx, JSProtoKey key)
static const JSFunctionSpec promise_methods[] = { static const JSFunctionSpec promise_methods[] = {
JS_SELF_HOSTED_FN("catch", "Promise_catch", 1, 0), JS_SELF_HOSTED_FN("catch", "Promise_catch", 1, 0),
JS_FN("then", Promise_then, 2, 0), JS_FN("then", Promise_then, 2, 0),
JS_SELF_HOSTED_FN("finally", "Promise_finally", 1, 0),
JS_FS_END JS_FS_END
}; };

View file

@ -124,6 +124,15 @@ OriginalPromiseThen(JSContext* cx, Handle<PromiseObject*> promise,
HandleValue onFulfilled, HandleValue onRejected, HandleValue onFulfilled, HandleValue onRejected,
MutableHandleObject dependent, bool createDependent); MutableHandleObject dependent, bool createDependent);
/**
* PromiseResolve ( C, x )
*
* The abstract operation PromiseResolve, given a constructor and a value,
* returns a new promise resolved with that value.
*/
MOZ_MUST_USE JSObject*
PromiseResolve(JSContext* cx, HandleObject constructor, HandleValue value);
MOZ_MUST_USE PromiseObject* MOZ_MUST_USE PromiseObject*
CreatePromiseObjectForAsync(JSContext* cx, HandleValue generatorVal); CreatePromiseObjectForAsync(JSContext* cx, HandleValue generatorVal);

View file

@ -7,3 +7,71 @@ function Promise_catch(onRejected) {
// Steps 1-2. // Steps 1-2.
return callContentFunction(this.then, this, undefined, onRejected); return callContentFunction(this.then, this, undefined, onRejected);
} }
// Promise.prototype.finally proposal, stage 3.
// Promise.prototype.finally ( onFinally )
function Promise_finally(onFinally) {
// Step 1.
var promise = this;
// Step 2.
if (!IsObject(promise))
ThrowTypeError(JSMSG_INCOMPATIBLE_PROTO, "Promise", "finally", "value");
// Step 3.
var C = SpeciesConstructor(promise, GetBuiltinConstructor("Promise"));
// Step 4.
assert(IsConstructor(C), "SpeciesConstructor returns a constructor function");
// Steps 5-6.
var thenFinally, catchFinally;
if (!IsCallable(onFinally)) {
thenFinally = onFinally;
catchFinally = onFinally;
} else {
// ThenFinally Function.
// The parentheses prevent the infering of a function name.
(thenFinally) = function(value) {
// Steps 1-2 (implicit).
// Step 3.
var result = onFinally();
// Steps 4-5 (implicit).
// Step 6.
var promise = PromiseResolve(C, result);
// Step 7.
// FIXME: spec issue - "be equivalent to a function that" is not a defined spec term.
// https://github.com/tc39/ecma262/issues/933
// Step 8.
return callContentFunction(promise.then, promise, function() { return value; });
};
// CatchFinally Function.
(catchFinally) = function(reason) {
// Steps 1-2 (implicit).
// Step 3.
var result = onFinally();
// Steps 4-5 (implicit).
// Step 6.
var promise = PromiseResolve(C, result);
// Step 7.
// FIXME: spec issue - "be equivalent to a function that" is not a defined spec term.
// https://github.com/tc39/ecma262/issues/933
// Step 8.
return callContentFunction(promise.then, promise, function() { throw reason; });
};
}
// Step 7.
return callContentFunction(promise.then, promise, thenFinally, catchFinally);
}

View file

@ -0,0 +1,37 @@
// |jit-test| --no-sse4;
// This test is a fork of dce-with-rinstructions.js. It tests recover
// instructions which are only executed on pre-SSE4 processors.
setJitCompilerOption("baseline.warmup.trigger", 10);
setJitCompilerOption("ion.warmup.trigger", 20);
const max = 200;
// Check that we are able to remove the operation inside recover test
// functions (denoted by "rop..."), when we inline the first version
// of uceFault, and ensure that the bailout is correct when uceFault
// is replaced (which cause an invalidation bailout)
let uceFault = function (i) {
if (i > 98)
uceFault = function (i) { return true; };
return false;
};
let uceFault_floor_double = eval(
uneval(uceFault)
.replace('uceFault', 'uceFault_floor_double')
);
function rfloor_double(i) {
const x = Math.floor(i + (-1 >>> 0));
if (uceFault_floor_double(i) || uceFault_floor_double(i))
assertEq(x, 99 + (-1 >>> 0)); /* = i + 2 ^ 32 - 1 */
assertRecoveredOnBailout(x, true);
return i;
}
for (let j = 100 - max; j < 100; j++) {
with({}){} // Do not Ion-compile this loop.
const i = j < 2 ? (Math.abs(j) % 50) + 2 : j;
rfloor_double(i);
}

View file

@ -4080,7 +4080,7 @@ AnalyzePoppedThis(JSContext* cx, ObjectGroup* group,
// Add the property to the object, being careful not to update type information. // Add the property to the object, being careful not to update type information.
DebugOnly<unsigned> slotSpan = baseobj->slotSpan(); DebugOnly<unsigned> slotSpan = baseobj->slotSpan();
MOZ_ASSERT(!baseobj->containsPure(id)); MOZ_ASSERT(!baseobj->containsPure(id));
if (!NativeObject::addDataProperty(cx, baseobj, id, baseobj->slotSpan(), JSPROP_ENUMERATE)) if (!NativeObject::addDataProperty(cx, baseobj, id, SHAPE_INVALID_SLOT, JSPROP_ENUMERATE))
return false; return false;
MOZ_ASSERT(baseobj->slotSpan() != slotSpan); MOZ_ASSERT(baseobj->slotSpan() != slotSpan);
MOZ_ASSERT(!baseobj->inDictionaryMode()); MOZ_ASSERT(!baseobj->inDictionaryMode());

View file

@ -858,8 +858,13 @@ IonBuilder::inlineArrayPush(CallInfo& callInfo)
value = valueDouble; value = valueDouble;
} }
if (needsPostBarrier(value)) if (needsPostBarrier(value)) {
current->add(MPostWriteBarrier::New(alloc(), obj, value)); MInstruction* elements = MElements::New(alloc(), obj);
current->add(elements);
MInstruction* initLength = MInitializedLength::New(alloc(), elements);
current->add(initLength);
current->add(MPostWriteElementBarrier::New(alloc(), obj, value, initLength));
}
ins = MArrayPush::New(alloc(), obj, value); ins = MArrayPush::New(alloc(), obj, value);
current->add(ins); current->add(ins);

View file

@ -7017,6 +7017,7 @@ class MMathFunction
switch(function_) { switch(function_) {
case Sin: case Sin:
case Log: case Log:
case Floor:
case Round: case Round:
return true; return true;
default: default:

View file

@ -962,6 +962,9 @@ MMathFunction::writeRecoverData(CompactBufferWriter& writer) const
{ {
MOZ_ASSERT(canRecoverOnBailout()); MOZ_ASSERT(canRecoverOnBailout());
switch (function_) { switch (function_) {
case Floor:
writer.writeUnsigned(uint32_t(RInstruction::Recover_Floor));
return true;
case Round: case Round:
writer.writeUnsigned(uint32_t(RInstruction::Recover_Round)); writer.writeUnsigned(uint32_t(RInstruction::Recover_Round));
return true; return true;

View file

@ -691,9 +691,7 @@ PostWriteElementBarrier(JSRuntime* rt, JSObject* obj, int32_t index)
if (InBounds == IndexInBounds::Yes) { if (InBounds == IndexInBounds::Yes) {
MOZ_ASSERT(uint32_t(index) < obj->as<NativeObject>().getDenseInitializedLength()); MOZ_ASSERT(uint32_t(index) < obj->as<NativeObject>().getDenseInitializedLength());
} else { } else {
if (MOZ_UNLIKELY(!obj->is<NativeObject>()) || if (MOZ_UNLIKELY(!obj->is<NativeObject>() || index < 0)) {
uint32_t(index) >= obj->as<NativeObject>().getDenseInitializedLength())
{
rt->gc.storeBuffer().putWholeCell(obj); rt->gc.storeBuffer().putWholeCell(obj);
return; return;
} }

View file

@ -394,12 +394,13 @@ END_TEST(testHashMapLookupWithDefaultOOM)
BEGIN_TEST(testHashTableMovableEnum) BEGIN_TEST(testHashTableMovableEnum)
{ {
IntSet set;
CHECK(set.init()); CHECK(set.init());
// Exercise returning a hash table Enum object from a function. // Exercise returning a hash table Enum object from a function.
CHECK(set.put(1)); CHECK(set.put(1));
for (auto e = enumerateSet(); !e.empty(); e.popFront()) for (auto e = enumerateSet(set); !e.empty(); e.popFront())
e.removeFront(); e.removeFront();
CHECK(set.count() == 0); CHECK(set.count() == 0);
@ -425,9 +426,7 @@ BEGIN_TEST(testHashTableMovableEnum)
return true; return true;
} }
IntSet set; IntSet::Enum enumerateSet(IntSet& set)
IntSet::Enum enumerateSet()
{ {
return IntSet::Enum(set); return IntSet::Enum(set);
} }

View file

@ -45,6 +45,7 @@ void JSAPITest::uninit()
destroyContext(); destroyContext();
cx = nullptr; cx = nullptr;
} }
msgs.clear();
} }
bool JSAPITest::exec(const char* bytes, const char* filename, int lineno) bool JSAPITest::exec(const char* bytes, const char* filename, int lineno)

View file

@ -33,6 +33,7 @@ class JSAPITestString {
const char* begin() const { return chars.begin(); } const char* begin() const { return chars.begin(); }
const char* end() const { return chars.end(); } const char* end() const { return chars.end(); }
size_t length() const { return chars.length(); } size_t length() const { return chars.length(); }
void clear() { chars.clearAndFree(); }
JSAPITestString& operator +=(const char* s) { JSAPITestString& operator +=(const char* s) {
if (!chars.append(s, strlen(s))) if (!chars.append(s, strlen(s)))

View file

@ -3868,7 +3868,12 @@ js::DuplicateString(JSContext* cx, const char16_t* s)
UniqueChars UniqueChars
js::DuplicateString(const char* s) js::DuplicateString(const char* s)
{ {
return UniqueChars(js_strdup(s)); size_t n = strlen(s) + 1;
UniqueChars ret(js_pod_malloc<char>(n));
if (!ret)
return ret;
PodCopy(ret.get(), s, n);
return ret;
} }
UniqueChars UniqueChars
@ -3899,6 +3904,12 @@ js::DuplicateString(const char16_t* s, size_t n)
return ret; return ret;
} }
JS_PUBLIC_API(char*)
js_strdup(const char* s)
{
return DuplicateString(s).release();
}
template <typename CharT> template <typename CharT>
const CharT* const CharT*
js_strchr_limit(const CharT* s, char16_t c, const CharT* limit) js_strchr_limit(const CharT* s, char16_t c, const CharT* limit)

View file

@ -170,6 +170,20 @@ ResetSimulatedInterrupt()
} // namespace js } // namespace js
#endif // defined(DEBUG) || defined(JS_OOM_BREAKPOINT) #endif // defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
JS_PUBLIC_DATA(arena_id_t) js::MallocArena;
void
js::InitMallocAllocator()
{
MallocArena = moz_create_arena();
}
void
js::ShutDownMallocAllocator()
{
moz_dispose_arena(MallocArena);
}
JS_PUBLIC_API(void) JS_PUBLIC_API(void)
JS_Assert(const char* s, const char* file, int ln) JS_Assert(const char* s, const char* file, int ln)
{ {

View file

@ -3993,6 +3993,8 @@ KillWorkerThreads(JSContext* cx)
thread->join(); thread->join();
} }
workerThreads.clearAndFree();
js_delete(workerThreadsLock); js_delete(workerThreadsLock);
workerThreadsLock = nullptr; workerThreadsLock = nullptr;
@ -4929,12 +4931,12 @@ NestedShell(JSContext* cx, unsigned argc, Value* vp)
JS_ReportErrorNumberASCII(cx, my_GetErrorMessage, nullptr, JSSMSG_NESTED_FAIL); JS_ReportErrorNumberASCII(cx, my_GetErrorMessage, nullptr, JSSMSG_NESTED_FAIL);
return false; return false;
} }
if (!argv.append(strdup(sArgv[0]))) if (!argv.append(js_strdup(sArgv[0])))
return false; return false;
// Propagate selected flags from the current shell // Propagate selected flags from the current shell
for (unsigned i = 0; i < sPropagatedFlags.length(); i++) { for (unsigned i = 0; i < sPropagatedFlags.length(); i++) {
char* cstr = strdup(sPropagatedFlags[i]); char* cstr = js_strdup(sPropagatedFlags[i]);
if (!cstr || !argv.append(cstr)) if (!cstr || !argv.append(cstr))
return false; return false;
} }
@ -8631,6 +8633,7 @@ main(int argc, char** argv, char** envp)
state->shutdown = true; state->shutdown = true;
while (!state->jobs.empty()) while (!state->jobs.empty())
state.wait(/* jobs empty */); state.wait(/* jobs empty */);
state->jobs.clearAndFree();
}); });
sArgc = argc; sArgc = argc;
@ -8652,6 +8655,12 @@ main(int argc, char** argv, char** envp)
SetOutputFile("JS_STDOUT", &rcStdout, &gOutFile); SetOutputFile("JS_STDOUT", &rcStdout, &gOutFile);
SetOutputFile("JS_STDERR", &rcStderr, &gErrFile); SetOutputFile("JS_STDERR", &rcStderr, &gErrFile);
// Start the engine.
if (!JS_Init())
return 1;
auto shutdownEngine = MakeScopeExit([]() { JS_ShutDown(); });
OptionParser op("Usage: {progname} [options] [[script] scriptArgs*]"); OptionParser op("Usage: {progname} [options] [[script] scriptArgs*]");
op.setDescription("The SpiderMonkey shell provides a command line interface to the " op.setDescription("The SpiderMonkey shell provides a command line interface to the "
@ -8875,10 +8884,6 @@ main(int argc, char** argv, char** envp)
if (op.getBoolOption("no-threads")) if (op.getBoolOption("no-threads"))
js::DisableExtraThreads(); js::DisableExtraThreads();
// Start the engine.
if (!JS_Init())
return 1;
if (!InitSharedArrayBufferMailbox()) if (!InitSharedArrayBufferMailbox())
return 1; return 1;
@ -8978,6 +8983,5 @@ main(int argc, char** argv, char** envp)
DestructSharedArrayBufferMailbox(); DestructSharedArrayBufferMailbox();
JS_DestroyContext(cx); JS_DestroyContext(cx);
JS_ShutDown();
return result; return result;
} }

View file

@ -22,7 +22,6 @@ UNSUPPORTED_FEATURES = set([
"tail-call-optimization", "tail-call-optimization",
"BigInt", "BigInt",
"class-fields", "class-fields",
"Promise.prototype.finally",
"optional-catch-binding", "optional-catch-binding",
"regexp-dotall", "regexp-dotall",
"regexp-lookbehind", "regexp-lookbehind",

View file

@ -1,4 +1,5 @@
commit a456b0a390bb0f70b4cb8d38cb5ab0ecb557a851 commit a456b0a390bb0f70b4cb8d38cb5ab0ecb557a851
Merge: db05f2f 297502b
Author: Rick Waldron <waldron.rick@gmail.com> Author: Rick Waldron <waldron.rick@gmail.com>
Date: Mon Oct 23 11:02:44 2017 -0400 Date: Mon Oct 23 11:02:44 2017 -0400

View file

@ -1,4 +1,3 @@
// |reftest| skip -- Promise.prototype.finally is not supported
// Copyright (C) 2017 Jordan Harband. All rights reserved. // Copyright (C) 2017 Jordan Harband. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file. // This code is governed by the BSD license found in the LICENSE file.
/*--- /*---

View file

@ -1,4 +1,3 @@
// |reftest| skip -- Promise.prototype.finally is not supported
// Copyright (C) 2017 Jordan Harband. All rights reserved. // Copyright (C) 2017 Jordan Harband. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file. // This code is governed by the BSD license found in the LICENSE file.
/*--- /*---

View file

@ -1,4 +1,3 @@
// |reftest| skip -- Promise.prototype.finally is not supported
// Copyright (C) 2017 Jordan Harband. All rights reserved. // Copyright (C) 2017 Jordan Harband. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file. // This code is governed by the BSD license found in the LICENSE file.
/*--- /*---

View file

@ -1,4 +1,3 @@
// |reftest| skip -- Promise.prototype.finally is not supported
// Copyright (C) 2017 Jordan Harband. All rights reserved. // Copyright (C) 2017 Jordan Harband. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file. // This code is governed by the BSD license found in the LICENSE file.
/*--- /*---

View file

@ -1,4 +1,3 @@
// |reftest| skip -- Promise.prototype.finally is not supported
// Copyright (C) 2017 Jordan Harband. All rights reserved. // Copyright (C) 2017 Jordan Harband. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file. // This code is governed by the BSD license found in the LICENSE file.
/*--- /*---

View file

@ -1,4 +1,3 @@
// |reftest| skip -- Promise.prototype.finally is not supported
// Copyright (C) 2017 Jordan Harband. All rights reserved. // Copyright (C) 2017 Jordan Harband. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file. // This code is governed by the BSD license found in the LICENSE file.
/*--- /*---

View file

@ -1,4 +1,3 @@
// |reftest| skip -- Promise.prototype.finally is not supported
// Copyright (C) 2017 Jordan Harband. All rights reserved. // Copyright (C) 2017 Jordan Harband. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file. // This code is governed by the BSD license found in the LICENSE file.
/*--- /*---

View file

@ -1,4 +1,3 @@
// |reftest| skip -- Promise.prototype.finally is not supported
// Copyright (C) 2017 Jordan Harband. All rights reserved. // Copyright (C) 2017 Jordan Harband. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file. // This code is governed by the BSD license found in the LICENSE file.
/*--- /*---

View file

@ -1,4 +1,3 @@
// |reftest| skip -- Promise.prototype.finally is not supported
// Copyright (C) 2017 Jordan Harband. All rights reserved. // Copyright (C) 2017 Jordan Harband. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file. // This code is governed by the BSD license found in the LICENSE file.
/*--- /*---

View file

@ -1,4 +1,3 @@
// |reftest| skip -- Promise.prototype.finally is not supported
// Copyright (C) 2017 Jordan Harband. All rights reserved. // Copyright (C) 2017 Jordan Harband. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file. // This code is governed by the BSD license found in the LICENSE file.
/*--- /*---

View file

@ -1,4 +1,3 @@
// |reftest| skip -- Promise.prototype.finally is not supported
// Copyright (C) 2017 Jordan Harband. All rights reserved. // Copyright (C) 2017 Jordan Harband. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file. // This code is governed by the BSD license found in the LICENSE file.
/*--- /*---

View file

@ -1,4 +1,3 @@
// |reftest| skip -- Promise.prototype.finally is not supported
// Copyright (C) 2017 Jordan Harband. All rights reserved. // Copyright (C) 2017 Jordan Harband. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file. // This code is governed by the BSD license found in the LICENSE file.
/*--- /*---

View file

@ -1,4 +1,3 @@
// |reftest| skip -- Promise.prototype.finally is not supported
// Copyright (C) 2017 Jordan Harband. All rights reserved. // Copyright (C) 2017 Jordan Harband. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file. // This code is governed by the BSD license found in the LICENSE file.
/*--- /*---

View file

@ -1,4 +1,3 @@
// |reftest| skip -- Promise.prototype.finally is not supported
// Copyright (C) 2017 Jordan Harband. All rights reserved. // Copyright (C) 2017 Jordan Harband. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file. // This code is governed by the BSD license found in the LICENSE file.
/*--- /*---

View file

@ -1,4 +1,3 @@
// |reftest| skip -- Promise.prototype.finally is not supported
// Copyright (C) 2017 Jordan Harband. All rights reserved. // Copyright (C) 2017 Jordan Harband. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file. // This code is governed by the BSD license found in the LICENSE file.
/*--- /*---

View file

@ -1,4 +1,3 @@
// |reftest| skip -- Promise.prototype.finally is not supported
// Copyright (C) 2017 Jordan Harband. All rights reserved. // Copyright (C) 2017 Jordan Harband. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file. // This code is governed by the BSD license found in the LICENSE file.
/*--- /*---

View file

@ -1,34 +1,3 @@
// file: timer.js
// Copyright (C) 2017 Ecma International. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: |
Used in website/scripts/sth.js
---*/
//setTimeout is not available, hence this script was loaded
if (Promise === undefined && this.setTimeout === undefined) {
if(/\$DONE()/.test(code))
$ERROR("Async test capability is not supported in your test environment");
}
if (Promise !== undefined && this.setTimeout === undefined) {
(function(that) {
that.setTimeout = function(callback, delay) {
var p = Promise.resolve();
var start = Date.now();
var end = start + delay;
function check(){
var timeLeft = end - Date.now();
if(timeLeft > 0)
p.then(check);
else
callback();
}
p.then(check);
}
})(this);
}
// file: fnGlobalObject.js // file: fnGlobalObject.js
// Copyright (C) 2017 Ecma International. All rights reserved. // Copyright (C) 2017 Ecma International. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file. // This code is governed by the BSD license found in the LICENSE file.
@ -570,6 +539,20 @@ var byteConversionValues = {
} }
}; };
// file: nans.js
// Copyright (C) 2017 Ecma International. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: |
A collection of NaN values produced from expressions that have been observed
to create distinct bit representations on various platforms. These provide a
weak basis for assertions regarding the consistent canonicalization of NaN
values in Array buffers.
---*/
var distinctNaNs = [
0/0, Infinity/Infinity, -(0/0), Math.pow(-1, 0.5), -Math.pow(-1, 0.5)
];
// file: testBuiltInObject.js // file: testBuiltInObject.js
// Copyright 2012 Mozilla Corporation. All rights reserved. // Copyright 2012 Mozilla Corporation. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file. // This code is governed by the BSD license found in the LICENSE file.
@ -699,26 +682,35 @@ function testBuiltInObject(obj, isFunction, isConstructor, properties, length) {
return true; return true;
} }
// file: promiseHelper.js // file: timer.js
// Copyright (C) 2017 Ecma International. All rights reserved. // Copyright (C) 2017 Ecma International. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file. // This code is governed by the BSD license found in the LICENSE file.
/*--- /*---
description: | description: |
Check that an array contains a numeric sequence starting at 1 Used in website/scripts/sth.js
and incrementing by 1 for each entry in the array. Used by
Promise tests to assert the order of execution in deep Promise
resolution pipelines.
---*/ ---*/
//setTimeout is not available, hence this script was loaded
if (Promise === undefined && this.setTimeout === undefined) {
if(/\$DONE()/.test(code))
$ERROR("Async test capability is not supported in your test environment");
}
function checkSequence(arr, message) { if (Promise !== undefined && this.setTimeout === undefined) {
arr.forEach(function(e, i) { (function(that) {
if (e !== (i+1)) { that.setTimeout = function(callback, delay) {
$ERROR((message ? message : "Steps in unexpected sequence:") + var p = Promise.resolve();
" '" + arr.join(',') + "'"); var start = Date.now();
var end = start + delay;
function check(){
var timeLeft = end - Date.now();
if(timeLeft > 0)
p.then(check);
else
callback();
}
p.then(check);
} }
}); })(this);
return true;
} }
// file: proxyTrapsHelper.js // file: proxyTrapsHelper.js
@ -851,19 +843,27 @@ description: |
var $MAX_ITERATIONS = 100000; var $MAX_ITERATIONS = 100000;
// file: nans.js // file: promiseHelper.js
// Copyright (C) 2017 Ecma International. All rights reserved. // Copyright (C) 2017 Ecma International. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file. // This code is governed by the BSD license found in the LICENSE file.
/*--- /*---
description: | description: |
A collection of NaN values produced from expressions that have been observed Check that an array contains a numeric sequence starting at 1
to create distinct bit representations on various platforms. These provide a and incrementing by 1 for each entry in the array. Used by
weak basis for assertions regarding the consistent canonicalization of NaN Promise tests to assert the order of execution in deep Promise
values in Array buffers. resolution pipelines.
---*/ ---*/
var distinctNaNs = [
0/0, Infinity/Infinity, -(0/0), Math.pow(-1, 0.5), -Math.pow(-1, 0.5) function checkSequence(arr, message) {
]; arr.forEach(function(e, i) {
if (e !== (i+1)) {
$ERROR((message ? message : "Steps in unexpected sequence:") +
" '" + arr.join(',') + "'");
}
});
return true;
}
// file: detachArrayBuffer.js // file: detachArrayBuffer.js
// Copyright (C) 2017 Ecma International. All rights reserved. // Copyright (C) 2017 Ecma International. All rights reserved.

View file

@ -6,6 +6,7 @@
#include "threading/Mutex.h" #include "threading/Mutex.h"
#include "js/Initialization.h"
#include "js/Utility.h" #include "js/Utility.h"
using namespace js; using namespace js;
@ -44,6 +45,11 @@ js::Mutex::heldMutexStack()
void void
js::Mutex::lock() js::Mutex::lock()
{ {
if (!JS_IsInitialized()) {
MutexImpl::lock();
return;
}
auto& stack = heldMutexStack(); auto& stack = heldMutexStack();
if (!stack.empty()) { if (!stack.empty()) {
const Mutex& prev = *stack.back(); const Mutex& prev = *stack.back();
@ -65,6 +71,11 @@ js::Mutex::lock()
void void
js::Mutex::unlock() js::Mutex::unlock()
{ {
if (!JS_IsInitialized()) {
MutexImpl::unlock();
return;
}
auto& stack = heldMutexStack(); auto& stack = heldMutexStack();
MOZ_ASSERT(stack.back() == this); MOZ_ASSERT(stack.back() == this);
MutexImpl::unlock(); MutexImpl::unlock();

View file

@ -812,7 +812,7 @@ GlobalObject::addIntrinsicValue(JSContext* cx, Handle<GlobalObject*> global,
Rooted<UnownedBaseShape*> base(cx, last->base()->unowned()); Rooted<UnownedBaseShape*> base(cx, last->base()->unowned());
RootedId id(cx, NameToId(name)); RootedId id(cx, NameToId(name));
Rooted<StackShape> child(cx, StackShape(base, id, slot, 0, 0)); Rooted<StackShape> child(cx, StackShape(base, id, slot, 0));
Shape* shape = cx->zone()->propertyTree().getChild(cx, last, child); Shape* shape = cx->zone()->propertyTree().getChild(cx, last, child);
if (!shape) if (!shape)
return false; return false;

View file

@ -100,6 +100,8 @@ JS::detail::InitWithFailureDiagnostic(bool isDebugBuild)
RETURN_IF_FAIL(js::oom::InitThreadType()); RETURN_IF_FAIL(js::oom::InitThreadType());
#endif #endif
js::InitMallocAllocator();
RETURN_IF_FAIL(js::Mutex::Init()); RETURN_IF_FAIL(js::Mutex::Init());
RETURN_IF_FAIL(js::wasm::InitInstanceStaticData()); RETURN_IF_FAIL(js::wasm::InitInstanceStaticData());
@ -170,6 +172,7 @@ JS_ShutDown(void)
js::MemoryProtectionExceptionHandler::uninstall(); js::MemoryProtectionExceptionHandler::uninstall();
js::wasm::ShutDownInstanceStaticData(); js::wasm::ShutDownInstanceStaticData();
js::wasm::ShutDownProcessStaticData();
js::Mutex::ShutDown(); js::Mutex::ShutDown();
@ -199,6 +202,8 @@ JS_ShutDown(void)
js::jit::ReleaseProcessExecutableMemory(); js::jit::ReleaseProcessExecutableMemory();
} }
js::ShutDownMallocAllocator();
libraryInitState = InitState::ShutDown; libraryInitState = InitState::ShutDown;
} }

View file

@ -481,8 +481,6 @@ NativeObject::sparsifyDenseElement(JSContext* cx, HandleNativeObject obj, uint32
removeDenseElementForSparseIndex(cx, obj, index); removeDenseElementForSparseIndex(cx, obj, index);
uint32_t slot = obj->slotSpan();
RootedId id(cx, INT_TO_JSID(index)); RootedId id(cx, INT_TO_JSID(index));
AutoKeepShapeTables keep(cx); AutoKeepShapeTables keep(cx);
@ -496,15 +494,15 @@ NativeObject::sparsifyDenseElement(JSContext* cx, HandleNativeObject obj, uint32
// NOTE: We don't use addDataProperty because we don't want the // NOTE: We don't use addDataProperty because we don't want the
// extensibility check if we're, for example, sparsifying frozen objects.. // extensibility check if we're, for example, sparsifying frozen objects..
if (!addDataPropertyInternal(cx, obj, id, slot, Shape* shape = addDataPropertyInternal(cx, obj, id, SHAPE_INVALID_SLOT,
obj->getElementsHeader()->elementAttributes(), obj->getElementsHeader()->elementAttributes(),
entry, keep)) { entry, keep);
if (!shape) {
obj->setDenseElementUnchecked(index, value); obj->setDenseElementUnchecked(index, value);
return false; return false;
} }
MOZ_ASSERT(slot == obj->slotSpan() - 1); obj->initSlot(shape->slot(), value);
obj->initSlot(slot, value);
return true; return true;
} }

View file

@ -847,9 +847,12 @@ class NativeObject : public ShapedObject
void freeSlot(JSContext* cx, uint32_t slot); void freeSlot(JSContext* cx, uint32_t slot);
private: private:
static MOZ_ALWAYS_INLINE Shape* getChildProperty(JSContext* cx, HandleNativeObject obj, static MOZ_ALWAYS_INLINE Shape* getChildDataProperty(JSContext* cx, HandleNativeObject obj,
HandleShape parent, HandleShape parent,
MutableHandle<StackShape> child); MutableHandle<StackShape> child);
static MOZ_ALWAYS_INLINE Shape* getChildAccessorProperty(JSContext* cx, HandleNativeObject obj,
HandleShape parent,
MutableHandle<StackShape> child);
public: public:
/* Add a property whose id is not yet in this scope. */ /* Add a property whose id is not yet in this scope. */

View file

@ -115,7 +115,7 @@ NextEnvironmentShape(JSContext* cx, HandleAtom name, BindingKind bindKind, uint3
} }
jsid id = NameToId(name->asPropertyName()); jsid id = NameToId(name->asPropertyName());
Rooted<StackShape> child(cx, StackShape(base, id, slot, attrs, 0)); Rooted<StackShape> child(cx, StackShape(base, id, slot, attrs));
return cx->zone()->propertyTree().getChild(cx, shape, child); return cx->zone()->propertyTree().getChild(cx, shape, child);
} }

View file

@ -2093,100 +2093,17 @@ intrinsic_ModuleNamespaceExports(JSContext* cx, unsigned argc, Value* vp)
} }
static bool static bool
intrinsic_CreatePendingPromise(JSContext* cx, unsigned argc, Value* vp) intrinsic_PromiseResolve(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
MOZ_ASSERT(args.length() == 0);
JSObject* promise = PromiseObject::createSkippingExecutor(cx);
if (!promise)
return false;
args.rval().setObject(*promise);
return true;
}
static bool
intrinsic_CreatePromiseResolvedWith(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
MOZ_ASSERT(args.length() == 1);
JSObject* promise = PromiseObject::unforgeableResolve(cx, args[0]);
if (!promise)
return false;
args.rval().setObject(*promise);
return true;
}
static bool
intrinsic_CreatePromiseRejectedWith(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
MOZ_ASSERT(args.length() == 1);
JSObject* promise = PromiseObject::unforgeableReject(cx, args[0]);
if (!promise)
return false;
args.rval().setObject(*promise);
return true;
}
static bool
intrinsic_ResolvePromise(JSContext* cx, unsigned argc, Value* vp)
{ {
CallArgs args = CallArgsFromVp(argc, vp); CallArgs args = CallArgsFromVp(argc, vp);
MOZ_ASSERT(args.length() == 2); MOZ_ASSERT(args.length() == 2);
Rooted<PromiseObject*> promise(cx, &args[0].toObject().as<PromiseObject>());
if (!PromiseObject::resolve(cx, promise, args[1])) RootedObject constructor(cx, &args[0].toObject());
JSObject* promise = js::PromiseResolve(cx, constructor, args[1]);
if (!promise)
return false; return false;
args.rval().setUndefined();
return true;
}
static bool args.rval().setObject(*promise);
intrinsic_RejectPromise(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
MOZ_ASSERT(args.length() == 2);
Rooted<PromiseObject*> promise(cx, &args[0].toObject().as<PromiseObject>());
if (!PromiseObject::reject(cx, promise, args[1]))
return false;
args.rval().setUndefined();
return true;
}
static bool
intrinsic_CallOriginalPromiseThen(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
MOZ_ASSERT(args.length() >= 2);
RootedObject promise(cx, &args[0].toObject());
Value val = args[1];
RootedObject onResolvedObj(cx, val.isUndefined() ? nullptr : val.toObjectOrNull());
val = args.get(2);
RootedObject onRejectedObj(cx, val.isUndefined() ? nullptr : val.toObjectOrNull());
JSObject* resultPromise = JS::CallOriginalPromiseThen(cx, promise, onResolvedObj,
onRejectedObj);
if (!resultPromise)
return false;
args.rval().setObject(*resultPromise);
return true;
}
static bool
intrinsic_AddPromiseReactions(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
MOZ_ASSERT(args.length() >= 2);
RootedObject promise(cx, &args[0].toObject());
Value val = args[1];
RootedObject onResolvedObj(cx, val.isUndefined() ? nullptr : val.toObjectOrNull());
val = args.get(2);
RootedObject onRejectedObj(cx, val.isUndefined() ? nullptr : val.toObjectOrNull());
if (!JS::AddPromiseReactions(cx, promise, onResolvedObj, onRejectedObj))
return false;
args.rval().setUndefined();
return true; return true;
} }
@ -2609,13 +2526,9 @@ static const JSFunctionSpec intrinsic_functions[] = {
JS_FN("AddModuleNamespaceBinding", intrinsic_AddModuleNamespaceBinding, 4, 0), JS_FN("AddModuleNamespaceBinding", intrinsic_AddModuleNamespaceBinding, 4, 0),
JS_FN("ModuleNamespaceExports", intrinsic_ModuleNamespaceExports, 1, 0), JS_FN("ModuleNamespaceExports", intrinsic_ModuleNamespaceExports, 1, 0),
JS_FN("CreatePendingPromise", intrinsic_CreatePendingPromise, 0, 0), JS_FN("IsPromiseObject", intrinsic_IsInstanceOfBuiltin<PromiseObject>, 1, 0),
JS_FN("CreatePromiseResolvedWith", intrinsic_CreatePromiseResolvedWith, 1, 0), JS_FN("CallPromiseMethodIfWrapped", CallNonGenericSelfhostedMethod<Is<PromiseObject>>, 2, 0),
JS_FN("CreatePromiseRejectedWith", intrinsic_CreatePromiseRejectedWith, 1, 0), JS_FN("PromiseResolve", intrinsic_PromiseResolve, 2, 0),
JS_FN("ResolvePromise", intrinsic_ResolvePromise, 2, 0),
JS_FN("RejectPromise", intrinsic_RejectPromise, 2, 0),
JS_FN("AddPromiseReactions", intrinsic_AddPromiseReactions, 3, 0),
JS_FN("CallOriginalPromiseThen", intrinsic_CallOriginalPromiseThen, 3, 0),
JS_FS_END JS_FS_END
}; };

View file

@ -292,56 +292,49 @@ Shape::replaceLastProperty(JSContext* cx, StackBaseShape& base,
* one of lastProperty() or lastProperty()->parent. * one of lastProperty() or lastProperty()->parent.
*/ */
/* static */ MOZ_ALWAYS_INLINE Shape* /* static */ MOZ_ALWAYS_INLINE Shape*
NativeObject::getChildProperty(JSContext* cx, NativeObject::getChildDataProperty(JSContext* cx,
HandleNativeObject obj, HandleShape parent, HandleNativeObject obj, HandleShape parent,
MutableHandle<StackShape> child) MutableHandle<StackShape> child)
{ {
/* MOZ_ASSERT(child.isDataProperty());
* Shared properties have no slot, but slot_ will reflect that of parent.
* Unshared properties allocate a slot here but may lose it due to a if (child.hasMissingSlot()) {
* JS_ClearScope call. uint32_t slot;
*/ if (obj->inDictionaryMode()) {
if (!child.isDataProperty()) { if (!allocDictionarySlot(cx, obj, &slot))
child.setSlot(parent->maybeSlot()); return nullptr;
} else {
if (child.hasMissingSlot()) {
uint32_t slot;
if (obj->inDictionaryMode()) {
if (!allocDictionarySlot(cx, obj, &slot))
return nullptr;
} else {
slot = obj->slotSpan();
MOZ_ASSERT(slot >= JSSLOT_FREE(obj->getClass()));
// Objects with many properties are converted to dictionary
// mode, so we can't overflow SHAPE_MAXIMUM_SLOT here.
MOZ_ASSERT(slot < JSSLOT_FREE(obj->getClass()) + PropertyTree::MAX_HEIGHT);
MOZ_ASSERT(slot < SHAPE_MAXIMUM_SLOT);
}
child.setSlot(slot);
} else { } else {
/* slot = obj->slotSpan();
* Slots can only be allocated out of order on objects in MOZ_ASSERT(slot >= JSSLOT_FREE(obj->getClass()));
* dictionary mode. Otherwise the child's slot must be after the // Objects with many properties are converted to dictionary
* parent's slot (if it has one), because slot number determines // mode, so we can't overflow SHAPE_MAXIMUM_SLOT here.
* slot span for objects with that shape. Usually child slot MOZ_ASSERT(slot < JSSLOT_FREE(obj->getClass()) + PropertyTree::MAX_HEIGHT);
* *immediately* follows parent slot, but there may be a slot gap MOZ_ASSERT(slot < SHAPE_MAXIMUM_SLOT);
* when the object uses some -- but not all -- of its reserved
* slots to store properties.
*/
MOZ_ASSERT(obj->inDictionaryMode() ||
parent->hasMissingSlot() ||
child.slot() == parent->maybeSlot() + 1 ||
(parent->maybeSlot() + 1 < JSSLOT_FREE(obj->getClass()) &&
child.slot() == JSSLOT_FREE(obj->getClass())));
} }
child.setSlot(slot);
} else {
/*
* Slots can only be allocated out of order on objects in
* dictionary mode. Otherwise the child's slot must be after the
* parent's slot (if it has one), because slot number determines
* slot span for objects with that shape. Usually child slot
* *immediately* follows parent slot, but there may be a slot gap
* when the object uses some -- but not all -- of its reserved
* slots to store properties.
*/
MOZ_ASSERT(obj->inDictionaryMode() ||
parent->hasMissingSlot() ||
child.slot() == parent->maybeSlot() + 1 ||
(parent->maybeSlot() + 1 < JSSLOT_FREE(obj->getClass()) &&
child.slot() == JSSLOT_FREE(obj->getClass())));
} }
if (obj->inDictionaryMode()) { if (obj->inDictionaryMode()) {
MOZ_ASSERT(parent == obj->lastProperty()); MOZ_ASSERT(parent == obj->lastProperty());
Shape* shape = child.isAccessorShape() ? Allocate<AccessorShape>(cx) : Allocate<Shape>(cx); Shape* shape = Allocate<Shape>(cx);
if (!shape) if (!shape)
return nullptr; return nullptr;
if (child.isDataProperty() && child.slot() >= obj->lastProperty()->base()->slotSpan()) { if (child.slot() >= obj->lastProperty()->base()->slotSpan()) {
if (!obj->setSlotSpan(cx, child.slot() + 1)) { if (!obj->setSlotSpan(cx, child.slot() + 1)) {
new (shape) Shape(obj->lastProperty()->base()->unowned(), 0); new (shape) Shape(obj->lastProperty()->base()->unowned(), 0);
return nullptr; return nullptr;
@ -363,6 +356,37 @@ NativeObject::getChildProperty(JSContext* cx,
return shape; return shape;
} }
/* static */ MOZ_ALWAYS_INLINE Shape*
NativeObject::getChildAccessorProperty(JSContext* cx,
HandleNativeObject obj, HandleShape parent,
MutableHandle<StackShape> child)
{
MOZ_ASSERT(!child.isDataProperty());
// Accessor properties have no slot, but slot_ will reflect that of parent.
child.setSlot(parent->maybeSlot());
if (obj->inDictionaryMode()) {
MOZ_ASSERT(parent == obj->lastProperty());
Shape* shape = Allocate<AccessorShape>(cx);
if (!shape)
return nullptr;
shape->initDictionaryShape(child, obj->numFixedSlots(), &obj->shape_);
return shape;
}
Shape* shape = cx->zone()->propertyTree().inlinedGetChild(cx, parent, child);
if (!shape)
return nullptr;
MOZ_ASSERT(shape->parent == parent);
MOZ_ASSERT_IF(parent != obj->lastProperty(), parent == obj->lastProperty()->parent);
if (!obj->setLastProperty(cx, shape))
return nullptr;
return shape;
}
/* static */ bool /* static */ bool
js::NativeObject::toDictionaryMode(JSContext* cx, HandleNativeObject obj) js::NativeObject::toDictionaryMode(JSContext* cx, HandleNativeObject obj)
{ {
@ -485,10 +509,8 @@ NativeObject::addAccessorPropertyInternal(JSContext* cx,
AutoCheckShapeConsistency check(obj); AutoCheckShapeConsistency check(obj);
AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter); AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
/* // The code below deals with either converting obj to dictionary mode or
* The code below deals with either converting obj to dictionary mode or // growing an object that's already in dictionary mode.
* growing an object that's already in dictionary mode.
*/
ShapeTable* table = nullptr; ShapeTable* table = nullptr;
if (!obj->inDictionaryMode()) { if (!obj->inDictionaryMode()) {
if (ShouldConvertToDictionary(obj)) { if (ShouldConvertToDictionary(obj)) {
@ -511,7 +533,7 @@ NativeObject::addAccessorPropertyInternal(JSContext* cx,
MOZ_ASSERT(!!table == !!entry); MOZ_ASSERT(!!table == !!entry);
/* Find or create a property tree node labeled by our arguments. */ // Find or create a property tree node labeled by our arguments.
RootedShape shape(cx); RootedShape shape(cx);
{ {
RootedShape last(cx, obj->lastProperty()); RootedShape last(cx, obj->lastProperty());
@ -519,9 +541,9 @@ NativeObject::addAccessorPropertyInternal(JSContext* cx,
if (!nbase) if (!nbase)
return nullptr; return nullptr;
Rooted<StackShape> child(cx, StackShape(nbase, id, SHAPE_INVALID_SLOT, attrs, 0)); Rooted<StackShape> child(cx, StackShape(nbase, id, SHAPE_INVALID_SLOT, attrs));
child.updateGetterSetter(getter, setter); child.updateGetterSetter(getter, setter);
shape = getChildProperty(cx, obj, last, &child); shape = getChildAccessorProperty(cx, obj, last, &child);
if (!shape) if (!shape)
return nullptr; return nullptr;
} }
@ -529,11 +551,11 @@ NativeObject::addAccessorPropertyInternal(JSContext* cx,
MOZ_ASSERT(shape == obj->lastProperty()); MOZ_ASSERT(shape == obj->lastProperty());
if (table) { if (table) {
/* Store the tree node pointer in the table entry for id. */ // Store the tree node pointer in the table entry for id.
entry->setPreservingCollision(shape); entry->setPreservingCollision(shape);
table->incEntryCount(); table->incEntryCount();
/* Pass the table along to the new last property, namely shape. */ // Pass the table along to the new last property, namely shape.
MOZ_ASSERT(shape->parent->maybeTable(keep) == table); MOZ_ASSERT(shape->parent->maybeTable(keep) == table);
shape->parent->handoffTableTo(shape); shape->parent->handoffTableTo(shape);
} }
@ -549,17 +571,15 @@ NativeObject::addDataPropertyInternal(JSContext* cx,
{ {
AutoCheckShapeConsistency check(obj); AutoCheckShapeConsistency check(obj);
/* // The slot, if any, must be a reserved slot.
* The code below deals with either converting obj to dictionary mode or MOZ_ASSERT(slot == SHAPE_INVALID_SLOT ||
* growing an object that's already in dictionary mode. slot < JSCLASS_RESERVED_SLOTS(obj->getClass()));
*/
// The code below deals with either converting obj to dictionary mode or
// growing an object that's already in dictionary mode.
ShapeTable* table = nullptr; ShapeTable* table = nullptr;
if (!obj->inDictionaryMode()) { if (!obj->inDictionaryMode()) {
bool stableSlot = if (ShouldConvertToDictionary(obj)) {
(slot == SHAPE_INVALID_SLOT) ||
obj->lastProperty()->hasMissingSlot() ||
(slot == obj->lastProperty()->maybeSlot() + 1);
if (!stableSlot || ShouldConvertToDictionary(obj)) {
if (!toDictionaryMode(cx, obj)) if (!toDictionaryMode(cx, obj))
return nullptr; return nullptr;
table = obj->lastProperty()->maybeTable(keep); table = obj->lastProperty()->maybeTable(keep);
@ -579,7 +599,7 @@ NativeObject::addDataPropertyInternal(JSContext* cx,
MOZ_ASSERT(!!table == !!entry); MOZ_ASSERT(!!table == !!entry);
/* Find or create a property tree node labeled by our arguments. */ // Find or create a property tree node labeled by our arguments.
RootedShape shape(cx); RootedShape shape(cx);
{ {
RootedShape last(cx, obj->lastProperty()); RootedShape last(cx, obj->lastProperty());
@ -587,8 +607,8 @@ NativeObject::addDataPropertyInternal(JSContext* cx,
if (!nbase) if (!nbase)
return nullptr; return nullptr;
Rooted<StackShape> child(cx, StackShape(nbase, id, slot, attrs, 0)); Rooted<StackShape> child(cx, StackShape(nbase, id, slot, attrs));
shape = getChildProperty(cx, obj, last, &child); shape = getChildDataProperty(cx, obj, last, &child);
if (!shape) if (!shape)
return nullptr; return nullptr;
} }
@ -596,11 +616,11 @@ NativeObject::addDataPropertyInternal(JSContext* cx,
MOZ_ASSERT(shape == obj->lastProperty()); MOZ_ASSERT(shape == obj->lastProperty());
if (table) { if (table) {
/* Store the tree node pointer in the table entry for id. */ // Store the tree node pointer in the table entry for id.
entry->setPreservingCollision(shape); entry->setPreservingCollision(shape);
table->incEntryCount(); table->incEntryCount();
/* Pass the table along to the new last property, namely shape. */ // Pass the table along to the new last property, namely shape.
MOZ_ASSERT(shape->parent->maybeTable(keep) == table); MOZ_ASSERT(shape->parent->maybeTable(keep) == table);
shape->parent->handoffTableTo(shape); shape->parent->handoffTableTo(shape);
} }
@ -653,7 +673,7 @@ NativeObject::addEnumerableDataProperty(JSContext* cx, HandleNativeObject obj, H
if (!allocDictionarySlot(cx, obj, &slot)) if (!allocDictionarySlot(cx, obj, &slot))
return nullptr; return nullptr;
Rooted<StackShape> child(cx, StackShape(nbase, id, slot, JSPROP_ENUMERATE, 0)); Rooted<StackShape> child(cx, StackShape(nbase, id, slot, JSPROP_ENUMERATE));
MOZ_ASSERT(last == obj->lastProperty()); MOZ_ASSERT(last == obj->lastProperty());
shape = Allocate<Shape>(cx); shape = Allocate<Shape>(cx);
@ -674,7 +694,7 @@ NativeObject::addEnumerableDataProperty(JSContext* cx, HandleNativeObject obj, H
MOZ_ASSERT(slot < JSSLOT_FREE(obj->getClass()) + PropertyTree::MAX_HEIGHT); MOZ_ASSERT(slot < JSSLOT_FREE(obj->getClass()) + PropertyTree::MAX_HEIGHT);
MOZ_ASSERT(slot < SHAPE_MAXIMUM_SLOT); MOZ_ASSERT(slot < SHAPE_MAXIMUM_SLOT);
Rooted<StackShape> child(cx, StackShape(nbase, id, slot, JSPROP_ENUMERATE, 0)); Rooted<StackShape> child(cx, StackShape(nbase, id, slot, JSPROP_ENUMERATE));
shape = cx->zone()->propertyTree().inlinedGetChild(cx, last, child); shape = cx->zone()->propertyTree().inlinedGetChild(cx, last, child);
if (!shape) if (!shape)
return nullptr; return nullptr;
@ -732,7 +752,7 @@ js::ReshapeForAllocKind(JSContext* cx, Shape* shape, TaggedProto proto,
if (!nbase) if (!nbase)
return nullptr; return nullptr;
Rooted<StackShape> child(cx, StackShape(nbase, id, i, JSPROP_ENUMERATE, 0)); Rooted<StackShape> child(cx, StackShape(nbase, id, i, JSPROP_ENUMERATE));
newShape = cx->zone()->propertyTree().getChild(cx, newShape, child); newShape = cx->zone()->propertyTree().getChild(cx, newShape, child);
if (!newShape) if (!newShape)
return nullptr; return nullptr;
@ -783,16 +803,7 @@ NativeObject::putDataProperty(JSContext* cx, HandleNativeObject obj, HandleId id
AutoCheckShapeConsistency check(obj); AutoCheckShapeConsistency check(obj);
AssertValidArrayIndex(obj, id); AssertValidArrayIndex(obj, id);
/* // Search for id in order to claim its entry if table has been allocated.
* Search for id in order to claim its entry if table has been allocated.
*
* Note that we can only try to claim an entry in a table that is thread
* local. An object may be thread local *without* its shape being thread
* local. The only thread local objects that *also* have thread local
* shapes are dictionaries that were allocated/converted thread
* locally. Only for those objects we can try to claim an entry in its
* shape table.
*/
AutoKeepShapeTables keep(cx); AutoKeepShapeTables keep(cx);
ShapeTable::Entry* entry; ShapeTable::Entry* entry;
RootedShape shape(cx); RootedShape shape(cx);
@ -803,25 +814,19 @@ NativeObject::putDataProperty(JSContext* cx, HandleNativeObject obj, HandleId id
} }
if (!shape) { if (!shape) {
/* MOZ_ASSERT(obj->nonProxyIsExtensible(),
* You can't add properties to a non-extensible object, but you can change "Can't add new property to non-extensible object");
* attributes of properties in such objects.
*/
MOZ_ASSERT(obj->nonProxyIsExtensible());
return addDataPropertyInternal(cx, obj, id, SHAPE_INVALID_SLOT, attrs, entry, keep); return addDataPropertyInternal(cx, obj, id, SHAPE_INVALID_SLOT, attrs, entry, keep);
} }
/* Property exists: search must have returned a valid entry. */ // Property exists: search must have returned a valid entry.
MOZ_ASSERT_IF(entry, !entry->isRemoved()); MOZ_ASSERT_IF(entry, !entry->isRemoved());
AssertCanChangeAttrs(shape, attrs); AssertCanChangeAttrs(shape, attrs);
/* // If the caller wants to allocate a slot, but doesn't care which slot,
* If the caller wants to allocate a slot, but doesn't care which slot, // copy the existing shape's slot into slot so we can match shape, if all
* copy the existing shape's slot into slot so we can match shape, if all // other members match.
* other members match.
*/
bool hadSlot = shape->isDataProperty(); bool hadSlot = shape->isDataProperty();
uint32_t oldSlot = shape->maybeSlot(); uint32_t oldSlot = shape->maybeSlot();
uint32_t slot = hadSlot ? oldSlot : SHAPE_INVALID_SLOT; uint32_t slot = hadSlot ? oldSlot : SHAPE_INVALID_SLOT;
@ -834,18 +839,14 @@ NativeObject::putDataProperty(JSContext* cx, HandleNativeObject obj, HandleId id
return nullptr; return nullptr;
} }
/* // Now that we've possibly preserved slot, check whether all members match.
* Now that we've possibly preserved slot, check whether all members match. // If so, this is a redundant "put" and we can return without more work.
* If so, this is a redundant "put" and we can return without more work. if (shape->matchesParamsAfterId(nbase, slot, attrs, nullptr, nullptr))
*/
if (shape->matchesParamsAfterId(nbase, slot, attrs, 0, nullptr, nullptr))
return shape; return shape;
/* // Overwriting a non-last property requires switching to dictionary mode.
* Overwriting a non-last property requires switching to dictionary mode. // The shape tree is shared immutable, and we can't removeProperty and then
* The shape tree is shared immutable, and we can't removeProperty and then // addDataPropertyInternal because a failure under add would lose data.
* addPropertyInternal because a failure under add would lose data.
*/
if (shape != obj->lastProperty() && !obj->inDictionaryMode()) { if (shape != obj->lastProperty() && !obj->inDictionaryMode()) {
if (!toDictionaryMode(cx, obj)) if (!toDictionaryMode(cx, obj))
return nullptr; return nullptr;
@ -858,12 +859,10 @@ NativeObject::putDataProperty(JSContext* cx, HandleNativeObject obj, HandleId id
MOZ_ASSERT_IF(shape->isDataProperty(), shape->slot() == slot); MOZ_ASSERT_IF(shape->isDataProperty(), shape->slot() == slot);
if (obj->inDictionaryMode()) { if (obj->inDictionaryMode()) {
/* // Updating some property in a dictionary-mode object. Create a new
* Updating some property in a dictionary-mode object. Create a new // shape for the existing property, and also generate a new shape for
* shape for the existing property, and also generate a new shape for // the last property of the dictionary (unless the modified property
* the last property of the dictionary (unless the modified property // is also the last property).
* is also the last property).
*/
bool updateLast = (shape == obj->lastProperty()); bool updateLast = (shape == obj->lastProperty());
shape = NativeObject::replaceWithNewEquivalentShape(cx, obj, shape, nullptr, shape = NativeObject::replaceWithNewEquivalentShape(cx, obj, shape, nullptr,
/* accessorShape = */ false); /* accessorShape = */ false);
@ -872,10 +871,6 @@ NativeObject::putDataProperty(JSContext* cx, HandleNativeObject obj, HandleId id
if (!updateLast && !NativeObject::generateOwnShape(cx, obj)) if (!updateLast && !NativeObject::generateOwnShape(cx, obj))
return nullptr; return nullptr;
/*
* FIXME bug 593129 -- slot allocation and NativeObject *this must move
* out of here!
*/
if (slot == SHAPE_INVALID_SLOT) { if (slot == SHAPE_INVALID_SLOT) {
if (!allocDictionarySlot(cx, obj, &slot)) if (!allocDictionarySlot(cx, obj, &slot))
return nullptr; return nullptr;
@ -890,10 +885,8 @@ NativeObject::putDataProperty(JSContext* cx, HandleNativeObject obj, HandleId id
shape->attrs = uint8_t(attrs); shape->attrs = uint8_t(attrs);
shape->flags = Shape::IN_DICTIONARY; shape->flags = Shape::IN_DICTIONARY;
} else { } else {
/* // Updating the last property in a non-dictionary-mode object. Find an
* Updating the last property in a non-dictionary-mode object. Find an // alternate shared child of the last property's previous shape.
* alternate shared child of the last property's previous shape.
*/
StackBaseShape base(obj->lastProperty()->base()); StackBaseShape base(obj->lastProperty()->base());
UnownedBaseShape* nbase = BaseShape::getUnowned(cx, base); UnownedBaseShape* nbase = BaseShape::getUnowned(cx, base);
@ -902,10 +895,10 @@ NativeObject::putDataProperty(JSContext* cx, HandleNativeObject obj, HandleId id
MOZ_ASSERT(shape == obj->lastProperty()); MOZ_ASSERT(shape == obj->lastProperty());
/* Find or create a property tree node labeled by our arguments. */ // Find or create a property tree node labeled by our arguments.
Rooted<StackShape> child(cx, StackShape(nbase, id, slot, attrs, 0)); Rooted<StackShape> child(cx, StackShape(nbase, id, slot, attrs));
RootedShape parent(cx, shape->parent); RootedShape parent(cx, shape->parent);
shape = getChildProperty(cx, obj, parent, &child); shape = getChildDataProperty(cx, obj, parent, &child);
if (!shape) if (!shape)
return nullptr; return nullptr;
} }
@ -925,16 +918,7 @@ NativeObject::putAccessorProperty(JSContext* cx, HandleNativeObject obj, HandleI
AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter); AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
/* // Search for id in order to claim its entry if table has been allocated.
* Search for id in order to claim its entry if table has been allocated.
*
* Note that we can only try to claim an entry in a table that is thread
* local. An object may be thread local *without* its shape being thread
* local. The only thread local objects that *also* have thread local
* shapes are dictionaries that were allocated/converted thread
* locally. Only for those objects we can try to claim an entry in its
* shape table.
*/
AutoKeepShapeTables keep(cx); AutoKeepShapeTables keep(cx);
ShapeTable::Entry* entry; ShapeTable::Entry* entry;
RootedShape shape(cx); RootedShape shape(cx);
@ -945,16 +929,12 @@ NativeObject::putAccessorProperty(JSContext* cx, HandleNativeObject obj, HandleI
} }
if (!shape) { if (!shape) {
/* MOZ_ASSERT(obj->nonProxyIsExtensible(),
* You can't add properties to a non-extensible object, but you can change "Can't add new property to non-extensible object");
* attributes of properties in such objects.
*/
MOZ_ASSERT(obj->nonProxyIsExtensible());
return addAccessorPropertyInternal(cx, obj, id, getter, setter, attrs, entry, keep); return addAccessorPropertyInternal(cx, obj, id, getter, setter, attrs, entry, keep);
} }
/* Property exists: search must have returned a valid entry. */ // Property exists: search must have returned a valid entry.
MOZ_ASSERT_IF(entry, !entry->isRemoved()); MOZ_ASSERT_IF(entry, !entry->isRemoved());
AssertCanChangeAttrs(shape, attrs); AssertCanChangeAttrs(shape, attrs);
@ -970,18 +950,14 @@ NativeObject::putAccessorProperty(JSContext* cx, HandleNativeObject obj, HandleI
return nullptr; return nullptr;
} }
/* // Check whether all members match. If so, this is a redundant "put" and we can
* Now that we've possibly preserved slot, check whether all members match. // return without more work.
* If so, this is a redundant "put" and we can return without more work. if (shape->matchesParamsAfterId(nbase, SHAPE_INVALID_SLOT, attrs, getter, setter))
*/
if (shape->matchesParamsAfterId(nbase, SHAPE_INVALID_SLOT, attrs, 0, getter, setter))
return shape; return shape;
/* // Overwriting a non-last property requires switching to dictionary mode.
* Overwriting a non-last property requires switching to dictionary mode. // The shape tree is shared immutable, and we can't removeProperty and then
* The shape tree is shared immutable, and we can't removeProperty and then // addAccessorPropertyInternal because a failure under add would lose data.
* addPropertyInternal because a failure under add would lose data.
*/
if (shape != obj->lastProperty() && !obj->inDictionaryMode()) { if (shape != obj->lastProperty() && !obj->inDictionaryMode()) {
if (!toDictionaryMode(cx, obj)) if (!toDictionaryMode(cx, obj))
return nullptr; return nullptr;
@ -992,12 +968,10 @@ NativeObject::putAccessorProperty(JSContext* cx, HandleNativeObject obj, HandleI
} }
if (obj->inDictionaryMode()) { if (obj->inDictionaryMode()) {
/* // Updating some property in a dictionary-mode object. Create a new
* Updating some property in a dictionary-mode object. Create a new // shape for the existing property, and also generate a new shape for
* shape for the existing property, and also generate a new shape for // the last property of the dictionary (unless the modified property
* the last property of the dictionary (unless the modified property // is also the last property).
* is also the last property).
*/
bool updateLast = (shape == obj->lastProperty()); bool updateLast = (shape == obj->lastProperty());
shape = NativeObject::replaceWithNewEquivalentShape(cx, obj, shape, nullptr, shape = NativeObject::replaceWithNewEquivalentShape(cx, obj, shape, nullptr,
/* accessorShape = */ true); /* accessorShape = */ true);
@ -1020,10 +994,8 @@ NativeObject::putAccessorProperty(JSContext* cx, HandleNativeObject obj, HandleI
accShape.rawSetter = setter; accShape.rawSetter = setter;
GetterSetterWriteBarrierPost(&accShape); GetterSetterWriteBarrierPost(&accShape);
} else { } else {
/* // Updating the last property in a non-dictionary-mode object. Find an
* Updating the last property in a non-dictionary-mode object. Find an // alternate shared child of the last property's previous shape.
* alternate shared child of the last property's previous shape.
*/
StackBaseShape base(obj->lastProperty()->base()); StackBaseShape base(obj->lastProperty()->base());
UnownedBaseShape* nbase = BaseShape::getUnowned(cx, base); UnownedBaseShape* nbase = BaseShape::getUnowned(cx, base);
@ -1032,21 +1004,19 @@ NativeObject::putAccessorProperty(JSContext* cx, HandleNativeObject obj, HandleI
MOZ_ASSERT(shape == obj->lastProperty()); MOZ_ASSERT(shape == obj->lastProperty());
/* Find or create a property tree node labeled by our arguments. */ // Find or create a property tree node labeled by our arguments.
Rooted<StackShape> child(cx, StackShape(nbase, id, SHAPE_INVALID_SLOT, attrs, 0)); Rooted<StackShape> child(cx, StackShape(nbase, id, SHAPE_INVALID_SLOT, attrs));
child.updateGetterSetter(getter, setter); child.updateGetterSetter(getter, setter);
RootedShape parent(cx, shape->parent); RootedShape parent(cx, shape->parent);
shape = getChildProperty(cx, obj, parent, &child); shape = getChildAccessorProperty(cx, obj, parent, &child);
if (!shape) if (!shape)
return nullptr; return nullptr;
} }
/* // Can't fail now, so free the previous incarnation's slot. But we do not
* Can't fail now, so free the previous incarnation's slot. But we do not // need to free oldSlot (and must not, as trying to will botch an assertion
* need to free oldSlot (and must not, as trying to will botch an assertion // in NativeObject::freeSlot) if the new last property (shape here) has a
* in JSObject::freeSlot) if the new last property (shape here) has a // slotSpan that does not cover it.
* slotSpan that does not cover it.
*/
if (hadSlot && oldSlot < obj->slotSpan()) if (hadSlot && oldSlot < obj->slotSpan())
obj->freeSlot(cx, oldSlot); obj->freeSlot(cx, oldSlot);
@ -1858,8 +1828,7 @@ Shape::fixupShapeTreeAfterMovingGC()
StackShape lookup(unowned, StackShape lookup(unowned,
const_cast<Shape*>(key)->propidRef(), const_cast<Shape*>(key)->propidRef(),
key->slotInfo & Shape::SLOT_MASK, key->slotInfo & Shape::SLOT_MASK,
key->attrs, key->attrs);
key->flags);
lookup.updateGetterSetter(getter, setter); lookup.updateGetterSetter(getter, setter);
e.rekeyFront(lookup, key); e.rekeyFront(lookup, key);
} }

View file

@ -994,13 +994,13 @@ class Shape : public gc::TenuredCell
bool matches(const Shape* other) const { bool matches(const Shape* other) const {
return propid_.get() == other->propid_.get() && return propid_.get() == other->propid_.get() &&
matchesParamsAfterId(other->base(), other->maybeSlot(), other->attrs, other->flags, matchesParamsAfterId(other->base(), other->maybeSlot(), other->attrs,
other->getter(), other->setter()); other->getter(), other->setter());
} }
inline bool matches(const StackShape& other) const; inline bool matches(const StackShape& other) const;
bool matchesParamsAfterId(BaseShape* base, uint32_t aslot, unsigned aattrs, unsigned aflags, bool matchesParamsAfterId(BaseShape* base, uint32_t aslot, unsigned aattrs,
GetterOp rawGetter, SetterOp rawSetter) const GetterOp rawGetter, SetterOp rawSetter) const
{ {
return base->unowned() == this->base()->unowned() && return base->unowned() == this->base()->unowned() &&
@ -1443,14 +1443,14 @@ struct StackShape
uint8_t flags; uint8_t flags;
explicit StackShape(UnownedBaseShape* base, jsid propid, uint32_t slot, explicit StackShape(UnownedBaseShape* base, jsid propid, uint32_t slot,
unsigned attrs, unsigned flags) unsigned attrs)
: base(base), : base(base),
propid(propid), propid(propid),
rawGetter(nullptr), rawGetter(nullptr),
rawSetter(nullptr), rawSetter(nullptr),
slot_(slot), slot_(slot),
attrs(uint8_t(attrs)), attrs(uint8_t(attrs)),
flags(uint8_t(flags)) flags(0)
{ {
MOZ_ASSERT(base); MOZ_ASSERT(base);
MOZ_ASSERT(!JSID_IS_VOID(propid)); MOZ_ASSERT(!JSID_IS_VOID(propid));
@ -1623,7 +1623,7 @@ inline bool
Shape::matches(const StackShape& other) const Shape::matches(const StackShape& other) const
{ {
return propid_.get() == other.propid && return propid_.get() == other.propid &&
matchesParamsAfterId(other.base, other.slot_, other.attrs, other.flags, matchesParamsAfterId(other.base, other.slot_, other.attrs,
other.rawGetter, other.rawSetter); other.rawGetter, other.rawSetter);
} }

View file

@ -398,8 +398,10 @@ MakeReplacementTemplateObject(JSContext* cx, HandleObjectGroup group, const Unbo
for (size_t i = 0; i < layout.properties().length(); i++) { for (size_t i = 0; i < layout.properties().length(); i++) {
const UnboxedLayout::Property& property = layout.properties()[i]; const UnboxedLayout::Property& property = layout.properties()[i];
id = NameToId(property.name); id = NameToId(property.name);
if (!NativeObject::addDataProperty(cx, obj, id, i, JSPROP_ENUMERATE)) Shape* shape = NativeObject::addDataProperty(cx, obj, id, SHAPE_INVALID_SLOT, JSPROP_ENUMERATE);
if (!shape)
return nullptr; return nullptr;
MOZ_ASSERT(shape->slot() == i);
MOZ_ASSERT(obj->slotSpan() == i + 1); MOZ_ASSERT(obj->slotSpan() == i + 1);
MOZ_ASSERT(!obj->inDictionaryMode()); MOZ_ASSERT(!obj->inDictionaryMode());
} }
@ -485,7 +487,7 @@ UnboxedLayout::makeNativeGroup(JSContext* cx, ObjectGroup* group)
const UnboxedLayout::Property& property = layout.properties()[i]; const UnboxedLayout::Property& property = layout.properties()[i];
Rooted<StackShape> child(cx, StackShape(shape->base()->unowned(), NameToId(property.name), Rooted<StackShape> child(cx, StackShape(shape->base()->unowned(), NameToId(property.name),
i, JSPROP_ENUMERATE, 0)); i, JSPROP_ENUMERATE));
shape = cx->zone()->propertyTree().getChild(cx, shape, child); shape = cx->zone()->propertyTree().getChild(cx, shape, child);
if (!shape) if (!shape)
return false; return false;

View file

@ -126,6 +126,13 @@ class ProcessCodeSegmentMap
MOZ_ASSERT(segments2_.empty()); MOZ_ASSERT(segments2_.empty());
} }
void freeAll() {
MOZ_ASSERT(segments1_.empty());
MOZ_ASSERT(segments2_.empty());
segments1_.clearAndFree();
segments2_.clearAndFree();
}
bool insert(const CodeSegment* cs) { bool insert(const CodeSegment* cs) {
LockGuard<Mutex> lock(mutatorsMutex_); LockGuard<Mutex> lock(mutatorsMutex_);
@ -230,3 +237,9 @@ wasm::LookupCode(const void* pc)
const CodeSegment* found = LookupCodeSegment(pc); const CodeSegment* found = LookupCodeSegment(pc);
return found ? found->code() : nullptr; return found ? found->code() : nullptr;
} }
void
wasm::ShutDownProcessStaticData()
{
processCodeSegmentMap.freeAll();
}

View file

@ -51,6 +51,9 @@ RegisterCodeSegment(const CodeSegment* cs);
void void
UnregisterCodeSegment(const CodeSegment* cs); UnregisterCodeSegment(const CodeSegment* cs);
void
ShutDownProcessStaticData();
} // namespace wasm } // namespace wasm
} // namespace js } // namespace js

View file

@ -249,7 +249,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=933681
"$`", "$'", Symbol.species]) "$`", "$'", Symbol.species])
gPrototypeProperties['Promise'] = gPrototypeProperties['Promise'] =
["constructor", "catch", "then", Symbol.toStringTag]; ["constructor", "catch", "then", "finally", Symbol.toStringTag];
gConstructorProperties['Promise'] = gConstructorProperties['Promise'] =
constructorProps(["resolve", "reject", "all", "race", Symbol.species]); constructorProps(["resolve", "reject", "all", "race", Symbol.species]);

View file

@ -742,6 +742,7 @@ nsIPresShell::nsIPresShell()
, mAutoWeakFrames(nullptr) , mAutoWeakFrames(nullptr)
, mCanvasBackgroundColor(NS_RGBA(0,0,0,0)) , mCanvasBackgroundColor(NS_RGBA(0,0,0,0))
, mSelectionFlags(0) , mSelectionFlags(0)
, mChangeNestCount(0)
, mRenderFlags(0) , mRenderFlags(0)
, mDidInitialize(false) , mDidInitialize(false)
, mIsDestroying(false) , mIsDestroying(false)
@ -787,7 +788,6 @@ PresShell::PresShell()
, mLastReflowStart(0.0) , mLastReflowStart(0.0)
, mLastAnchorScrollPositionY(0) , mLastAnchorScrollPositionY(0)
, mAPZFocusSequenceNumber(0) , mAPZFocusSequenceNumber(0)
, mChangeNestCount(0)
, mDocumentLoading(false) , mDocumentLoading(false)
, mIgnoreFrameDestruction(false) , mIgnoreFrameDestruction(false)
, mHaveShutDown(false) , mHaveShutDown(false)
@ -3075,10 +3075,9 @@ PresShell::GoToAnchor(const nsAString& aAnchorName, bool aScroll,
// Search for an anchor element with a matching "name" attribute // Search for an anchor element with a matching "name" attribute
if (!content && htmlDoc) { if (!content && htmlDoc) {
nsCOMPtr<nsIDOMNodeList> list;
// Find a matching list of named nodes // Find a matching list of named nodes
rv = htmlDoc->GetElementsByName(aAnchorName, getter_AddRefs(list)); nsCOMPtr<nsIDOMNodeList> list = mDocument->GetElementsByName(aAnchorName);
if (NS_SUCCEEDED(rv) && list) { if (list) {
uint32_t i; uint32_t i;
// Loop through the named nodes looking for the first anchor // Loop through the named nodes looking for the first anchor
for (i = 0; true; i++) { for (i = 0; true; i++) {
@ -4038,25 +4037,23 @@ PresShell::HandlePostedReflowCallbacks(bool aInterruptible)
} }
bool bool
PresShell::IsSafeToFlush() const nsIPresShell::IsSafeToFlush() const
{ {
// Not safe if we are reflowing or in the middle of frame construction // Not safe if we are reflowing or in the middle of frame construction
bool isSafeToFlush = !mIsReflowing && if (mIsReflowing || mChangeNestCount) {
!mChangeNestCount; return false;
}
if (isSafeToFlush) {
// Not safe if we are painting // Not safe if we are painting
nsViewManager* viewManager = GetViewManager(); if (nsViewManager* viewManager = GetViewManager()) {
if (viewManager) { bool isPainting = false;
bool isPainting = false; viewManager->IsPainting(isPainting);
viewManager->IsPainting(isPainting); if (isPainting) {
if (isPainting) { return false;
isSafeToFlush = false;
}
} }
} }
return isSafeToFlush; return true;
} }

View file

@ -128,7 +128,6 @@ public:
eInferFromBitToAdd) override; eInferFromBitToAdd) override;
virtual void FrameNeedsToContinueReflow(nsIFrame *aFrame) override; virtual void FrameNeedsToContinueReflow(nsIFrame *aFrame) override;
virtual void CancelAllPendingReflows() override; virtual void CancelAllPendingReflows() override;
virtual bool IsSafeToFlush() const override;
virtual void DoFlushPendingNotifications(mozilla::FlushType aType) override; virtual void DoFlushPendingNotifications(mozilla::FlushType aType) override;
virtual void DoFlushPendingNotifications(mozilla::ChangesToFlush aType) override; virtual void DoFlushPendingNotifications(mozilla::ChangesToFlush aType) override;
virtual void DestroyFramesForAndRestyle(mozilla::dom::Element* aElement) override; virtual void DestroyFramesForAndRestyle(mozilla::dom::Element* aElement) override;
@ -857,11 +856,6 @@ protected:
// The focus information needed for async keyboard scrolling // The focus information needed for async keyboard scrolling
FocusTarget mAPZFocusTarget; FocusTarget mAPZFocusTarget;
// This is used to protect ourselves from triggering reflow while in the
// middle of frame construction and the like... it really shouldn't be
// needed, one hopes, but it is for now.
uint16_t mChangeNestCount;
bool mDocumentLoading : 1; bool mDocumentLoading : 1;
bool mIgnoreFrameDestruction : 1; bool mIgnoreFrameDestruction : 1;
bool mHaveShutDown : 1; bool mHaveShutDown : 1;

View file

@ -541,11 +541,9 @@ public:
virtual void RecordShadowStyleChange(mozilla::dom::ShadowRoot* aShadowRoot) = 0; virtual void RecordShadowStyleChange(mozilla::dom::ShadowRoot* aShadowRoot) = 0;
/** /**
* Determine if it is safe to flush all pending notifications * Determine if it is safe to flush all pending notifications.
* @param aIsSafeToFlush true if it is safe, false otherwise.
*
*/ */
virtual bool IsSafeToFlush() const = 0; bool IsSafeToFlush() const;
/** /**
* Flush pending notifications of the type specified. This method * Flush pending notifications of the type specified. This method
@ -1708,6 +1706,11 @@ protected:
int16_t mSelectionFlags; int16_t mSelectionFlags;
// This is used to protect ourselves from triggering reflow while in the
// middle of frame construction and the like... it really shouldn't be
// needed, one hopes, but it is for now.
uint16_t mChangeNestCount;
// Flags controlling how our document is rendered. These persist // Flags controlling how our document is rendered. These persist
// between paints and so are tied with retained layer pixels. // between paints and so are tied with retained layer pixels.
// PresShell flushes retained layers when the rendering state // PresShell flushes retained layers when the rendering state

View file

@ -0,0 +1,9 @@
<!DOCTYPE html>
<html dir="rtl">
<head>
<meta charset="UTF-8">
</head>
<body>
<div style="unicode-bidi: bidi-override;">u&#x0302;&#x0302;</div>
</body>
</html>

View file

@ -0,0 +1,37 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script>
function repeatManyTimes(s)
{
while (s.length < 0x8000)
s = s + s;
return s;
}
function boom()
{
var initialText =
"\u062A" + // ARABIC LETTER TEH
repeatManyTimes(
"\u2029" + // PARAGRAPH SEPARATOR
"\u202D" + // LEFT-TO-RIGHT OVERRIDE
" "
) +
"1"; // THE LONELIEST ASCII CHARACTER
var textNode = document.createTextNode(initialText);
document.getElementById("v").appendChild(textNode);
document.documentElement.offsetHeight;
textNode.data = "*" + textNode.data;
}
</script>
</head>
<body onload="boom();">
<div id="v" style="display: table-row; font-size: 500%;"></div>
</body>
</html>

Some files were not shown because too many files have changed in this diff Show more