forked from mirrors/gecko-dev
merge mozilla-inbound to mozilla-central. r=merge a=merge
This commit is contained in:
commit
a353221537
166 changed files with 1510 additions and 1556 deletions
|
|
@ -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;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
||||||
|
|
|
||||||
18
dom/canvas/crashtests/844280.html
Normal file
18
dom/canvas/crashtests/844280.html
Normal 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>
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@
|
||||||
|
|
||||||
#include "ClientState.h"
|
#include "ClientState.h"
|
||||||
|
|
||||||
|
#include "mozilla/dom/ClientIPCTypes.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
||||||
|
|
|
||||||
22
dom/html/crashtests/768344.html
Normal file
22
dom/html/crashtests/768344.html
Normal 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>
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
19
dom/media/test/crashtests/1267263.html
Normal file
19
dom/media/test/crashtests/1267263.html
Normal 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>
|
||||||
32
dom/media/test/crashtests/1389304.html
Normal file
32
dom/media/test/crashtests/1389304.html
Normal 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>
|
||||||
BIN
dom/media/test/crashtests/1389304.mp4
Normal file
BIN
dom/media/test/crashtests/1389304.mp4
Normal file
Binary file not shown.
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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]
|
||||||
|
|
|
||||||
6
gfx/tests/crashtests/766422-1.html
Normal file
6
gfx/tests/crashtests/766422-1.html
Normal 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>
|
||||||
17
gfx/tests/crashtests/766422-2.html
Normal file
17
gfx/tests/crashtests/766422-2.html
Normal 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>
|
||||||
7
gfx/tests/crashtests/951893.xhtml
Normal file
7
gfx/tests/crashtests/951893.xhtml
Normal 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>
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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 },
|
||||||
|
|
|
||||||
|
|
@ -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']
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
|
||||||
};
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
@ -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__
|
|
||||||
|
|
||||||
|
|
@ -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];
|
|
||||||
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
@ -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);
|
|
||||||
|
|
@ -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'
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
[DEFAULT]
|
|
||||||
head =
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
||||||
37
js/src/jit-test/tests/ion/rinstructions-no-sse4.js
Normal file
37
js/src/jit-test/tests/ion/rinstructions-no-sse4.js
Normal 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);
|
||||||
|
}
|
||||||
|
|
@ -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());
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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)))
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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",
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
/*---
|
/*---
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
/*---
|
/*---
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
/*---
|
/*---
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
/*---
|
/*---
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
/*---
|
/*---
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
/*---
|
/*---
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
/*---
|
/*---
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
/*---
|
/*---
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
/*---
|
/*---
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
/*---
|
/*---
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
/*---
|
/*---
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
/*---
|
/*---
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
/*---
|
/*---
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
/*---
|
/*---
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
/*---
|
/*---
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
/*---
|
/*---
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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. */
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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]);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
9
layout/generic/crashtests/849987.html
Normal file
9
layout/generic/crashtests/849987.html
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html dir="rtl">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div style="unicode-bidi: bidi-override;">û̂</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
37
layout/generic/crashtests/963878.html
Normal file
37
layout/generic/crashtests/963878.html
Normal 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
Loading…
Reference in a new issue