зеркало из https://github.com/mozilla/gecko-dev.git
Merge inbound to mozilla-central. a=merge
This commit is contained in:
Коммит
ed1521707f
|
@ -4701,7 +4701,7 @@ var XULBrowserWindow = {
|
|||
url = url.replace(/[\u200e\u200f\u202a\u202b\u202c\u202d\u202e]/g,
|
||||
encodeURIComponent);
|
||||
|
||||
if (gURLBar && gURLBar._mayTrimURLs /* corresponds to browser.urlbar.trimURLs */)
|
||||
if (gURLBar._mayTrimURLs /* corresponds to browser.urlbar.trimURLs */)
|
||||
url = trimURL(url);
|
||||
}
|
||||
|
||||
|
|
|
@ -547,9 +547,7 @@ namespace module_getter {
|
|||
|
||||
js::SetFunctionNativeReserved(getter, SLOT_URI, uri);
|
||||
|
||||
return JS_DefinePropertyById(aCx, aTarget, id,
|
||||
JS_DATA_TO_FUNC_PTR(JSNative, getter.get()),
|
||||
JS_DATA_TO_FUNC_PTR(JSNative, setter.get()),
|
||||
return JS_DefinePropertyById(aCx, aTarget, id, getter, setter,
|
||||
JSPROP_GETTER | JSPROP_SETTER | JSPROP_ENUMERATE);
|
||||
}
|
||||
} // namespace module_getter
|
||||
|
|
|
@ -189,7 +189,7 @@ public:
|
|||
/**
|
||||
* Holds any SMIL override style declaration for this element.
|
||||
*/
|
||||
RefPtr<mozilla::DeclarationBlock> mSMILOverrideStyleDeclaration;
|
||||
RefPtr<DeclarationBlock> mSMILOverrideStyleDeclaration;
|
||||
|
||||
/**
|
||||
* The controllers of the XUL Element.
|
||||
|
|
|
@ -186,7 +186,7 @@ NS_NewElement(Element** aResult,
|
|||
{
|
||||
RefPtr<mozilla::dom::NodeInfo> ni = aNodeInfo;
|
||||
int32_t ns = ni->NamespaceID();
|
||||
RefPtr<nsAtom> isAtom = aIs ? NS_Atomize(*aIs) : nullptr;
|
||||
RefPtr<nsAtom> isAtom = aIs ? NS_AtomizeMainThread(*aIs) : nullptr;
|
||||
if (ns == kNameSpaceID_XHTML) {
|
||||
return NS_NewHTMLElement(aResult, ni.forget(), aFromParser, isAtom);
|
||||
}
|
||||
|
|
|
@ -1974,8 +1974,7 @@ Console::PopulateConsoleNotificationInTheTargetScope(JSContext* aCx,
|
|||
JS::PrivateValue(aData->mStack.get()));
|
||||
|
||||
if (NS_WARN_IF(!JS_DefineProperty(aCx, eventObj, "stacktrace",
|
||||
JS_DATA_TO_FUNC_PTR(JSNative, funObj.get()),
|
||||
nullptr,
|
||||
funObj, nullptr,
|
||||
JSPROP_ENUMERATE |
|
||||
JSPROP_GETTER | JSPROP_SETTER))) {
|
||||
return false;
|
||||
|
|
|
@ -3228,6 +3228,9 @@ TabChild::ReinitRendering()
|
|||
gfx::VRManagerChild::IdentifyTextureHost(mTextureFactoryIdentifier);
|
||||
|
||||
InitAPZState();
|
||||
RefPtr<LayerManager> lm = mPuppetWidget->GetLayerManager();
|
||||
MOZ_ASSERT(lm);
|
||||
lm->SetLayerObserverEpoch(mLayerObserverEpoch);
|
||||
|
||||
nsCOMPtr<nsIDocument> doc(GetDocument());
|
||||
doc->NotifyLayerManagerRecreated();
|
||||
|
|
|
@ -94,5 +94,7 @@ BlockSubresourceFTP=Loading FTP subresource within http(s) page not allowed (Blo
|
|||
# LOCALIZATION NOTE (BrowserUpgradeInsecureDisplayRequest):
|
||||
# %1$S is the browser name "brandShortName"; %2$S is the URL of the upgraded request; %1$S is the upgraded scheme.
|
||||
BrowserUpgradeInsecureDisplayRequest = %1$S is upgrading an insecure display request ‘%2$S’ to use ‘%3$S’
|
||||
RunningClearSiteDataValue=Clear-Site-Data header forces the clean up of “%S” data.
|
||||
# LOCALIZATION NOTE (RunningClearSiteDataValue):
|
||||
# %S is the URI of the resource whose data was cleaned up
|
||||
RunningClearSiteDataValue=Clear-Site-Data header forced the clean up of “%S” data.
|
||||
UnknownClearSiteDataValue=Clear-Site-Data header found. Unknown value “%S”.
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
* http://dev.w3.org/csswg/cssom/
|
||||
*/
|
||||
|
||||
// Because of getComputedStyle, many CSSStyleDeclaration objects can be
|
||||
// short-living.
|
||||
[ProbablyShortLivingWrapper]
|
||||
interface CSSStyleDeclaration {
|
||||
[CEReactions, SetterNeedsSubjectPrincipal=NonSystem, SetterThrows]
|
||||
attribute DOMString cssText;
|
||||
|
|
|
@ -361,9 +361,7 @@ nsXBLProtoImplField::InstallAccessors(JSContext* aCx,
|
|||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
if (!::JS_DefinePropertyById(aCx, aTargetClassObject, id,
|
||||
JS_DATA_TO_FUNC_PTR(JSNative, get.get()),
|
||||
JS_DATA_TO_FUNC_PTR(JSNative, set.get()),
|
||||
if (!::JS_DefinePropertyById(aCx, aTargetClassObject, id, get, set,
|
||||
AccessorAttributes())) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
|
|
@ -151,8 +151,7 @@ nsXBLProtoImplProperty::InstallMember(JSContext *aCx,
|
|||
if (!::JS_DefineUCProperty(aCx, aTargetClassObject,
|
||||
static_cast<const char16_t*>(mName),
|
||||
name.Length(),
|
||||
JS_DATA_TO_FUNC_PTR(JSNative, getter.get()),
|
||||
JS_DATA_TO_FUNC_PTR(JSNative, setter.get()),
|
||||
getter, setter,
|
||||
mJSAttributes))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
|
|
@ -17,7 +17,8 @@
|
|||
* Creates a new ExprLexer
|
||||
*/
|
||||
txExprLexer::txExprLexer()
|
||||
: mCurrentItem(nullptr),
|
||||
: mPosition(nullptr),
|
||||
mCurrentItem(nullptr),
|
||||
mFirstItem(nullptr),
|
||||
mLastItem(nullptr),
|
||||
mTokenCount(0)
|
||||
|
|
|
@ -56,6 +56,7 @@ txExecutionState::txExecutionState(txStylesheet* aStylesheet,
|
|||
bool aDisableLoads)
|
||||
: mOutputHandler(nullptr),
|
||||
mResultHandler(nullptr),
|
||||
mOutputHandlerFactory(nullptr),
|
||||
mStylesheet(aStylesheet),
|
||||
mNextInstruction(nullptr),
|
||||
mLocalVariables(nullptr),
|
||||
|
|
|
@ -523,9 +523,11 @@ txStylesheetCompilerState::txStylesheetCompilerState(txACompileObserver* aObserv
|
|||
mDisAllowed(0),
|
||||
mObserver(aObserver),
|
||||
mEmbedStatus(eNoEmbed),
|
||||
mIsTopCompiler(false),
|
||||
mDoneWithThisStylesheet(false),
|
||||
mNextInstrPtr(nullptr),
|
||||
mToplevelIterator(nullptr)
|
||||
mToplevelIterator(nullptr),
|
||||
mReferrerPolicy(mozilla::net::RP_Unset)
|
||||
{
|
||||
// Embedded stylesheets have another handler, which is set in
|
||||
// txStylesheetCompiler::init if the baseURI has a fragment identifier.
|
||||
|
|
|
@ -682,10 +682,6 @@ WebRenderBridgeParent::RecvSetDisplayList(const gfx::IntSize& aSize,
|
|||
// build is done, so we don't need to do it here.
|
||||
ScheduleGenerateFrame();
|
||||
}
|
||||
|
||||
if (ShouldParentObserveEpoch()) {
|
||||
mCompositorBridge->ObserveLayerUpdate(GetLayersId(), GetChildLayerObserverEpoch(), true);
|
||||
}
|
||||
}
|
||||
|
||||
HoldPendingTransactionId(wrEpoch, aTransactionId, aTxnStartTime, aFwdTime);
|
||||
|
@ -697,6 +693,10 @@ WebRenderBridgeParent::RecvSetDisplayList(const gfx::IntSize& aSize,
|
|||
mCompositorBridge->DidComposite(GetLayersId(), now, now);
|
||||
}
|
||||
|
||||
if (ShouldParentObserveEpoch()) {
|
||||
mCompositorBridge->ObserveLayerUpdate(GetLayersId(), GetChildLayerObserverEpoch(), true);
|
||||
}
|
||||
|
||||
wr::IpcResourceUpdateQueue::ReleaseShmems(this, aSmallShmems);
|
||||
wr::IpcResourceUpdateQueue::ReleaseShmems(this, aLargeShmems);
|
||||
return IPC_OK();
|
||||
|
@ -771,6 +771,10 @@ WebRenderBridgeParent::RecvEmptyTransaction(const FocusTarget& aFocusTarget,
|
|||
mCompositorBridge->DidComposite(GetLayersId(), now, now);
|
||||
}
|
||||
|
||||
if (ShouldParentObserveEpoch()) {
|
||||
mCompositorBridge->ObserveLayerUpdate(GetLayersId(), GetChildLayerObserverEpoch(), true);
|
||||
}
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
|
|
|
@ -1027,7 +1027,7 @@ AddLengthProperty(JSContext* cx, HandleArrayObject obj)
|
|||
|
||||
return NativeObject::addAccessorProperty(cx, obj, lengthId,
|
||||
array_length_getter, array_length_setter,
|
||||
JSPROP_PERMANENT | JSPROP_SHADOWABLE);
|
||||
JSPROP_PERMANENT);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
|
@ -6163,8 +6163,7 @@ StructType::DefineInternal(JSContext* cx, JSObject* typeObj_, JSObject* fieldsOb
|
|||
|
||||
if (!JS_DefineUCProperty(cx, prototype,
|
||||
nameChars.twoByteChars(), name->length(),
|
||||
JS_DATA_TO_FUNC_PTR(JSNative, getterObj.get()),
|
||||
JS_DATA_TO_FUNC_PTR(JSNative, setterObj.get()),
|
||||
getterObj, setterObj,
|
||||
JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_GETTER | JSPROP_SETTER))
|
||||
{
|
||||
return false;
|
||||
|
|
|
@ -281,8 +281,8 @@ const v2vSigSection = sigSection([v2vSig]);
|
|||
const i2vSig = {args:[I32Code], ret:VoidCode};
|
||||
const v2vBody = funcBody({locals:[], body:[]});
|
||||
|
||||
assertErrorMessage(() => wasmEval(moduleWithSections([ {name: typeId, body: U32MAX_LEB } ])), CompileError, /too many signatures/);
|
||||
assertErrorMessage(() => wasmEval(moduleWithSections([ {name: typeId, body: [1, 0], } ])), CompileError, /expected function form/);
|
||||
assertErrorMessage(() => wasmEval(moduleWithSections([ {name: typeId, body: U32MAX_LEB } ])), CompileError, /too many types/);
|
||||
assertErrorMessage(() => wasmEval(moduleWithSections([ {name: typeId, body: [1, 0], } ])), CompileError, /expected type form/);
|
||||
assertErrorMessage(() => wasmEval(moduleWithSections([ {name: typeId, body: [1, FuncCode, ...U32MAX_LEB], } ])), CompileError, /too many arguments in signature/);
|
||||
|
||||
assertThrowsInstanceOf(() => wasmEval(moduleWithSections([{name: typeId, body: [1]}])), CompileError);
|
||||
|
|
|
@ -0,0 +1,162 @@
|
|||
if (!wasmGcEnabled()) {
|
||||
assertErrorMessage(() => wasmEvalText(`(module (type $s (struct)))`),
|
||||
WebAssembly.CompileError, /Structure types not enabled/);
|
||||
quit();
|
||||
}
|
||||
|
||||
var bin = wasmTextToBinary(
|
||||
`(module
|
||||
|
||||
(table 2 anyfunc)
|
||||
(elem (i32.const 0) $doit $doitagain)
|
||||
|
||||
;; Type array has a mix of types
|
||||
|
||||
(type $f1 (func (param i32) (result i32)))
|
||||
|
||||
(type $point (struct
|
||||
(field $point_x i32)
|
||||
(field $point_y i32)))
|
||||
|
||||
(type $f2 (func (param f64) (result f64)))
|
||||
|
||||
(type $int_node (struct
|
||||
(field $intbox_val (mut i32))
|
||||
(field $intbox_next (mut anyref))))
|
||||
|
||||
;; Test all the types.
|
||||
|
||||
(type $omni (struct
|
||||
(field $omni_i32 i32)
|
||||
(field $omni_i32m (mut i32))
|
||||
(field $omni_i64 i64)
|
||||
(field $omni_i64m (mut i64))
|
||||
(field $omni_f32 f32)
|
||||
(field $omni_f32m (mut f32))
|
||||
(field $omni_f64 f64)
|
||||
(field $omni_f64m (mut f64))
|
||||
(field $omni_anyref anyref)
|
||||
(field $omni_anyrefm (mut anyref))))
|
||||
|
||||
;; Various ways to reference a type in the middle of the
|
||||
;; type array, make sure we get the right one
|
||||
|
||||
(func $x1 (import "m" "x1") (type $f1))
|
||||
(func $x2 (import "m" "x2") (type $f2))
|
||||
|
||||
(func (export "hello") (param f64) (param i32) (result f64)
|
||||
(call_indirect $f2 (get_local 0) (get_local 1)))
|
||||
|
||||
(func $doit (param f64) (result f64)
|
||||
(f64.sqrt (get_local 0)))
|
||||
|
||||
(func $doitagain (param f64) (result f64)
|
||||
(f64.mul (get_local 0) (get_local 0)))
|
||||
|
||||
(func (export "x1") (param i32) (result i32)
|
||||
(call $x1 (get_local 0)))
|
||||
|
||||
(func (export "x2") (param f64) (result f64)
|
||||
(call $x2 (get_local 0)))
|
||||
)`)
|
||||
|
||||
var mod = new WebAssembly.Module(bin);
|
||||
var ins = new WebAssembly.Instance(mod, {m:{x1(x){ return x*3 }, x2(x){ return Math.PI }}}).exports;
|
||||
|
||||
assertEq(ins.hello(4.0, 0), 2.0)
|
||||
assertEq(ins.hello(4.0, 1), 16.0)
|
||||
|
||||
assertEq(ins.x1(12), 36)
|
||||
assertEq(ins.x2(8), Math.PI)
|
||||
|
||||
// Crude but at least checks that we have *something*.
|
||||
|
||||
var txt = wasmBinaryToText(bin);
|
||||
var re = /\(type\s+\$[a-z0-9]+\s+\(struct/gm;
|
||||
assertEq(Array.isArray(re.exec(txt)), true);
|
||||
assertEq(Array.isArray(re.exec(txt)), true);
|
||||
assertEq(Array.isArray(re.exec(txt)), true);
|
||||
assertEq(Array.isArray(re.exec(txt)), false);
|
||||
|
||||
// The field name is optional, so this should work.
|
||||
|
||||
wasmEvalText(`
|
||||
(module
|
||||
(type $s (struct (field i32))))
|
||||
`)
|
||||
|
||||
// Empty structs are OK.
|
||||
|
||||
wasmEvalText(`
|
||||
(module
|
||||
(type $s (struct)))
|
||||
`)
|
||||
|
||||
// Bogus type definition syntax.
|
||||
|
||||
assertErrorMessage(() => wasmEvalText(`
|
||||
(module
|
||||
(type $s))
|
||||
`),
|
||||
SyntaxError, /parsing wasm text/);
|
||||
|
||||
assertErrorMessage(() => wasmEvalText(`
|
||||
(module
|
||||
(type $s (field $x i32)))
|
||||
`),
|
||||
SyntaxError, /bad type definition/);
|
||||
|
||||
assertErrorMessage(() => wasmEvalText(`
|
||||
(module
|
||||
(type $s (struct (field $x i31))))
|
||||
`),
|
||||
SyntaxError, /parsing wasm text/);
|
||||
|
||||
assertErrorMessage(() => wasmEvalText(`
|
||||
(module
|
||||
(type $s (struct (fjeld $x i32))))
|
||||
`),
|
||||
SyntaxError, /parsing wasm text/);
|
||||
|
||||
assertErrorMessage(() => wasmEvalText(`
|
||||
(module
|
||||
(type $s (struct abracadabra)))
|
||||
`),
|
||||
SyntaxError, /parsing wasm text/);
|
||||
|
||||
// Function should not reference struct type: syntactic test
|
||||
|
||||
assertErrorMessage(() => wasmEvalText(`
|
||||
(module
|
||||
(type $s (struct))
|
||||
(type $f (func (param i32) (result i32)))
|
||||
(func (type 0) (param i32) (result i32) (unreachable)))
|
||||
`),
|
||||
WebAssembly.CompileError, /signature index references non-signature/);
|
||||
|
||||
// Function should not reference struct type: binary test
|
||||
|
||||
var bad = new Uint8Array([0x00, 0x61, 0x73, 0x6d,
|
||||
0x01, 0x00, 0x00, 0x00,
|
||||
|
||||
0x01, // Type section
|
||||
0x03, // Section size
|
||||
0x01, // One type
|
||||
0x50, // Struct
|
||||
0x00, // Zero fields
|
||||
|
||||
0x03, // Function section
|
||||
0x02, // Section size
|
||||
0x01, // One function
|
||||
0x00, // Type of function
|
||||
|
||||
0x0a, // Code section
|
||||
0x05, // Section size
|
||||
0x01, // One body
|
||||
0x03, // Body size
|
||||
0x00, // Zero locals
|
||||
0x00, // UNREACHABLE
|
||||
0x0b]); // END
|
||||
|
||||
assertErrorMessage(() => new WebAssembly.Module(bad),
|
||||
WebAssembly.CompileError, /signature index references non-signature/);
|
|
@ -34,13 +34,11 @@ BEGIN_TEST(testDefineGetterSetterNonEnumerable)
|
|||
|
||||
JS::RootedObject vObject(cx, vobj.toObjectOrNull());
|
||||
CHECK(JS_DefineProperty(cx, vObject, PROPERTY_NAME,
|
||||
JS_DATA_TO_FUNC_PTR(JSNative, (JSObject*) funGetObj),
|
||||
JS_DATA_TO_FUNC_PTR(JSNative, (JSObject*) funSetObj),
|
||||
funGetObj, funSetObj,
|
||||
JSPROP_GETTER | JSPROP_SETTER | JSPROP_ENUMERATE));
|
||||
|
||||
CHECK(JS_DefineProperty(cx, vObject, PROPERTY_NAME,
|
||||
JS_DATA_TO_FUNC_PTR(JSNative, (JSObject*) funGetObj),
|
||||
JS_DATA_TO_FUNC_PTR(JSNative, (JSObject*) funSetObj),
|
||||
funGetObj, funSetObj,
|
||||
JSPROP_GETTER | JSPROP_SETTER | JSPROP_PERMANENT));
|
||||
|
||||
JS::Rooted<JS::PropertyDescriptor> desc(cx);
|
||||
|
|
|
@ -7,61 +7,6 @@
|
|||
|
||||
#include "jsapi-tests/tests.h"
|
||||
|
||||
BEGIN_TEST(testSetProperty_NativeGetterStubSetter)
|
||||
{
|
||||
JS::RootedObject obj(cx, JS_NewPlainObject(cx));
|
||||
CHECK(obj);
|
||||
|
||||
CHECK(JS_DefineProperty(cx, global, "globalProp", obj, JSPROP_ENUMERATE));
|
||||
|
||||
CHECK(JS_DefineProperty(cx, obj, "prop",
|
||||
JS_PROPERTYOP_GETTER(NativeGet), nullptr,
|
||||
JSPROP_PROPOP_ACCESSORS));
|
||||
|
||||
EXEC("'use strict'; \n"
|
||||
"var error, passed = false; \n"
|
||||
"try \n"
|
||||
"{ \n"
|
||||
" this.globalProp.prop = 42; \n"
|
||||
" throw new Error('setting property succeeded!'); \n"
|
||||
"} \n"
|
||||
"catch (e) \n"
|
||||
"{ \n"
|
||||
" error = e; \n"
|
||||
" if (e instanceof TypeError) \n"
|
||||
" passed = true; \n"
|
||||
"} \n"
|
||||
" \n"
|
||||
"if (!passed) \n"
|
||||
" throw error; \n");
|
||||
|
||||
EXEC("var error, passed = false; \n"
|
||||
"try \n"
|
||||
"{ \n"
|
||||
" this.globalProp.prop = 42; \n"
|
||||
" if (this.globalProp.prop === 17) \n"
|
||||
" passed = true; \n"
|
||||
" else \n"
|
||||
" throw new Error('bad value after set!'); \n"
|
||||
"} \n"
|
||||
"catch (e) \n"
|
||||
"{ \n"
|
||||
" error = e; \n"
|
||||
"} \n"
|
||||
" \n"
|
||||
"if (!passed) \n"
|
||||
" throw error; \n");
|
||||
|
||||
return true;
|
||||
}
|
||||
static bool
|
||||
NativeGet(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandleValue vp)
|
||||
{
|
||||
vp.setInt32(17);
|
||||
return true;
|
||||
}
|
||||
END_TEST(testSetProperty_NativeGetterStubSetter)
|
||||
|
||||
BEGIN_TEST(testSetProperty_InheritedGlobalSetter)
|
||||
{
|
||||
// This is a JSAPI test because jsapi-test globals do not have a resolve
|
||||
|
|
199
js/src/jsapi.cpp
199
js/src/jsapi.cpp
|
@ -2099,11 +2099,10 @@ JS_DefinePropertyById(JSContext* cx, HandleObject obj, HandleId id,
|
|||
|
||||
static bool
|
||||
DefineAccessorPropertyById(JSContext* cx, HandleObject obj, HandleId id,
|
||||
const JSNativeWrapper& get, const JSNativeWrapper& set,
|
||||
unsigned attrs)
|
||||
HandleObject getter, HandleObject setter, unsigned attrs)
|
||||
{
|
||||
JSGetterOp getter = JS_CAST_NATIVE_TO(get.op, JSGetterOp);
|
||||
JSSetterOp setter = JS_CAST_NATIVE_TO(set.op, JSSetterOp);
|
||||
MOZ_ASSERT_IF(getter, attrs & JSPROP_GETTER);
|
||||
MOZ_ASSERT_IF(setter, attrs & JSPROP_SETTER);
|
||||
|
||||
// JSPROP_READONLY has no meaning when accessors are involved. Ideally we'd
|
||||
// throw if this happens, but we've accepted it for long enough that it's
|
||||
|
@ -2112,67 +2111,61 @@ DefineAccessorPropertyById(JSContext* cx, HandleObject obj, HandleId id,
|
|||
if (attrs & (JSPROP_GETTER | JSPROP_SETTER))
|
||||
attrs &= ~JSPROP_READONLY;
|
||||
|
||||
// When we use DefineProperty, we need full scriptable Function objects rather
|
||||
// than JSNatives. However, we might be pulling this property descriptor off
|
||||
// of something with JSNative property descriptors. If we are, wrap them in
|
||||
// JS Function objects.
|
||||
|
||||
// If !(attrs & JSPROP_PROPOP_ACCESSORS), then getter/setter are both
|
||||
// possibly-null JSNatives (or possibly-null JSFunction* if JSPROP_GETTER or
|
||||
// JSPROP_SETTER is appropriately set).
|
||||
if (!(attrs & JSPROP_PROPOP_ACCESSORS)) {
|
||||
if (getter && !(attrs & JSPROP_GETTER)) {
|
||||
RootedAtom atom(cx, IdToFunctionName(cx, id, FunctionPrefixKind::Get));
|
||||
if (!atom)
|
||||
return false;
|
||||
JSFunction* getobj = NewNativeFunction(cx, (Native) getter, 0, atom);
|
||||
if (!getobj)
|
||||
return false;
|
||||
|
||||
if (get.info)
|
||||
getobj->setJitInfo(get.info);
|
||||
|
||||
getter = JS_DATA_TO_FUNC_PTR(GetterOp, getobj);
|
||||
attrs |= JSPROP_GETTER;
|
||||
}
|
||||
if (setter && !(attrs & JSPROP_SETTER)) {
|
||||
// Root just the getter, since the setter is not yet a JSObject.
|
||||
AutoRooterGetterSetter getRoot(cx, JSPROP_GETTER, &getter, nullptr);
|
||||
RootedAtom atom(cx, IdToFunctionName(cx, id, FunctionPrefixKind::Set));
|
||||
if (!atom)
|
||||
return false;
|
||||
JSFunction* setobj = NewNativeFunction(cx, (Native) setter, 1, atom);
|
||||
if (!setobj)
|
||||
return false;
|
||||
|
||||
if (set.info)
|
||||
setobj->setJitInfo(set.info);
|
||||
|
||||
setter = JS_DATA_TO_FUNC_PTR(SetterOp, setobj);
|
||||
attrs |= JSPROP_SETTER;
|
||||
}
|
||||
} else {
|
||||
attrs &= ~JSPROP_PROPOP_ACCESSORS;
|
||||
}
|
||||
|
||||
AssertHeapIsIdle();
|
||||
CHECK_REQUEST(cx);
|
||||
assertSameCompartment(cx, obj, id,
|
||||
(attrs & JSPROP_GETTER)
|
||||
? JS_FUNC_TO_DATA_PTR(JSObject*, getter)
|
||||
: nullptr,
|
||||
(attrs & JSPROP_SETTER)
|
||||
? JS_FUNC_TO_DATA_PTR(JSObject*, setter)
|
||||
: nullptr);
|
||||
assertSameCompartment(cx, obj, id, getter, setter);
|
||||
|
||||
return js::DefineAccessorProperty(cx, obj, id, getter, setter, attrs);
|
||||
}
|
||||
|
||||
static bool
|
||||
DefineAccessorPropertyById(JSContext* cx, HandleObject obj, HandleId id,
|
||||
const JSNativeWrapper& get, const JSNativeWrapper& set,
|
||||
unsigned attrs)
|
||||
{
|
||||
// Getter/setter are both possibly-null JSNatives. Wrap them in JSFunctions.
|
||||
|
||||
MOZ_ASSERT(!(attrs & (JSPROP_GETTER | JSPROP_SETTER)));
|
||||
|
||||
RootedFunction getter(cx);
|
||||
if (get.op) {
|
||||
RootedAtom atom(cx, IdToFunctionName(cx, id, FunctionPrefixKind::Get));
|
||||
if (!atom)
|
||||
return false;
|
||||
getter = NewNativeFunction(cx, get.op, 0, atom);
|
||||
if (!getter)
|
||||
return false;
|
||||
|
||||
if (get.info)
|
||||
getter->setJitInfo(get.info);
|
||||
|
||||
attrs |= JSPROP_GETTER;
|
||||
}
|
||||
|
||||
RootedFunction setter(cx);
|
||||
if (set.op) {
|
||||
RootedAtom atom(cx, IdToFunctionName(cx, id, FunctionPrefixKind::Set));
|
||||
if (!atom)
|
||||
return false;
|
||||
setter = NewNativeFunction(cx, set.op, 1, atom);
|
||||
if (!setter)
|
||||
return false;
|
||||
|
||||
if (set.info)
|
||||
setter->setJitInfo(set.info);
|
||||
|
||||
attrs |= JSPROP_SETTER;
|
||||
}
|
||||
|
||||
return DefineAccessorPropertyById(cx, obj, id, getter, setter, attrs);
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
DefineDataPropertyById(JSContext* cx, HandleObject obj, HandleId id, HandleValue value,
|
||||
unsigned attrs)
|
||||
{
|
||||
MOZ_ASSERT(!(attrs & (JSPROP_GETTER | JSPROP_SETTER | JSPROP_PROPOP_ACCESSORS)));
|
||||
MOZ_ASSERT(!(attrs & (JSPROP_GETTER | JSPROP_SETTER)));
|
||||
|
||||
AssertHeapIsIdle();
|
||||
CHECK_REQUEST(cx);
|
||||
|
@ -2210,6 +2203,13 @@ JS_DefinePropertyById(JSContext* cx, HandleObject obj, HandleId id, Native gette
|
|||
attrs);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_DefinePropertyById(JSContext* cx, HandleObject obj, HandleId id, HandleObject getter,
|
||||
HandleObject setter, unsigned attrs)
|
||||
{
|
||||
return DefineAccessorPropertyById(cx, obj, id, getter, setter, attrs);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_DefinePropertyById(JSContext* cx, HandleObject obj, HandleId id, HandleObject valueArg,
|
||||
unsigned attrs)
|
||||
|
@ -2250,22 +2250,6 @@ JS_DefinePropertyById(JSContext* cx, HandleObject obj, HandleId id, double value
|
|||
return DefineDataPropertyById(cx, obj, id, HandleValue::fromMarkedLocation(&value), attrs);
|
||||
}
|
||||
|
||||
static bool
|
||||
DefineAccessorProperty(JSContext* cx, HandleObject obj, const char* name,
|
||||
const JSNativeWrapper& getter, const JSNativeWrapper& setter,
|
||||
unsigned attrs)
|
||||
{
|
||||
AutoRooterGetterSetter gsRoot(cx, attrs, const_cast<JSNative*>(&getter.op),
|
||||
const_cast<JSNative*>(&setter.op));
|
||||
|
||||
JSAtom* atom = Atomize(cx, name, strlen(name));
|
||||
if (!atom)
|
||||
return false;
|
||||
RootedId id(cx, AtomToId(atom));
|
||||
|
||||
return DefineAccessorPropertyById(cx, obj, id, getter, setter, attrs);
|
||||
}
|
||||
|
||||
static bool
|
||||
DefineDataProperty(JSContext* cx, HandleObject obj, const char* name, HandleValue value,
|
||||
unsigned attrs)
|
||||
|
@ -2289,8 +2273,24 @@ JS_PUBLIC_API(bool)
|
|||
JS_DefineProperty(JSContext* cx, HandleObject obj, const char* name, Native getter, Native setter,
|
||||
unsigned attrs)
|
||||
{
|
||||
return DefineAccessorProperty(cx, obj, name, NativeOpWrapper(getter), NativeOpWrapper(setter),
|
||||
attrs);
|
||||
JSAtom* atom = Atomize(cx, name, strlen(name));
|
||||
if (!atom)
|
||||
return false;
|
||||
RootedId id(cx, AtomToId(atom));
|
||||
return DefineAccessorPropertyById(cx, obj, id, NativeOpWrapper(getter),
|
||||
NativeOpWrapper(setter), attrs);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_DefineProperty(JSContext* cx, HandleObject obj, const char* name, HandleObject getter,
|
||||
HandleObject setter, unsigned attrs)
|
||||
{
|
||||
JSAtom* atom = Atomize(cx, name, strlen(name));
|
||||
if (!atom)
|
||||
return false;
|
||||
RootedId id(cx, AtomToId(atom));
|
||||
|
||||
return DefineAccessorPropertyById(cx, obj, id, getter, setter, attrs);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
|
@ -2360,20 +2360,6 @@ JS_DefineUCProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_
|
|||
result.checkStrict(cx, obj, id);
|
||||
}
|
||||
|
||||
static bool
|
||||
DefineUCAccessorProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen,
|
||||
Native getter, Native setter, unsigned attrs)
|
||||
{
|
||||
AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
|
||||
JSAtom* atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
|
||||
if (!atom)
|
||||
return false;
|
||||
RootedId id(cx, AtomToId(atom));
|
||||
return DefineAccessorPropertyById(cx, obj, id,
|
||||
NativeOpWrapper(getter), NativeOpWrapper(setter),
|
||||
attrs);
|
||||
}
|
||||
|
||||
static bool
|
||||
DefineUCDataProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen,
|
||||
HandleValue value, unsigned attrs)
|
||||
|
@ -2394,9 +2380,13 @@ JS_DefineUCProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_
|
|||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_DefineUCProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen,
|
||||
Native getter, Native setter, unsigned attrs)
|
||||
HandleObject getter, HandleObject setter, unsigned attrs)
|
||||
{
|
||||
return DefineUCAccessorProperty(cx, obj, name, namelen, getter, setter, attrs);
|
||||
JSAtom* atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
|
||||
if (!atom)
|
||||
return false;
|
||||
RootedId id(cx, AtomToId(atom));
|
||||
return DefineAccessorPropertyById(cx, obj, id, getter, setter, attrs);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
|
@ -2442,22 +2432,6 @@ JS_DefineUCProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_
|
|||
attrs);
|
||||
}
|
||||
|
||||
static bool
|
||||
DefineAccessorElement(JSContext* cx, HandleObject obj, uint32_t index, unsigned attrs,
|
||||
Native getter, Native setter)
|
||||
{
|
||||
assertSameCompartment(cx, obj);
|
||||
AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
|
||||
AssertHeapIsIdle();
|
||||
CHECK_REQUEST(cx);
|
||||
RootedId id(cx);
|
||||
if (!IndexToId(cx, index, &id))
|
||||
return false;
|
||||
return DefineAccessorPropertyById(cx, obj, id,
|
||||
NativeOpWrapper(getter), NativeOpWrapper(setter),
|
||||
attrs);
|
||||
}
|
||||
|
||||
static bool
|
||||
DefineDataElement(JSContext* cx, HandleObject obj, uint32_t index, HandleValue value,
|
||||
unsigned attrs)
|
||||
|
@ -2479,10 +2453,13 @@ JS_DefineElement(JSContext* cx, HandleObject obj, uint32_t index, HandleValue va
|
|||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_DefineElement(JSContext* cx, HandleObject obj, uint32_t index, Native getter, Native setter,
|
||||
unsigned attrs)
|
||||
JS_DefineElement(JSContext* cx, HandleObject obj, uint32_t index, HandleObject getter,
|
||||
HandleObject setter, unsigned attrs)
|
||||
{
|
||||
return DefineAccessorElement(cx, obj, index, attrs, getter, setter);
|
||||
RootedId id(cx);
|
||||
if (!IndexToId(cx, index, &id))
|
||||
return false;
|
||||
return DefineAccessorPropertyById(cx, obj, id, getter, setter, attrs);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
|
@ -3081,7 +3058,6 @@ DefineSelfHostedProperty(JSContext* cx, HandleObject obj, HandleId id,
|
|||
}
|
||||
MOZ_ASSERT(getterValue.isObject() && getterValue.toObject().is<JSFunction>());
|
||||
RootedFunction getterFunc(cx, &getterValue.toObject().as<JSFunction>());
|
||||
JSNative getterOp = JS_DATA_TO_FUNC_PTR(JSNative, getterFunc.get());
|
||||
|
||||
RootedFunction setterFunc(cx);
|
||||
if (setterName) {
|
||||
|
@ -3099,11 +3075,8 @@ DefineSelfHostedProperty(JSContext* cx, HandleObject obj, HandleId id,
|
|||
MOZ_ASSERT(setterValue.isObject() && setterValue.toObject().is<JSFunction>());
|
||||
setterFunc = &setterValue.toObject().as<JSFunction>();
|
||||
}
|
||||
JSNative setterOp = JS_DATA_TO_FUNC_PTR(JSNative, setterFunc.get());
|
||||
|
||||
return DefineAccessorPropertyById(cx, obj, id,
|
||||
NativeOpWrapper(getterOp), NativeOpWrapper(setterOp),
|
||||
attrs);
|
||||
return DefineAccessorPropertyById(cx, obj, id, getterFunc, setterFunc, attrs);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSObject*)
|
||||
|
|
|
@ -476,9 +476,7 @@ static const uint8_t JSPROP_READONLY = 0x02;
|
|||
/* property cannot be deleted */
|
||||
static const uint8_t JSPROP_PERMANENT = 0x04;
|
||||
|
||||
/* Passed to JS_Define(UC)Property* and JS_DefineElement if getters/setters are
|
||||
JSGetterOp/JSSetterOp */
|
||||
static const uint8_t JSPROP_PROPOP_ACCESSORS = 0x08;
|
||||
/* (0x08 is unused) */
|
||||
|
||||
/* property holds getter function */
|
||||
static const uint8_t JSPROP_GETTER = 0x10;
|
||||
|
@ -1462,9 +1460,6 @@ private:
|
|||
namespace JS {
|
||||
namespace detail {
|
||||
|
||||
/* NEVER DEFINED, DON'T USE. For use by JS_CAST_NATIVE_TO only. */
|
||||
inline int CheckIsNative(JSNative native);
|
||||
|
||||
/* NEVER DEFINED, DON'T USE. For use by JS_CAST_STRING_TO only. */
|
||||
template<size_t N>
|
||||
inline int
|
||||
|
@ -1473,19 +1468,9 @@ CheckIsCharacterLiteral(const char (&arr)[N]);
|
|||
/* NEVER DEFINED, DON'T USE. For use by JS_CAST_INT32_TO only. */
|
||||
inline int CheckIsInt32(int32_t value);
|
||||
|
||||
/* NEVER DEFINED, DON'T USE. For use by JS_PROPERTYOP_GETTER only. */
|
||||
inline int CheckIsGetterOp(JSGetterOp op);
|
||||
|
||||
/* NEVER DEFINED, DON'T USE. For use by JS_PROPERTYOP_SETTER only. */
|
||||
inline int CheckIsSetterOp(JSSetterOp op);
|
||||
|
||||
} // namespace detail
|
||||
} // namespace JS
|
||||
|
||||
#define JS_CAST_NATIVE_TO(v, To) \
|
||||
(static_cast<void>(sizeof(JS::detail::CheckIsNative(v))), \
|
||||
reinterpret_cast<To>(v))
|
||||
|
||||
#define JS_CAST_STRING_TO(s, To) \
|
||||
(static_cast<void>(sizeof(JS::detail::CheckIsCharacterLiteral(s))), \
|
||||
reinterpret_cast<To>(s))
|
||||
|
@ -1498,14 +1483,6 @@ inline int CheckIsSetterOp(JSSetterOp op);
|
|||
(static_cast<mozilla::EnableIf<((flags) & ~(JSPROP_ENUMERATE | JSPROP_PERMANENT)) == 0>::Type>(0), \
|
||||
(flags))
|
||||
|
||||
#define JS_PROPERTYOP_GETTER(v) \
|
||||
(static_cast<void>(sizeof(JS::detail::CheckIsGetterOp(v))), \
|
||||
reinterpret_cast<JSNative>(v))
|
||||
|
||||
#define JS_PROPERTYOP_SETTER(v) \
|
||||
(static_cast<void>(sizeof(JS::detail::CheckIsSetterOp(v))), \
|
||||
reinterpret_cast<JSNative>(v))
|
||||
|
||||
#define JS_PS_ACCESSOR_SPEC(name, getter, setter, flags, extraFlags) \
|
||||
{ name, uint8_t(JS_CHECK_ACCESSOR_FLAGS(flags) | extraFlags), \
|
||||
{ { getter, setter } } }
|
||||
|
@ -2039,9 +2016,6 @@ class WrappedPtrOperations<JS::PropertyDescriptor, Wrapper>
|
|||
return (desc().attrs & bits) == bits;
|
||||
}
|
||||
|
||||
// Non-API attributes bit used internally for arguments objects.
|
||||
enum { SHADOWABLE = JSPROP_INTERNAL_USE_BIT };
|
||||
|
||||
public:
|
||||
// Descriptors with JSGetterOp/JSSetterOp are considered data
|
||||
// descriptors. It's complicated.
|
||||
|
@ -2098,14 +2072,14 @@ class WrappedPtrOperations<JS::PropertyDescriptor, Wrapper>
|
|||
JSPROP_GETTER |
|
||||
JSPROP_SETTER |
|
||||
JSPROP_RESOLVING |
|
||||
SHADOWABLE)) == 0);
|
||||
JSPROP_INTERNAL_USE_BIT)) == 0);
|
||||
MOZ_ASSERT(!hasAll(JSPROP_IGNORE_ENUMERATE | JSPROP_ENUMERATE));
|
||||
MOZ_ASSERT(!hasAll(JSPROP_IGNORE_PERMANENT | JSPROP_PERMANENT));
|
||||
if (isAccessorDescriptor()) {
|
||||
MOZ_ASSERT(!has(JSPROP_READONLY));
|
||||
MOZ_ASSERT(!has(JSPROP_IGNORE_READONLY));
|
||||
MOZ_ASSERT(!has(JSPROP_IGNORE_VALUE));
|
||||
MOZ_ASSERT(!has(SHADOWABLE));
|
||||
MOZ_ASSERT(!has(JSPROP_INTERNAL_USE_BIT));
|
||||
MOZ_ASSERT(value().isUndefined());
|
||||
MOZ_ASSERT_IF(!has(JSPROP_GETTER), !getter());
|
||||
MOZ_ASSERT_IF(!has(JSPROP_SETTER), !setter());
|
||||
|
@ -2130,7 +2104,7 @@ class WrappedPtrOperations<JS::PropertyDescriptor, Wrapper>
|
|||
JSPROP_GETTER |
|
||||
JSPROP_SETTER |
|
||||
JSPROP_RESOLVING |
|
||||
SHADOWABLE)) == 0);
|
||||
JSPROP_INTERNAL_USE_BIT)) == 0);
|
||||
MOZ_ASSERT_IF(isAccessorDescriptor(), has(JSPROP_GETTER) && has(JSPROP_SETTER));
|
||||
#endif
|
||||
}
|
||||
|
@ -2420,6 +2394,10 @@ extern JS_PUBLIC_API(bool)
|
|||
JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JSNative getter,
|
||||
JSNative setter, unsigned attrs);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleObject getter,
|
||||
JS::HandleObject setter, unsigned attrs);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleObject value,
|
||||
unsigned attrs);
|
||||
|
@ -2448,6 +2426,10 @@ extern JS_PUBLIC_API(bool)
|
|||
JS_DefineProperty(JSContext* cx, JS::HandleObject obj, const char* name, JSNative getter,
|
||||
JSNative setter, unsigned attrs);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_DefineProperty(JSContext* cx, JS::HandleObject obj, const char* name, JS::HandleObject getter,
|
||||
JS::HandleObject setter, unsigned attrs);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_DefineProperty(JSContext* cx, JS::HandleObject obj, const char* name, JS::HandleObject value,
|
||||
unsigned attrs);
|
||||
|
@ -2483,7 +2465,7 @@ JS_DefineUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, s
|
|||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_DefineUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen,
|
||||
JSNative getter, JSNative setter, unsigned attrs);
|
||||
JS::HandleObject getter, JS::HandleObject setter, unsigned attrs);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_DefineUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen,
|
||||
|
@ -2510,8 +2492,8 @@ JS_DefineElement(JSContext* cx, JS::HandleObject obj, uint32_t index, JS::Handle
|
|||
unsigned attrs);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_DefineElement(JSContext* cx, JS::HandleObject obj, uint32_t index, JSNative getter,
|
||||
JSNative setter, unsigned attrs);
|
||||
JS_DefineElement(JSContext* cx, JS::HandleObject obj, uint32_t index, JS::HandleObject getter,
|
||||
JS::HandleObject setter, unsigned attrs);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_DefineElement(JSContext* cx, JS::HandleObject obj, uint32_t index, JS::HandleObject value,
|
||||
|
|
|
@ -576,7 +576,7 @@ MappedArgumentsObject::obj_resolve(JSContext* cx, HandleObject obj, HandleId id,
|
|||
return true;
|
||||
}
|
||||
|
||||
unsigned attrs = JSPROP_SHADOWABLE | JSPROP_RESOLVING;
|
||||
unsigned attrs = JSPROP_RESOLVING;
|
||||
if (JSID_IS_INT(id)) {
|
||||
uint32_t arg = uint32_t(JSID_TO_INT(id));
|
||||
if (arg >= argsobj->initialLength() || argsobj->isElementDeleted(arg))
|
||||
|
@ -776,10 +776,20 @@ UnmappedArgumentsObject::obj_resolve(JSContext* cx, HandleObject obj, HandleId i
|
|||
return true;
|
||||
}
|
||||
|
||||
unsigned attrs = JSPROP_SHADOWABLE;
|
||||
GetterOp getter = UnmappedArgGetter;
|
||||
SetterOp setter = UnmappedArgSetter;
|
||||
if (JSID_IS_ATOM(id, cx->names().callee)) {
|
||||
RootedObject throwTypeError(cx, GlobalObject::getOrCreateThrowTypeError(cx, cx->global()));
|
||||
if (!throwTypeError)
|
||||
return false;
|
||||
|
||||
unsigned attrs = JSPROP_RESOLVING | JSPROP_PERMANENT | JSPROP_GETTER | JSPROP_SETTER;
|
||||
if (!NativeDefineAccessorProperty(cx, argsobj, id, throwTypeError, throwTypeError, attrs))
|
||||
return false;
|
||||
|
||||
*resolvedp = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned attrs = JSPROP_RESOLVING;
|
||||
if (JSID_IS_INT(id)) {
|
||||
uint32_t arg = uint32_t(JSID_TO_INT(id));
|
||||
if (arg >= argsobj->initialLength() || argsobj->isElementDeleted(arg))
|
||||
|
@ -790,21 +800,14 @@ UnmappedArgumentsObject::obj_resolve(JSContext* cx, HandleObject obj, HandleId i
|
|||
if (argsobj->hasOverriddenLength())
|
||||
return true;
|
||||
} else {
|
||||
if (!JSID_IS_ATOM(id, cx->names().callee))
|
||||
return true;
|
||||
|
||||
JSObject* throwTypeError = GlobalObject::getOrCreateThrowTypeError(cx, cx->global());
|
||||
if (!throwTypeError)
|
||||
return false;
|
||||
|
||||
attrs = JSPROP_PERMANENT | JSPROP_GETTER | JSPROP_SETTER;
|
||||
getter = CastAsGetterOp(throwTypeError);
|
||||
setter = CastAsSetterOp(throwTypeError);
|
||||
return true;
|
||||
}
|
||||
|
||||
attrs |= JSPROP_RESOLVING;
|
||||
if (!NativeDefineAccessorProperty(cx, argsobj, id, getter, setter, attrs))
|
||||
if (!NativeDefineAccessorProperty(cx, argsobj, id, UnmappedArgGetter, UnmappedArgSetter,
|
||||
attrs))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
*resolvedp = true;
|
||||
return true;
|
||||
|
|
|
@ -8431,8 +8431,7 @@ DebuggerArguments::create(JSContext* cx, HandleObject proto, HandleDebuggerFrame
|
|||
return nullptr;
|
||||
id = INT_TO_JSID(i);
|
||||
if (!getobj ||
|
||||
!NativeDefineAccessorProperty(cx, obj, id,
|
||||
JS_DATA_TO_FUNC_PTR(GetterOp, getobj.get()), nullptr,
|
||||
!NativeDefineAccessorProperty(cx, obj, id, getobj, nullptr,
|
||||
JSPROP_ENUMERATE | JSPROP_GETTER))
|
||||
{
|
||||
return nullptr;
|
||||
|
|
|
@ -4834,8 +4834,6 @@ js::InitGetterSetterOperation(JSContext* cx, jsbytecode* pc, HandleObject obj, H
|
|||
HandleObject val)
|
||||
{
|
||||
MOZ_ASSERT(val->isCallable());
|
||||
GetterOp getter;
|
||||
SetterOp setter;
|
||||
|
||||
JSOp op = JSOp(*pc);
|
||||
|
||||
|
@ -4846,18 +4844,14 @@ js::InitGetterSetterOperation(JSContext* cx, jsbytecode* pc, HandleObject obj, H
|
|||
if (op == JSOP_INITPROP_GETTER || op == JSOP_INITELEM_GETTER ||
|
||||
op == JSOP_INITHIDDENPROP_GETTER || op == JSOP_INITHIDDENELEM_GETTER)
|
||||
{
|
||||
getter = CastAsGetterOp(val);
|
||||
setter = nullptr;
|
||||
attrs |= JSPROP_GETTER;
|
||||
} else {
|
||||
MOZ_ASSERT(op == JSOP_INITPROP_SETTER || op == JSOP_INITELEM_SETTER ||
|
||||
op == JSOP_INITHIDDENPROP_SETTER || op == JSOP_INITHIDDENELEM_SETTER);
|
||||
getter = nullptr;
|
||||
setter = CastAsSetterOp(val);
|
||||
attrs |= JSPROP_SETTER;
|
||||
return DefineAccessorProperty(cx, obj, id, val, nullptr, attrs);
|
||||
}
|
||||
|
||||
return DefineAccessorProperty(cx, obj, id, getter, setter, attrs);
|
||||
MOZ_ASSERT(op == JSOP_INITPROP_SETTER || op == JSOP_INITELEM_SETTER ||
|
||||
op == JSOP_INITHIDDENPROP_SETTER || op == JSOP_INITHIDDENELEM_SETTER);
|
||||
attrs |= JSPROP_SETTER;
|
||||
return DefineAccessorProperty(cx, obj, id, nullptr, val, attrs);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -2803,13 +2803,17 @@ js::DefineProperty(JSContext* cx, HandleObject obj, HandleId id, Handle<Property
|
|||
|
||||
bool
|
||||
js::DefineAccessorProperty(JSContext* cx, HandleObject obj, HandleId id,
|
||||
JSGetterOp getter, JSSetterOp setter, unsigned attrs,
|
||||
HandleObject getter, HandleObject setter, unsigned attrs,
|
||||
ObjectOpResult& result)
|
||||
{
|
||||
MOZ_ASSERT(!(attrs & JSPROP_PROPOP_ACCESSORS));
|
||||
|
||||
Rooted<PropertyDescriptor> desc(cx);
|
||||
desc.initFields(nullptr, UndefinedHandleValue, attrs, getter, setter);
|
||||
|
||||
{
|
||||
GetterOp getterOp = JS_DATA_TO_FUNC_PTR(GetterOp, getter.get());
|
||||
SetterOp setterOp = JS_DATA_TO_FUNC_PTR(SetterOp, setter.get());
|
||||
desc.initFields(nullptr, UndefinedHandleValue, attrs, getterOp, setterOp);
|
||||
}
|
||||
|
||||
if (DefinePropertyOp op = obj->getOpsDefineProperty()) {
|
||||
MOZ_ASSERT(!cx->helperThread());
|
||||
return op(cx, obj, id, desc, result);
|
||||
|
@ -2830,15 +2834,6 @@ js::DefineDataProperty(JSContext* cx, HandleObject obj, HandleId id, HandleValue
|
|||
return NativeDefineProperty(cx, obj.as<NativeObject>(), id, desc, result);
|
||||
}
|
||||
|
||||
bool
|
||||
js::DefineAccessorProperty(JSContext* cx, HandleObject obj, PropertyName* name,
|
||||
JSGetterOp getter, JSSetterOp setter, unsigned attrs,
|
||||
ObjectOpResult& result)
|
||||
{
|
||||
RootedId id(cx, NameToId(name));
|
||||
return DefineAccessorProperty(cx, obj, id, getter, setter, attrs, result);
|
||||
}
|
||||
|
||||
bool
|
||||
js::DefineDataProperty(JSContext* cx, HandleObject obj, PropertyName* name, HandleValue value,
|
||||
unsigned attrs, ObjectOpResult& result)
|
||||
|
@ -2847,17 +2842,6 @@ js::DefineDataProperty(JSContext* cx, HandleObject obj, PropertyName* name, Hand
|
|||
return DefineDataProperty(cx, obj, id, value, attrs, result);
|
||||
}
|
||||
|
||||
bool
|
||||
js::DefineAccessorElement(JSContext* cx, HandleObject obj, uint32_t index,
|
||||
JSGetterOp getter, JSSetterOp setter, unsigned attrs,
|
||||
ObjectOpResult& result)
|
||||
{
|
||||
RootedId id(cx);
|
||||
if (!IndexToId(cx, index, &id))
|
||||
return false;
|
||||
return DefineAccessorProperty(cx, obj, id, getter, setter, attrs, result);
|
||||
}
|
||||
|
||||
bool
|
||||
js::DefineDataElement(JSContext* cx, HandleObject obj, uint32_t index, HandleValue value,
|
||||
unsigned attrs, ObjectOpResult& result)
|
||||
|
@ -2870,7 +2854,7 @@ js::DefineDataElement(JSContext* cx, HandleObject obj, uint32_t index, HandleVal
|
|||
|
||||
bool
|
||||
js::DefineAccessorProperty(JSContext* cx, HandleObject obj, HandleId id,
|
||||
JSGetterOp getter, JSSetterOp setter, unsigned attrs)
|
||||
HandleObject getter, HandleObject setter, unsigned attrs)
|
||||
{
|
||||
ObjectOpResult result;
|
||||
if (!DefineAccessorProperty(cx, obj, id, getter, setter, attrs, result))
|
||||
|
@ -2898,14 +2882,6 @@ js::DefineDataProperty(JSContext* cx, HandleObject obj, HandleId id, HandleValue
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
js::DefineAccessorProperty(JSContext* cx, HandleObject obj, PropertyName* name,
|
||||
JSGetterOp getter, JSSetterOp setter, unsigned attrs)
|
||||
{
|
||||
RootedId id(cx, NameToId(name));
|
||||
return DefineAccessorProperty(cx, obj, id, getter, setter, attrs);
|
||||
}
|
||||
|
||||
bool
|
||||
js::DefineDataProperty(JSContext* cx, HandleObject obj, PropertyName* name, HandleValue value,
|
||||
unsigned attrs)
|
||||
|
@ -2914,16 +2890,6 @@ js::DefineDataProperty(JSContext* cx, HandleObject obj, PropertyName* name, Hand
|
|||
return DefineDataProperty(cx, obj, id, value, attrs);
|
||||
}
|
||||
|
||||
bool
|
||||
js::DefineAccessorElement(JSContext* cx, HandleObject obj, uint32_t index,
|
||||
JSGetterOp getter, JSSetterOp setter, unsigned attrs)
|
||||
{
|
||||
RootedId id(cx);
|
||||
if (!IndexToId(cx, index, &id))
|
||||
return false;
|
||||
return DefineAccessorProperty(cx, obj, id, getter, setter, attrs);
|
||||
}
|
||||
|
||||
bool
|
||||
js::DefineDataElement(JSContext* cx, HandleObject obj, uint32_t index, HandleValue value,
|
||||
unsigned attrs)
|
||||
|
|
|
@ -716,27 +716,17 @@ DefineProperty(JSContext* cx, HandleObject obj, HandleId id,
|
|||
|
||||
extern bool
|
||||
DefineAccessorProperty(JSContext* cx, HandleObject obj, HandleId id,
|
||||
JSGetterOp getter, JSSetterOp setter, unsigned attrs,
|
||||
HandleObject getter, HandleObject setter, unsigned attrs,
|
||||
ObjectOpResult& result);
|
||||
|
||||
extern bool
|
||||
DefineDataProperty(JSContext* cx, HandleObject obj, HandleId id, HandleValue value,
|
||||
unsigned attrs, ObjectOpResult& result);
|
||||
|
||||
extern bool
|
||||
DefineAccessorProperty(JSContext* cx, HandleObject obj, PropertyName* name,
|
||||
JSGetterOp getter, JSSetterOp setter, unsigned attrs,
|
||||
ObjectOpResult& result);
|
||||
|
||||
extern bool
|
||||
DefineDataProperty(JSContext* cx, HandleObject obj, PropertyName* name, HandleValue value,
|
||||
unsigned attrs, ObjectOpResult& result);
|
||||
|
||||
extern bool
|
||||
DefineAccessorElement(JSContext* cx, HandleObject obj, uint32_t index,
|
||||
JSGetterOp getter, JSSetterOp setter, unsigned attrs,
|
||||
ObjectOpResult& result);
|
||||
|
||||
extern bool
|
||||
DefineDataElement(JSContext* cx, HandleObject obj, uint32_t index, HandleValue value,
|
||||
unsigned attrs, ObjectOpResult& result);
|
||||
|
@ -750,24 +740,17 @@ DefineProperty(JSContext* cx, HandleObject obj, HandleId id, Handle<JS::Property
|
|||
|
||||
extern bool
|
||||
DefineAccessorProperty(JSContext* cx, HandleObject obj, HandleId id,
|
||||
JSGetterOp getter, JSSetterOp setter, unsigned attrs = JSPROP_ENUMERATE);
|
||||
HandleObject getter, HandleObject setter,
|
||||
unsigned attrs = JSPROP_ENUMERATE);
|
||||
|
||||
extern bool
|
||||
DefineDataProperty(JSContext* cx, HandleObject obj, HandleId id, HandleValue value,
|
||||
unsigned attrs = JSPROP_ENUMERATE);
|
||||
|
||||
extern bool
|
||||
DefineAccessorProperty(JSContext* cx, HandleObject obj, PropertyName* name,
|
||||
JSGetterOp getter, JSSetterOp setter, unsigned attrs = JSPROP_ENUMERATE);
|
||||
|
||||
extern bool
|
||||
DefineDataProperty(JSContext* cx, HandleObject obj, PropertyName* name, HandleValue value,
|
||||
unsigned attrs = JSPROP_ENUMERATE);
|
||||
|
||||
extern bool
|
||||
DefineAccessorElement(JSContext* cx, HandleObject obj, uint32_t index,
|
||||
JSGetterOp getter, JSSetterOp setter, unsigned attrs = JSPROP_ENUMERATE);
|
||||
|
||||
extern bool
|
||||
DefineDataElement(JSContext* cx, HandleObject obj, uint32_t index, HandleValue value,
|
||||
unsigned attrs = JSPROP_ENUMERATE);
|
||||
|
@ -1094,18 +1077,6 @@ CloneObject(JSContext* cx, HandleObject obj, Handle<js::TaggedProto> proto);
|
|||
extern JSObject*
|
||||
DeepCloneObjectLiteral(JSContext* cx, HandleObject obj, NewObjectKind newKind = GenericObject);
|
||||
|
||||
inline JSGetterOp
|
||||
CastAsGetterOp(JSObject* object)
|
||||
{
|
||||
return JS_DATA_TO_FUNC_PTR(JSGetterOp, object);
|
||||
}
|
||||
|
||||
inline JSSetterOp
|
||||
CastAsSetterOp(JSObject* object)
|
||||
{
|
||||
return JS_DATA_TO_FUNC_PTR(JSSetterOp, object);
|
||||
}
|
||||
|
||||
/* ES6 draft rev 32 (2015 Feb 2) 6.2.4.5 ToPropertyDescriptor(Obj) */
|
||||
bool
|
||||
ToPropertyDescriptor(JSContext* cx, HandleValue descval, bool checkAccessors,
|
||||
|
|
|
@ -1823,16 +1823,6 @@ js::NativeDefineProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
|
|||
return result.succeed();
|
||||
}
|
||||
|
||||
bool
|
||||
js::NativeDefineAccessorProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
|
||||
GetterOp getter, SetterOp setter, unsigned attrs,
|
||||
ObjectOpResult& result)
|
||||
{
|
||||
Rooted<PropertyDescriptor> desc(cx);
|
||||
desc.initFields(nullptr, UndefinedHandleValue, attrs, getter, setter);
|
||||
return NativeDefineProperty(cx, obj, id, desc, result);
|
||||
}
|
||||
|
||||
bool
|
||||
js::NativeDefineDataProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
|
||||
HandleValue value, unsigned attrs, ObjectOpResult& result)
|
||||
|
@ -1844,11 +1834,15 @@ js::NativeDefineDataProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
|
|||
|
||||
bool
|
||||
js::NativeDefineAccessorProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
|
||||
JSGetterOp getter, JSSetterOp setter, unsigned attrs)
|
||||
GetterOp getter, SetterOp setter, unsigned attrs)
|
||||
{
|
||||
Rooted<PropertyDescriptor> desc(cx);
|
||||
desc.initFields(nullptr, UndefinedHandleValue, attrs, getter, setter);
|
||||
|
||||
ObjectOpResult result;
|
||||
if (!NativeDefineAccessorProperty(cx, obj, id, getter, setter, attrs, result))
|
||||
if (!NativeDefineProperty(cx, obj, id, desc, result))
|
||||
return false;
|
||||
|
||||
if (!result) {
|
||||
// Off-thread callers should not get here: they must call this
|
||||
// function only with known-valid arguments. Populating a new
|
||||
|
@ -1857,6 +1851,34 @@ js::NativeDefineAccessorProperty(JSContext* cx, HandleNativeObject obj, HandleId
|
|||
result.reportError(cx, obj, id);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
js::NativeDefineAccessorProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
|
||||
HandleObject getter, HandleObject setter, unsigned attrs)
|
||||
{
|
||||
Rooted<PropertyDescriptor> desc(cx);
|
||||
{
|
||||
GetterOp getterOp = JS_DATA_TO_FUNC_PTR(GetterOp, getter.get());
|
||||
SetterOp setterOp = JS_DATA_TO_FUNC_PTR(SetterOp, setter.get());
|
||||
desc.initFields(nullptr, UndefinedHandleValue, attrs, getterOp, setterOp);
|
||||
}
|
||||
|
||||
ObjectOpResult result;
|
||||
if (!NativeDefineProperty(cx, obj, id, desc, result))
|
||||
return false;
|
||||
|
||||
if (!result) {
|
||||
// Off-thread callers should not get here: they must call this
|
||||
// function only with known-valid arguments. Populating a new
|
||||
// PlainObject with configurable properties is fine.
|
||||
MOZ_ASSERT(!cx->helperThread());
|
||||
result.reportError(cx, obj, id);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1878,14 +1900,6 @@ js::NativeDefineDataProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
js::NativeDefineAccessorProperty(JSContext* cx, HandleNativeObject obj, PropertyName* name,
|
||||
JSGetterOp getter, JSSetterOp setter, unsigned attrs)
|
||||
{
|
||||
RootedId id(cx, NameToId(name));
|
||||
return NativeDefineAccessorProperty(cx, obj, id, getter, setter, attrs);
|
||||
}
|
||||
|
||||
bool
|
||||
js::NativeDefineDataProperty(JSContext* cx, HandleNativeObject obj, PropertyName* name,
|
||||
HandleValue value, unsigned attrs)
|
||||
|
@ -2687,25 +2701,9 @@ SetExistingProperty(JSContext* cx, HandleNativeObject obj, HandleId id, HandleVa
|
|||
// result is |shape|.
|
||||
|
||||
// Steps 5.e.i-ii.
|
||||
if (pobj->is<ArrayObject>() && id == NameToId(cx->names().length)) {
|
||||
Rooted<ArrayObject*> arr(cx, &pobj->as<ArrayObject>());
|
||||
return ArraySetLength(cx, arr, id, shape->attributes(), v, result);
|
||||
}
|
||||
return NativeSetExistingDataProperty(cx, pobj, shape, v, result);
|
||||
}
|
||||
|
||||
// SpiderMonkey special case: assigning to an inherited slotless
|
||||
// property causes the setter to be called, instead of shadowing,
|
||||
// unless the existing property is JSPROP_SHADOWABLE (see bug 552432).
|
||||
if (!shape->isDataProperty() && !shape->hasShadowable()) {
|
||||
// Even weirder sub-special-case: inherited slotless data property
|
||||
// with default setter. Wut.
|
||||
if (shape->hasDefaultSetter())
|
||||
return result.succeed();
|
||||
|
||||
return CallJSSetterOp(cx, shape->setterOp(), obj, id, v, result);
|
||||
}
|
||||
|
||||
// Shadow pobj[id] by defining a new data property receiver[id].
|
||||
// Delegate everything to SetPropertyByDefining.
|
||||
return SetPropertyByDefining(cx, id, v, receiver, result);
|
||||
|
|
|
@ -1528,11 +1528,6 @@ NativeDefineProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
|
|||
Handle<JS::PropertyDescriptor> desc,
|
||||
ObjectOpResult& result);
|
||||
|
||||
extern bool
|
||||
NativeDefineAccessorProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
|
||||
JSGetterOp getter, JSSetterOp setter, unsigned attrs,
|
||||
ObjectOpResult& result);
|
||||
|
||||
extern bool
|
||||
NativeDefineDataProperty(JSContext* cx, HandleNativeObject obj, HandleId id, HandleValue value,
|
||||
unsigned attrs, ObjectOpResult& result);
|
||||
|
@ -1540,16 +1535,16 @@ NativeDefineDataProperty(JSContext* cx, HandleNativeObject obj, HandleId id, Han
|
|||
/* If the result out-param is omitted, throw on failure. */
|
||||
extern bool
|
||||
NativeDefineAccessorProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
|
||||
JSGetterOp getter, JSSetterOp setter, unsigned attrs);
|
||||
GetterOp getter, SetterOp setter, unsigned attrs);
|
||||
|
||||
extern bool
|
||||
NativeDefineAccessorProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
|
||||
HandleObject getter, HandleObject setter, unsigned attrs);
|
||||
|
||||
extern bool
|
||||
NativeDefineDataProperty(JSContext* cx, HandleNativeObject obj, HandleId id, HandleValue value,
|
||||
unsigned attrs);
|
||||
|
||||
extern bool
|
||||
NativeDefineAccessorProperty(JSContext* cx, HandleNativeObject obj, PropertyName* name,
|
||||
JSGetterOp getter, JSSetterOp setter, unsigned attrs);
|
||||
|
||||
extern bool
|
||||
NativeDefineDataProperty(JSContext* cx, HandleNativeObject obj, PropertyName* name,
|
||||
HandleValue value, unsigned attrs);
|
||||
|
|
|
@ -238,18 +238,6 @@ AutoRooterGetterSetter::AutoRooterGetterSetter(JSContext* cx, uint8_t attrs,
|
|||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
|
||||
inline
|
||||
AutoRooterGetterSetter::AutoRooterGetterSetter(JSContext* cx, uint8_t attrs,
|
||||
JSNative* pgetter, JSNative* psetter
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
|
||||
{
|
||||
if (attrs & (JSPROP_GETTER | JSPROP_SETTER)) {
|
||||
inner.emplace(cx, attrs, reinterpret_cast<GetterOp*>(pgetter),
|
||||
reinterpret_cast<SetterOp*>(psetter));
|
||||
}
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
|
||||
static inline uint8_t
|
||||
GetPropertyAttributes(JSObject* obj, PropertyResult prop)
|
||||
{
|
||||
|
|
|
@ -541,6 +541,21 @@ Shape::updateDictionaryTable(ShapeTable* table, ShapeTable::Entry* entry,
|
|||
parent->handoffTableTo(this);
|
||||
}
|
||||
|
||||
static void
|
||||
AssertValidPropertyOp(NativeObject* obj, GetterOp getter, SetterOp setter, unsigned attrs)
|
||||
{
|
||||
// We only support PropertyOp accessors on ArrayObject and ArgumentsObject
|
||||
// and we don't want to add more of these properties (bug 1404885).
|
||||
|
||||
#ifdef DEBUG
|
||||
if ((getter && !(attrs & JSPROP_GETTER)) ||
|
||||
(setter && !(attrs & JSPROP_SETTER)))
|
||||
{
|
||||
MOZ_ASSERT(obj->is<ArrayObject>() || obj->is<ArgumentsObject>());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* static */ Shape*
|
||||
NativeObject::addAccessorPropertyInternal(JSContext* cx,
|
||||
HandleNativeObject obj, HandleId id,
|
||||
|
@ -551,6 +566,8 @@ NativeObject::addAccessorPropertyInternal(JSContext* cx,
|
|||
AutoCheckShapeConsistency check(obj);
|
||||
AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
|
||||
|
||||
AssertValidPropertyOp(obj, getter, setter, attrs);
|
||||
|
||||
if (!maybeConvertToOrGrowDictionaryForAdd(cx, obj, id, &table, &entry, keep))
|
||||
return nullptr;
|
||||
|
||||
|
@ -972,6 +989,7 @@ NativeObject::putAccessorProperty(JSContext* cx, HandleNativeObject obj, HandleI
|
|||
|
||||
AutoCheckShapeConsistency check(obj);
|
||||
AssertValidArrayIndex(obj, id);
|
||||
AssertValidPropertyOp(obj, getter, setter, attrs);
|
||||
|
||||
AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
|
||||
|
||||
|
|
|
@ -387,11 +387,6 @@ class MOZ_RAII AutoKeepShapeTables
|
|||
inline ~AutoKeepShapeTables();
|
||||
};
|
||||
|
||||
/*
|
||||
* Use the reserved attribute bit to mean shadowability.
|
||||
*/
|
||||
#define JSPROP_SHADOWABLE JSPROP_INTERNAL_USE_BIT
|
||||
|
||||
/*
|
||||
* Shapes encode information about both a property lineage *and* a particular
|
||||
* property. This information is split across the Shape and the BaseShape
|
||||
|
@ -1078,8 +1073,6 @@ class Shape : public gc::TenuredCell
|
|||
return (attrs & (JSPROP_SETTER | JSPROP_GETTER)) != 0;
|
||||
}
|
||||
|
||||
bool hasShadowable() const { return attrs & JSPROP_SHADOWABLE; }
|
||||
|
||||
uint32_t entryCount() {
|
||||
JS::AutoCheckCannotGC nogc;
|
||||
if (ShapeTable* table = maybeTable(nogc))
|
||||
|
@ -1216,9 +1209,6 @@ class MOZ_RAII AutoRooterGetterSetter
|
|||
inline AutoRooterGetterSetter(JSContext* cx, uint8_t attrs,
|
||||
GetterOp* pgetter, SetterOp* psetter
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
|
||||
inline AutoRooterGetterSetter(JSContext* cx, uint8_t attrs,
|
||||
JSNative* pgetter, JSNative* psetter
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
|
||||
|
||||
private:
|
||||
mozilla::Maybe<Inner> inner;
|
||||
|
|
|
@ -1638,17 +1638,17 @@ class MOZ_STACK_CLASS JS_HAZ_ROOTED ModuleValidator
|
|||
class HashableSig
|
||||
{
|
||||
uint32_t sigIndex_;
|
||||
const SigWithIdVector& sigs_;
|
||||
const TypeDefVector& types_;
|
||||
|
||||
public:
|
||||
HashableSig(uint32_t sigIndex, const SigWithIdVector& sigs)
|
||||
: sigIndex_(sigIndex), sigs_(sigs)
|
||||
HashableSig(uint32_t sigIndex, const TypeDefVector& types)
|
||||
: sigIndex_(sigIndex), types_(types)
|
||||
{}
|
||||
uint32_t sigIndex() const {
|
||||
return sigIndex_;
|
||||
}
|
||||
const Sig& sig() const {
|
||||
return sigs_[sigIndex_];
|
||||
return types_[sigIndex_].funcType();
|
||||
}
|
||||
|
||||
// Implement HashPolicy:
|
||||
|
@ -1666,8 +1666,8 @@ class MOZ_STACK_CLASS JS_HAZ_ROOTED ModuleValidator
|
|||
PropertyName* name_;
|
||||
|
||||
public:
|
||||
NamedSig(PropertyName* name, uint32_t sigIndex, const SigWithIdVector& sigs)
|
||||
: HashableSig(sigIndex, sigs), name_(name)
|
||||
NamedSig(PropertyName* name, uint32_t sigIndex, const TypeDefVector& types)
|
||||
: HashableSig(sigIndex, types), name_(name)
|
||||
{}
|
||||
PropertyName* name() const {
|
||||
return name_;
|
||||
|
@ -1755,22 +1755,22 @@ class MOZ_STACK_CLASS JS_HAZ_ROOTED ModuleValidator
|
|||
return standardLibrarySimdOpNames_.putNew(atom->asPropertyName(), op);
|
||||
}
|
||||
bool newSig(Sig&& sig, uint32_t* sigIndex) {
|
||||
if (env_.sigs.length() >= MaxTypes)
|
||||
if (env_.types.length() >= MaxTypes)
|
||||
return failCurrentOffset("too many signatures");
|
||||
|
||||
*sigIndex = env_.sigs.length();
|
||||
return env_.sigs.append(std::move(sig));
|
||||
*sigIndex = env_.types.length();
|
||||
return env_.types.append(std::move(sig));
|
||||
}
|
||||
bool declareSig(Sig&& sig, uint32_t* sigIndex) {
|
||||
SigSet::AddPtr p = sigSet_.lookupForAdd(sig);
|
||||
if (p) {
|
||||
*sigIndex = p->sigIndex();
|
||||
MOZ_ASSERT(env_.sigs[*sigIndex] == sig);
|
||||
MOZ_ASSERT(env_.types[*sigIndex].funcType() == sig);
|
||||
return true;
|
||||
}
|
||||
|
||||
return newSig(std::move(sig), sigIndex) &&
|
||||
sigSet_.add(p, HashableSig(*sigIndex, env_.sigs));
|
||||
sigSet_.add(p, HashableSig(*sigIndex, env_.types));
|
||||
}
|
||||
|
||||
public:
|
||||
|
@ -2308,7 +2308,7 @@ class MOZ_STACK_CLASS JS_HAZ_ROOTED ModuleValidator
|
|||
if (!declareSig(std::move(sig), &sigIndex))
|
||||
return false;
|
||||
|
||||
return funcImportMap_.add(p, NamedSig(name, sigIndex, env_.sigs), *importIndex);
|
||||
return funcImportMap_.add(p, NamedSig(name, sigIndex, env_.types), *importIndex);
|
||||
}
|
||||
|
||||
bool tryConstantAccess(uint64_t start, uint64_t width) {
|
||||
|
@ -2457,12 +2457,12 @@ class MOZ_STACK_CLASS JS_HAZ_ROOTED ModuleValidator
|
|||
for (FuncImportMap::Range r = funcImportMap_.all(); !r.empty(); r.popFront()) {
|
||||
uint32_t funcIndex = r.front().value();
|
||||
MOZ_ASSERT(!env_.funcSigs[funcIndex]);
|
||||
env_.funcSigs[funcIndex] = &env_.sigs[r.front().key().sigIndex()];
|
||||
env_.funcSigs[funcIndex] = &env_.types[r.front().key().sigIndex()].funcType();
|
||||
}
|
||||
for (const Func& func : funcDefs_) {
|
||||
uint32_t funcIndex = funcImportMap_.count() + func.funcDefIndex();
|
||||
MOZ_ASSERT(!env_.funcSigs[funcIndex]);
|
||||
env_.funcSigs[funcIndex] = &env_.sigs[func.sigIndex()];
|
||||
env_.funcSigs[funcIndex] = &env_.types[func.sigIndex()].funcType();
|
||||
}
|
||||
|
||||
if (!env_.funcImportGlobalDataOffsets.resize(funcImportMap_.count()))
|
||||
|
@ -4893,7 +4893,7 @@ CheckFunctionSignature(ModuleValidator& m, ParseNode* usepn, Sig&& sig, Property
|
|||
return m.addFuncDef(name, usepn->pn_pos.begin, std::move(sig), func);
|
||||
}
|
||||
|
||||
const SigWithId& existingSig = m.env().sigs[existing->sigIndex()];
|
||||
const SigWithId& existingSig = m.env().types[existing->sigIndex()].funcType();
|
||||
|
||||
if (!CheckSignatureAgainstExisting(m, usepn, sig, existingSig))
|
||||
return false;
|
||||
|
@ -4951,7 +4951,7 @@ CheckFuncPtrTableAgainstExisting(ModuleValidator& m, ParseNode* usepn, PropertyN
|
|||
if (mask != table.mask())
|
||||
return m.failf(usepn, "mask does not match previous value (%u)", table.mask());
|
||||
|
||||
if (!CheckSignatureAgainstExisting(m, usepn, sig, m.env().sigs[table.sigIndex()]))
|
||||
if (!CheckSignatureAgainstExisting(m, usepn, sig, m.env().types[table.sigIndex()].funcType()))
|
||||
return false;
|
||||
|
||||
*tableIndex = existing->tableIndex();
|
||||
|
@ -7376,7 +7376,7 @@ CheckFuncPtrTable(ModuleValidator& m, ParseNode* var)
|
|||
if (!func)
|
||||
return m.fail(elem, "function-pointer table's elements must be names of functions");
|
||||
|
||||
const Sig& funcSig = m.env().sigs[func->sigIndex()];
|
||||
const Sig& funcSig = m.env().types[func->sigIndex()].funcType();
|
||||
if (sig) {
|
||||
if (*sig != funcSig)
|
||||
return m.fail(elem, "all functions in table must have same signature");
|
||||
|
|
|
@ -126,7 +126,29 @@ struct AstBase
|
|||
}
|
||||
};
|
||||
|
||||
class AstSig : public AstBase
|
||||
class AstSig;
|
||||
class AstStruct;
|
||||
|
||||
class AstTypeDef : public AstBase
|
||||
{
|
||||
protected:
|
||||
enum class Which { IsSig, IsStruct };
|
||||
|
||||
private:
|
||||
Which which_;
|
||||
|
||||
public:
|
||||
explicit AstTypeDef(Which which) : which_(which) {}
|
||||
|
||||
bool isSig() const { return which_ == Which::IsSig; }
|
||||
bool isStruct() const { return which_ == Which::IsStruct; }
|
||||
inline AstSig& asSig();
|
||||
inline AstStruct& asStruct();
|
||||
inline const AstSig& asSig() const;
|
||||
inline const AstStruct& asStruct() const;
|
||||
};
|
||||
|
||||
class AstSig : public AstTypeDef
|
||||
{
|
||||
AstName name_;
|
||||
AstValTypeVector args_;
|
||||
|
@ -134,15 +156,18 @@ class AstSig : public AstBase
|
|||
|
||||
public:
|
||||
explicit AstSig(LifoAlloc& lifo)
|
||||
: args_(lifo),
|
||||
: AstTypeDef(Which::IsSig),
|
||||
args_(lifo),
|
||||
ret_(ExprType::Void)
|
||||
{}
|
||||
AstSig(AstValTypeVector&& args, ExprType ret)
|
||||
: args_(std::move(args)),
|
||||
: AstTypeDef(Which::IsSig),
|
||||
args_(std::move(args)),
|
||||
ret_(ret)
|
||||
{}
|
||||
AstSig(AstName name, AstSig&& rhs)
|
||||
: name_(name),
|
||||
: AstTypeDef(Which::IsSig),
|
||||
name_(name),
|
||||
args_(std::move(rhs.args_)),
|
||||
ret_(rhs.ret_)
|
||||
{}
|
||||
|
@ -171,6 +196,68 @@ class AstSig : public AstBase
|
|||
}
|
||||
};
|
||||
|
||||
class AstStruct : public AstTypeDef
|
||||
{
|
||||
AstName name_;
|
||||
AstNameVector fieldNames_;
|
||||
AstValTypeVector fieldTypes_;
|
||||
|
||||
public:
|
||||
explicit AstStruct(LifoAlloc& lifo)
|
||||
: AstTypeDef(Which::IsStruct),
|
||||
fieldNames_(lifo),
|
||||
fieldTypes_(lifo)
|
||||
{}
|
||||
AstStruct(AstNameVector&& names, AstValTypeVector&& types)
|
||||
: AstTypeDef(Which::IsStruct),
|
||||
fieldNames_(std::move(names)),
|
||||
fieldTypes_(std::move(types))
|
||||
{}
|
||||
AstStruct(AstName name, AstStruct&& rhs)
|
||||
: AstTypeDef(Which::IsStruct),
|
||||
name_(name),
|
||||
fieldNames_(std::move(rhs.fieldNames_)),
|
||||
fieldTypes_(std::move(rhs.fieldTypes_))
|
||||
{}
|
||||
AstName name() const {
|
||||
return name_;
|
||||
}
|
||||
const AstNameVector& fieldNames() const {
|
||||
return fieldNames_;
|
||||
}
|
||||
const AstValTypeVector& fieldTypes() const {
|
||||
return fieldTypes_;
|
||||
}
|
||||
};
|
||||
|
||||
inline AstSig&
|
||||
AstTypeDef::asSig()
|
||||
{
|
||||
MOZ_ASSERT(isSig());
|
||||
return *static_cast<AstSig*>(this);
|
||||
}
|
||||
|
||||
inline AstStruct&
|
||||
AstTypeDef::asStruct()
|
||||
{
|
||||
MOZ_ASSERT(isStruct());
|
||||
return *static_cast<AstStruct*>(this);
|
||||
}
|
||||
|
||||
inline const AstSig&
|
||||
AstTypeDef::asSig() const
|
||||
{
|
||||
MOZ_ASSERT(isSig());
|
||||
return *static_cast<const AstSig*>(this);
|
||||
}
|
||||
|
||||
inline const AstStruct&
|
||||
AstTypeDef::asStruct() const
|
||||
{
|
||||
MOZ_ASSERT(isStruct());
|
||||
return *static_cast<const AstStruct*>(this);
|
||||
}
|
||||
|
||||
const uint32_t AstNodeUnknownOffset = 0;
|
||||
|
||||
class AstNode : public AstBase
|
||||
|
@ -948,7 +1035,7 @@ class AstModule : public AstNode
|
|||
typedef AstVector<AstFunc*> FuncVector;
|
||||
typedef AstVector<AstImport*> ImportVector;
|
||||
typedef AstVector<AstExport*> ExportVector;
|
||||
typedef AstVector<AstSig*> SigVector;
|
||||
typedef AstVector<AstTypeDef*> TypeDefVector;
|
||||
typedef AstVector<AstName> NameVector;
|
||||
typedef AstVector<AstResizable> AstResizableVector;
|
||||
|
||||
|
@ -956,7 +1043,7 @@ class AstModule : public AstNode
|
|||
typedef AstHashMap<AstSig*, uint32_t, AstSig> SigMap;
|
||||
|
||||
LifoAlloc& lifo_;
|
||||
SigVector sigs_;
|
||||
TypeDefVector types_;
|
||||
SigMap sigMap_;
|
||||
ImportVector imports_;
|
||||
NameVector funcImportNames_;
|
||||
|
@ -974,7 +1061,7 @@ class AstModule : public AstNode
|
|||
public:
|
||||
explicit AstModule(LifoAlloc& lifo)
|
||||
: lifo_(lifo),
|
||||
sigs_(lifo),
|
||||
types_(lifo),
|
||||
sigMap_(lifo),
|
||||
imports_(lifo),
|
||||
funcImportNames_(lifo),
|
||||
|
@ -1038,21 +1125,21 @@ class AstModule : public AstNode
|
|||
*sigIndex = p->value();
|
||||
return true;
|
||||
}
|
||||
*sigIndex = sigs_.length();
|
||||
*sigIndex = types_.length();
|
||||
auto* lifoSig = new (lifo_) AstSig(AstName(), std::move(sig));
|
||||
return lifoSig &&
|
||||
sigs_.append(lifoSig) &&
|
||||
sigMap_.add(p, sigs_.back(), *sigIndex);
|
||||
types_.append(lifoSig) &&
|
||||
sigMap_.add(p, static_cast<AstSig*>(types_.back()), *sigIndex);
|
||||
}
|
||||
bool append(AstSig* sig) {
|
||||
uint32_t sigIndex = sigs_.length();
|
||||
if (!sigs_.append(sig))
|
||||
uint32_t sigIndex = types_.length();
|
||||
if (!types_.append(sig))
|
||||
return false;
|
||||
SigMap::AddPtr p = sigMap_.lookupForAdd(*sig);
|
||||
return p || sigMap_.add(p, sig, sigIndex);
|
||||
}
|
||||
const SigVector& sigs() const {
|
||||
return sigs_;
|
||||
const TypeDefVector& types() const {
|
||||
return types_;
|
||||
}
|
||||
bool append(AstFunc* func) {
|
||||
return funcs_.append(func);
|
||||
|
@ -1060,6 +1147,9 @@ class AstModule : public AstNode
|
|||
const FuncVector& funcs() const {
|
||||
return funcs_;
|
||||
}
|
||||
bool append(AstStruct* str) {
|
||||
return types_.append(str);
|
||||
}
|
||||
bool append(AstImport* imp) {
|
||||
switch (imp->kind()) {
|
||||
case DefinitionKind::Function:
|
||||
|
|
|
@ -3762,7 +3762,7 @@ class BaseCompiler final : public BaseCompilerInterface
|
|||
|
||||
void callIndirect(uint32_t sigIndex, const Stk& indexVal, const FunctionCall& call)
|
||||
{
|
||||
const SigWithId& sig = env_.sigs[sigIndex];
|
||||
const SigWithId& sig = env_.types[sigIndex].funcType();
|
||||
MOZ_ASSERT(sig.id.kind() != SigIdDesc::Kind::None);
|
||||
|
||||
MOZ_ASSERT(env_.tables.length() == 1);
|
||||
|
@ -7861,7 +7861,7 @@ BaseCompiler::emitCallIndirect()
|
|||
|
||||
sync();
|
||||
|
||||
const SigWithId& sig = env_.sigs[sigIndex];
|
||||
const SigWithId& sig = env_.types[sigIndex].funcType();
|
||||
|
||||
// Stack: ... arg1 .. argn callee
|
||||
|
||||
|
@ -8830,6 +8830,9 @@ BaseCompiler::emitInstanceCall(uint32_t lineOrBytecode, const MIRTypeVector& sig
|
|||
|
||||
popValueStackBy(numArgs);
|
||||
|
||||
// Note, a number of clients of emitInstanceCall currently assume that the
|
||||
// following operation does not destroy ReturnReg.
|
||||
|
||||
pushReturnedIfNonVoid(baselineCall, retType);
|
||||
}
|
||||
|
||||
|
|
|
@ -68,6 +68,9 @@ enum class TypeCode
|
|||
// Type constructor for function types
|
||||
Func = 0x60, // SLEB128(-0x20)
|
||||
|
||||
// Type constructor for structure types - unofficial
|
||||
Struct = 0x50, // SLEB128(-0x30)
|
||||
|
||||
// Special code representing the block signature ()->()
|
||||
BlockVoid = 0x40, // SLEB128(-0x40)
|
||||
|
||||
|
@ -603,6 +606,7 @@ static const unsigned MaxElemSegments = 10000000;
|
|||
static const unsigned MaxTableMaximumLength = 10000000;
|
||||
static const unsigned MaxLocals = 50000;
|
||||
static const unsigned MaxParams = 1000;
|
||||
static const unsigned MaxStructFields = 1000;
|
||||
static const unsigned MaxMemoryMaximumPages = 65536;
|
||||
static const unsigned MaxStringBytes = 100000;
|
||||
static const unsigned MaxModuleBytes = 1024 * 1024 * 1024;
|
||||
|
|
|
@ -97,12 +97,12 @@ class AstDecodeContext
|
|||
|
||||
public:
|
||||
AstDecodeContext(JSContext* cx, LifoAlloc& lifo, Decoder& d, AstModule& module,
|
||||
bool generateNames)
|
||||
bool generateNames, HasGcTypes hasGcTypes)
|
||||
: cx(cx),
|
||||
lifo(lifo),
|
||||
d(d),
|
||||
generateNames(generateNames),
|
||||
env_(CompileMode::Once, Tier::Ion, DebugEnabled::False, HasGcTypes::False,
|
||||
env_(CompileMode::Once, Tier::Ion, DebugEnabled::False, hasGcTypes,
|
||||
cx->realm()->creationOptions().getSharedMemoryAndAtomicsEnabled()
|
||||
? Shareable::True
|
||||
: Shareable::False),
|
||||
|
@ -351,7 +351,7 @@ AstDecodeCallIndirect(AstDecodeContext& c)
|
|||
if (!GenerateRef(c, AstName(u"type"), sigIndex, &sigRef))
|
||||
return false;
|
||||
|
||||
const SigWithId& sig = c.env().sigs[sigIndex];
|
||||
const SigWithId& sig = c.env().types[sigIndex].funcType();
|
||||
AstExprVector args(c.lifo);
|
||||
if (!AstDecodeCallArgs(c, sig, &args))
|
||||
return false;
|
||||
|
@ -1958,26 +1958,59 @@ AstDecodeFunctionBody(AstDecodeContext &c, uint32_t funcIndex, AstFunc** func)
|
|||
// wasm decoding and generation
|
||||
|
||||
static bool
|
||||
AstCreateSignatures(AstDecodeContext& c)
|
||||
AstCreateTypes(AstDecodeContext& c)
|
||||
{
|
||||
SigWithIdVector& sigs = c.env().sigs;
|
||||
uint32_t typeIndexForNames = 0;
|
||||
for (const TypeDef& td : c.env().types) {
|
||||
if (td.isFuncType()) {
|
||||
const Sig& sig = td.funcType();
|
||||
|
||||
for (size_t sigIndex = 0; sigIndex < sigs.length(); sigIndex++) {
|
||||
const Sig& sig = sigs[sigIndex];
|
||||
AstValTypeVector args(c.lifo);
|
||||
if (!args.appendAll(sig.args()))
|
||||
return false;
|
||||
|
||||
AstValTypeVector args(c.lifo);
|
||||
if (!args.appendAll(sig.args()))
|
||||
return false;
|
||||
AstSig sigNoName(std::move(args), sig.ret());
|
||||
|
||||
AstSig sigNoName(std::move(args), sig.ret());
|
||||
AstName sigName;
|
||||
if (!GenerateName(c, AstName(u"type"), typeIndexForNames, &sigName))
|
||||
return false;
|
||||
|
||||
AstName sigName;
|
||||
if (!GenerateName(c, AstName(u"type"), sigIndex, &sigName))
|
||||
return false;
|
||||
AstSig* astSig = new(c.lifo) AstSig(sigName, std::move(sigNoName));
|
||||
if (!astSig || !c.module().append(astSig))
|
||||
return false;
|
||||
} else if (td.isStructType()) {
|
||||
const StructType& str = td.structType();
|
||||
|
||||
AstSig* astSig = new(c.lifo) AstSig(sigName, std::move(sigNoName));
|
||||
if (!astSig || !c.module().append(astSig))
|
||||
return false;
|
||||
AstValTypeVector fieldTypes(c.lifo);
|
||||
if (!fieldTypes.appendAll(str.fields_))
|
||||
return false;
|
||||
|
||||
AstNameVector fieldNames(c.lifo);
|
||||
if (!fieldNames.resize(fieldTypes.length()))
|
||||
return false;
|
||||
|
||||
// The multiplication ensures that generated field names are unique
|
||||
// within the module, though the resulting namespace is very sparse.
|
||||
|
||||
for (size_t fieldIndex = 0; fieldIndex < fieldTypes.length(); fieldIndex++) {
|
||||
size_t idx = (typeIndexForNames * MaxStructFields) + fieldIndex;
|
||||
if (!GenerateName(c, AstName(u"f"), idx, &fieldNames[fieldIndex]))
|
||||
return false;
|
||||
}
|
||||
|
||||
AstStruct structNoName(std::move(fieldNames), std::move(fieldTypes));
|
||||
|
||||
AstName structName;
|
||||
if (!GenerateName(c, AstName(u"type"), typeIndexForNames, &structName))
|
||||
return false;
|
||||
|
||||
AstStruct* astStruct = new(c.lifo) AstStruct(structName, std::move(structNoName));
|
||||
if (!astStruct || !c.module().append(astStruct))
|
||||
return false;
|
||||
} else {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
typeIndexForNames++;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -2230,7 +2263,7 @@ AstDecodeEnvironment(AstDecodeContext& c)
|
|||
if (!DecodeModuleEnvironment(c.d, &c.env()))
|
||||
return false;
|
||||
|
||||
if (!AstCreateSignatures(c))
|
||||
if (!AstCreateTypes(c))
|
||||
return false;
|
||||
|
||||
if (!AstCreateImports(c))
|
||||
|
@ -2333,7 +2366,7 @@ wasm::BinaryToAst(JSContext* cx, const uint8_t* bytes, uint32_t length, LifoAllo
|
|||
|
||||
UniqueChars error;
|
||||
Decoder d(bytes, bytes + length, 0, &error, nullptr, /* resilient */ true);
|
||||
AstDecodeContext c(cx, lifo, d, *result, true);
|
||||
AstDecodeContext c(cx, lifo, d, *result, /* generateNames */ true, HasGcTypes::True);
|
||||
|
||||
if (!AstDecodeEnvironment(c) ||
|
||||
!AstDecodeCodeSection(c) ||
|
||||
|
|
|
@ -191,6 +191,7 @@ RenderExprType(WasmRenderContext& c, ExprType type)
|
|||
case ExprType::I64: return c.buffer.append("i64");
|
||||
case ExprType::F32: return c.buffer.append("f32");
|
||||
case ExprType::F64: return c.buffer.append("f64");
|
||||
case ExprType::AnyRef: return c.buffer.append("anyref");
|
||||
default:;
|
||||
}
|
||||
|
||||
|
@ -209,6 +210,12 @@ RenderName(WasmRenderContext& c, const AstName& name)
|
|||
return c.buffer.append(name.begin(), name.end());
|
||||
}
|
||||
|
||||
static bool
|
||||
RenderNonemptyName(WasmRenderContext& c, const AstName& name)
|
||||
{
|
||||
return name.empty() || (RenderName(c, name) && c.buffer.append(' '));
|
||||
}
|
||||
|
||||
static bool
|
||||
RenderRef(WasmRenderContext& c, const AstRef& ref)
|
||||
{
|
||||
|
@ -1481,12 +1488,8 @@ RenderSignature(WasmRenderContext& c, const AstSig& sig, const AstNameVector* ma
|
|||
if (!c.buffer.append(" (param "))
|
||||
return false;
|
||||
const AstName& name = (*maybeLocals)[i];
|
||||
if (!name.empty()) {
|
||||
if (!RenderName(c, name))
|
||||
return false;
|
||||
if (!c.buffer.append(" "))
|
||||
return false;
|
||||
}
|
||||
if (!RenderNonemptyName(c, name))
|
||||
return false;
|
||||
ValType arg = sig.args()[i];
|
||||
if (!RenderValType(c, arg))
|
||||
return false;
|
||||
|
@ -1518,34 +1521,76 @@ RenderSignature(WasmRenderContext& c, const AstSig& sig, const AstNameVector* ma
|
|||
}
|
||||
|
||||
static bool
|
||||
RenderTypeSection(WasmRenderContext& c, const AstModule::SigVector& sigs)
|
||||
RenderFields(WasmRenderContext& c, const AstStruct& str)
|
||||
{
|
||||
uint32_t numSigs = sigs.length();
|
||||
if (!numSigs)
|
||||
return true;
|
||||
const AstNameVector& fieldNames = str.fieldNames();
|
||||
const AstValTypeVector& fieldTypes = str.fieldTypes();
|
||||
|
||||
for (uint32_t sigIndex = 0; sigIndex < numSigs; sigIndex++) {
|
||||
const AstSig* sig = sigs[sigIndex];
|
||||
for (uint32_t fieldIndex = 0; fieldIndex < fieldTypes.length(); fieldIndex++) {
|
||||
if (!c.buffer.append("\n"))
|
||||
return false;
|
||||
if (!RenderIndent(c))
|
||||
return false;
|
||||
if (!c.buffer.append("(type"))
|
||||
if (!c.buffer.append("(field "))
|
||||
return false;
|
||||
if (!sig->name().empty()) {
|
||||
if (!c.buffer.append(" "))
|
||||
return false;
|
||||
if (!RenderName(c, sig->name()))
|
||||
return false;
|
||||
}
|
||||
if (!c.buffer.append(" (func"))
|
||||
if (!RenderNonemptyName(c, fieldNames[fieldIndex]))
|
||||
return false;
|
||||
if (!RenderSignature(c, *sig))
|
||||
if (!RenderValType(c, fieldTypes[fieldIndex]))
|
||||
return false;
|
||||
if (!c.buffer.append("))\n"))
|
||||
if (!c.buffer.append(')'))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<size_t ArrayLength>
|
||||
static bool
|
||||
RenderTypeStart(WasmRenderContext& c, const AstName& name, const char (&keyword)[ArrayLength])
|
||||
{
|
||||
if (!RenderIndent(c))
|
||||
return false;
|
||||
if (!c.buffer.append("(type "))
|
||||
return false;
|
||||
if (!RenderNonemptyName(c, name))
|
||||
return false;
|
||||
if (!c.buffer.append("("))
|
||||
return false;
|
||||
return c.buffer.append(keyword);
|
||||
}
|
||||
|
||||
static bool
|
||||
RenderTypeEnd(WasmRenderContext& c)
|
||||
{
|
||||
return c.buffer.append("))\n");
|
||||
}
|
||||
|
||||
static bool
|
||||
RenderTypeSection(WasmRenderContext& c, const AstModule::TypeDefVector& types)
|
||||
{
|
||||
for (uint32_t typeIndex = 0; typeIndex < types.length(); typeIndex++) {
|
||||
const AstTypeDef* type = types[typeIndex];
|
||||
if (type->isSig()) {
|
||||
const AstSig* sig = &type->asSig();
|
||||
if (!RenderTypeStart(c, sig->name(), "func"))
|
||||
return false;
|
||||
if (!RenderSignature(c, *sig))
|
||||
return false;
|
||||
} else {
|
||||
const AstStruct* strukt = &type->asStruct();
|
||||
if (!RenderTypeStart(c, strukt->name(), "struct"))
|
||||
return false;
|
||||
c.indent++;
|
||||
if (!RenderFields(c, *strukt))
|
||||
return false;
|
||||
c.indent--;
|
||||
}
|
||||
if (!RenderTypeEnd(c))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
RenderLimits(WasmRenderContext& c, const Limits& limits)
|
||||
{
|
||||
|
@ -1755,7 +1800,7 @@ RenderImport(WasmRenderContext& c, AstImport& import, const AstModule& module)
|
|||
case DefinitionKind::Function: {
|
||||
if (!c.buffer.append("(func"))
|
||||
return false;
|
||||
const AstSig* sig = module.sigs()[import.funcSig().index()];
|
||||
const AstSig* sig = &module.types()[import.funcSig().index()]->asSig();
|
||||
if (!RenderSignature(c, *sig))
|
||||
return false;
|
||||
if (!c.buffer.append(")"))
|
||||
|
@ -1858,9 +1903,9 @@ RenderExportSection(WasmRenderContext& c, const AstModule::ExportVector& exports
|
|||
}
|
||||
|
||||
static bool
|
||||
RenderFunctionBody(WasmRenderContext& c, AstFunc& func, const AstModule::SigVector& sigs)
|
||||
RenderFunctionBody(WasmRenderContext& c, AstFunc& func, const AstModule::TypeDefVector& types)
|
||||
{
|
||||
const AstSig* sig = sigs[func.sig().index()];
|
||||
const AstSig* sig = &types[func.sig().index()]->asSig();
|
||||
|
||||
uint32_t argsNum = sig->args().length();
|
||||
uint32_t localsNum = func.vars().length();
|
||||
|
@ -1904,13 +1949,13 @@ RenderFunctionBody(WasmRenderContext& c, AstFunc& func, const AstModule::SigVect
|
|||
|
||||
static bool
|
||||
RenderCodeSection(WasmRenderContext& c, const AstModule::FuncVector& funcs,
|
||||
const AstModule::SigVector& sigs)
|
||||
const AstModule::TypeDefVector& types)
|
||||
{
|
||||
uint32_t numFuncBodies = funcs.length();
|
||||
for (uint32_t funcIndex = 0; funcIndex < numFuncBodies; funcIndex++) {
|
||||
AstFunc* func = funcs[funcIndex];
|
||||
uint32_t sigIndex = func->sig().index();
|
||||
AstSig* sig = sigs[sigIndex];
|
||||
AstSig* sig = &types[sigIndex]->asSig();
|
||||
|
||||
if (!RenderIndent(c))
|
||||
return false;
|
||||
|
@ -1929,7 +1974,7 @@ RenderCodeSection(WasmRenderContext& c, const AstModule::FuncVector& funcs,
|
|||
c.currentFuncIndex = funcIndex;
|
||||
|
||||
c.indent++;
|
||||
if (!RenderFunctionBody(c, *func, sigs))
|
||||
if (!RenderFunctionBody(c, *func, types))
|
||||
return false;
|
||||
c.indent--;
|
||||
if (!RenderIndent(c))
|
||||
|
@ -2026,7 +2071,7 @@ RenderModule(WasmRenderContext& c, AstModule& module)
|
|||
|
||||
c.indent++;
|
||||
|
||||
if (!RenderTypeSection(c, module.sigs()))
|
||||
if (!RenderTypeSection(c, module.types()))
|
||||
return false;
|
||||
|
||||
if (!RenderImportSection(c, module))
|
||||
|
@ -2050,7 +2095,7 @@ RenderModule(WasmRenderContext& c, AstModule& module)
|
|||
if (!RenderElemSection(c, module))
|
||||
return false;
|
||||
|
||||
if (!RenderCodeSection(c, module.funcs(), module.sigs()))
|
||||
if (!RenderCodeSection(c, module.funcs(), module.types()))
|
||||
return false;
|
||||
|
||||
if (!RenderDataSection(c, module))
|
||||
|
|
|
@ -243,7 +243,11 @@ ModuleGenerator::init(Metadata* maybeAsmJSMetadata)
|
|||
}
|
||||
|
||||
if (!isAsmJS()) {
|
||||
for (SigWithId& sig : env_->sigs) {
|
||||
for (TypeDef& td : env_->types) {
|
||||
if (!td.isFuncType())
|
||||
continue;
|
||||
|
||||
SigWithId& sig = td.funcType();
|
||||
if (SigIdDesc::isGlobal(sig)) {
|
||||
uint32_t globalDataOffset;
|
||||
if (!allocateGlobalBytes(sizeof(void*), sizeof(void*), &globalDataOffset))
|
||||
|
@ -979,6 +983,12 @@ ModuleGenerator::finishModule(const ShareableBytes& bytecode)
|
|||
if (!code || !code->initialize(bytecode, *linkDataTier_))
|
||||
return nullptr;
|
||||
|
||||
StructTypeVector structTypes;
|
||||
for (TypeDef& td : env_->types) {
|
||||
if (td.isStructType() && !structTypes.append(std::move(td.structType())))
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SharedModule module(js_new<Module>(std::move(assumptions_),
|
||||
*code,
|
||||
std::move(maybeDebuggingBytes),
|
||||
|
@ -987,6 +997,7 @@ ModuleGenerator::finishModule(const ShareableBytes& bytecode)
|
|||
std::move(env_->exports),
|
||||
std::move(env_->dataSegments),
|
||||
std::move(env_->elemSegments),
|
||||
std::move(structTypes),
|
||||
bytecode));
|
||||
if (!module)
|
||||
return nullptr;
|
||||
|
|
|
@ -1212,7 +1212,7 @@ class FunctionCompiler
|
|||
return true;
|
||||
}
|
||||
|
||||
const SigWithId& sig = env_.sigs[sigIndex];
|
||||
const SigWithId& sig = env_.types[sigIndex].funcType();
|
||||
|
||||
CalleeDesc callee;
|
||||
if (env_.isAsmJS()) {
|
||||
|
@ -2235,7 +2235,7 @@ EmitCallIndirect(FunctionCompiler& f, bool oldStyle)
|
|||
if (f.inDeadCode())
|
||||
return true;
|
||||
|
||||
const Sig& sig = f.env().sigs[sigIndex];
|
||||
const Sig& sig = f.env().types[sigIndex].funcType();
|
||||
|
||||
CallCompileState call(f, lineOrBytecode);
|
||||
if (!EmitCallArgs(f, sig, args, &call))
|
||||
|
|
|
@ -398,6 +398,7 @@ Module::compiledSerializedSize() const
|
|||
SerializedVectorSize(exports_) +
|
||||
SerializedPodVectorSize(dataSegments_) +
|
||||
SerializedVectorSize(elemSegments_) +
|
||||
SerializedVectorSize(structTypes_) +
|
||||
code_->serializedSize();
|
||||
}
|
||||
|
||||
|
@ -423,6 +424,7 @@ Module::compiledSerialize(uint8_t* compiledBegin, size_t compiledSize) const
|
|||
cursor = SerializeVector(cursor, exports_);
|
||||
cursor = SerializePodVector(cursor, dataSegments_);
|
||||
cursor = SerializeVector(cursor, elemSegments_);
|
||||
cursor = SerializeVector(cursor, structTypes_);
|
||||
cursor = code_->serialize(cursor, linkData_);
|
||||
MOZ_RELEASE_ASSERT(cursor == compiledBegin + compiledSize);
|
||||
}
|
||||
|
@ -486,6 +488,11 @@ Module::deserialize(const uint8_t* bytecodeBegin, size_t bytecodeSize,
|
|||
if (!cursor)
|
||||
return nullptr;
|
||||
|
||||
StructTypeVector structTypes;
|
||||
cursor = DeserializeVector(cursor, &structTypes);
|
||||
if (!cursor)
|
||||
return nullptr;
|
||||
|
||||
SharedCode code;
|
||||
cursor = Code::deserialize(cursor, *bytecode, linkData, *metadata, &code);
|
||||
if (!cursor)
|
||||
|
@ -502,6 +509,7 @@ Module::deserialize(const uint8_t* bytecodeBegin, size_t bytecodeSize,
|
|||
std::move(exports),
|
||||
std::move(dataSegments),
|
||||
std::move(elemSegments),
|
||||
std::move(structTypes),
|
||||
*bytecode);
|
||||
}
|
||||
|
||||
|
@ -627,6 +635,7 @@ Module::addSizeOfMisc(MallocSizeOf mallocSizeOf,
|
|||
SizeOfVectorExcludingThis(exports_, mallocSizeOf) +
|
||||
dataSegments_.sizeOfExcludingThis(mallocSizeOf) +
|
||||
SizeOfVectorExcludingThis(elemSegments_, mallocSizeOf) +
|
||||
SizeOfVectorExcludingThis(structTypes_, mallocSizeOf) +
|
||||
bytecode_->sizeOfIncludingThisIfNotSeen(mallocSizeOf, seenBytes);
|
||||
if (unlinkedCodeForDebugging_)
|
||||
*data += unlinkedCodeForDebugging_->sizeOfExcludingThis(mallocSizeOf);
|
||||
|
|
|
@ -135,6 +135,7 @@ class Module : public JS::WasmModule
|
|||
const ExportVector exports_;
|
||||
const DataSegmentVector dataSegments_;
|
||||
const ElemSegmentVector elemSegments_;
|
||||
const StructTypeVector structTypes_;
|
||||
const SharedBytes bytecode_;
|
||||
ExclusiveTiering tiering_;
|
||||
|
||||
|
@ -170,6 +171,7 @@ class Module : public JS::WasmModule
|
|||
ExportVector&& exports,
|
||||
DataSegmentVector&& dataSegments,
|
||||
ElemSegmentVector&& elemSegments,
|
||||
StructTypeVector&& structTypes,
|
||||
const ShareableBytes& bytecode)
|
||||
: assumptions_(std::move(assumptions)),
|
||||
code_(&code),
|
||||
|
@ -179,6 +181,7 @@ class Module : public JS::WasmModule
|
|||
exports_(std::move(exports)),
|
||||
dataSegments_(std::move(dataSegments)),
|
||||
elemSegments_(std::move(elemSegments)),
|
||||
structTypes_(std::move(structTypes)),
|
||||
bytecode_(&bytecode),
|
||||
tiering_(mutexid::WasmModuleTieringLock),
|
||||
codeIsBusy_(false)
|
||||
|
|
|
@ -1732,7 +1732,7 @@ OpIter<Policy>::readCallIndirect(uint32_t* sigIndex, Value* callee, ValueVector*
|
|||
if (!readVarU32(sigIndex))
|
||||
return fail("unable to read call_indirect signature index");
|
||||
|
||||
if (*sigIndex >= env_.numSigs())
|
||||
if (*sigIndex >= env_.numTypes())
|
||||
return fail("signature index out of range");
|
||||
|
||||
uint8_t flags;
|
||||
|
@ -1745,7 +1745,10 @@ OpIter<Policy>::readCallIndirect(uint32_t* sigIndex, Value* callee, ValueVector*
|
|||
if (!popWithType(ValType::I32, callee))
|
||||
return false;
|
||||
|
||||
const Sig& sig = env_.sigs[*sigIndex];
|
||||
if (!env_.types[*sigIndex].isFuncType())
|
||||
return fail("expected signature type");
|
||||
|
||||
const Sig& sig = env_.types[*sigIndex].funcType();
|
||||
|
||||
if (!popCallArgs(sig.args(), argValues))
|
||||
return false;
|
||||
|
@ -1789,10 +1792,13 @@ OpIter<Policy>::readOldCallIndirect(uint32_t* sigIndex, Value* callee, ValueVect
|
|||
if (!readVarU32(sigIndex))
|
||||
return fail("unable to read call_indirect signature index");
|
||||
|
||||
if (*sigIndex >= env_.numSigs())
|
||||
if (*sigIndex >= env_.numTypes())
|
||||
return fail("signature index out of range");
|
||||
|
||||
const Sig& sig = env_.sigs[*sigIndex];
|
||||
if (!env_.types[*sigIndex].isFuncType())
|
||||
return fail("expected signature type");
|
||||
|
||||
const Sig& sig = env_.types[*sigIndex].funcType();
|
||||
|
||||
if (!popCallArgs(sig.args(), argValues))
|
||||
return false;
|
||||
|
|
|
@ -94,6 +94,7 @@ class WasmToken
|
|||
#ifdef ENABLE_WASM_SATURATING_TRUNC_OPS
|
||||
ExtraConversionOpcode,
|
||||
#endif
|
||||
Field,
|
||||
Float,
|
||||
Func,
|
||||
GetGlobal,
|
||||
|
@ -127,6 +128,7 @@ class WasmToken
|
|||
Shared,
|
||||
SignedInteger,
|
||||
Start,
|
||||
Struct,
|
||||
Store,
|
||||
Table,
|
||||
TeeLocal,
|
||||
|
@ -364,6 +366,7 @@ class WasmToken
|
|||
case End:
|
||||
case Error:
|
||||
case Export:
|
||||
case Field:
|
||||
case Float:
|
||||
case Func:
|
||||
case Global:
|
||||
|
@ -382,6 +385,7 @@ class WasmToken
|
|||
case Shared:
|
||||
case SignedInteger:
|
||||
case Start:
|
||||
case Struct:
|
||||
case Table:
|
||||
case Text:
|
||||
case Then:
|
||||
|
@ -951,6 +955,9 @@ WasmTokenStream::next()
|
|||
break;
|
||||
|
||||
case 'f':
|
||||
if (consume(u"field"))
|
||||
return WasmToken(WasmToken::Field, begin, cur_);
|
||||
|
||||
if (consume(u"func"))
|
||||
return WasmToken(WasmToken::Func, begin, cur_);
|
||||
|
||||
|
@ -1708,6 +1715,8 @@ WasmTokenStream::next()
|
|||
#endif
|
||||
if (consume(u"start"))
|
||||
return WasmToken(WasmToken::Start, begin, cur_);
|
||||
if (consume(u"struct"))
|
||||
return WasmToken(WasmToken::Struct, begin, cur_);
|
||||
break;
|
||||
|
||||
case 't':
|
||||
|
@ -3331,24 +3340,71 @@ ParseFunc(WasmParseContext& c, AstModule* module)
|
|||
return func && module->append(func);
|
||||
}
|
||||
|
||||
static AstSig*
|
||||
static bool
|
||||
ParseGlobalType(WasmParseContext& c, WasmToken* typeToken, bool* isMutable);
|
||||
|
||||
static bool
|
||||
ParseStructFields(WasmParseContext& c, AstStruct* str)
|
||||
{
|
||||
AstNameVector names(c.lifo);
|
||||
AstValTypeVector types(c.lifo);
|
||||
|
||||
while (true) {
|
||||
if (!c.ts.getIf(WasmToken::OpenParen))
|
||||
break;
|
||||
|
||||
if (!c.ts.match(WasmToken::Field, c.error))
|
||||
return false;
|
||||
|
||||
AstName name = c.ts.getIfName();
|
||||
|
||||
WasmToken typeToken;
|
||||
bool isMutable;
|
||||
if (!ParseGlobalType(c, &typeToken, &isMutable))
|
||||
return false;
|
||||
if (!c.ts.match(WasmToken::CloseParen, c.error))
|
||||
return false;
|
||||
|
||||
if (!names.append(name))
|
||||
return false;
|
||||
if (!types.append(typeToken.valueType()))
|
||||
return false;
|
||||
}
|
||||
|
||||
*str = AstStruct(std::move(names), std::move(types));
|
||||
return true;
|
||||
}
|
||||
|
||||
static AstTypeDef*
|
||||
ParseTypeDef(WasmParseContext& c)
|
||||
{
|
||||
AstName name = c.ts.getIfName();
|
||||
|
||||
if (!c.ts.match(WasmToken::OpenParen, c.error))
|
||||
return nullptr;
|
||||
if (!c.ts.match(WasmToken::Func, c.error))
|
||||
return nullptr;
|
||||
|
||||
AstSig sig(c.lifo);
|
||||
if (!ParseFuncSig(c, &sig))
|
||||
AstTypeDef* type = nullptr;
|
||||
if (c.ts.getIf(WasmToken::Func)) {
|
||||
AstSig sig(c.lifo);
|
||||
if (!ParseFuncSig(c, &sig))
|
||||
return nullptr;
|
||||
|
||||
type = new(c.lifo) AstSig(name, std::move(sig));
|
||||
} else if (c.ts.getIf(WasmToken::Struct)) {
|
||||
AstStruct str(c.lifo);
|
||||
if (!ParseStructFields(c, &str))
|
||||
return nullptr;
|
||||
|
||||
type = new(c.lifo) AstStruct(name, std::move(str));
|
||||
} else {
|
||||
c.ts.generateError(c.ts.peek(), "bad type definition", c.error);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!c.ts.match(WasmToken::CloseParen, c.error))
|
||||
return nullptr;
|
||||
|
||||
return new(c.lifo) AstSig(name, std::move(sig));
|
||||
return type;
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -3922,8 +3978,10 @@ ParseModule(const char16_t* text, uintptr_t stackLimit, LifoAlloc& lifo, UniqueC
|
|||
|
||||
switch (section.kind()) {
|
||||
case WasmToken::Type: {
|
||||
AstSig* sig = ParseTypeDef(c);
|
||||
if (!sig || !module->append(sig))
|
||||
AstTypeDef* typeDef = ParseTypeDef(c);
|
||||
if (!typeDef)
|
||||
return nullptr;
|
||||
if (!module->append(static_cast<AstSig*>(typeDef)))
|
||||
return nullptr;
|
||||
break;
|
||||
}
|
||||
|
@ -4008,6 +4066,7 @@ class Resolver
|
|||
AstNameMap importMap_;
|
||||
AstNameMap tableMap_;
|
||||
AstNameMap memoryMap_;
|
||||
AstNameMap typeMap_;
|
||||
AstNameVector targetStack_;
|
||||
|
||||
bool registerName(AstNameMap& map, AstName name, size_t index) {
|
||||
|
@ -4045,6 +4104,7 @@ class Resolver
|
|||
importMap_(lifo),
|
||||
tableMap_(lifo),
|
||||
memoryMap_(lifo),
|
||||
typeMap_(lifo),
|
||||
targetStack_(lifo)
|
||||
{}
|
||||
bool init() {
|
||||
|
@ -4053,6 +4113,7 @@ class Resolver
|
|||
importMap_.init() &&
|
||||
tableMap_.init() &&
|
||||
memoryMap_.init() &&
|
||||
typeMap_.init() &&
|
||||
varMap_.init() &&
|
||||
globalMap_.init();
|
||||
}
|
||||
|
@ -4072,6 +4133,7 @@ class Resolver
|
|||
REGISTER(Global, globalMap_)
|
||||
REGISTER(Table, tableMap_)
|
||||
REGISTER(Memory, memoryMap_)
|
||||
REGISTER(Type, typeMap_)
|
||||
|
||||
#undef REGISTER
|
||||
|
||||
|
@ -4097,6 +4159,7 @@ class Resolver
|
|||
RESOLVE(globalMap_, Global)
|
||||
RESOLVE(tableMap_, Table)
|
||||
RESOLVE(memoryMap_, Memory)
|
||||
RESOLVE(typeMap_, Type)
|
||||
|
||||
#undef RESOLVE
|
||||
|
||||
|
@ -4538,11 +4601,18 @@ ResolveModule(LifoAlloc& lifo, AstModule* module, UniqueChars* error)
|
|||
if (!r.init())
|
||||
return false;
|
||||
|
||||
size_t numSigs = module->sigs().length();
|
||||
for (size_t i = 0; i < numSigs; i++) {
|
||||
AstSig* sig = module->sigs()[i];
|
||||
if (!r.registerSigName(sig->name(), i))
|
||||
return r.fail("duplicate signature");
|
||||
size_t numTypes = module->types().length();
|
||||
for (size_t i = 0; i < numTypes; i++) {
|
||||
AstTypeDef* ty = module->types()[i];
|
||||
if (ty->isSig()) {
|
||||
AstSig* sig = static_cast<AstSig*>(ty);
|
||||
if (!r.registerSigName(sig->name(), i))
|
||||
return r.fail("duplicate signature");
|
||||
} else if (ty->isStruct()) {
|
||||
AstStruct* str = static_cast<AstStruct*>(ty);
|
||||
if (!r.registerTypeName(str->name(), i))
|
||||
return r.fail("duplicate struct");
|
||||
}
|
||||
}
|
||||
|
||||
size_t lastFuncIndex = 0;
|
||||
|
@ -5169,34 +5239,51 @@ EncodeExpr(Encoder& e, AstExpr& expr)
|
|||
static bool
|
||||
EncodeTypeSection(Encoder& e, AstModule& module)
|
||||
{
|
||||
if (module.sigs().empty())
|
||||
if (module.types().empty())
|
||||
return true;
|
||||
|
||||
size_t offset;
|
||||
if (!e.startSection(SectionId::Type, &offset))
|
||||
return false;
|
||||
|
||||
if (!e.writeVarU32(module.sigs().length()))
|
||||
if (!e.writeVarU32(module.types().length()))
|
||||
return false;
|
||||
|
||||
for (AstSig* sig : module.sigs()) {
|
||||
if (!e.writeVarU32(uint32_t(TypeCode::Func)))
|
||||
return false;
|
||||
|
||||
if (!e.writeVarU32(sig->args().length()))
|
||||
return false;
|
||||
|
||||
for (ValType t : sig->args()) {
|
||||
if (!e.writeValType(t))
|
||||
for (AstTypeDef* ty : module.types()) {
|
||||
if (ty->isSig()) {
|
||||
AstSig* sig = static_cast<AstSig*>(ty);
|
||||
if (!e.writeVarU32(uint32_t(TypeCode::Func)))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!e.writeVarU32(!IsVoid(sig->ret())))
|
||||
return false;
|
||||
|
||||
if (!IsVoid(sig->ret())) {
|
||||
if (!e.writeValType(NonVoidToValType(sig->ret())))
|
||||
if (!e.writeVarU32(sig->args().length()))
|
||||
return false;
|
||||
|
||||
for (ValType t : sig->args()) {
|
||||
if (!e.writeValType(t))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!e.writeVarU32(!IsVoid(sig->ret())))
|
||||
return false;
|
||||
|
||||
if (!IsVoid(sig->ret())) {
|
||||
if (!e.writeValType(NonVoidToValType(sig->ret())))
|
||||
return false;
|
||||
}
|
||||
} else if (ty->isStruct()) {
|
||||
AstStruct* str = static_cast<AstStruct*>(ty);
|
||||
if (!e.writeVarU32(uint32_t(TypeCode::Struct)))
|
||||
return false;
|
||||
|
||||
if (!e.writeVarU32(str->fieldTypes().length()))
|
||||
return false;
|
||||
|
||||
for (ValType t : str->fieldTypes()) {
|
||||
if (!e.writeValType(t))
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -327,6 +327,36 @@ SigWithId::sizeOfExcludingThis(MallocSizeOf mallocSizeOf) const
|
|||
return Sig::sizeOfExcludingThis(mallocSizeOf);
|
||||
}
|
||||
|
||||
size_t
|
||||
StructType::serializedSize() const
|
||||
{
|
||||
return SerializedPodVectorSize(fields_) +
|
||||
SerializedPodVectorSize(fieldOffsets_);
|
||||
}
|
||||
|
||||
uint8_t*
|
||||
StructType::serialize(uint8_t* cursor) const
|
||||
{
|
||||
cursor = SerializePodVector(cursor, fields_);
|
||||
cursor = SerializePodVector(cursor, fieldOffsets_);
|
||||
return cursor;
|
||||
}
|
||||
|
||||
const uint8_t*
|
||||
StructType::deserialize(const uint8_t* cursor)
|
||||
{
|
||||
(cursor = DeserializePodVector(cursor, &fields_));
|
||||
(cursor = DeserializePodVector(cursor, &fieldOffsets_));
|
||||
return cursor;
|
||||
}
|
||||
|
||||
size_t
|
||||
StructType::sizeOfExcludingThis(MallocSizeOf mallocSizeOf) const
|
||||
{
|
||||
return fields_.sizeOfExcludingThis(mallocSizeOf) +
|
||||
fieldOffsets_.sizeOfExcludingThis(mallocSizeOf);
|
||||
}
|
||||
|
||||
size_t
|
||||
Import::serializedSize() const
|
||||
{
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include "mozilla/EnumeratedArray.h"
|
||||
#include "mozilla/HashFunctions.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/Move.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/Unused.h"
|
||||
|
||||
|
@ -753,6 +752,31 @@ struct SigHashPolicy
|
|||
static bool match(const Sig* lhs, Lookup rhs) { return *lhs == rhs; }
|
||||
};
|
||||
|
||||
// Structure type.
|
||||
//
|
||||
// The Module owns a dense array of Struct values that represent the structure
|
||||
// types that the module knows about. It is created from the sparse array of
|
||||
// types in the ModuleEnvironment when the Module is created.
|
||||
|
||||
class StructType
|
||||
{
|
||||
public:
|
||||
ValTypeVector fields_; // Scalar types of fields
|
||||
Uint32Vector fieldOffsets_; // Byte offsets into an object for corresponding field
|
||||
|
||||
public:
|
||||
StructType() : fields_(), fieldOffsets_() {}
|
||||
|
||||
StructType(ValTypeVector&& fields, Uint32Vector&& fieldOffsets)
|
||||
: fields_(std::move(fields)),
|
||||
fieldOffsets_(std::move(fieldOffsets))
|
||||
{}
|
||||
|
||||
WASM_DECLARE_SERIALIZABLE(StructType)
|
||||
};
|
||||
|
||||
typedef Vector<StructType, 0, SystemAllocPolicy> StructTypeVector;
|
||||
|
||||
// An InitExpr describes a deferred initializer expression, used to initialize
|
||||
// a global or a table element offset. Such expressions are created during
|
||||
// decoding and actually executed on module instantiation.
|
||||
|
@ -1113,6 +1137,97 @@ struct SigWithId : Sig
|
|||
typedef Vector<SigWithId, 0, SystemAllocPolicy> SigWithIdVector;
|
||||
typedef Vector<const SigWithId*, 0, SystemAllocPolicy> SigWithIdPtrVector;
|
||||
|
||||
// A tagged container for the various types that can be present in a wasm
|
||||
// module's type section.
|
||||
|
||||
class TypeDef
|
||||
{
|
||||
enum { IsFuncType, IsStructType, IsNone } tag_;
|
||||
union {
|
||||
SigWithId funcType_;
|
||||
StructType structType_;
|
||||
};
|
||||
|
||||
public:
|
||||
TypeDef() : tag_(IsNone), structType_(StructType()) {}
|
||||
|
||||
explicit TypeDef(Sig&& sig) : tag_(IsFuncType), funcType_(SigWithId(std::move(sig))) {}
|
||||
|
||||
explicit TypeDef(StructType&& structType) : tag_(IsStructType), structType_(std::move(structType)) {}
|
||||
|
||||
TypeDef(TypeDef&& td) : tag_(td.tag_), structType_(StructType()) {
|
||||
switch (tag_) {
|
||||
case IsFuncType: funcType_ = std::move(td.funcType_); break;
|
||||
case IsStructType: structType_ = std::move(td.structType_); break;
|
||||
case IsNone: break;
|
||||
}
|
||||
}
|
||||
|
||||
~TypeDef() {
|
||||
switch (tag_) {
|
||||
case IsFuncType: funcType_.~SigWithId(); break;
|
||||
case IsStructType: structType_.~StructType(); break;
|
||||
case IsNone: break;
|
||||
}
|
||||
}
|
||||
|
||||
TypeDef& operator=(TypeDef&& that) {
|
||||
tag_ = that.tag_;
|
||||
switch (tag_) {
|
||||
case IsFuncType: funcType_ = std::move(that.funcType_); break;
|
||||
case IsStructType: structType_ = std::move(that.structType_); break;
|
||||
case IsNone: break;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool isFuncType() const {
|
||||
return tag_ == IsFuncType;
|
||||
}
|
||||
|
||||
bool isStructType() const {
|
||||
return tag_ == IsStructType;
|
||||
}
|
||||
|
||||
const SigWithId& funcType() const {
|
||||
MOZ_ASSERT(isFuncType());
|
||||
return funcType_;
|
||||
}
|
||||
|
||||
SigWithId& funcType() {
|
||||
MOZ_ASSERT(isFuncType());
|
||||
return funcType_;
|
||||
}
|
||||
|
||||
// p has to point to the sig_ embedded within a TypeDef for this to be
|
||||
// valid.
|
||||
static const TypeDef* fromSigWithIdPtr(const SigWithId* p) {
|
||||
const TypeDef* q = (const TypeDef*)((char*)p - offsetof(TypeDef, funcType_));
|
||||
MOZ_ASSERT(q->tag_ == IsFuncType);
|
||||
return q;
|
||||
}
|
||||
|
||||
const StructType& structType() const {
|
||||
MOZ_ASSERT(isStructType());
|
||||
return structType_;
|
||||
}
|
||||
|
||||
StructType& structType() {
|
||||
MOZ_ASSERT(isStructType());
|
||||
return structType_;
|
||||
}
|
||||
|
||||
// p has to point to the struct_ embedded within a TypeDef for this to be
|
||||
// valid.
|
||||
static const TypeDef* fromStructPtr(const StructType* p) {
|
||||
const TypeDef* q = (const TypeDef*)((char*)p - offsetof(TypeDef, structType_));
|
||||
MOZ_ASSERT(q->tag_ == IsStructType);
|
||||
return q;
|
||||
}
|
||||
};
|
||||
|
||||
typedef Vector<TypeDef, 0, SystemAllocPolicy> TypeDefVector;
|
||||
|
||||
// A wasm::Trap represents a wasm-defined trap that can occur during execution
|
||||
// which triggers a WebAssembly.RuntimeError. Generated code may jump to a Trap
|
||||
// symbolically, passing the bytecode offset to report as the trap offset. The
|
||||
|
|
|
@ -1063,6 +1063,78 @@ DecodePreamble(Decoder& d)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
DecodeFuncType(Decoder& d, ModuleEnvironment* env, uint32_t typeIndex)
|
||||
{
|
||||
uint32_t numArgs;
|
||||
if (!d.readVarU32(&numArgs))
|
||||
return d.fail("bad number of function args");
|
||||
|
||||
if (numArgs > MaxParams)
|
||||
return d.fail("too many arguments in signature");
|
||||
|
||||
ValTypeVector args;
|
||||
if (!args.resize(numArgs))
|
||||
return false;
|
||||
|
||||
for (uint32_t i = 0; i < numArgs; i++) {
|
||||
if (!DecodeValType(d, ModuleKind::Wasm, env->gcTypesEnabled, &args[i]))
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t numRets;
|
||||
if (!d.readVarU32(&numRets))
|
||||
return d.fail("bad number of function returns");
|
||||
|
||||
if (numRets > 1)
|
||||
return d.fail("too many returns in signature");
|
||||
|
||||
ExprType result = ExprType::Void;
|
||||
|
||||
if (numRets == 1) {
|
||||
ValType type;
|
||||
if (!DecodeValType(d, ModuleKind::Wasm, env->gcTypesEnabled, &type))
|
||||
return false;
|
||||
|
||||
result = ToExprType(type);
|
||||
}
|
||||
|
||||
env->types[typeIndex] = TypeDef(Sig(std::move(args), result));
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
DecodeStructType(Decoder& d, ModuleEnvironment* env, uint32_t typeIndex)
|
||||
{
|
||||
if (env->gcTypesEnabled == HasGcTypes::False)
|
||||
return d.fail("Structure types not enabled");
|
||||
|
||||
uint32_t numFields;
|
||||
if (!d.readVarU32(&numFields))
|
||||
return d.fail("Bad number of fields");
|
||||
|
||||
if (numFields > MaxStructFields)
|
||||
return d.fail("too many fields in structure");
|
||||
|
||||
ValTypeVector fields;
|
||||
if (!fields.resize(numFields))
|
||||
return false;
|
||||
|
||||
Uint32Vector fieldOffsets;
|
||||
if (!fieldOffsets.resize(numFields))
|
||||
return false;
|
||||
|
||||
// TODO (subsequent patch): lay out the fields.
|
||||
|
||||
for (uint32_t i = 0; i < numFields; i++) {
|
||||
if (!DecodeValType(d, ModuleKind::Wasm, env->gcTypesEnabled, &fields[i]))
|
||||
return false;
|
||||
}
|
||||
|
||||
env->types[typeIndex] = TypeDef(StructType(std::move(fields), std::move(fieldOffsets)));
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
DecodeTypeSection(Decoder& d, ModuleEnvironment* env)
|
||||
{
|
||||
|
@ -1072,55 +1144,33 @@ DecodeTypeSection(Decoder& d, ModuleEnvironment* env)
|
|||
if (!range)
|
||||
return true;
|
||||
|
||||
uint32_t numSigs;
|
||||
if (!d.readVarU32(&numSigs))
|
||||
return d.fail("expected number of signatures");
|
||||
uint32_t numTypes;
|
||||
if (!d.readVarU32(&numTypes))
|
||||
return d.fail("expected number of types");
|
||||
|
||||
if (numSigs > MaxTypes)
|
||||
return d.fail("too many signatures");
|
||||
if (numTypes > MaxTypes)
|
||||
return d.fail("too many types");
|
||||
|
||||
if (!env->sigs.resize(numSigs))
|
||||
if (!env->types.resize(numTypes))
|
||||
return false;
|
||||
|
||||
for (uint32_t sigIndex = 0; sigIndex < numSigs; sigIndex++) {
|
||||
for (uint32_t typeIndex = 0; typeIndex < numTypes; typeIndex++) {
|
||||
uint8_t form;
|
||||
if (!d.readFixedU8(&form) || form != uint8_t(TypeCode::Func))
|
||||
return d.fail("expected function form");
|
||||
if (!d.readFixedU8(&form))
|
||||
return d.fail("expected type form");
|
||||
|
||||
uint32_t numArgs;
|
||||
if (!d.readVarU32(&numArgs))
|
||||
return d.fail("bad number of function args");
|
||||
|
||||
if (numArgs > MaxParams)
|
||||
return d.fail("too many arguments in signature");
|
||||
|
||||
ValTypeVector args;
|
||||
if (!args.resize(numArgs))
|
||||
return false;
|
||||
|
||||
for (uint32_t i = 0; i < numArgs; i++) {
|
||||
if (!DecodeValType(d, ModuleKind::Wasm, env->gcTypesEnabled, &args[i]))
|
||||
switch (form) {
|
||||
case uint8_t(TypeCode::Func):
|
||||
if (!DecodeFuncType(d, env, typeIndex))
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t numRets;
|
||||
if (!d.readVarU32(&numRets))
|
||||
return d.fail("bad number of function returns");
|
||||
|
||||
if (numRets > 1)
|
||||
return d.fail("too many returns in signature");
|
||||
|
||||
ExprType result = ExprType::Void;
|
||||
|
||||
if (numRets == 1) {
|
||||
ValType type;
|
||||
if (!DecodeValType(d, ModuleKind::Wasm, env->gcTypesEnabled, &type))
|
||||
break;
|
||||
case uint8_t(TypeCode::Struct):
|
||||
if (!DecodeStructType(d, env, typeIndex))
|
||||
return false;
|
||||
|
||||
result = ToExprType(type);
|
||||
break;
|
||||
default:
|
||||
return d.fail("expected type form");
|
||||
}
|
||||
|
||||
env->sigs[sigIndex] = Sig(std::move(args), result);
|
||||
}
|
||||
|
||||
return d.finishSection(*range, "type");
|
||||
|
@ -1154,14 +1204,17 @@ DecodeName(Decoder& d)
|
|||
}
|
||||
|
||||
static bool
|
||||
DecodeSignatureIndex(Decoder& d, const SigWithIdVector& sigs, uint32_t* sigIndex)
|
||||
DecodeSignatureIndex(Decoder& d, const TypeDefVector& types, uint32_t* sigIndex)
|
||||
{
|
||||
if (!d.readVarU32(sigIndex))
|
||||
return d.fail("expected signature index");
|
||||
|
||||
if (*sigIndex >= sigs.length())
|
||||
if (*sigIndex >= types.length())
|
||||
return d.fail("signature index out of range");
|
||||
|
||||
if (!types[*sigIndex].isFuncType())
|
||||
return d.fail("signature index references non-signature");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1335,9 +1388,9 @@ DecodeImport(Decoder& d, ModuleEnvironment* env)
|
|||
switch (importKind) {
|
||||
case DefinitionKind::Function: {
|
||||
uint32_t sigIndex;
|
||||
if (!DecodeSignatureIndex(d, env->sigs, &sigIndex))
|
||||
if (!DecodeSignatureIndex(d, env->types, &sigIndex))
|
||||
return false;
|
||||
if (!env->funcSigs.append(&env->sigs[sigIndex]))
|
||||
if (!env->funcSigs.append(&env->types[sigIndex].funcType()))
|
||||
return false;
|
||||
if (env->funcSigs.length() > MaxFuncs)
|
||||
return d.fail("too many functions");
|
||||
|
@ -1428,9 +1481,9 @@ DecodeFunctionSection(Decoder& d, ModuleEnvironment* env)
|
|||
|
||||
for (uint32_t i = 0; i < numDefs; i++) {
|
||||
uint32_t sigIndex;
|
||||
if (!DecodeSignatureIndex(d, env->sigs, &sigIndex))
|
||||
if (!DecodeSignatureIndex(d, env->types, &sigIndex))
|
||||
return false;
|
||||
env->funcSigs.infallibleAppend(&env->sigs[sigIndex]);
|
||||
env->funcSigs.infallibleAppend(&env->types[sigIndex].funcType());
|
||||
}
|
||||
|
||||
return d.finishSection(*range, "function");
|
||||
|
|
|
@ -68,7 +68,7 @@ struct ModuleEnvironment
|
|||
MemoryUsage memoryUsage;
|
||||
uint32_t minMemoryLength;
|
||||
Maybe<uint32_t> maxMemoryLength;
|
||||
SigWithIdVector sigs;
|
||||
TypeDefVector types;
|
||||
SigWithIdPtrVector funcSigs;
|
||||
Uint32Vector funcImportGlobalDataOffsets;
|
||||
GlobalDescVector globals;
|
||||
|
@ -105,8 +105,8 @@ struct ModuleEnvironment
|
|||
size_t numTables() const {
|
||||
return tables.length();
|
||||
}
|
||||
size_t numSigs() const {
|
||||
return sigs.length();
|
||||
size_t numTypes() const {
|
||||
return types.length();
|
||||
}
|
||||
size_t numFuncs() const {
|
||||
return funcSigs.length();
|
||||
|
@ -133,7 +133,7 @@ struct ModuleEnvironment
|
|||
return funcIndex < funcImportGlobalDataOffsets.length();
|
||||
}
|
||||
uint32_t funcIndexToSigIndex(uint32_t funcIndex) const {
|
||||
return funcSigs[funcIndex] - sigs.begin();
|
||||
return TypeDef::fromSigWithIdPtr(funcSigs[funcIndex]) - types.begin();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -49,6 +49,8 @@ public:
|
|||
, mGlobalObject(aGlobal)
|
||||
, mPromise(aPromise)
|
||||
, mCharset(aOptions.mCharset)
|
||||
, mToken(nullptr)
|
||||
, mScriptLength(0)
|
||||
{
|
||||
mOptions.setNoScriptRval(!aOptions.mHasReturnValue)
|
||||
.setCanLazilyParse(aOptions.mLazilyParse)
|
||||
|
|
|
@ -41,7 +41,8 @@ public:
|
|||
void SetGlobalObject(JSObject* global);
|
||||
|
||||
explicit BackstagePass(nsIPrincipal* prin) :
|
||||
mPrincipal(prin)
|
||||
mPrincipal(prin),
|
||||
mWrapper(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,12 @@ XPCCallContext::XPCCallContext(JSContext* cx,
|
|||
mJSContext(cx),
|
||||
mWrapper(nullptr),
|
||||
mTearOff(nullptr),
|
||||
mName(cx)
|
||||
mMember(nullptr),
|
||||
mName(cx),
|
||||
mStaticMemberIsLocal(false),
|
||||
mArgc(0),
|
||||
mArgv(nullptr),
|
||||
mRetVal(nullptr)
|
||||
{
|
||||
MOZ_ASSERT(cx);
|
||||
MOZ_ASSERT(cx == nsContentUtils::GetCurrentJSContext());
|
||||
|
|
|
@ -340,10 +340,7 @@ DefinePropertyIfFound(XPCCallContext& ccx,
|
|||
AutoResolveName arn(ccx, id);
|
||||
if (resolved)
|
||||
*resolved = true;
|
||||
return JS_DefinePropertyById(ccx, obj, id,
|
||||
JS_DATA_TO_FUNC_PTR(JSNative, funobj.get()),
|
||||
nullptr,
|
||||
propFlags);
|
||||
return JS_DefinePropertyById(ccx, obj, id, funobj, nullptr, propFlags);
|
||||
}
|
||||
|
||||
if (resolved)
|
||||
|
@ -406,21 +403,18 @@ DefinePropertyIfFound(XPCCallContext& ccx,
|
|||
|
||||
propFlags |= JSPROP_GETTER;
|
||||
propFlags &= ~JSPROP_READONLY;
|
||||
JSObject* funobj = funval.toObjectOrNull();
|
||||
JSNative getter = JS_DATA_TO_FUNC_PTR(JSNative, funobj);
|
||||
JSNative setter;
|
||||
RootedObject funobjGetter(ccx, funval.toObjectOrNull());
|
||||
RootedObject funobjSetter(ccx);
|
||||
if (member->IsWritableAttribute()) {
|
||||
propFlags |= JSPROP_SETTER;
|
||||
setter = JS_DATA_TO_FUNC_PTR(JSNative, funobj);
|
||||
} else {
|
||||
setter = nullptr;
|
||||
funobjSetter = funobjGetter;
|
||||
}
|
||||
|
||||
AutoResolveName arn(ccx, id);
|
||||
if (resolved)
|
||||
*resolved = true;
|
||||
|
||||
return JS_DefinePropertyById(ccx, obj, id, getter, setter, propFlags);
|
||||
return JS_DefinePropertyById(ccx, obj, id, funobjGetter, funobjSetter, propFlags);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
|
|
@ -293,12 +293,10 @@ public:
|
|||
class XPCRootSetElem
|
||||
{
|
||||
public:
|
||||
XPCRootSetElem()
|
||||
XPCRootSetElem() :
|
||||
mNext(nullptr),
|
||||
mSelfp(nullptr)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
mNext = nullptr;
|
||||
mSelfp = nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
~XPCRootSetElem()
|
||||
|
|
|
@ -421,37 +421,29 @@ TryResolvePropertyFromSpecs(JSContext* cx, HandleId id, HandleObject holder,
|
|||
desc.value().setUndefined();
|
||||
unsigned flags = psMatch->flags;
|
||||
if (psMatch->isAccessor()) {
|
||||
RootedFunction getterObj(cx);
|
||||
RootedFunction setterObj(cx);
|
||||
if (psMatch->isSelfHosted()) {
|
||||
getterObj = JS::GetSelfHostedFunction(cx, psMatch->accessors.getter.selfHosted.funname, id, 0);
|
||||
if (!getterObj)
|
||||
JSFunction* getterFun = JS::GetSelfHostedFunction(cx, psMatch->accessors.getter.selfHosted.funname, id, 0);
|
||||
if (!getterFun)
|
||||
return false;
|
||||
desc.setGetterObject(JS_GetFunctionObject(getterObj));
|
||||
RootedObject getterObj(cx, JS_GetFunctionObject(getterFun));
|
||||
RootedObject setterObj(cx);
|
||||
if (psMatch->accessors.setter.selfHosted.funname) {
|
||||
MOZ_ASSERT(flags & JSPROP_SETTER);
|
||||
setterObj = JS::GetSelfHostedFunction(cx, psMatch->accessors.setter.selfHosted.funname, id, 0);
|
||||
if (!setterObj)
|
||||
JSFunction* setterFun = JS::GetSelfHostedFunction(cx, psMatch->accessors.setter.selfHosted.funname, id, 0);
|
||||
if (!setterFun)
|
||||
return false;
|
||||
desc.setSetterObject(JS_GetFunctionObject(setterObj));
|
||||
setterObj = JS_GetFunctionObject(setterFun);
|
||||
}
|
||||
if (!JS_DefinePropertyById(cx, holder, id, getterObj, setterObj, flags))
|
||||
return false;
|
||||
} else {
|
||||
desc.setGetter(JS_CAST_NATIVE_TO(psMatch->accessors.getter.native.op,
|
||||
JSGetterOp));
|
||||
desc.setSetter(JS_CAST_NATIVE_TO(psMatch->accessors.setter.native.op,
|
||||
JSSetterOp));
|
||||
}
|
||||
desc.setAttributes(flags);
|
||||
if (!JS_DefinePropertyById(cx, holder, id,
|
||||
JS_PROPERTYOP_GETTER(desc.getter()),
|
||||
JS_PROPERTYOP_SETTER(desc.setter()),
|
||||
// This particular descriptor, unlike most,
|
||||
// actually stores JSNatives directly,
|
||||
// since we just set it up. Do NOT pass
|
||||
// JSPROP_PROPOP_ACCESSORS here!
|
||||
desc.attributes()))
|
||||
{
|
||||
return false;
|
||||
if (!JS_DefinePropertyById(cx, holder, id,
|
||||
psMatch->accessors.getter.native.op,
|
||||
psMatch->accessors.setter.native.op,
|
||||
flags))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
RootedValue v(cx);
|
||||
|
|
|
@ -396,6 +396,4 @@ nsLayoutStatics::Shutdown()
|
|||
PromiseDebugging::Shutdown();
|
||||
|
||||
BlobURLProtocolHandler::RemoveDataEntries();
|
||||
|
||||
ClearSiteData::Shutdown();
|
||||
}
|
||||
|
|
|
@ -339,7 +339,8 @@ nsComputedDOMStyle::nsComputedDOMStyle(dom::Element* aElement,
|
|||
|
||||
nsComputedDOMStyle::~nsComputedDOMStyle()
|
||||
{
|
||||
ClearComputedStyle();
|
||||
MOZ_ASSERT(!mResolvedComputedStyle,
|
||||
"Should have called ClearComputedStyle() during last release.");
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(nsComputedDOMStyle)
|
||||
|
@ -375,8 +376,9 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsComputedDOMStyle)
|
|||
NS_INTERFACE_MAP_END_INHERITING(nsDOMCSSDeclaration)
|
||||
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsComputedDOMStyle)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsComputedDOMStyle)
|
||||
NS_IMPL_MAIN_THREAD_ONLY_CYCLE_COLLECTING_ADDREF(nsComputedDOMStyle)
|
||||
NS_IMPL_MAIN_THREAD_ONLY_CYCLE_COLLECTING_RELEASE_WITH_LAST_RELEASE(
|
||||
nsComputedDOMStyle, ClearComputedStyle())
|
||||
|
||||
nsresult
|
||||
nsComputedDOMStyle::GetPropertyValue(const nsCSSPropertyID aPropID,
|
||||
|
|
|
@ -9343,7 +9343,11 @@ class CopyNonDefaultHeaderVisitor final : public nsIHttpHeaderVisitor
|
|||
NS_IMETHOD
|
||||
VisitHeader(const nsACString& aHeader, const nsACString& aValue) override
|
||||
{
|
||||
return mTarget->SetRequestHeader(aHeader, aValue, false /* merge */);
|
||||
if (aValue.IsEmpty()) {
|
||||
return mTarget->SetEmptyRequestHeader(aHeader);
|
||||
} else {
|
||||
return mTarget->SetRequestHeader(aHeader, aValue, false /* merge */);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
|
|
@ -1 +1 @@
|
|||
30a4b03cd9d1
|
||||
NSS_3_38_RTM
|
||||
|
|
|
@ -10,4 +10,3 @@
|
|||
*/
|
||||
|
||||
#error "Do not include this header file."
|
||||
|
||||
|
|
|
@ -22,12 +22,12 @@
|
|||
* The format of the version string should be
|
||||
* "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
|
||||
*/
|
||||
#define NSS_VERSION "3.38" _NSS_CUSTOMIZED " Beta"
|
||||
#define NSS_VERSION "3.38" _NSS_CUSTOMIZED
|
||||
#define NSS_VMAJOR 3
|
||||
#define NSS_VMINOR 38
|
||||
#define NSS_VPATCH 0
|
||||
#define NSS_VBUILD 0
|
||||
#define NSS_BETA PR_TRUE
|
||||
#define NSS_BETA PR_FALSE
|
||||
|
||||
#ifndef RC_INVOKED
|
||||
|
||||
|
|
|
@ -17,11 +17,11 @@
|
|||
* The format of the version string should be
|
||||
* "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
|
||||
*/
|
||||
#define SOFTOKEN_VERSION "3.38" SOFTOKEN_ECC_STRING " Beta"
|
||||
#define SOFTOKEN_VERSION "3.38" SOFTOKEN_ECC_STRING
|
||||
#define SOFTOKEN_VMAJOR 3
|
||||
#define SOFTOKEN_VMINOR 38
|
||||
#define SOFTOKEN_VPATCH 0
|
||||
#define SOFTOKEN_VBUILD 0
|
||||
#define SOFTOKEN_BETA PR_TRUE
|
||||
#define SOFTOKEN_BETA PR_FALSE
|
||||
|
||||
#endif /* _SOFTKVER_H_ */
|
||||
|
|
|
@ -19,12 +19,12 @@
|
|||
* The format of the version string should be
|
||||
* "<major version>.<minor version>[.<patch level>[.<build number>]][ <Beta>]"
|
||||
*/
|
||||
#define NSSUTIL_VERSION "3.38 Beta"
|
||||
#define NSSUTIL_VERSION "3.38"
|
||||
#define NSSUTIL_VMAJOR 3
|
||||
#define NSSUTIL_VMINOR 38
|
||||
#define NSSUTIL_VPATCH 0
|
||||
#define NSSUTIL_VBUILD 0
|
||||
#define NSSUTIL_BETA PR_TRUE
|
||||
#define NSSUTIL_BETA PR_FALSE
|
||||
|
||||
SEC_BEGIN_PROTOS
|
||||
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
use Atom;
|
||||
use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser};
|
||||
use cssparser::{CowRcStr, Parser, SourceLocation, Token};
|
||||
use error_reporting::{ContextualParseError, ParseErrorReporter};
|
||||
use parser::{Parse, ParserContext, ParserErrorContext};
|
||||
use error_reporting::ContextualParseError;
|
||||
use parser::{Parse, ParserContext};
|
||||
use selectors::parser::SelectorParseErrorKind;
|
||||
use shared_lock::{SharedRwLockReadGuard, ToCssWithGuard};
|
||||
use std::fmt::{self, Write};
|
||||
|
@ -73,16 +73,12 @@ pub fn parse_counter_style_name_definition<'i, 't>(
|
|||
}
|
||||
|
||||
/// Parse the body (inside `{}`) of an @counter-style rule
|
||||
pub fn parse_counter_style_body<'i, 't, R>(
|
||||
pub fn parse_counter_style_body<'i, 't>(
|
||||
name: CustomIdent,
|
||||
context: &ParserContext,
|
||||
error_context: &ParserErrorContext<R>,
|
||||
input: &mut Parser<'i, 't>,
|
||||
location: SourceLocation,
|
||||
) -> Result<CounterStyleRuleData, ParseError<'i>>
|
||||
where
|
||||
R: ParseErrorReporter,
|
||||
{
|
||||
) -> Result<CounterStyleRuleData, ParseError<'i>> {
|
||||
let start = input.current_source_location();
|
||||
let mut rule = CounterStyleRuleData::empty(name, location);
|
||||
{
|
||||
|
@ -98,7 +94,7 @@ where
|
|||
slice,
|
||||
error,
|
||||
);
|
||||
context.log_css_error(error_context, location, error)
|
||||
context.log_css_error(location, error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -134,7 +130,7 @@ where
|
|||
_ => None,
|
||||
};
|
||||
if let Some(error) = error {
|
||||
context.log_css_error(error_context, start, error);
|
||||
context.log_css_error(start, error);
|
||||
Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
|
||||
} else {
|
||||
Ok(rule)
|
||||
|
|
|
@ -249,17 +249,3 @@ impl ParseErrorReporter for RustLogReporter {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Error reporter which silently forgets errors
|
||||
pub struct NullReporter;
|
||||
|
||||
impl ParseErrorReporter for NullReporter {
|
||||
fn report_error(
|
||||
&self,
|
||||
_url: &UrlExtraData,
|
||||
_location: SourceLocation,
|
||||
_error: ContextualParseError,
|
||||
) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,8 +10,8 @@ use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser, Parser};
|
|||
use cssparser::{CowRcStr, SourceLocation};
|
||||
#[cfg(feature = "gecko")]
|
||||
use cssparser::UnicodeRange;
|
||||
use error_reporting::{ContextualParseError, ParseErrorReporter};
|
||||
use parser::{Parse, ParserContext, ParserErrorContext};
|
||||
use error_reporting::ContextualParseError;
|
||||
use parser::{Parse, ParserContext};
|
||||
#[cfg(feature = "gecko")]
|
||||
use properties::longhands::font_language_override;
|
||||
use selectors::parser::SelectorParseErrorKind;
|
||||
|
@ -186,15 +186,11 @@ impl ToCss for FontStyle {
|
|||
/// Parse the block inside a `@font-face` rule.
|
||||
///
|
||||
/// Note that the prelude parsing code lives in the `stylesheets` module.
|
||||
pub fn parse_font_face_block<R>(
|
||||
pub fn parse_font_face_block(
|
||||
context: &ParserContext,
|
||||
error_context: &ParserErrorContext<R>,
|
||||
input: &mut Parser,
|
||||
location: SourceLocation,
|
||||
) -> FontFaceRuleData
|
||||
where
|
||||
R: ParseErrorReporter,
|
||||
{
|
||||
) -> FontFaceRuleData {
|
||||
let mut rule = FontFaceRuleData::empty(location);
|
||||
{
|
||||
let parser = FontFaceRuleParser {
|
||||
|
@ -206,7 +202,7 @@ where
|
|||
if let Err((error, slice)) = declaration {
|
||||
let location = error.location;
|
||||
let error = ContextualParseError::UnsupportedFontFaceDescriptor(slice, error);
|
||||
context.log_css_error(error_context, location, error)
|
||||
context.log_css_error(location, error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
use context::QuirksMode;
|
||||
use cssparser::{Delimiter, Parser};
|
||||
use cssparser::{ParserInput, Token};
|
||||
use error_reporting::{ContextualParseError, ParseErrorReporter};
|
||||
use parser::{ParserContext, ParserErrorContext};
|
||||
use error_reporting::ContextualParseError;
|
||||
use parser::ParserContext;
|
||||
use super::{Device, MediaQuery, Qualifier};
|
||||
|
||||
/// A type that encapsulates a media query list.
|
||||
|
@ -30,14 +30,10 @@ impl MediaList {
|
|||
/// "not all", see:
|
||||
///
|
||||
/// <https://drafts.csswg.org/mediaqueries/#error-handling>
|
||||
pub fn parse<R>(
|
||||
pub fn parse(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser,
|
||||
error_reporter: &R,
|
||||
) -> MediaList
|
||||
where
|
||||
R: ParseErrorReporter,
|
||||
{
|
||||
) -> Self {
|
||||
if input.is_exhausted() {
|
||||
return Self::empty();
|
||||
}
|
||||
|
@ -54,8 +50,7 @@ impl MediaList {
|
|||
let location = err.location;
|
||||
let error =
|
||||
ContextualParseError::InvalidMediaRule(input.slice_from(start_position), err);
|
||||
let error_context = ParserErrorContext { error_reporter };
|
||||
context.log_css_error(&error_context, location, error);
|
||||
context.log_css_error(location, error);
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -36,12 +36,6 @@ pub fn assert_parsing_mode_match() {
|
|||
}
|
||||
}
|
||||
|
||||
/// The context required to report a parse error.
|
||||
pub struct ParserErrorContext<'a, R: 'a> {
|
||||
/// An error reporter to report syntax errors.
|
||||
pub error_reporter: &'a R,
|
||||
}
|
||||
|
||||
/// The data that the parser needs from outside in order to parse a stylesheet.
|
||||
pub struct ParserContext<'a> {
|
||||
/// The `Origin` of the stylesheet, whether it's a user, author or
|
||||
|
@ -55,6 +49,8 @@ pub struct ParserContext<'a> {
|
|||
pub parsing_mode: ParsingMode,
|
||||
/// The quirks mode of this stylesheet.
|
||||
pub quirks_mode: QuirksMode,
|
||||
/// The active error reporter, or none if error reporting is disabled.
|
||||
error_reporter: Option<&'a ParseErrorReporter>,
|
||||
/// The currently active namespaces.
|
||||
pub namespaces: Option<&'a Namespaces>,
|
||||
}
|
||||
|
@ -68,6 +64,7 @@ impl<'a> ParserContext<'a> {
|
|||
rule_type: Option<CssRuleType>,
|
||||
parsing_mode: ParsingMode,
|
||||
quirks_mode: QuirksMode,
|
||||
error_reporter: Option<&'a ParseErrorReporter>,
|
||||
) -> Self {
|
||||
ParserContext {
|
||||
stylesheet_origin,
|
||||
|
@ -75,6 +72,7 @@ impl<'a> ParserContext<'a> {
|
|||
rule_type,
|
||||
parsing_mode,
|
||||
quirks_mode,
|
||||
error_reporter,
|
||||
namespaces: None,
|
||||
}
|
||||
}
|
||||
|
@ -86,6 +84,7 @@ impl<'a> ParserContext<'a> {
|
|||
rule_type: Option<CssRuleType>,
|
||||
parsing_mode: ParsingMode,
|
||||
quirks_mode: QuirksMode,
|
||||
error_reporter: Option<&'a ParseErrorReporter>,
|
||||
) -> Self {
|
||||
Self::new(
|
||||
Origin::Author,
|
||||
|
@ -93,6 +92,7 @@ impl<'a> ParserContext<'a> {
|
|||
rule_type,
|
||||
parsing_mode,
|
||||
quirks_mode,
|
||||
error_reporter,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -110,6 +110,7 @@ impl<'a> ParserContext<'a> {
|
|||
parsing_mode: context.parsing_mode,
|
||||
quirks_mode: context.quirks_mode,
|
||||
namespaces: Some(namespaces),
|
||||
error_reporter: context.error_reporter,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -127,21 +128,17 @@ impl<'a> ParserContext<'a> {
|
|||
}
|
||||
|
||||
/// Record a CSS parse error with this context’s error reporting.
|
||||
pub fn log_css_error<R>(
|
||||
pub fn log_css_error(
|
||||
&self,
|
||||
context: &ParserErrorContext<R>,
|
||||
location: SourceLocation,
|
||||
error: ContextualParseError,
|
||||
) where
|
||||
R: ParseErrorReporter,
|
||||
{
|
||||
let location = SourceLocation {
|
||||
line: location.line,
|
||||
column: location.column,
|
||||
) {
|
||||
let error_reporter = match self.error_reporter {
|
||||
Some(r) => r,
|
||||
None => return,
|
||||
};
|
||||
context
|
||||
.error_reporter
|
||||
.report_error(self.url_data, location, error)
|
||||
|
||||
error_reporter.report_error(self.url_data, location, error)
|
||||
}
|
||||
|
||||
/// Returns whether chrome-only rules should be parsed.
|
||||
|
|
|
@ -11,7 +11,7 @@ use cssparser::{DeclarationListParser, parse_important, ParserInput, CowRcStr};
|
|||
use cssparser::{Parser, AtRuleParser, DeclarationParser, Delimiter, ParseErrorKind};
|
||||
use custom_properties::CustomPropertiesBuilder;
|
||||
use error_reporting::{ParseErrorReporter, ContextualParseError};
|
||||
use parser::{ParserContext, ParserErrorContext};
|
||||
use parser::ParserContext;
|
||||
use properties::animated_properties::AnimationValue;
|
||||
use shared_lock::Locked;
|
||||
use smallbitvec::{self, SmallBitVec};
|
||||
|
@ -1077,50 +1077,49 @@ where
|
|||
|
||||
/// A helper to parse the style attribute of an element, in order for this to be
|
||||
/// shared between Servo and Gecko.
|
||||
pub fn parse_style_attribute<R>(
|
||||
///
|
||||
/// Inline because we call this cross-crate.
|
||||
#[inline]
|
||||
pub fn parse_style_attribute(
|
||||
input: &str,
|
||||
url_data: &UrlExtraData,
|
||||
error_reporter: &R,
|
||||
error_reporter: Option<&ParseErrorReporter>,
|
||||
quirks_mode: QuirksMode,
|
||||
) -> PropertyDeclarationBlock
|
||||
where
|
||||
R: ParseErrorReporter
|
||||
{
|
||||
) -> PropertyDeclarationBlock {
|
||||
let context = ParserContext::new(
|
||||
Origin::Author,
|
||||
url_data,
|
||||
Some(CssRuleType::Style),
|
||||
ParsingMode::DEFAULT,
|
||||
quirks_mode,
|
||||
error_reporter,
|
||||
);
|
||||
|
||||
let error_context = ParserErrorContext { error_reporter: error_reporter };
|
||||
let mut input = ParserInput::new(input);
|
||||
parse_property_declaration_list(&context, &error_context, &mut Parser::new(&mut input))
|
||||
parse_property_declaration_list(&context, &mut Parser::new(&mut input))
|
||||
}
|
||||
|
||||
/// Parse a given property declaration. Can result in multiple
|
||||
/// `PropertyDeclaration`s when expanding a shorthand, for example.
|
||||
///
|
||||
/// This does not attempt to parse !important at all.
|
||||
pub fn parse_one_declaration_into<R>(
|
||||
#[inline]
|
||||
pub fn parse_one_declaration_into(
|
||||
declarations: &mut SourcePropertyDeclaration,
|
||||
id: PropertyId,
|
||||
input: &str,
|
||||
url_data: &UrlExtraData,
|
||||
error_reporter: &R,
|
||||
error_reporter: Option<&ParseErrorReporter>,
|
||||
parsing_mode: ParsingMode,
|
||||
quirks_mode: QuirksMode
|
||||
) -> Result<(), ()>
|
||||
where
|
||||
R: ParseErrorReporter
|
||||
{
|
||||
) -> Result<(), ()> {
|
||||
let context = ParserContext::new(
|
||||
Origin::Author,
|
||||
url_data,
|
||||
Some(CssRuleType::Style),
|
||||
parsing_mode,
|
||||
quirks_mode,
|
||||
error_reporter,
|
||||
);
|
||||
|
||||
let mut input = ParserInput::new(input);
|
||||
|
@ -1131,9 +1130,10 @@ where
|
|||
}).map_err(|err| {
|
||||
let location = err.location;
|
||||
let error = ContextualParseError::UnsupportedPropertyDeclaration(
|
||||
parser.slice_from(start_position), err);
|
||||
let error_context = ParserErrorContext { error_reporter: error_reporter };
|
||||
context.log_css_error(&error_context, location, error);
|
||||
parser.slice_from(start_position),
|
||||
err,
|
||||
);
|
||||
context.log_css_error(location, error);
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -1193,14 +1193,10 @@ impl<'a, 'b, 'i> DeclarationParser<'i> for PropertyDeclarationParser<'a, 'b> {
|
|||
|
||||
/// Parse a list of property declarations and return a property declaration
|
||||
/// block.
|
||||
pub fn parse_property_declaration_list<R>(
|
||||
pub fn parse_property_declaration_list(
|
||||
context: &ParserContext,
|
||||
error_context: &ParserErrorContext<R>,
|
||||
input: &mut Parser,
|
||||
) -> PropertyDeclarationBlock
|
||||
where
|
||||
R: ParseErrorReporter
|
||||
{
|
||||
) -> PropertyDeclarationBlock {
|
||||
let mut declarations = SourcePropertyDeclaration::new();
|
||||
let mut block = PropertyDeclarationBlock::new();
|
||||
let parser = PropertyDeclarationParser {
|
||||
|
@ -1228,7 +1224,7 @@ where
|
|||
|
||||
let location = error.location;
|
||||
let error = ContextualParseError::UnsupportedPropertyDeclaration(slice, error);
|
||||
context.log_css_error(error_context, location, error);
|
||||
context.log_css_error(location, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1442,6 +1442,7 @@ impl UnparsedValue {
|
|||
None,
|
||||
ParsingMode::DEFAULT,
|
||||
quirks_mode,
|
||||
None,
|
||||
);
|
||||
|
||||
let mut input = ParserInput::new(&css);
|
||||
|
|
|
@ -10,12 +10,12 @@ use Atom;
|
|||
use cssparser::{AtRuleParser, AtRuleType, BasicParseErrorKind, CowRcStr};
|
||||
use cssparser::{DeclarationListParser, DeclarationParser, Parser};
|
||||
use cssparser::{QualifiedRuleParser, RuleListParser, SourceLocation, Token};
|
||||
use error_reporting::{ContextualParseError, ParseErrorReporter};
|
||||
use error_reporting::ContextualParseError;
|
||||
#[cfg(feature = "gecko")]
|
||||
use gecko_bindings::bindings::Gecko_AppendFeatureValueHashEntry;
|
||||
#[cfg(feature = "gecko")]
|
||||
use gecko_bindings::structs::{self, gfxFontFeatureValueSet, nsTArray};
|
||||
use parser::{Parse, ParserContext, ParserErrorContext};
|
||||
use parser::{Parse, ParserContext};
|
||||
use shared_lock::{SharedRwLockReadGuard, ToCssWithGuard};
|
||||
use std::fmt::{self, Write};
|
||||
use str::CssStringWriter;
|
||||
|
@ -267,27 +267,24 @@ macro_rules! font_feature_values_blocks {
|
|||
}
|
||||
|
||||
/// Parses a `FontFeatureValuesRule`.
|
||||
pub fn parse<R>(context: &ParserContext,
|
||||
error_context: &ParserErrorContext<R>,
|
||||
input: &mut Parser,
|
||||
family_names: Vec<FamilyName>,
|
||||
location: SourceLocation)
|
||||
-> FontFeatureValuesRule
|
||||
where R: ParseErrorReporter
|
||||
{
|
||||
pub fn parse(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser,
|
||||
family_names: Vec<FamilyName>,
|
||||
location: SourceLocation,
|
||||
) -> Self {
|
||||
let mut rule = FontFeatureValuesRule::new(family_names, location);
|
||||
|
||||
{
|
||||
let mut iter = RuleListParser::new_for_nested_rule(input, FontFeatureValuesRuleParser {
|
||||
context: context,
|
||||
error_context: error_context,
|
||||
rule: &mut rule,
|
||||
});
|
||||
while let Some(result) = iter.next() {
|
||||
if let Err((error, slice)) = result {
|
||||
let location = error.location;
|
||||
let error = ContextualParseError::UnsupportedRule(slice, error);
|
||||
context.log_css_error(error_context, location, error);
|
||||
context.log_css_error(location, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -398,20 +395,19 @@ macro_rules! font_feature_values_blocks {
|
|||
/// }
|
||||
/// <feature-type> = @stylistic | @historical-forms | @styleset |
|
||||
/// @character-variant | @swash | @ornaments | @annotation
|
||||
struct FontFeatureValuesRuleParser<'a, R: 'a> {
|
||||
struct FontFeatureValuesRuleParser<'a> {
|
||||
context: &'a ParserContext<'a>,
|
||||
error_context: &'a ParserErrorContext<'a, R>,
|
||||
rule: &'a mut FontFeatureValuesRule,
|
||||
}
|
||||
|
||||
/// Default methods reject all qualified rules.
|
||||
impl<'a, 'i, R: ParseErrorReporter> QualifiedRuleParser<'i> for FontFeatureValuesRuleParser<'a, R> {
|
||||
impl<'a, 'i> QualifiedRuleParser<'i> for FontFeatureValuesRuleParser<'a> {
|
||||
type Prelude = ();
|
||||
type QualifiedRule = ();
|
||||
type Error = StyleParseErrorKind<'i>;
|
||||
}
|
||||
|
||||
impl<'a, 'i, R: ParseErrorReporter> AtRuleParser<'i> for FontFeatureValuesRuleParser<'a, R> {
|
||||
impl<'a, 'i> AtRuleParser<'i> for FontFeatureValuesRuleParser<'a> {
|
||||
type PreludeNoBlock = ();
|
||||
type PreludeBlock = BlockType;
|
||||
type AtRule = ();
|
||||
|
@ -450,7 +446,7 @@ macro_rules! font_feature_values_blocks {
|
|||
let error = ContextualParseError::UnsupportedKeyframePropertyDeclaration(
|
||||
slice, error
|
||||
);
|
||||
self.context.log_css_error(self.error_context, location, error);
|
||||
self.context.log_css_error(location, error);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
|
||||
use cssparser::{AtRuleParser, CowRcStr, Parser, ParserInput, QualifiedRuleParser, RuleListParser};
|
||||
use cssparser::{parse_one_rule, DeclarationListParser, DeclarationParser, SourceLocation, Token};
|
||||
use error_reporting::{ContextualParseError, NullReporter, ParseErrorReporter};
|
||||
use parser::{ParserContext, ParserErrorContext};
|
||||
use error_reporting::ContextualParseError;
|
||||
use parser::ParserContext;
|
||||
use properties::{DeclarationSource, Importance, PropertyDeclaration};
|
||||
use properties::{LonghandId, PropertyDeclarationBlock, PropertyId};
|
||||
use properties::{PropertyDeclarationId, SourcePropertyDeclaration};
|
||||
|
@ -211,7 +211,6 @@ impl Keyframe {
|
|||
lock: &SharedRwLock,
|
||||
) -> Result<Arc<Locked<Self>>, ParseError<'i>> {
|
||||
let url_data = parent_stylesheet_contents.url_data.read();
|
||||
let error_reporter = NullReporter;
|
||||
let namespaces = parent_stylesheet_contents.namespaces.read();
|
||||
let mut context = ParserContext::new(
|
||||
parent_stylesheet_contents.origin,
|
||||
|
@ -219,10 +218,8 @@ impl Keyframe {
|
|||
Some(CssRuleType::Keyframe),
|
||||
ParsingMode::DEFAULT,
|
||||
parent_stylesheet_contents.quirks_mode,
|
||||
None,
|
||||
);
|
||||
let error_context = ParserErrorContext {
|
||||
error_reporter: &error_reporter,
|
||||
};
|
||||
context.namespaces = Some(&*namespaces);
|
||||
let mut input = ParserInput::new(css);
|
||||
let mut input = Parser::new(&mut input);
|
||||
|
@ -230,7 +227,6 @@ impl Keyframe {
|
|||
let mut declarations = SourcePropertyDeclaration::new();
|
||||
let mut rule_parser = KeyframeListParser {
|
||||
context: &context,
|
||||
error_context: &error_context,
|
||||
shared_lock: &lock,
|
||||
declarations: &mut declarations,
|
||||
};
|
||||
|
@ -477,23 +473,18 @@ impl KeyframesAnimation {
|
|||
/// 40%, 60%, 100% {
|
||||
/// width: 100%;
|
||||
/// }
|
||||
struct KeyframeListParser<'a, R: 'a> {
|
||||
struct KeyframeListParser<'a> {
|
||||
context: &'a ParserContext<'a>,
|
||||
error_context: &'a ParserErrorContext<'a, R>,
|
||||
shared_lock: &'a SharedRwLock,
|
||||
declarations: &'a mut SourcePropertyDeclaration,
|
||||
}
|
||||
|
||||
/// Parses a keyframe list from CSS input.
|
||||
pub fn parse_keyframe_list<R>(
|
||||
pub fn parse_keyframe_list(
|
||||
context: &ParserContext,
|
||||
error_context: &ParserErrorContext<R>,
|
||||
input: &mut Parser,
|
||||
shared_lock: &SharedRwLock,
|
||||
) -> Vec<Arc<Locked<Keyframe>>>
|
||||
where
|
||||
R: ParseErrorReporter,
|
||||
{
|
||||
) -> Vec<Arc<Locked<Keyframe>>> {
|
||||
debug_assert!(
|
||||
context.namespaces.is_some(),
|
||||
"Parsing a keyframe list from a context without namespaces?"
|
||||
|
@ -504,7 +495,6 @@ where
|
|||
input,
|
||||
KeyframeListParser {
|
||||
context: context,
|
||||
error_context: error_context,
|
||||
shared_lock: shared_lock,
|
||||
declarations: &mut declarations,
|
||||
},
|
||||
|
@ -512,7 +502,7 @@ where
|
|||
.collect()
|
||||
}
|
||||
|
||||
impl<'a, 'i, R> AtRuleParser<'i> for KeyframeListParser<'a, R> {
|
||||
impl<'a, 'i> AtRuleParser<'i> for KeyframeListParser<'a> {
|
||||
type PreludeNoBlock = ();
|
||||
type PreludeBlock = ();
|
||||
type AtRule = Arc<Locked<Keyframe>>;
|
||||
|
@ -525,7 +515,7 @@ struct KeyframeSelectorParserPrelude {
|
|||
source_location: SourceLocation,
|
||||
}
|
||||
|
||||
impl<'a, 'i, R: ParseErrorReporter> QualifiedRuleParser<'i> for KeyframeListParser<'a, R> {
|
||||
impl<'a, 'i> QualifiedRuleParser<'i> for KeyframeListParser<'a> {
|
||||
type Prelude = KeyframeSelectorParserPrelude;
|
||||
type QualifiedRule = Arc<Locked<Keyframe>>;
|
||||
type Error = StyleParseErrorKind<'i>;
|
||||
|
@ -547,8 +537,7 @@ impl<'a, 'i, R: ParseErrorReporter> QualifiedRuleParser<'i> for KeyframeListPars
|
|||
input.slice_from(start_position),
|
||||
e.clone(),
|
||||
);
|
||||
self.context
|
||||
.log_css_error(self.error_context, location, error);
|
||||
self.context.log_css_error(location, error);
|
||||
Err(e)
|
||||
},
|
||||
}
|
||||
|
@ -585,7 +574,7 @@ impl<'a, 'i, R: ParseErrorReporter> QualifiedRuleParser<'i> for KeyframeListPars
|
|||
let location = error.location;
|
||||
let error =
|
||||
ContextualParseError::UnsupportedKeyframePropertyDeclaration(slice, error);
|
||||
context.log_css_error(self.error_context, location, error);
|
||||
context.log_css_error(location, error);
|
||||
},
|
||||
}
|
||||
// `parse_important` is not called here, `!important` is not allowed in keyframe blocks.
|
||||
|
|
|
@ -24,10 +24,9 @@ pub mod supports_rule;
|
|||
pub mod viewport_rule;
|
||||
|
||||
use cssparser::{parse_one_rule, Parser, ParserInput};
|
||||
use error_reporting::NullReporter;
|
||||
#[cfg(feature = "gecko")]
|
||||
use malloc_size_of::{MallocSizeOfOps, MallocUnconditionalShallowSizeOf};
|
||||
use parser::{ParserContext, ParserErrorContext};
|
||||
use parser::ParserContext;
|
||||
use servo_arc::Arc;
|
||||
use shared_lock::{DeepCloneParams, DeepCloneWithLock, Locked};
|
||||
use shared_lock::{SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
|
||||
|
@ -228,13 +227,13 @@ impl CssRule {
|
|||
loader: Option<&StylesheetLoader>,
|
||||
) -> Result<Self, RulesMutateError> {
|
||||
let url_data = parent_stylesheet_contents.url_data.read();
|
||||
let error_reporter = NullReporter;
|
||||
let context = ParserContext::new(
|
||||
parent_stylesheet_contents.origin,
|
||||
&url_data,
|
||||
None,
|
||||
ParsingMode::DEFAULT,
|
||||
parent_stylesheet_contents.quirks_mode,
|
||||
None,
|
||||
);
|
||||
|
||||
let mut input = ParserInput::new(css);
|
||||
|
@ -246,9 +245,6 @@ impl CssRule {
|
|||
let mut rule_parser = TopLevelRuleParser {
|
||||
stylesheet_origin: parent_stylesheet_contents.origin,
|
||||
context,
|
||||
error_context: ParserErrorContext {
|
||||
error_reporter: &error_reporter,
|
||||
},
|
||||
shared_lock: &shared_lock,
|
||||
loader,
|
||||
state,
|
||||
|
|
|
@ -8,10 +8,10 @@ use {Namespace, Prefix};
|
|||
use counter_style::{parse_counter_style_body, parse_counter_style_name_definition};
|
||||
use cssparser::{AtRuleParser, AtRuleType, Parser, QualifiedRuleParser, RuleListParser};
|
||||
use cssparser::{BasicParseError, BasicParseErrorKind, CowRcStr, SourceLocation};
|
||||
use error_reporting::{ContextualParseError, ParseErrorReporter};
|
||||
use error_reporting::ContextualParseError;
|
||||
use font_face::parse_font_face_block;
|
||||
use media_queries::MediaList;
|
||||
use parser::{Parse, ParserContext, ParserErrorContext};
|
||||
use parser::{Parse, ParserContext};
|
||||
use properties::parse_property_declaration_list;
|
||||
use selector_parser::{SelectorImpl, SelectorParser};
|
||||
use selectors::SelectorList;
|
||||
|
@ -40,7 +40,7 @@ pub struct InsertRuleContext<'a> {
|
|||
}
|
||||
|
||||
/// The parser for the top-level rules in a stylesheet.
|
||||
pub struct TopLevelRuleParser<'a, R: 'a> {
|
||||
pub struct TopLevelRuleParser<'a> {
|
||||
/// The origin of the stylesheet we're parsing.
|
||||
pub stylesheet_origin: Origin,
|
||||
/// A reference to the lock we need to use to create rules.
|
||||
|
@ -52,8 +52,6 @@ pub struct TopLevelRuleParser<'a, R: 'a> {
|
|||
/// This won't contain any namespaces, and only nested parsers created with
|
||||
/// `ParserContext::new_with_rule_type` will.
|
||||
pub context: ParserContext<'a>,
|
||||
/// The context required for reporting parse errors.
|
||||
pub error_context: ParserErrorContext<'a, R>,
|
||||
/// The current state of the parser.
|
||||
pub state: State,
|
||||
/// Whether we have tried to parse was invalid due to being in the wrong
|
||||
|
@ -68,13 +66,12 @@ pub struct TopLevelRuleParser<'a, R: 'a> {
|
|||
pub insert_rule_context: Option<InsertRuleContext<'a>>,
|
||||
}
|
||||
|
||||
impl<'b, R> TopLevelRuleParser<'b, R> {
|
||||
fn nested<'a: 'b>(&'a self) -> NestedRuleParser<'a, 'b, R> {
|
||||
impl<'b> TopLevelRuleParser<'b> {
|
||||
fn nested<'a: 'b>(&'a self) -> NestedRuleParser<'a, 'b> {
|
||||
NestedRuleParser {
|
||||
stylesheet_origin: self.stylesheet_origin,
|
||||
shared_lock: self.shared_lock,
|
||||
context: &self.context,
|
||||
error_context: &self.error_context,
|
||||
namespaces: &self.namespaces,
|
||||
}
|
||||
}
|
||||
|
@ -176,7 +173,7 @@ pub enum AtRuleNonBlockPrelude {
|
|||
Namespace(Option<Prefix>, Namespace, SourceLocation),
|
||||
}
|
||||
|
||||
impl<'a, 'i, R: ParseErrorReporter> AtRuleParser<'i> for TopLevelRuleParser<'a, R> {
|
||||
impl<'a, 'i> AtRuleParser<'i> for TopLevelRuleParser<'a> {
|
||||
type PreludeNoBlock = AtRuleNonBlockPrelude;
|
||||
type PreludeBlock = AtRuleBlockPrelude;
|
||||
type AtRule = CssRule;
|
||||
|
@ -197,11 +194,7 @@ impl<'a, 'i, R: ParseErrorReporter> AtRuleParser<'i> for TopLevelRuleParser<'a,
|
|||
let url_string = input.expect_url_or_string()?.as_ref().to_owned();
|
||||
let url = CssUrl::parse_from_string(url_string, &self.context);
|
||||
|
||||
let media = MediaList::parse(
|
||||
&self.context,
|
||||
input,
|
||||
self.error_context.error_reporter,
|
||||
);
|
||||
let media = MediaList::parse(&self.context, input);
|
||||
let media = Arc::new(self.shared_lock.wrap(media));
|
||||
|
||||
let prelude = AtRuleNonBlockPrelude::Import(url, media, location);
|
||||
|
@ -296,7 +289,7 @@ pub struct QualifiedRuleParserPrelude {
|
|||
source_location: SourceLocation,
|
||||
}
|
||||
|
||||
impl<'a, 'i, R: ParseErrorReporter> QualifiedRuleParser<'i> for TopLevelRuleParser<'a, R> {
|
||||
impl<'a, 'i> QualifiedRuleParser<'i> for TopLevelRuleParser<'a> {
|
||||
type Prelude = QualifiedRuleParserPrelude;
|
||||
type QualifiedRule = CssRule;
|
||||
type Error = StyleParseErrorKind<'i>;
|
||||
|
@ -327,27 +320,29 @@ impl<'a, 'i, R: ParseErrorReporter> QualifiedRuleParser<'i> for TopLevelRulePars
|
|||
}
|
||||
|
||||
#[derive(Clone)] // shallow, relatively cheap .clone
|
||||
struct NestedRuleParser<'a, 'b: 'a, R: 'b> {
|
||||
struct NestedRuleParser<'a, 'b: 'a> {
|
||||
stylesheet_origin: Origin,
|
||||
shared_lock: &'a SharedRwLock,
|
||||
context: &'a ParserContext<'b>,
|
||||
error_context: &'a ParserErrorContext<'b, R>,
|
||||
namespaces: &'a Namespaces,
|
||||
}
|
||||
|
||||
impl<'a, 'b, R: ParseErrorReporter> NestedRuleParser<'a, 'b, R> {
|
||||
impl<'a, 'b> NestedRuleParser<'a, 'b> {
|
||||
fn parse_nested_rules(
|
||||
&mut self,
|
||||
input: &mut Parser,
|
||||
rule_type: CssRuleType,
|
||||
) -> Arc<Locked<CssRules>> {
|
||||
let context = ParserContext::new_with_rule_type(self.context, rule_type, self.namespaces);
|
||||
let context = ParserContext::new_with_rule_type(
|
||||
self.context,
|
||||
rule_type,
|
||||
self.namespaces,
|
||||
);
|
||||
|
||||
let nested_parser = NestedRuleParser {
|
||||
stylesheet_origin: self.stylesheet_origin,
|
||||
shared_lock: self.shared_lock,
|
||||
context: &context,
|
||||
error_context: &self.error_context,
|
||||
namespaces: self.namespaces,
|
||||
};
|
||||
|
||||
|
@ -359,8 +354,7 @@ impl<'a, 'b, R: ParseErrorReporter> NestedRuleParser<'a, 'b, R> {
|
|||
Err((error, slice)) => {
|
||||
let location = error.location;
|
||||
let error = ContextualParseError::InvalidRule(slice, error);
|
||||
self.context
|
||||
.log_css_error(self.error_context, location, error);
|
||||
self.context.log_css_error(location, error);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -368,7 +362,7 @@ impl<'a, 'b, R: ParseErrorReporter> NestedRuleParser<'a, 'b, R> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b, 'i, R: ParseErrorReporter> AtRuleParser<'i> for NestedRuleParser<'a, 'b, R> {
|
||||
impl<'a, 'b, 'i> AtRuleParser<'i> for NestedRuleParser<'a, 'b> {
|
||||
type PreludeNoBlock = AtRuleNonBlockPrelude;
|
||||
type PreludeBlock = AtRuleBlockPrelude;
|
||||
type AtRule = CssRule;
|
||||
|
@ -383,11 +377,7 @@ impl<'a, 'b, 'i, R: ParseErrorReporter> AtRuleParser<'i> for NestedRuleParser<'a
|
|||
|
||||
match_ignore_ascii_case! { &*name,
|
||||
"media" => {
|
||||
let media_queries = MediaList::parse(
|
||||
self.context,
|
||||
input,
|
||||
self.error_context.error_reporter,
|
||||
);
|
||||
let media_queries = MediaList::parse(self.context, input);
|
||||
let arc = Arc::new(self.shared_lock.wrap(media_queries));
|
||||
Ok(AtRuleType::WithBlock(AtRuleBlockPrelude::Media(arc, location)))
|
||||
},
|
||||
|
@ -473,7 +463,7 @@ impl<'a, 'b, 'i, R: ParseErrorReporter> AtRuleParser<'i> for NestedRuleParser<'a
|
|||
);
|
||||
|
||||
Ok(CssRule::FontFace(Arc::new(self.shared_lock.wrap(
|
||||
parse_font_face_block(&context, self.error_context, input, location).into(),
|
||||
parse_font_face_block(&context, input, location).into(),
|
||||
))))
|
||||
},
|
||||
AtRuleBlockPrelude::FontFeatureValues(family_names, location) => {
|
||||
|
@ -486,7 +476,6 @@ impl<'a, 'b, 'i, R: ParseErrorReporter> AtRuleParser<'i> for NestedRuleParser<'a
|
|||
Ok(CssRule::FontFeatureValues(Arc::new(self.shared_lock.wrap(
|
||||
FontFeatureValuesRule::parse(
|
||||
&context,
|
||||
self.error_context,
|
||||
input,
|
||||
family_names,
|
||||
location,
|
||||
|
@ -505,7 +494,6 @@ impl<'a, 'b, 'i, R: ParseErrorReporter> AtRuleParser<'i> for NestedRuleParser<'a
|
|||
parse_counter_style_body(
|
||||
name,
|
||||
&context,
|
||||
self.error_context,
|
||||
input,
|
||||
location,
|
||||
)?.into(),
|
||||
|
@ -544,7 +532,7 @@ impl<'a, 'b, 'i, R: ParseErrorReporter> AtRuleParser<'i> for NestedRuleParser<'a
|
|||
);
|
||||
|
||||
Ok(CssRule::Viewport(Arc::new(self.shared_lock.wrap(
|
||||
ViewportRule::parse(&context, self.error_context, input)?,
|
||||
ViewportRule::parse(&context, input)?,
|
||||
))))
|
||||
},
|
||||
AtRuleBlockPrelude::Keyframes(name, vendor_prefix, source_location) => {
|
||||
|
@ -559,7 +547,6 @@ impl<'a, 'b, 'i, R: ParseErrorReporter> AtRuleParser<'i> for NestedRuleParser<'a
|
|||
name,
|
||||
keyframes: parse_keyframe_list(
|
||||
&context,
|
||||
self.error_context,
|
||||
input,
|
||||
self.shared_lock,
|
||||
),
|
||||
|
@ -576,7 +563,7 @@ impl<'a, 'b, 'i, R: ParseErrorReporter> AtRuleParser<'i> for NestedRuleParser<'a
|
|||
);
|
||||
|
||||
let declarations =
|
||||
parse_property_declaration_list(&context, self.error_context, input);
|
||||
parse_property_declaration_list(&context, input);
|
||||
Ok(CssRule::Page(Arc::new(self.shared_lock.wrap(PageRule {
|
||||
block: Arc::new(self.shared_lock.wrap(declarations)),
|
||||
source_location,
|
||||
|
@ -598,7 +585,7 @@ impl<'a, 'b, 'i, R: ParseErrorReporter> AtRuleParser<'i> for NestedRuleParser<'a
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b, 'i, R: ParseErrorReporter> QualifiedRuleParser<'i> for NestedRuleParser<'a, 'b, R> {
|
||||
impl<'a, 'b, 'i> QualifiedRuleParser<'i> for NestedRuleParser<'a, 'b> {
|
||||
type Prelude = QualifiedRuleParserPrelude;
|
||||
type QualifiedRule = CssRule;
|
||||
type Error = StyleParseErrorKind<'i>;
|
||||
|
@ -627,7 +614,7 @@ impl<'a, 'b, 'i, R: ParseErrorReporter> QualifiedRuleParser<'i> for NestedRulePa
|
|||
let context =
|
||||
ParserContext::new_with_rule_type(self.context, CssRuleType::Style, self.namespaces);
|
||||
|
||||
let declarations = parse_property_declaration_list(&context, self.error_context, input);
|
||||
let declarations = parse_property_declaration_list(&context, input);
|
||||
Ok(CssRule::Style(Arc::new(self.shared_lock.wrap(StyleRule {
|
||||
selectors: prelude.selectors,
|
||||
block: Arc::new(self.shared_lock.wrap(declarations)),
|
||||
|
|
|
@ -13,7 +13,7 @@ use invalidation::media_queries::{MediaListKey, ToMediaListKey};
|
|||
use malloc_size_of::{MallocSizeOfOps, MallocUnconditionalShallowSizeOf};
|
||||
use media_queries::{Device, MediaList};
|
||||
use parking_lot::RwLock;
|
||||
use parser::{ParserContext, ParserErrorContext};
|
||||
use parser::ParserContext;
|
||||
use servo_arc::Arc;
|
||||
use shared_lock::{DeepCloneParams, DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard};
|
||||
use std::mem;
|
||||
|
@ -69,13 +69,13 @@ pub struct StylesheetContents {
|
|||
impl StylesheetContents {
|
||||
/// Parse a given CSS string, with a given url-data, origin, and
|
||||
/// quirks mode.
|
||||
pub fn from_str<R: ParseErrorReporter>(
|
||||
pub fn from_str(
|
||||
css: &str,
|
||||
url_data: UrlExtraData,
|
||||
origin: Origin,
|
||||
shared_lock: &SharedRwLock,
|
||||
stylesheet_loader: Option<&StylesheetLoader>,
|
||||
error_reporter: &R,
|
||||
error_reporter: Option<&ParseErrorReporter>,
|
||||
quirks_mode: QuirksMode,
|
||||
line_number_offset: u32,
|
||||
) -> Self {
|
||||
|
@ -137,7 +137,7 @@ impl DeepCloneWithLock for StylesheetContents {
|
|||
url_data: RwLock::new((*self.url_data.read()).clone()),
|
||||
namespaces: RwLock::new((*self.namespaces.read()).clone()),
|
||||
source_map_url: RwLock::new((*self.source_map_url.read()).clone()),
|
||||
source_url: RwLock::new((*self.source_map_url.read()).clone()),
|
||||
source_url: RwLock::new((*self.source_url.read()).clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -306,18 +306,16 @@ impl StylesheetInDocument for DocumentStyleSheet {
|
|||
|
||||
impl Stylesheet {
|
||||
/// Updates an empty stylesheet from a given string of text.
|
||||
pub fn update_from_str<R>(
|
||||
pub fn update_from_str(
|
||||
existing: &Stylesheet,
|
||||
css: &str,
|
||||
url_data: UrlExtraData,
|
||||
stylesheet_loader: Option<&StylesheetLoader>,
|
||||
error_reporter: &R,
|
||||
error_reporter: Option<&ParseErrorReporter>,
|
||||
line_number_offset: u32,
|
||||
) where
|
||||
R: ParseErrorReporter,
|
||||
{
|
||||
) {
|
||||
let namespaces = RwLock::new(Namespaces::default());
|
||||
let (rules, source_map_url, source_url) = Stylesheet::parse_rules(
|
||||
let (rules, source_map_url, source_url) = Self::parse_rules(
|
||||
css,
|
||||
&url_data,
|
||||
existing.contents.origin,
|
||||
|
@ -342,14 +340,14 @@ impl Stylesheet {
|
|||
*existing.contents.source_url.write() = source_url;
|
||||
}
|
||||
|
||||
fn parse_rules<R: ParseErrorReporter>(
|
||||
fn parse_rules(
|
||||
css: &str,
|
||||
url_data: &UrlExtraData,
|
||||
origin: Origin,
|
||||
namespaces: &mut Namespaces,
|
||||
shared_lock: &SharedRwLock,
|
||||
stylesheet_loader: Option<&StylesheetLoader>,
|
||||
error_reporter: &R,
|
||||
error_reporter: Option<&ParseErrorReporter>,
|
||||
quirks_mode: QuirksMode,
|
||||
line_number_offset: u32,
|
||||
) -> (Vec<CssRule>, Option<String>, Option<String>) {
|
||||
|
@ -357,16 +355,20 @@ impl Stylesheet {
|
|||
let mut input = ParserInput::new_with_line_number_offset(css, line_number_offset);
|
||||
let mut input = Parser::new(&mut input);
|
||||
|
||||
let context = ParserContext::new(origin, url_data, None, ParsingMode::DEFAULT, quirks_mode);
|
||||
|
||||
let error_context = ParserErrorContext { error_reporter };
|
||||
let context = ParserContext::new(
|
||||
origin,
|
||||
url_data,
|
||||
None,
|
||||
ParsingMode::DEFAULT,
|
||||
quirks_mode,
|
||||
error_reporter,
|
||||
);
|
||||
|
||||
let rule_parser = TopLevelRuleParser {
|
||||
stylesheet_origin: origin,
|
||||
shared_lock,
|
||||
loader: stylesheet_loader,
|
||||
context,
|
||||
error_context,
|
||||
state: State::Start,
|
||||
dom_error: None,
|
||||
insert_rule_context: None,
|
||||
|
@ -390,7 +392,6 @@ impl Stylesheet {
|
|||
let location = error.location;
|
||||
let error = ContextualParseError::InvalidRule(slice, error);
|
||||
iter.parser.context.log_css_error(
|
||||
&iter.parser.error_context,
|
||||
location,
|
||||
error,
|
||||
);
|
||||
|
@ -409,17 +410,17 @@ impl Stylesheet {
|
|||
///
|
||||
/// Effectively creates a new stylesheet and forwards the hard work to
|
||||
/// `Stylesheet::update_from_str`.
|
||||
pub fn from_str<R: ParseErrorReporter>(
|
||||
pub fn from_str(
|
||||
css: &str,
|
||||
url_data: UrlExtraData,
|
||||
origin: Origin,
|
||||
media: Arc<Locked<MediaList>>,
|
||||
shared_lock: SharedRwLock,
|
||||
stylesheet_loader: Option<&StylesheetLoader>,
|
||||
error_reporter: &R,
|
||||
error_reporter: Option<&ParseErrorReporter>,
|
||||
quirks_mode: QuirksMode,
|
||||
line_number_offset: u32,
|
||||
) -> Stylesheet {
|
||||
) -> Self {
|
||||
let contents = StylesheetContents::from_str(
|
||||
css,
|
||||
url_data,
|
||||
|
|
|
@ -11,11 +11,11 @@ use app_units::Au;
|
|||
use context::QuirksMode;
|
||||
use cssparser::{parse_important, AtRuleParser, DeclarationListParser, DeclarationParser, Parser};
|
||||
use cssparser::CowRcStr;
|
||||
use error_reporting::{ContextualParseError, ParseErrorReporter};
|
||||
use error_reporting::ContextualParseError;
|
||||
use euclid::TypedSize2D;
|
||||
use font_metrics::get_metrics_provider_for_product;
|
||||
use media_queries::Device;
|
||||
use parser::{ParserContext, ParserErrorContext};
|
||||
use parser::ParserContext;
|
||||
use properties::StyleBuilder;
|
||||
use rule_cache::RuleCacheConditions;
|
||||
use selectors::parser::SelectorParseErrorKind;
|
||||
|
@ -355,15 +355,13 @@ fn is_whitespace_separator_or_equals(c: &char) -> bool {
|
|||
|
||||
impl ViewportRule {
|
||||
/// Parse a single @viewport rule.
|
||||
pub fn parse<'i, 't, R>(
|
||||
///
|
||||
/// TODO(emilio): This could use the `Parse` trait now.
|
||||
pub fn parse<'i, 't>(
|
||||
context: &ParserContext,
|
||||
error_context: &ParserErrorContext<R>,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<Self, ParseError<'i>>
|
||||
where
|
||||
R: ParseErrorReporter,
|
||||
{
|
||||
let parser = ViewportRuleParser { context: context };
|
||||
) -> Result<Self, ParseError<'i>> {
|
||||
let parser = ViewportRuleParser { context };
|
||||
|
||||
let mut cascade = Cascade::new();
|
||||
let mut parser = DeclarationListParser::new(input, parser);
|
||||
|
@ -380,7 +378,7 @@ impl ViewportRule {
|
|||
slice,
|
||||
error,
|
||||
);
|
||||
context.log_css_error(error_context, location, error);
|
||||
context.log_css_error(location, error);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
use cssparser::{CowRcStr, serialize_identifier, ToCss};
|
||||
use cssparser::{SourceLocation, ParseError, ParseErrorKind, Token, BasicParseErrorKind};
|
||||
use selectors::parser::SelectorParseErrorKind;
|
||||
use std::cell::Cell;
|
||||
use std::ffi::CStr;
|
||||
use std::ptr;
|
||||
use style::error_reporting::{ParseErrorReporter, ContextualParseError};
|
||||
|
@ -26,28 +25,31 @@ pub struct ErrorReporter {
|
|||
sheet: *const DomStyleSheet,
|
||||
loader: *const Loader,
|
||||
uri: *mut nsIURI,
|
||||
cached_error_reporting_enabled: Cell<Option<bool>>,
|
||||
}
|
||||
|
||||
impl ErrorReporter {
|
||||
/// Create a new instance of the Gecko error reporter.
|
||||
/// Create a new instance of the Gecko error reporter, if error reporting is
|
||||
/// enabled.
|
||||
pub fn new(
|
||||
sheet: *mut DomStyleSheet,
|
||||
loader: *mut Loader,
|
||||
extra_data: *mut RawUrlExtraData,
|
||||
) -> Self {
|
||||
) -> Option<Self> {
|
||||
if !Self::reporting_enabled(sheet, loader) {
|
||||
return None;
|
||||
}
|
||||
|
||||
let uri = unsafe {
|
||||
extra_data.as_ref()
|
||||
.map(|d| d.mBaseURI.raw::<nsIURI>())
|
||||
.unwrap_or(ptr::null_mut())
|
||||
};
|
||||
|
||||
ErrorReporter {
|
||||
Some(ErrorReporter {
|
||||
sheet,
|
||||
loader,
|
||||
uri,
|
||||
cached_error_reporting_enabled: Cell::new(None),
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -393,21 +395,15 @@ impl<'a> ErrorHelpers<'a> for ContextualParseError<'a> {
|
|||
}
|
||||
|
||||
impl ErrorReporter {
|
||||
fn reporting_enabled(&self) -> bool {
|
||||
if let Some(enabled) = self.cached_error_reporting_enabled.get() {
|
||||
return enabled;
|
||||
}
|
||||
let enabled = unsafe {
|
||||
bindings::Gecko_ErrorReportingEnabled(self.sheet, self.loader)
|
||||
};
|
||||
self.cached_error_reporting_enabled.set(Some(enabled));
|
||||
enabled
|
||||
fn reporting_enabled(
|
||||
sheet: *const DomStyleSheet,
|
||||
loader: *const Loader,
|
||||
) -> bool {
|
||||
unsafe { bindings::Gecko_ErrorReportingEnabled(sheet, loader) }
|
||||
}
|
||||
|
||||
pub fn report(&self, location: SourceLocation, error: ContextualParseError) {
|
||||
if !self.reporting_enabled() {
|
||||
return;
|
||||
}
|
||||
debug_assert!(Self::reporting_enabled(self.sheet, self.loader));
|
||||
|
||||
let (pre, name, action) = error.to_gecko_message();
|
||||
let suffix = match action {
|
||||
|
|
|
@ -26,7 +26,7 @@ use style::data::{ElementStyles, self};
|
|||
use style::dom::{ShowSubtreeData, TDocument, TElement, TNode};
|
||||
use style::driver;
|
||||
use style::element_state::{DocumentState, ElementState};
|
||||
use style::error_reporting::{ContextualParseError, NullReporter, ParseErrorReporter};
|
||||
use style::error_reporting::{ContextualParseError, ParseErrorReporter};
|
||||
use style::font_metrics::{FontMetricsProvider, get_metrics_provider_for_product};
|
||||
use style::gecko::data::{GeckoStyleSheet, PerDocumentStyleData, PerDocumentStyleDataImpl};
|
||||
use style::gecko::global_style_data::{GLOBAL_STYLE_DATA, GlobalStyleData, STYLE_THREAD_POOL};
|
||||
|
@ -1155,7 +1155,7 @@ pub extern "C" fn Servo_StyleSheet_Empty(mode: SheetParsingMode) -> RawServoStyl
|
|||
origin,
|
||||
shared_lock,
|
||||
/* loader = */ None,
|
||||
&NullReporter,
|
||||
None,
|
||||
QuirksMode::NoQuirks,
|
||||
0
|
||||
)
|
||||
|
@ -1196,10 +1196,15 @@ pub extern "C" fn Servo_StyleSheet_FromUTF8Bytes(
|
|||
|
||||
|
||||
Arc::new(StylesheetContents::from_str(
|
||||
input, url_data.clone(), mode_to_origin(mode),
|
||||
&global_style_data.shared_lock, loader, &reporter,
|
||||
quirks_mode.into(), line_number_offset)
|
||||
).into_strong()
|
||||
input,
|
||||
url_data.clone(),
|
||||
mode_to_origin(mode),
|
||||
&global_style_data.shared_lock,
|
||||
loader,
|
||||
reporter.as_ref().map(|r| r as &ParseErrorReporter),
|
||||
quirks_mode.into(),
|
||||
line_number_offset,
|
||||
)).into_strong()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
@ -2515,6 +2520,7 @@ pub unsafe extern "C" fn Servo_FontFaceRule_SetDescriptor(
|
|||
Some(CssRuleType::FontFace),
|
||||
ParsingMode::DEFAULT,
|
||||
QuirksMode::NoQuirks,
|
||||
None,
|
||||
);
|
||||
|
||||
write_locked_arc(rule, |rule: &mut FontFaceRule| {
|
||||
|
@ -2724,6 +2730,7 @@ macro_rules! counter_style_descriptors {
|
|||
Some(CssRuleType::CounterStyle),
|
||||
ParsingMode::DEFAULT,
|
||||
QuirksMode::NoQuirks,
|
||||
None,
|
||||
);
|
||||
|
||||
write_locked_arc(rule, |rule: &mut CounterStyleRule| {
|
||||
|
@ -3206,18 +3213,15 @@ pub unsafe extern "C" fn Servo_StyleSet_CompatModeChanged(raw_data: RawServoStyl
|
|||
data.stylist.set_quirks_mode(QuirksMode::from(doc.mCompatMode));
|
||||
}
|
||||
|
||||
fn parse_property_into<R>(
|
||||
fn parse_property_into(
|
||||
declarations: &mut SourcePropertyDeclaration,
|
||||
property_id: PropertyId,
|
||||
value: *const nsACString,
|
||||
data: *mut URLExtraData,
|
||||
parsing_mode: structs::ParsingMode,
|
||||
quirks_mode: QuirksMode,
|
||||
reporter: &R
|
||||
) -> Result<(), ()>
|
||||
where
|
||||
R: ParseErrorReporter
|
||||
{
|
||||
reporter: Option<&ParseErrorReporter>,
|
||||
) -> Result<(), ()> {
|
||||
use style_traits::ParsingMode;
|
||||
let value = unsafe { value.as_ref().unwrap().as_str_unchecked() };
|
||||
let url_data = unsafe { RefPtr::from_ptr_ref(&data) };
|
||||
|
@ -3246,8 +3250,17 @@ pub extern "C" fn Servo_ParseProperty(
|
|||
RawServoDeclarationBlockStrong::null());
|
||||
let mut declarations = SourcePropertyDeclaration::new();
|
||||
let reporter = ErrorReporter::new(ptr::null_mut(), loader, data);
|
||||
match parse_property_into(&mut declarations, id, value, data,
|
||||
parsing_mode, quirks_mode.into(), &reporter) {
|
||||
let result = parse_property_into(
|
||||
&mut declarations,
|
||||
id,
|
||||
value,
|
||||
data,
|
||||
parsing_mode,
|
||||
quirks_mode.into(),
|
||||
reporter.as_ref().map(|r| r as &ParseErrorReporter),
|
||||
);
|
||||
|
||||
match result {
|
||||
Ok(()) => {
|
||||
let global_style_data = &*GLOBAL_STYLE_DATA;
|
||||
let mut block = PropertyDeclarationBlock::new();
|
||||
|
@ -3278,6 +3291,7 @@ pub extern "C" fn Servo_ParseEasing(
|
|||
Some(CssRuleType::Style),
|
||||
ParsingMode::DEFAULT,
|
||||
QuirksMode::NoQuirks,
|
||||
None,
|
||||
);
|
||||
let easing = unsafe { (*easing).to_string() };
|
||||
let mut input = ParserInput::new(&easing);
|
||||
|
@ -3368,7 +3382,7 @@ pub extern "C" fn Servo_ParseStyleAttribute(
|
|||
parse_style_attribute(
|
||||
value,
|
||||
url_data,
|
||||
&reporter,
|
||||
reporter.as_ref().map(|r| r as &ParseErrorReporter),
|
||||
quirks_mode.into(),
|
||||
)
|
||||
)).into_strong()
|
||||
|
@ -3553,7 +3567,7 @@ fn set_property(
|
|||
data,
|
||||
parsing_mode,
|
||||
quirks_mode,
|
||||
&reporter,
|
||||
reporter.as_ref().map(|r| r as &ParseErrorReporter),
|
||||
);
|
||||
|
||||
if result.is_err() {
|
||||
|
@ -3757,14 +3771,12 @@ pub unsafe extern "C" fn Servo_MediaList_SetText(
|
|||
Some(CssRuleType::Media),
|
||||
ParsingMode::DEFAULT,
|
||||
QuirksMode::NoQuirks,
|
||||
// TODO(emilio): Looks like error reporting could be useful here?
|
||||
None,
|
||||
);
|
||||
|
||||
write_locked_arc(list, |list: &mut MediaList| {
|
||||
*list = MediaList::parse(
|
||||
&context,
|
||||
&mut parser,
|
||||
&NullReporter,
|
||||
);
|
||||
*list = MediaList::parse(&context, &mut parser);
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -3801,6 +3813,7 @@ pub extern "C" fn Servo_MediaList_AppendMedium(
|
|||
Some(CssRuleType::Media),
|
||||
ParsingMode::DEFAULT,
|
||||
QuirksMode::NoQuirks,
|
||||
None,
|
||||
);
|
||||
write_locked_arc(list, |list: &mut MediaList| {
|
||||
list.append_medium(&context, new_medium);
|
||||
|
@ -3819,6 +3832,7 @@ pub extern "C" fn Servo_MediaList_DeleteMedium(
|
|||
Some(CssRuleType::Media),
|
||||
ParsingMode::DEFAULT,
|
||||
QuirksMode::NoQuirks,
|
||||
None,
|
||||
);
|
||||
write_locked_arc(list, |list: &mut MediaList| list.delete_medium(&context, old_medium))
|
||||
}
|
||||
|
@ -4210,6 +4224,7 @@ pub extern "C" fn Servo_DeclarationBlock_SetBackgroundImage(
|
|||
Some(CssRuleType::Style),
|
||||
ParsingMode::DEFAULT,
|
||||
QuirksMode::NoQuirks,
|
||||
None,
|
||||
);
|
||||
let url = SpecifiedImageUrl::parse_from_string(string.into(), &context);
|
||||
let decl = PropertyDeclaration::BackgroundImage(BackgroundImage(
|
||||
|
@ -4250,7 +4265,7 @@ pub unsafe extern "C" fn Servo_CSSSupports2(
|
|||
DUMMY_URL_DATA,
|
||||
structs::ParsingMode_Default,
|
||||
QuirksMode::NoQuirks,
|
||||
&NullReporter,
|
||||
None,
|
||||
).is_ok()
|
||||
}
|
||||
|
||||
|
@ -4269,6 +4284,7 @@ pub extern "C" fn Servo_CSSSupports(cond: *const nsACString) -> bool {
|
|||
Some(CssRuleType::Style),
|
||||
ParsingMode::DEFAULT,
|
||||
QuirksMode::NoQuirks,
|
||||
None,
|
||||
);
|
||||
|
||||
cond.eval(&context)
|
||||
|
@ -5328,7 +5344,7 @@ pub unsafe extern "C" fn Servo_SelectorList_Drop(list: RawServoSelectorListOwned
|
|||
|
||||
fn parse_color(
|
||||
value: &str,
|
||||
error_reporter: Option<&ErrorReporter>,
|
||||
error_reporter: Option<&ParseErrorReporter>,
|
||||
) -> Result<specified::Color, ()> {
|
||||
let mut input = ParserInput::new(value);
|
||||
let mut parser = Parser::new(&mut input);
|
||||
|
@ -5339,11 +5355,12 @@ fn parse_color(
|
|||
Some(CssRuleType::Style),
|
||||
ParsingMode::DEFAULT,
|
||||
QuirksMode::NoQuirks,
|
||||
error_reporter,
|
||||
);
|
||||
|
||||
let start_position = parser.position();
|
||||
parser.parse_entirely(|i| specified::Color::parse(&context, i)).map_err(|err| {
|
||||
if let Some(error_reporter) = error_reporter {
|
||||
if error_reporter.is_some() {
|
||||
match err.kind {
|
||||
ParseErrorKind::Custom(StyleParseErrorKind::ValueError(..)) => {
|
||||
let location = err.location.clone();
|
||||
|
@ -5351,7 +5368,7 @@ fn parse_color(
|
|||
parser.slice_from(start_position),
|
||||
err,
|
||||
);
|
||||
error_reporter.report(location, error);
|
||||
context.log_css_error(location, error);
|
||||
}
|
||||
// Ignore other kinds of errors that might be reported, such as
|
||||
// ParseErrorKind::Basic(BasicParseErrorKind::UnexpectedToken),
|
||||
|
@ -5385,12 +5402,12 @@ pub extern "C" fn Servo_ComputeColor(
|
|||
let value = unsafe { (*value).to_string() };
|
||||
let result_color = unsafe { result_color.as_mut().unwrap() };
|
||||
|
||||
let reporter = unsafe { loader.as_mut() }.map(|loader| {
|
||||
let reporter = unsafe { loader.as_mut() }.and_then(|loader| {
|
||||
// Make an ErrorReporter that will report errors as being "from DOM".
|
||||
ErrorReporter::new(ptr::null_mut(), loader, ptr::null_mut())
|
||||
});
|
||||
|
||||
match parse_color(&value, reporter.as_ref()) {
|
||||
match parse_color(&value, reporter.as_ref().map(|r| r as &ParseErrorReporter)) {
|
||||
Ok(specified_color) => {
|
||||
let computed_color = match raw_data {
|
||||
Some(raw_data) => {
|
||||
|
@ -5442,6 +5459,7 @@ pub unsafe extern "C" fn Servo_IntersectionObserverRootMargin_Parse(
|
|||
Some(CssRuleType::Style),
|
||||
ParsingMode::DEFAULT,
|
||||
QuirksMode::NoQuirks,
|
||||
None,
|
||||
);
|
||||
|
||||
let margin = parser.parse_entirely(|p| {
|
||||
|
@ -5484,7 +5502,8 @@ pub extern "C" fn Servo_ParseTransformIntoMatrix(
|
|||
unsafe { dummy_url_data() },
|
||||
Some(CssRuleType::Style),
|
||||
ParsingMode::DEFAULT,
|
||||
QuirksMode::NoQuirks
|
||||
QuirksMode::NoQuirks,
|
||||
None,
|
||||
);
|
||||
|
||||
let transform = match parser.parse_entirely(|t| transform::parse(&context, t)) {
|
||||
|
@ -5527,6 +5546,7 @@ pub extern "C" fn Servo_ParseFontShorthandForMatching(
|
|||
Some(CssRuleType::FontFace),
|
||||
ParsingMode::DEFAULT,
|
||||
QuirksMode::NoQuirks,
|
||||
None,
|
||||
);
|
||||
|
||||
let font = match parser.parse_entirely(|f| font::parse_value(&context, f)) {
|
||||
|
@ -5584,6 +5604,7 @@ pub unsafe extern "C" fn Servo_SourceSizeList_Parse(
|
|||
Some(CssRuleType::Style),
|
||||
ParsingMode::DEFAULT,
|
||||
QuirksMode::NoQuirks,
|
||||
None,
|
||||
);
|
||||
|
||||
// NB: Intentionally not calling parse_entirely.
|
||||
|
|
|
@ -6,7 +6,6 @@ use cssparser::SourceLocation;
|
|||
use nsstring::nsCString;
|
||||
use servo_arc::Arc;
|
||||
use style::context::QuirksMode;
|
||||
use style::error_reporting::NullReporter;
|
||||
use style::gecko::data::GeckoStyleSheet;
|
||||
use style::gecko::global_style_data::GLOBAL_STYLE_DATA;
|
||||
use style::gecko_bindings::bindings;
|
||||
|
@ -104,10 +103,15 @@ impl AsyncStylesheetParser {
|
|||
// are being logged, Gecko prevents the parallel parsing path from
|
||||
// running.
|
||||
let sheet = Arc::new(StylesheetContents::from_str(
|
||||
input, self.extra_data.clone(), self.origin,
|
||||
&global_style_data.shared_lock, Some(&self), &NullReporter,
|
||||
self.quirks_mode.into(), self.line_number_offset)
|
||||
);
|
||||
input,
|
||||
self.extra_data.clone(),
|
||||
self.origin,
|
||||
&global_style_data.shared_lock,
|
||||
Some(&self),
|
||||
None,
|
||||
self.quirks_mode.into(),
|
||||
self.line_number_offset,
|
||||
));
|
||||
|
||||
unsafe {
|
||||
bindings::Gecko_StyleSheet_FinishAsyncParse(self.load_data.get(), sheet.into_strong());
|
||||
|
|
|
@ -363,6 +363,31 @@ test(function () {
|
|||
|
||||
}, 'document.createElement must report an exception thrown by a custom element constructor');
|
||||
|
||||
test(function () {
|
||||
var exceptionToThrow = {name: 'exception thrown by a custom constructor'};
|
||||
class ThrowCustomBuiltinElement extends HTMLDivElement {
|
||||
constructor()
|
||||
{
|
||||
super();
|
||||
if (exceptionToThrow)
|
||||
throw exceptionToThrow;
|
||||
}
|
||||
};
|
||||
customElements.define('throw-custom-builtin-element', ThrowCustomBuiltinElement, { extends: 'div' });
|
||||
|
||||
assert_throws(exceptionToThrow, function () { new ThrowCustomBuiltinElement; });
|
||||
var instance;
|
||||
assert_reports(exceptionToThrow, function () { instance = document.createElement('div', { is: 'throw-custom-builtin-element' }); });
|
||||
assert_equals(instance.localName, 'div');
|
||||
assert_true(instance instanceof HTMLDivElement);
|
||||
|
||||
exceptionToThrow = false;
|
||||
var instance = document.createElement('div', { is: 'throw-custom-builtin-element' });
|
||||
assert_true(instance instanceof ThrowCustomBuiltinElement);
|
||||
assert_equals(instance.localName, 'div');
|
||||
|
||||
}, 'document.createElement must report an exception thrown by a custom built-in element constructor');
|
||||
|
||||
test(() => {
|
||||
class MyElement extends HTMLDivElement {}
|
||||
|
||||
|
|
|
@ -15,6 +15,10 @@ EXTRA_COMPONENTS += [
|
|||
'ClearDataService.manifest',
|
||||
]
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'ServiceWorkerCleanUp.jsm',
|
||||
]
|
||||
|
||||
XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']
|
||||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
|
|
@ -135,6 +135,7 @@ ClearSiteData::Initialize()
|
|||
}
|
||||
|
||||
obs->AddObserver(service, NS_HTTP_ON_EXAMINE_RESPONSE_TOPIC, false);
|
||||
obs->AddObserver(service, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
|
||||
gClearSiteData = service;
|
||||
}
|
||||
|
||||
|
@ -156,6 +157,7 @@ ClearSiteData::Shutdown()
|
|||
}
|
||||
|
||||
obs->RemoveObserver(service, NS_HTTP_ON_EXAMINE_RESPONSE_TOPIC);
|
||||
obs->RemoveObserver(service, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
|
||||
}
|
||||
|
||||
ClearSiteData::ClearSiteData() = default;
|
||||
|
@ -165,6 +167,11 @@ NS_IMETHODIMP
|
|||
ClearSiteData::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
const char16_t* aData)
|
||||
{
|
||||
if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
|
||||
Shutdown();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!strcmp(aTopic, NS_HTTP_ON_EXAMINE_RESPONSE_TOPIC));
|
||||
|
||||
// Pref disabled.
|
||||
|
|
|
@ -25,13 +25,13 @@ public:
|
|||
static void
|
||||
Initialize();
|
||||
|
||||
static void
|
||||
Shutdown();
|
||||
|
||||
private:
|
||||
ClearSiteData();
|
||||
~ClearSiteData();
|
||||
|
||||
static void
|
||||
Shutdown();
|
||||
|
||||
class PendingCleanupHolder;
|
||||
|
||||
// Starts the cleanup if the channel contains the Clear-Site-Data header and
|
||||
|
|
|
@ -9,7 +9,6 @@ XPCSHELL_TESTS_MANIFESTS += ['test/unit/xpcshell.ini']
|
|||
|
||||
EXTRA_JS_MODULES += [
|
||||
'ForgetAboutSite.jsm',
|
||||
'ServiceWorkerCleanUp.jsm',
|
||||
]
|
||||
|
||||
with Files('**'):
|
||||
|
|
|
@ -40,6 +40,9 @@ private:
|
|||
|
||||
public:
|
||||
nsReadingIterator()
|
||||
: mStart(nullptr)
|
||||
, mEnd(nullptr)
|
||||
, mPosition(nullptr)
|
||||
{
|
||||
}
|
||||
// nsReadingIterator( const nsReadingIterator<CharT>& ); // auto-generated copy-constructor OK
|
||||
|
@ -142,6 +145,9 @@ private:
|
|||
|
||||
public:
|
||||
nsWritingIterator()
|
||||
: mStart(nullptr)
|
||||
, mEnd(nullptr)
|
||||
, mPosition(nullptr)
|
||||
{
|
||||
}
|
||||
// nsWritingIterator( const nsWritingIterator<CharT>& ); // auto-generated copy-constructor OK
|
||||
|
|
Загрузка…
Ссылка в новой задаче