зеркало из https://github.com/mozilla/gecko-dev.git
Merge the last green PGO changeset of mozilla-inbound to mozilla-central
This commit is contained in:
Коммит
624a77c0c9
|
@ -20,7 +20,7 @@ filters::GetSelected(Accessible* aAccessible)
|
|||
bool
|
||||
filters::GetSelectable(Accessible* aAccessible)
|
||||
{
|
||||
return aAccessible->State() & states::SELECTABLE;
|
||||
return aAccessible->InteractiveState() & states::SELECTABLE;
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -653,7 +653,6 @@ Accessible::NativeState()
|
|||
if (!document || !document->IsInDocument(this))
|
||||
state |= states::STALE;
|
||||
|
||||
bool disabled = false;
|
||||
if (mContent->IsElement()) {
|
||||
nsEventStates elementState = mContent->AsElement()->State();
|
||||
|
||||
|
@ -663,23 +662,7 @@ Accessible::NativeState()
|
|||
if (elementState.HasState(NS_EVENT_STATE_REQUIRED))
|
||||
state |= states::REQUIRED;
|
||||
|
||||
disabled = mContent->IsHTML() ?
|
||||
(elementState.HasState(NS_EVENT_STATE_DISABLED)) :
|
||||
(mContent->AttrValueIs(kNameSpaceID_None,
|
||||
nsGkAtoms::disabled,
|
||||
nsGkAtoms::_true,
|
||||
eCaseMatters));
|
||||
}
|
||||
|
||||
// Set unavailable state based on disabled state, otherwise set focus states
|
||||
if (disabled) {
|
||||
state |= states::UNAVAILABLE;
|
||||
}
|
||||
else if (mContent->IsElement()) {
|
||||
nsIFrame* frame = GetFrame();
|
||||
if (frame && frame->IsFocusable())
|
||||
state |= states::FOCUSABLE;
|
||||
|
||||
state |= NativeInteractiveState();
|
||||
if (FocusMgr()->IsFocused(this))
|
||||
state |= states::FOCUSED;
|
||||
}
|
||||
|
@ -704,6 +687,22 @@ Accessible::NativeState()
|
|||
return state;
|
||||
}
|
||||
|
||||
PRUint64
|
||||
Accessible::NativeInteractiveState() const
|
||||
{
|
||||
if (!mContent->IsElement())
|
||||
return 0;
|
||||
|
||||
if (NativelyUnavailable())
|
||||
return states::UNAVAILABLE;
|
||||
|
||||
nsIFrame* frame = GetFrame();
|
||||
if (frame && frame->IsFocusable())
|
||||
return states::FOCUSABLE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
PRUint64
|
||||
Accessible::NativeLinkState() const
|
||||
{
|
||||
|
@ -711,6 +710,16 @@ Accessible::NativeLinkState() const
|
|||
return nsCoreUtils::IsXLink(mContent) ? states::LINKED : 0;
|
||||
}
|
||||
|
||||
bool
|
||||
Accessible::NativelyUnavailable() const
|
||||
{
|
||||
if (mContent->IsHTML())
|
||||
return mContent->AsElement()->State().HasState(NS_EVENT_STATE_DISABLED);
|
||||
|
||||
return mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::disabled,
|
||||
nsGkAtoms::_true, eCaseMatters);
|
||||
}
|
||||
|
||||
/* readonly attribute boolean focusedChild; */
|
||||
NS_IMETHODIMP
|
||||
Accessible::GetFocusedChild(nsIAccessible** aChild)
|
||||
|
@ -1838,7 +1847,7 @@ Accessible::GetActionCount(PRUint8* aActionCount)
|
|||
PRUint8
|
||||
Accessible::ActionCount()
|
||||
{
|
||||
return GetActionRule(State()) == eNoAction ? 0 : 1;
|
||||
return GetActionRule() == eNoAction ? 0 : 1;
|
||||
}
|
||||
|
||||
/* DOMString getAccActionName (in PRUint8 index); */
|
||||
|
@ -1853,8 +1862,7 @@ Accessible::GetActionName(PRUint8 aIndex, nsAString& aName)
|
|||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
PRUint64 states = State();
|
||||
PRUint32 actionRule = GetActionRule(states);
|
||||
PRUint32 actionRule = GetActionRule();
|
||||
|
||||
switch (actionRule) {
|
||||
case eActivateAction:
|
||||
|
@ -1870,20 +1878,23 @@ Accessible::GetActionName(PRUint8 aIndex, nsAString& aName)
|
|||
return NS_OK;
|
||||
|
||||
case eCheckUncheckAction:
|
||||
if (states & states::CHECKED)
|
||||
{
|
||||
PRUint64 state = State();
|
||||
if (state & states::CHECKED)
|
||||
aName.AssignLiteral("uncheck");
|
||||
else if (states & states::MIXED)
|
||||
else if (state & states::MIXED)
|
||||
aName.AssignLiteral("cycle");
|
||||
else
|
||||
aName.AssignLiteral("check");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
case eJumpAction:
|
||||
aName.AssignLiteral("jump");
|
||||
return NS_OK;
|
||||
|
||||
case eOpenCloseAction:
|
||||
if (states & states::COLLAPSED)
|
||||
if (State() & states::COLLAPSED)
|
||||
aName.AssignLiteral("open");
|
||||
else
|
||||
aName.AssignLiteral("close");
|
||||
|
@ -1896,13 +1907,13 @@ Accessible::GetActionName(PRUint8 aIndex, nsAString& aName)
|
|||
case eSwitchAction:
|
||||
aName.AssignLiteral("switch");
|
||||
return NS_OK;
|
||||
|
||||
|
||||
case eSortAction:
|
||||
aName.AssignLiteral("sort");
|
||||
return NS_OK;
|
||||
|
||||
|
||||
case eExpandAction:
|
||||
if (states & states::COLLAPSED)
|
||||
if (State() & states::COLLAPSED)
|
||||
aName.AssignLiteral("expand");
|
||||
else
|
||||
aName.AssignLiteral("collapse");
|
||||
|
@ -1935,7 +1946,7 @@ Accessible::DoAction(PRUint8 aIndex)
|
|||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (GetActionRule(State()) != eNoAction) {
|
||||
if (GetActionRule() != eNoAction) {
|
||||
DoCommand();
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -3142,11 +3153,11 @@ Accessible::GetAttrValue(nsIAtom *aProperty, double *aValue)
|
|||
}
|
||||
|
||||
PRUint32
|
||||
Accessible::GetActionRule(PRUint64 aStates)
|
||||
Accessible::GetActionRule()
|
||||
{
|
||||
if (aStates & states::UNAVAILABLE)
|
||||
if (InteractiveState() & states::UNAVAILABLE)
|
||||
return eNoAction;
|
||||
|
||||
|
||||
// Check if it's simple xlink.
|
||||
if (nsCoreUtils::IsXLink(mContent))
|
||||
return eJumpAction;
|
||||
|
|
|
@ -207,6 +207,17 @@ public:
|
|||
*/
|
||||
virtual PRUint64 State();
|
||||
|
||||
/**
|
||||
* Return interactive states present on the accessible
|
||||
* (@see NativeInteractiveState).
|
||||
*/
|
||||
PRUint64 InteractiveState() const
|
||||
{
|
||||
PRUint64 state = NativeInteractiveState();
|
||||
ApplyARIAState(&state);
|
||||
return state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return link states present on the accessible.
|
||||
*/
|
||||
|
@ -223,6 +234,11 @@ public:
|
|||
*/
|
||||
virtual PRUint64 NativeState();
|
||||
|
||||
/**
|
||||
* Return native interactice state (unavailable, focusable or selectable).
|
||||
*/
|
||||
virtual PRUint64 NativeInteractiveState() const;
|
||||
|
||||
/**
|
||||
* Return native link states present on the accessible.
|
||||
*/
|
||||
|
@ -233,6 +249,11 @@ public:
|
|||
*/
|
||||
PRUint64 VisibilityState();
|
||||
|
||||
/**
|
||||
* Return true if native unavailable state present.
|
||||
*/
|
||||
virtual bool NativelyUnavailable() const;
|
||||
|
||||
/**
|
||||
* Returns attributes for accessible without explicitly setted ARIA
|
||||
* attributes.
|
||||
|
@ -824,10 +845,8 @@ protected:
|
|||
/**
|
||||
* Return the action rule based on ARIA enum constants EActionRule
|
||||
* (see nsARIAMap.h). Used by ActionCount() and GetActionName().
|
||||
*
|
||||
* @param aStates [in] states of the accessible
|
||||
*/
|
||||
PRUint32 GetActionRule(PRUint64 aStates);
|
||||
PRUint32 GetActionRule();
|
||||
|
||||
/**
|
||||
* Return group info.
|
||||
|
|
|
@ -285,7 +285,7 @@ DocAccessible::NativeState()
|
|||
0 : states::STALE;
|
||||
|
||||
// Document is always focusable.
|
||||
state |= states::FOCUSABLE;
|
||||
state |= states::FOCUSABLE; // keep in sync with NativeIteractiveState() impl
|
||||
if (FocusMgr()->IsFocused(this))
|
||||
state |= states::FOCUSED;
|
||||
|
||||
|
@ -311,6 +311,19 @@ DocAccessible::NativeState()
|
|||
return state;
|
||||
}
|
||||
|
||||
PRUint64
|
||||
DocAccessible::NativeInteractiveState() const
|
||||
{
|
||||
// Document is always focusable.
|
||||
return states::FOCUSABLE;
|
||||
}
|
||||
|
||||
bool
|
||||
DocAccessible::NativelyUnavailable() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Accessible public method
|
||||
void
|
||||
DocAccessible::ApplyARIAState(PRUint64* aState) const
|
||||
|
|
|
@ -84,6 +84,8 @@ public:
|
|||
virtual Accessible* FocusedChild();
|
||||
virtual mozilla::a11y::role NativeRole();
|
||||
virtual PRUint64 NativeState();
|
||||
virtual PRUint64 NativeInteractiveState() const;
|
||||
virtual bool NativelyUnavailable() const;
|
||||
virtual void ApplyARIAState(PRUint64* aState) const;
|
||||
|
||||
virtual void SetRoleMapEntry(nsRoleMapEntry* aRoleMapEntry);
|
||||
|
|
|
@ -1541,7 +1541,7 @@ HyperTextAccessible::GetEditor() const
|
|||
nsresult
|
||||
HyperTextAccessible::SetSelectionRange(PRInt32 aStartPos, PRInt32 aEndPos)
|
||||
{
|
||||
bool isFocusable = State() & states::FOCUSABLE;
|
||||
bool isFocusable = InteractiveState() & states::FOCUSABLE;
|
||||
|
||||
// If accessible is focusable then focus it before setting the selection to
|
||||
// neglect control's selection changes on focus if any (for example, inputs
|
||||
|
@ -1612,7 +1612,7 @@ HyperTextAccessible::GetCaretOffset(PRInt32* aCaretOffset)
|
|||
// Not focused focusable accessible except document accessible doesn't have
|
||||
// a caret.
|
||||
if (!IsDoc() && !FocusMgr()->IsFocused(this) &&
|
||||
(State() & states::FOCUSABLE)) {
|
||||
(InteractiveState() & states::FOCUSABLE)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -188,11 +188,7 @@ HTMLListBulletAccessible::NativeRole()
|
|||
PRUint64
|
||||
HTMLListBulletAccessible::NativeState()
|
||||
{
|
||||
PRUint64 state = nsLeafAccessible::NativeState();
|
||||
|
||||
state &= ~states::FOCUSABLE;
|
||||
state |= states::READONLY;
|
||||
return state;
|
||||
return nsLeafAccessible::NativeState() | states::READONLY;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -42,18 +42,7 @@ nsHTMLLinkAccessible::NativeRole()
|
|||
PRUint64
|
||||
nsHTMLLinkAccessible::NativeState()
|
||||
{
|
||||
PRUint64 states = HyperTextAccessibleWrap::NativeState();
|
||||
|
||||
states &= ~states::READONLY;
|
||||
|
||||
if (mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::name)) {
|
||||
// This is how we indicate it is a named anchor
|
||||
// In other words, this anchor can be selected as a location :)
|
||||
// There is no other better state to use to indicate this.
|
||||
states |= states::SELECTABLE;
|
||||
}
|
||||
|
||||
return states;
|
||||
return HyperTextAccessibleWrap::NativeState() & ~states::READONLY;
|
||||
}
|
||||
|
||||
PRUint64
|
||||
|
@ -72,6 +61,20 @@ nsHTMLLinkAccessible::NativeLinkState() const
|
|||
return nsCoreUtils::HasClickListener(mContent) ? states::LINKED : 0;
|
||||
}
|
||||
|
||||
PRUint64
|
||||
nsHTMLLinkAccessible::NativeInteractiveState() const
|
||||
{
|
||||
PRUint64 state = HyperTextAccessibleWrap::NativeInteractiveState();
|
||||
|
||||
// This is how we indicate it is a named anchor. In other words, this anchor
|
||||
// can be selected as a location :) There is no other better state to use to
|
||||
// indicate this.
|
||||
if (mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::name))
|
||||
state |= states::SELECTABLE;
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
void
|
||||
nsHTMLLinkAccessible::Value(nsString& aValue)
|
||||
{
|
||||
|
|
|
@ -24,6 +24,7 @@ public:
|
|||
virtual mozilla::a11y::role NativeRole();
|
||||
virtual PRUint64 NativeState();
|
||||
virtual PRUint64 NativeLinkState() const;
|
||||
virtual PRUint64 NativeInteractiveState() const;
|
||||
|
||||
// ActionAccessible
|
||||
virtual PRUint8 ActionCount();
|
||||
|
|
|
@ -237,10 +237,6 @@ nsHTMLSelectOptionAccessible::NativeState()
|
|||
if (selectState & states::INVISIBLE)
|
||||
return state;
|
||||
|
||||
// Focusable and selectable
|
||||
if (!(state & states::UNAVAILABLE))
|
||||
state |= (states::FOCUSABLE | states::SELECTABLE);
|
||||
|
||||
// Are we selected?
|
||||
bool isSelected = false;
|
||||
nsCOMPtr<nsIDOMHTMLOptionElement> option(do_QueryInterface(mContent));
|
||||
|
@ -285,6 +281,13 @@ nsHTMLSelectOptionAccessible::NativeState()
|
|||
return state;
|
||||
}
|
||||
|
||||
PRUint64
|
||||
nsHTMLSelectOptionAccessible::NativeInteractiveState() const
|
||||
{
|
||||
return NativelyUnavailable() ?
|
||||
states::UNAVAILABLE : states::FOCUSABLE | states::SELECTABLE;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
nsHTMLSelectOptionAccessible::GetLevelInternal()
|
||||
{
|
||||
|
@ -376,13 +379,9 @@ nsHTMLSelectOptGroupAccessible::NativeRole()
|
|||
}
|
||||
|
||||
PRUint64
|
||||
nsHTMLSelectOptGroupAccessible::NativeState()
|
||||
nsHTMLSelectOptGroupAccessible::NativeInteractiveState() const
|
||||
{
|
||||
PRUint64 state = nsHTMLSelectOptionAccessible::NativeState();
|
||||
|
||||
state &= ~(states::FOCUSABLE | states::SELECTABLE);
|
||||
|
||||
return state;
|
||||
return NativelyUnavailable() ? states::UNAVAILABLE : 0;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsHTMLSelectOptGroupAccessible::DoAction(PRUint8 index)
|
||||
|
|
|
@ -86,6 +86,7 @@ public:
|
|||
virtual nsresult GetNameInternal(nsAString& aName);
|
||||
virtual mozilla::a11y::role NativeRole();
|
||||
virtual PRUint64 NativeState();
|
||||
virtual PRUint64 NativeInteractiveState() const;
|
||||
|
||||
virtual PRInt32 GetLevelInternal();
|
||||
virtual void GetBoundsRect(nsRect& aTotalBounds, nsIFrame** aBoundingFrame);
|
||||
|
@ -141,7 +142,7 @@ public:
|
|||
|
||||
// Accessible
|
||||
virtual mozilla::a11y::role NativeRole();
|
||||
virtual PRUint64 NativeState();
|
||||
virtual PRUint64 NativeInteractiveState() const;
|
||||
|
||||
// ActionAccessible
|
||||
virtual PRUint8 ActionCount();
|
||||
|
|
|
@ -72,15 +72,18 @@ nsHTMLTableCellAccessible::NativeState()
|
|||
nsIFrame *frame = mContent->GetPrimaryFrame();
|
||||
NS_ASSERTION(frame, "No frame for valid cell accessible!");
|
||||
|
||||
if (frame) {
|
||||
state |= states::SELECTABLE;
|
||||
if (frame->IsSelected())
|
||||
state |= states::SELECTED;
|
||||
}
|
||||
if (frame && frame->IsSelected())
|
||||
state |= states::SELECTED;
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
PRUint64
|
||||
nsHTMLTableCellAccessible::NativeInteractiveState() const
|
||||
{
|
||||
return HyperTextAccessibleWrap::NativeInteractiveState() | states::SELECTABLE;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLTableCellAccessible::GetAttributesInternal(nsIPersistentProperties *aAttributes)
|
||||
{
|
||||
|
|
|
@ -32,6 +32,7 @@ public:
|
|||
// Accessible
|
||||
virtual mozilla::a11y::role NativeRole();
|
||||
virtual PRUint64 NativeState();
|
||||
virtual PRUint64 NativeInteractiveState() const;
|
||||
virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
|
||||
|
||||
protected:
|
||||
|
|
|
@ -351,6 +351,11 @@ var AccessFu = {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case Ci.nsIAccessibleEvent.EVENT_SCROLLING_START:
|
||||
{
|
||||
VirtualCursorController.moveCursorToObject(aEvent.accessible);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -165,6 +165,22 @@ var VirtualCursorController = {
|
|||
QueryInterface(Ci.nsIAccessibleCursorable).virtualCursor;
|
||||
},
|
||||
|
||||
moveCursorToObject: function moveCursorToObject(aAccessible, aRule) {
|
||||
let doc = aAccessible.document;
|
||||
while (doc) {
|
||||
let vc = null;
|
||||
try {
|
||||
vc = doc.QueryInterface(Ci.nsIAccessibleCursorable).virtualCursor;
|
||||
} catch (x) {
|
||||
doc = doc.parentDocument;
|
||||
continue;
|
||||
}
|
||||
if (vc)
|
||||
vc.moveNext(aRule || this.SimpleTraversalRule, aAccessible, true);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
SimpleTraversalRule: {
|
||||
getMatchRoles: function SimpleTraversalRule_getmatchRoles(aRules) {
|
||||
aRules.value = this._matchRoles;
|
||||
|
|
|
@ -556,12 +556,12 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
|
|||
|
||||
- (BOOL)isFocused
|
||||
{
|
||||
return (mGeckoAccessible->State() & states::FOCUSED) != 0;
|
||||
return FocusMgr()->IsFocused(mGeckoAccessible);
|
||||
}
|
||||
|
||||
- (BOOL)canBeFocused
|
||||
{
|
||||
return mGeckoAccessible->State() & states::FOCUSABLE;
|
||||
return mGeckoAccessible->InteractiveState() & states::FOCUSABLE;
|
||||
}
|
||||
|
||||
- (BOOL)focus
|
||||
|
@ -572,7 +572,7 @@ GetNativeFromGeckoAccessible(nsIAccessible *anAccessible)
|
|||
|
||||
- (BOOL)isEnabled
|
||||
{
|
||||
return (mGeckoAccessible->State() & states::UNAVAILABLE) == 0;
|
||||
return (mGeckoAccessible->InteractiveState() & states::UNAVAILABLE) == 0;
|
||||
}
|
||||
|
||||
// The root accessible calls this when the focused node was
|
||||
|
|
|
@ -42,12 +42,12 @@ nsHTMLWin32ObjectOwnerAccessible::NativeRole()
|
|||
return roles::EMBEDDED_OBJECT;
|
||||
}
|
||||
|
||||
PRUint64
|
||||
nsHTMLWin32ObjectOwnerAccessible::NativeState()
|
||||
bool
|
||||
nsHTMLWin32ObjectOwnerAccessible::NativelyUnavailable() const
|
||||
{
|
||||
// XXX: No HWND means this is windowless plugin which is not accessible in
|
||||
// the meantime.
|
||||
return mHwnd ? AccessibleWrap::NativeState() : states::UNAVAILABLE;
|
||||
return !mHwnd;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -28,7 +28,7 @@ public:
|
|||
|
||||
// Accessible
|
||||
virtual mozilla::a11y::role NativeRole();
|
||||
virtual PRUint64 NativeState();
|
||||
virtual bool NativelyUnavailable() const;
|
||||
|
||||
protected:
|
||||
|
||||
|
|
|
@ -119,12 +119,8 @@ nsXFormsAccessible::NativeState()
|
|||
|
||||
nsCOMPtr<nsIDOMNode> DOMNode(do_QueryInterface(mContent));
|
||||
|
||||
bool isRelevant = false;
|
||||
nsresult rv = sXFormsService->IsRelevant(DOMNode, &isRelevant);
|
||||
NS_ENSURE_SUCCESS(rv, 0);
|
||||
|
||||
bool isReadonly = false;
|
||||
rv = sXFormsService->IsReadonly(DOMNode, &isReadonly);
|
||||
nsresult rv = sXFormsService->IsReadonly(DOMNode, &isReadonly);
|
||||
NS_ENSURE_SUCCESS(rv, 0);
|
||||
|
||||
bool isRequired = false;
|
||||
|
@ -137,7 +133,7 @@ nsXFormsAccessible::NativeState()
|
|||
|
||||
PRUint64 states = HyperTextAccessibleWrap::NativeState();
|
||||
|
||||
if (!isRelevant)
|
||||
if (NativelyUnavailable())
|
||||
states |= states::UNAVAILABLE;
|
||||
|
||||
if (isReadonly)
|
||||
|
@ -152,6 +148,16 @@ nsXFormsAccessible::NativeState()
|
|||
return states;
|
||||
}
|
||||
|
||||
bool
|
||||
nsXFormsAccessible::NativelyUnavailable() const
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> DOMNode(do_QueryInterface(mContent));
|
||||
|
||||
bool isRelevant = false;
|
||||
sXFormsService->IsRelevant(DOMNode, &isRelevant);
|
||||
return !isRelevant;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXFormsAccessible::GetNameInternal(nsAString& aName)
|
||||
{
|
||||
|
|
|
@ -52,6 +52,7 @@ public:
|
|||
// Returns state of xforms element taking into account state of instance node
|
||||
// that it is bound to.
|
||||
virtual PRUint64 NativeState();
|
||||
virtual bool NativelyUnavailable() const;
|
||||
|
||||
// Denies accessible nodes in anonymous content of xforms element by
|
||||
// always returning false value.
|
||||
|
|
|
@ -555,7 +555,13 @@ nsXFormsSelectComboboxAccessible::NativeState()
|
|||
else
|
||||
state |= states::COLLAPSED;
|
||||
|
||||
return state | states::HASPOPUP | states::FOCUSABLE;
|
||||
return state | states::HASPOPUP;
|
||||
}
|
||||
|
||||
PRUint64
|
||||
nsXFormsSelectComboboxAccessible::NativeInteractiveState() const
|
||||
{
|
||||
return NativelyUnavailable() ? states::UNAVAILABLE : states::FOCUSABLE;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -585,17 +591,19 @@ PRUint64
|
|||
nsXFormsItemComboboxAccessible::NativeState()
|
||||
{
|
||||
PRUint64 state = nsXFormsSelectableItemAccessible::NativeState();
|
||||
|
||||
if (state & states::UNAVAILABLE)
|
||||
return state;
|
||||
|
||||
state |= states::SELECTABLE;
|
||||
if (IsSelected())
|
||||
state |= states::SELECTED;
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
PRUint64
|
||||
nsXFormsItemComboboxAccessible::NativeInteractiveState() const
|
||||
{
|
||||
return NativelyUnavailable() ?
|
||||
states::UNAVAILABLE : states::FOCUSABLE | states::SELECTABLE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsItemComboboxAccessible::GetActionName(PRUint8 aIndex, nsAString& aName)
|
||||
{
|
||||
|
|
|
@ -261,6 +261,7 @@ public:
|
|||
// Accessible
|
||||
virtual mozilla::a11y::role NativeRole();
|
||||
virtual PRUint64 NativeState();
|
||||
virtual PRUint64 NativeInteractiveState() const;
|
||||
virtual bool CanHaveAnonChildren();
|
||||
};
|
||||
|
||||
|
@ -283,6 +284,7 @@ public:
|
|||
// Accessible
|
||||
virtual mozilla::a11y::role NativeRole();
|
||||
virtual PRUint64 NativeState();
|
||||
virtual PRUint64 NativeInteractiveState() const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -119,8 +119,6 @@ nsXFormsComboboxPopupWidgetAccessible::NativeState()
|
|||
nsresult rv = sXFormsService->IsDropmarkerOpen(DOMNode, &isOpen);
|
||||
NS_ENSURE_SUCCESS(rv, state);
|
||||
|
||||
state |= states::FOCUSABLE;
|
||||
|
||||
if (isOpen)
|
||||
state = states::FLOATING;
|
||||
else
|
||||
|
@ -129,6 +127,12 @@ nsXFormsComboboxPopupWidgetAccessible::NativeState()
|
|||
return state;
|
||||
}
|
||||
|
||||
PRUint64
|
||||
nsXFormsComboboxPopupWidgetAccessible::NativeInteractiveState() const
|
||||
{
|
||||
return NativelyUnavailable() ? states::UNAVAILABLE : states::FOCUSABLE;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXFormsComboboxPopupWidgetAccessible::GetNameInternal(nsAString& aName)
|
||||
{
|
||||
|
|
|
@ -64,6 +64,7 @@ public:
|
|||
virtual nsresult GetNameInternal(nsAString& aName);
|
||||
virtual mozilla::a11y::role NativeRole();
|
||||
virtual PRUint64 NativeState();
|
||||
virtual PRUint64 NativeInteractiveState() const;
|
||||
|
||||
protected:
|
||||
// Accessible
|
||||
|
|
|
@ -95,16 +95,6 @@ XULButtonAccessible::NativeState()
|
|||
// get focus and disable status from base class
|
||||
PRUint64 state = Accessible::NativeState();
|
||||
|
||||
bool disabled = false;
|
||||
nsCOMPtr<nsIDOMXULControlElement> xulFormElement(do_QueryInterface(mContent));
|
||||
if (xulFormElement) {
|
||||
xulFormElement->GetDisabled(&disabled);
|
||||
if (disabled)
|
||||
state |= states::UNAVAILABLE;
|
||||
else
|
||||
state |= states::FOCUSABLE;
|
||||
}
|
||||
|
||||
// Buttons can be checked -- they simply appear pressed in rather than checked
|
||||
nsCOMPtr<nsIDOMXULButtonElement> xulButtonElement(do_QueryInterface(mContent));
|
||||
if (xulButtonElement) {
|
||||
|
@ -481,9 +471,6 @@ XULRadioButtonAccessible::NativeState()
|
|||
PRUint64 state = nsLeafAccessible::NativeState();
|
||||
state |= states::CHECKABLE;
|
||||
|
||||
if (!(state & states::UNAVAILABLE))
|
||||
state |= states::FOCUSABLE;
|
||||
|
||||
nsCOMPtr<nsIDOMXULSelectControlItemElement> radioButton =
|
||||
do_QueryInterface(mContent);
|
||||
if (radioButton) {
|
||||
|
@ -497,6 +484,12 @@ XULRadioButtonAccessible::NativeState()
|
|||
return state;
|
||||
}
|
||||
|
||||
PRUint64
|
||||
XULRadioButtonAccessible::NativeInteractiveState() const
|
||||
{
|
||||
return NativelyUnavailable() ? states::UNAVAILABLE : states::FOCUSABLE;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// XULRadioButtonAccessible: Widgets
|
||||
|
||||
|
@ -533,12 +526,12 @@ XULRadioGroupAccessible::NativeRole()
|
|||
}
|
||||
|
||||
PRUint64
|
||||
XULRadioGroupAccessible::NativeState()
|
||||
XULRadioGroupAccessible::NativeInteractiveState() const
|
||||
{
|
||||
// The radio group is not focusable. Sometimes the focus controller will
|
||||
// report that it is focused. That means that the actual selected radio button
|
||||
// should be considered focused.
|
||||
return Accessible::NativeState() & ~(states::FOCUSABLE | states::FOCUSED);
|
||||
return NativelyUnavailable() ? states::UNAVAILABLE : 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -132,6 +132,7 @@ public:
|
|||
|
||||
// Accessible
|
||||
virtual PRUint64 NativeState();
|
||||
virtual PRUint64 NativeInteractiveState() const;
|
||||
|
||||
// Widgets
|
||||
virtual Accessible* ContainerWidget() const;
|
||||
|
@ -147,7 +148,7 @@ public:
|
|||
|
||||
// Accessible
|
||||
virtual mozilla::a11y::role NativeRole();
|
||||
virtual PRUint64 NativeState();
|
||||
virtual PRUint64 NativeInteractiveState() const;
|
||||
|
||||
// Widgets
|
||||
virtual bool IsWidget() const;
|
||||
|
|
|
@ -52,15 +52,19 @@ PRUint64
|
|||
nsXULColorPickerTileAccessible::NativeState()
|
||||
{
|
||||
PRUint64 state = AccessibleWrap::NativeState();
|
||||
if (!(state & states::UNAVAILABLE))
|
||||
state |= states::FOCUSABLE | states::SELECTABLE;
|
||||
|
||||
if (mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::selected))
|
||||
state |= states::SELECTED;
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
PRUint64
|
||||
nsXULColorPickerTileAccessible::NativeInteractiveState() const
|
||||
{
|
||||
return NativelyUnavailable() ?
|
||||
states::UNAVAILABLE : states::FOCUSABLE | states::SELECTABLE;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsXULColorPickerTileAccessible: Widgets
|
||||
|
||||
|
@ -93,14 +97,8 @@ nsXULColorPickerAccessible::
|
|||
PRUint64
|
||||
nsXULColorPickerAccessible::NativeState()
|
||||
{
|
||||
// Possible states: focused, focusable, unavailable(disabled).
|
||||
|
||||
// get focus and disable status from base class
|
||||
PRUint64 states = AccessibleWrap::NativeState();
|
||||
|
||||
states |= states::FOCUSABLE | states::HASPOPUP;
|
||||
|
||||
return states;
|
||||
PRUint64 state = AccessibleWrap::NativeState();
|
||||
return state | states::HASPOPUP;
|
||||
}
|
||||
|
||||
role
|
||||
|
|
|
@ -21,6 +21,7 @@ public:
|
|||
virtual void Value(nsString& aValue);
|
||||
virtual mozilla::a11y::role NativeRole();
|
||||
virtual PRUint64 NativeState();
|
||||
virtual PRUint64 NativeInteractiveState() const;
|
||||
|
||||
// Widgets
|
||||
virtual Accessible* ContainerWidget() const;
|
||||
|
|
|
@ -50,23 +50,19 @@ nsXULComboboxAccessible::NativeState()
|
|||
// STATE_COLLAPSED
|
||||
|
||||
// Get focus status from base class
|
||||
PRUint64 states = Accessible::NativeState();
|
||||
PRUint64 state = Accessible::NativeState();
|
||||
|
||||
nsCOMPtr<nsIDOMXULMenuListElement> menuList(do_QueryInterface(mContent));
|
||||
if (menuList) {
|
||||
bool isOpen;
|
||||
bool isOpen = false;
|
||||
menuList->GetOpen(&isOpen);
|
||||
if (isOpen) {
|
||||
states |= states::EXPANDED;
|
||||
}
|
||||
else {
|
||||
states |= states::COLLAPSED;
|
||||
}
|
||||
if (isOpen)
|
||||
state |= states::EXPANDED;
|
||||
else
|
||||
state |= states::COLLAPSED;
|
||||
}
|
||||
|
||||
states |= states::HASPOPUP | states::FOCUSABLE;
|
||||
|
||||
return states;
|
||||
return state | states::HASPOPUP;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -869,7 +869,7 @@ nsXULListitemAccessible::NativeState()
|
|||
if (mIsCheckbox)
|
||||
return nsXULMenuitemAccessible::NativeState();
|
||||
|
||||
PRUint64 states = states::FOCUSABLE | states::SELECTABLE;
|
||||
PRUint64 states = NativeInteractiveState();
|
||||
|
||||
nsCOMPtr<nsIDOMXULSelectControlItemElement> listItem =
|
||||
do_QueryInterface(mContent);
|
||||
|
@ -887,6 +887,13 @@ nsXULListitemAccessible::NativeState()
|
|||
return states;
|
||||
}
|
||||
|
||||
PRUint64
|
||||
nsXULListitemAccessible::NativeInteractiveState() const
|
||||
{
|
||||
return NativelyUnavailable() || mParent->NativelyUnavailable() ?
|
||||
states::UNAVAILABLE : states::FOCUSABLE | states::SELECTABLE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsXULListitemAccessible::GetActionName(PRUint8 aIndex, nsAString& aName)
|
||||
{
|
||||
if (aIndex == eAction_Click && mIsCheckbox) {
|
||||
|
|
|
@ -117,6 +117,7 @@ public:
|
|||
virtual nsresult GetNameInternal(nsAString& aName);
|
||||
virtual mozilla::a11y::role NativeRole();
|
||||
virtual PRUint64 NativeState();
|
||||
virtual PRUint64 NativeInteractiveState() const;
|
||||
virtual bool CanHaveAnonChildren();
|
||||
|
||||
// Widgets
|
||||
|
|
|
@ -110,24 +110,28 @@ nsXULMenuitemAccessible::NativeState()
|
|||
} // isSelected
|
||||
} // ROLE_COMBOBOX_OPTION
|
||||
|
||||
// Set focusable and selectable for items that are available
|
||||
// and whose metric setting does allow disabled items to be focused.
|
||||
if (state & states::UNAVAILABLE) {
|
||||
// Honour the LookAndFeel metric.
|
||||
PRInt32 skipDisabledMenuItems =
|
||||
LookAndFeel::GetInt(LookAndFeel::eIntID_SkipNavigatingDisabledMenuItem);
|
||||
// We don't want the focusable and selectable states for combobox items,
|
||||
// so exclude them here as well.
|
||||
if (skipDisabledMenuItems || isComboboxOption) {
|
||||
return state;
|
||||
return state;
|
||||
}
|
||||
|
||||
PRUint64
|
||||
nsXULMenuitemAccessible::NativeInteractiveState() const
|
||||
{
|
||||
if (NativelyUnavailable()) {
|
||||
// Note: keep in sinc with nsXULPopupManager::IsValidMenuItem() logic.
|
||||
bool skipNavigatingDisabledMenuItem = true;
|
||||
nsMenuFrame* menuFrame = do_QueryFrame(GetFrame());
|
||||
if (!menuFrame->IsOnMenuBar()) {
|
||||
skipNavigatingDisabledMenuItem = LookAndFeel::
|
||||
GetInt(LookAndFeel::eIntID_SkipNavigatingDisabledMenuItem, 0) != 0;
|
||||
}
|
||||
|
||||
if (skipNavigatingDisabledMenuItem)
|
||||
return states::UNAVAILABLE;
|
||||
|
||||
return states::UNAVAILABLE | states::FOCUSABLE | states::SELECTABLE;
|
||||
}
|
||||
|
||||
state |= (states::FOCUSABLE | states::SELECTABLE);
|
||||
if (FocusMgr()->IsFocused(this))
|
||||
state |= states::FOCUSED;
|
||||
|
||||
return state;
|
||||
return states::FOCUSABLE | states::SELECTABLE;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -555,17 +559,6 @@ nsXULMenubarAccessible::
|
|||
{
|
||||
}
|
||||
|
||||
PRUint64
|
||||
nsXULMenubarAccessible::NativeState()
|
||||
{
|
||||
PRUint64 state = Accessible::NativeState();
|
||||
|
||||
// Menu bar itself is not actually focusable
|
||||
state &= ~states::FOCUSABLE;
|
||||
return state;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsXULMenubarAccessible::GetNameInternal(nsAString& aName)
|
||||
{
|
||||
|
|
|
@ -29,6 +29,7 @@ public:
|
|||
virtual nsresult GetNameInternal(nsAString& aName);
|
||||
virtual mozilla::a11y::role NativeRole();
|
||||
virtual PRUint64 NativeState();
|
||||
virtual PRUint64 NativeInteractiveState() const;
|
||||
virtual PRInt32 GetLevelInternal();
|
||||
|
||||
virtual bool CanHaveAnonChildren();
|
||||
|
@ -98,7 +99,6 @@ public:
|
|||
// Accessible
|
||||
virtual nsresult GetNameInternal(nsAString& aName);
|
||||
virtual mozilla::a11y::role NativeRole();
|
||||
virtual PRUint64 NativeState();
|
||||
|
||||
// Widget
|
||||
virtual bool IsActiveWidget() const;
|
||||
|
|
|
@ -38,22 +38,26 @@ nsXULSliderAccessible::NativeRole()
|
|||
}
|
||||
|
||||
PRUint64
|
||||
nsXULSliderAccessible::NativeState()
|
||||
{
|
||||
PRUint64 state = AccessibleWrap::NativeState();
|
||||
nsXULSliderAccessible::NativeInteractiveState() const
|
||||
{
|
||||
if (NativelyUnavailable())
|
||||
return states::UNAVAILABLE;
|
||||
|
||||
nsIContent* sliderElm = GetSliderElement();
|
||||
if (!sliderElm)
|
||||
return state;
|
||||
if (sliderElm) {
|
||||
nsIFrame* frame = sliderElm->GetPrimaryFrame();
|
||||
if (frame && frame->IsFocusable())
|
||||
return states::FOCUSABLE;
|
||||
}
|
||||
|
||||
nsIFrame *frame = sliderElm->GetPrimaryFrame();
|
||||
if (frame && frame->IsFocusable())
|
||||
state |= states::FOCUSABLE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (FocusMgr()->IsFocused(this))
|
||||
state |= states::FOCUSED;
|
||||
|
||||
return state;
|
||||
bool
|
||||
nsXULSliderAccessible::NativelyUnavailable() const
|
||||
{
|
||||
return mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::disabled,
|
||||
nsGkAtoms::_true, eCaseMatters);
|
||||
}
|
||||
|
||||
// nsIAccessible
|
||||
|
@ -165,7 +169,7 @@ nsXULSliderAccessible::CanHaveAnonChildren()
|
|||
// Utils
|
||||
|
||||
nsIContent*
|
||||
nsXULSliderAccessible::GetSliderElement()
|
||||
nsXULSliderAccessible::GetSliderElement() const
|
||||
{
|
||||
if (!mSliderNode) {
|
||||
// XXX: we depend on anonymous content.
|
||||
|
|
|
@ -31,7 +31,8 @@ public:
|
|||
// Accessible
|
||||
virtual void Value(nsString& aValue);
|
||||
virtual mozilla::a11y::role NativeRole();
|
||||
virtual PRUint64 NativeState();
|
||||
virtual PRUint64 NativeInteractiveState() const;
|
||||
virtual bool NativelyUnavailable() const;
|
||||
virtual bool CanHaveAnonChildren();
|
||||
|
||||
// ActionAccessible
|
||||
|
@ -41,7 +42,7 @@ protected:
|
|||
/**
|
||||
* Return anonymous slider element.
|
||||
*/
|
||||
nsIContent* GetSliderElement();
|
||||
nsIContent* GetSliderElement() const;
|
||||
|
||||
nsresult GetSliderAttr(nsIAtom *aName, nsAString& aValue);
|
||||
nsresult SetSliderAttr(nsIAtom *aName, const nsAString& aValue);
|
||||
|
@ -50,7 +51,7 @@ protected:
|
|||
nsresult SetSliderAttr(nsIAtom *aName, double aValue);
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIContent> mSliderNode;
|
||||
mutable nsCOMPtr<nsIContent> mSliderNode;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -82,21 +82,7 @@ nsXULTabAccessible::NativeState()
|
|||
// get focus and disable status from base class
|
||||
PRUint64 state = AccessibleWrap::NativeState();
|
||||
|
||||
// In the past, tabs have been focusable in classic theme
|
||||
// They may be again in the future
|
||||
// Check style for -moz-user-focus: normal to see if it's focusable
|
||||
state &= ~states::FOCUSABLE;
|
||||
|
||||
nsIFrame *frame = mContent->GetPrimaryFrame();
|
||||
if (frame) {
|
||||
const nsStyleUserInterface* ui = frame->GetStyleUserInterface();
|
||||
if (ui->mUserFocus == NS_STYLE_USER_FOCUS_NORMAL)
|
||||
state |= states::FOCUSABLE;
|
||||
}
|
||||
|
||||
// Check whether the tab is selected
|
||||
state |= states::SELECTABLE;
|
||||
state &= ~states::SELECTED;
|
||||
nsCOMPtr<nsIDOMXULSelectControlItemElement> tab(do_QueryInterface(mContent));
|
||||
if (tab) {
|
||||
bool selected = false;
|
||||
|
@ -106,6 +92,13 @@ nsXULTabAccessible::NativeState()
|
|||
return state;
|
||||
}
|
||||
|
||||
PRUint64
|
||||
nsXULTabAccessible::NativeInteractiveState() const
|
||||
{
|
||||
PRUint64 state = Accessible::NativeInteractiveState();
|
||||
return (state & states::UNAVAILABLE) ? state : state | states::SELECTABLE;
|
||||
}
|
||||
|
||||
// nsIAccessible
|
||||
Relation
|
||||
nsXULTabAccessible::RelationByType(PRUint32 aType)
|
||||
|
|
|
@ -28,6 +28,7 @@ public:
|
|||
// Accessible
|
||||
virtual mozilla::a11y::role NativeRole();
|
||||
virtual PRUint64 NativeState();
|
||||
virtual PRUint64 NativeInteractiveState() const;
|
||||
virtual Relation RelationByType(PRUint32 aType);
|
||||
|
||||
// ActionAccessible
|
||||
|
|
|
@ -87,11 +87,7 @@ nsXULTooltipAccessible::
|
|||
PRUint64
|
||||
nsXULTooltipAccessible::NativeState()
|
||||
{
|
||||
PRUint64 states = nsLeafAccessible::NativeState();
|
||||
|
||||
states &= ~states::FOCUSABLE;
|
||||
states |= states::READONLY;
|
||||
return states;
|
||||
return nsLeafAccessible::NativeState() | states::READONLY;
|
||||
}
|
||||
|
||||
role
|
||||
|
|
|
@ -948,7 +948,7 @@ nsXULTreeItemAccessibleBase::NativeState()
|
|||
return states::DEFUNCT;
|
||||
|
||||
// focusable and selectable states
|
||||
PRUint64 state = states::FOCUSABLE | states::SELECTABLE;
|
||||
PRUint64 state = NativeInteractiveState();
|
||||
|
||||
// expanded/collapsed state
|
||||
if (IsExpandable()) {
|
||||
|
@ -981,6 +981,12 @@ nsXULTreeItemAccessibleBase::NativeState()
|
|||
return state;
|
||||
}
|
||||
|
||||
PRUint64
|
||||
nsXULTreeItemAccessibleBase::NativeInteractiveState() const
|
||||
{
|
||||
return states::FOCUSABLE | states::SELECTABLE;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
nsXULTreeItemAccessibleBase::IndexInParent() const
|
||||
{
|
||||
|
|
|
@ -156,6 +156,7 @@ public:
|
|||
// Accessible
|
||||
virtual mozilla::a11y::GroupPos GroupPosition();
|
||||
virtual PRUint64 NativeState();
|
||||
virtual PRUint64 NativeInteractiveState() const;
|
||||
virtual PRInt32 IndexInParent() const;
|
||||
virtual Relation RelationByType(PRUint32 aType);
|
||||
virtual Accessible* FocusedChild();
|
||||
|
|
|
@ -1103,7 +1103,7 @@ nsXULTreeGridCellAccessible::NativeState()
|
|||
return states::DEFUNCT;
|
||||
|
||||
// selectable/selected state
|
||||
PRUint64 states = states::SELECTABLE;
|
||||
PRUint64 states = states::SELECTABLE; // keep in sync with NativeInteractiveState
|
||||
|
||||
nsCOMPtr<nsITreeSelection> selection;
|
||||
mTreeView->GetSelection(getter_AddRefs(selection));
|
||||
|
@ -1128,6 +1128,12 @@ nsXULTreeGridCellAccessible::NativeState()
|
|||
return states;
|
||||
}
|
||||
|
||||
PRUint64
|
||||
nsXULTreeGridCellAccessible::NativeInteractiveState() const
|
||||
{
|
||||
return states::SELECTABLE;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
nsXULTreeGridCellAccessible::IndexInParent() const
|
||||
{
|
||||
|
|
|
@ -142,6 +142,7 @@ public:
|
|||
virtual Relation RelationByType(PRUint32 aType);
|
||||
virtual mozilla::a11y::role NativeRole();
|
||||
virtual PRUint64 NativeState();
|
||||
virtual PRUint64 NativeInteractiveState() const;
|
||||
|
||||
// ActionAccessible
|
||||
virtual PRUint8 ActionCount();
|
||||
|
|
|
@ -99,6 +99,10 @@
|
|||
{
|
||||
this.__proto__ = new loadURIInvoker(aNestedDocURI);
|
||||
|
||||
// Remove reorder event checker since the event is likely coalesced by
|
||||
// reorder event on Firefox UI (refer to bug 759670 for details).
|
||||
this.eventSeq.shift();
|
||||
|
||||
this.unexpectedEventSeq = [
|
||||
new invokerChecker(EVENT_DOCUMENT_LOAD_COMPLETE, getNestedDoc),
|
||||
new invokerChecker(EVENT_STATE_CHANGE, getNestedDoc)
|
||||
|
@ -183,14 +187,12 @@
|
|||
////////////////////////////////////////////////////////////////////////////
|
||||
// Tests
|
||||
|
||||
gA11yEventDumpToConsole = true; // debug
|
||||
gA11yEventDumpFeature = "parentchain:reorder";
|
||||
//gA11yEventDumpToConsole = true; // debug
|
||||
//gA11yEventDumpFeature = "parentchain:reorder";
|
||||
|
||||
var gQueue = null;
|
||||
function doTests()
|
||||
{
|
||||
enableLogging("events");
|
||||
|
||||
gQueue = new eventQueue();
|
||||
|
||||
var dataURL =
|
||||
|
@ -206,7 +208,7 @@
|
|||
gQueue.push(new loadErrorPageInvoker("https://nocert.example.com:443",
|
||||
"Untrusted Connection"));
|
||||
|
||||
gQueue.onFinish = function() { closeBrowserWindow(); disableLogging(); }
|
||||
gQueue.onFinish = function() { closeBrowserWindow(); }
|
||||
gQueue.invoke();
|
||||
}
|
||||
|
||||
|
|
|
@ -15,21 +15,69 @@
|
|||
src="../role.js" />
|
||||
<script type="application/javascript"
|
||||
src="../states.js" />
|
||||
<script type="application/javascript"
|
||||
src="../events.js" />
|
||||
|
||||
<script type="application/javascript">
|
||||
<![CDATA[
|
||||
function openColorpicker(aID)
|
||||
{
|
||||
this.popupNode = getNode(aID).mPicker.parentNode;
|
||||
this.popup = getAccessible(this.popupNode);
|
||||
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_REORDER, this.popupNode)
|
||||
];
|
||||
|
||||
this.invoke = function openColorpicker_invoke()
|
||||
{
|
||||
getNode(aID).showPopup();
|
||||
}
|
||||
|
||||
this.finalCheck = function openColorpicker_finalCheck()
|
||||
{
|
||||
testStates(this.popup.firstChild,
|
||||
STATE_FOCUSABLE | STATE_SELECTABLE, 0,
|
||||
STATE_UNAVAILABLE);
|
||||
}
|
||||
|
||||
this.getID = function openColorpicker_getID()
|
||||
{
|
||||
return "open colorpicker";
|
||||
}
|
||||
}
|
||||
|
||||
var gQueue = null;
|
||||
function doTest()
|
||||
{
|
||||
testStates("checkbox", STATE_FOCUSABLE, 0, STATE_UNAVAILABLE);
|
||||
testStates("checkbox2", STATE_UNAVAILABLE, 0 , STATE_FOCUSABLE);
|
||||
testStates("radio-group", 0, 0, STATE_UNAVAILABLE);
|
||||
testStates("orange", STATE_UNAVAILABLE, 0 , STATE_FOCUSABLE);
|
||||
testStates("violet", 0, 0, STATE_UNAVAILABLE);
|
||||
testStates("radio-group2", STATE_UNAVAILABLE, 0 , STATE_FOCUSABLE);
|
||||
testStates("orange2", STATE_UNAVAILABLE, 0 , STATE_FOCUSABLE);
|
||||
testStates("radiogroup", 0, 0, STATE_FOCUSABLE | STATE_UNAVAILABLE);
|
||||
testStates("radio", STATE_FOCUSABLE, 0, STATE_UNAVAILABLE);
|
||||
testStates("radio-disabled", STATE_UNAVAILABLE, 0 , STATE_FOCUSABLE);
|
||||
testStates("radiogroup-disabled", STATE_UNAVAILABLE, 0 , STATE_FOCUSABLE);
|
||||
testStates("radio-disabledradiogroup", STATE_UNAVAILABLE, 0 , STATE_FOCUSABLE);
|
||||
testStates("button", STATE_FOCUSABLE, 0, STATE_UNAVAILABLE);
|
||||
testStates("button-disabled", STATE_UNAVAILABLE, 0 , STATE_FOCUSABLE);
|
||||
testStates("colorpicker", STATE_FOCUSABLE | STATE_HASPOPUP, 0, STATE_UNAVAILABLE);
|
||||
testStates("colorpicker-disabled", STATE_HASPOPUP, 0, STATE_FOCUSABLE);
|
||||
testStates("combobox", STATE_FOCUSABLE | STATE_HASPOPUP, 0, STATE_UNAVAILABLE);
|
||||
testStates("combobox-disabled", STATE_UNAVAILABLE | STATE_HASPOPUP, 0, STATE_FOCUSABLE);
|
||||
testStates("listbox", STATE_FOCUSABLE, 0, STATE_UNAVAILABLE);
|
||||
testStates("listitem", STATE_FOCUSABLE | STATE_SELECTABLE, 0, STATE_UNAVAILABLE);
|
||||
testStates("listbox-disabled", STATE_UNAVAILABLE, 0, STATE_FOCUSABLE | STATE_SELECTABLE);
|
||||
testStates("listitem-disabledlistbox", STATE_UNAVAILABLE, 0, STATE_FOCUSABLE | STATE_SELECTABLE);
|
||||
testStates("menubar", 0, 0, STATE_FOCUSABLE);
|
||||
testStates("menu", STATE_FOCUSABLE, 0, STATE_UNAVAILABLE);
|
||||
testStates("menu-disabled", STATE_UNAVAILABLE, 0, STATE_FOCUSABLE | STATE_SELECTABLE);
|
||||
testStates("scale", STATE_FOCUSABLE, 0, STATE_UNAVAILABLE);
|
||||
testStates("scale-disabled", STATE_UNAVAILABLE, 0, STATE_FOCUSABLE);
|
||||
testStates("tab", STATE_FOCUSABLE | STATE_SELECTABLE | STATE_SELECTED, 0, STATE_UNAVAILABLE);
|
||||
testStates("tab-disabled", STATE_UNAVAILABLE, 0, STATE_FOCUSABLE | STATE_SELECTABLE | STATE_SELECTED);
|
||||
|
||||
SimpleTest.finish()
|
||||
gQueue = new eventQueue();
|
||||
gQueue.push(new openColorpicker("colorpicker"));
|
||||
gQueue.invoke(); // Will call SimpleTest.finish()
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
@ -43,7 +91,12 @@
|
|||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=599163"
|
||||
title="check disabled state instead of attribute">
|
||||
Mozilla Bug 599163
|
||||
</a><br/>
|
||||
</a>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=756983"
|
||||
title="Isolate focusable and unavailable states from State()">
|
||||
Mozilla Bug 756983
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
|
@ -56,18 +109,72 @@
|
|||
<checkbox id="checkbox" checked="true" label="Steak"/>
|
||||
<checkbox id="checkbox2" checked="true" label="Salad" disabled="true"/>
|
||||
|
||||
<radiogroup id="radio-group">
|
||||
<radio id="orange" label="Orange" disabled="true"/>
|
||||
<radio id="violet" selected="true" label="Violet"/>
|
||||
<radio id="yellow" label="Yellow"/>
|
||||
<radiogroup id="radiogroup">
|
||||
<radio id="radio" label="Orange"/>
|
||||
<radio id="radio-disabled" selected="true" label="Violet" disabled="true"/>
|
||||
</radiogroup>
|
||||
|
||||
<radiogroup id="radio-group2" disabled="true">
|
||||
<radio id="orange2" label="Orange"/>
|
||||
<radiogroup id="radiogroup-disabled" disabled="true">
|
||||
<radio id="radio-disabledradiogroup" label="Orange"/>
|
||||
<radio id="violet2" selected="true" label="Violet"/>
|
||||
<radio id="yellow2" label="Yellow"/>
|
||||
</radiogroup>
|
||||
|
||||
<button id="button" value="button"/>
|
||||
<button id="button-disabled" disabled="true" value="button"/>
|
||||
|
||||
<colorpicker id="colorpicker" type="button"/>
|
||||
<colorpicker id="colorpicker-disabled" type="button" disabled="true"/>
|
||||
|
||||
<menulist id="combobox">
|
||||
<menupopup>
|
||||
<menuitem label="item1"/>
|
||||
</menupopup>
|
||||
</menulist>
|
||||
|
||||
<menulist id="combobox-disabled" disabled="true">
|
||||
<menupopup>
|
||||
<menuitem label="item1"/>
|
||||
</menupopup>
|
||||
</menulist>
|
||||
|
||||
<listbox id="listbox">
|
||||
<listitem id="listitem" label="list item"/>
|
||||
</listbox>
|
||||
|
||||
<listbox id="listbox-disabled" disabled="true">
|
||||
<listitem id="listitem-disabledlistbox" label="list item"/>
|
||||
</listbox>
|
||||
|
||||
<toolbox>
|
||||
<menubar id="menubar">
|
||||
<menu id="menu" label="menu1">
|
||||
<menupopup>
|
||||
<menuitem id="menu1-item1" label="menuitem1.1"/>
|
||||
</menupopup>
|
||||
</menu>
|
||||
<menu id="menu-disabled" label="menu2" disabled="true">
|
||||
<menupopup>
|
||||
<menuitem id="menu-disabled-item1" label="menuitem2.1"/>
|
||||
</menupopup>
|
||||
</menu>
|
||||
</menubar>
|
||||
</toolbox>
|
||||
|
||||
<scale id="scale" min="1" max="10"/>
|
||||
<scale id="scale-disabled" min="1" max="10" disabled="true"/>
|
||||
|
||||
<tabbox>
|
||||
<tabs>
|
||||
<tab id="tab" label="tab1" tooltip="tooltip"/>
|
||||
<tab id="tab-disabled" label="tab1" disabled="true"/>
|
||||
</tabs>
|
||||
<tabpanels>
|
||||
<tabpanel/>
|
||||
<tabpanel/>
|
||||
</tabpanels>
|
||||
</tabbox>
|
||||
|
||||
<tooltip id="tooltip"><description>tooltip</description></tooltip>
|
||||
</vbox>
|
||||
</hbox>
|
||||
|
||||
|
|
|
@ -74,21 +74,53 @@
|
|||
STATE_FOCUSED, EXT_STATE_ACTIVE);
|
||||
|
||||
// listbox
|
||||
var listbox = getAccessible("listbox");
|
||||
testStates(listbox, STATE_FOCUSABLE, 0,
|
||||
testStates("listbox",
|
||||
STATE_FOCUSABLE, 0,
|
||||
STATE_HASPOPUP | STATE_COLLAPSED | STATE_FOCUSED);
|
||||
|
||||
testStates(listbox.firstChild, STATE_SELECTABLE, EXT_STATE_ACTIVE,
|
||||
STATE_SELECTED | STATE_FOCUSED | STATE_FOCUSED);
|
||||
testStates("listitem-active",
|
||||
STATE_FOCUSABLE | STATE_SELECTABLE, EXT_STATE_ACTIVE,
|
||||
STATE_SELECTED | STATE_FOCUSED);
|
||||
|
||||
testStates(listbox.lastChild, STATE_SELECTABLE, 0,
|
||||
STATE_SELECTED | STATE_FOCUSED | STATE_FOCUSED,
|
||||
0, 0, EXT_STATE_ACTIVE);
|
||||
testStates("listitem",
|
||||
STATE_FOCUSABLE | STATE_SELECTABLE, 0,
|
||||
STATE_SELECTED | STATE_FOCUSED, EXT_STATE_ACTIVE);
|
||||
|
||||
testStates("listitem-disabled",
|
||||
STATE_UNAVAILABLE, 0,
|
||||
STATE_SELECTABLE | STATE_SELECTED | STATE_FOCUSABLE,
|
||||
EXT_STATE_ACTIVE);
|
||||
|
||||
testStates("listgroup",
|
||||
0, 0,
|
||||
STATE_UNAVAILABLE | STATE_SELECTABLE | STATE_SELECTED | STATE_FOCUSABLE,
|
||||
EXT_STATE_ACTIVE);
|
||||
|
||||
testStates("listgroup-disabled",
|
||||
STATE_UNAVAILABLE, 0,
|
||||
STATE_SELECTABLE | STATE_SELECTED | STATE_FOCUSABLE,
|
||||
EXT_STATE_ACTIVE);
|
||||
|
||||
todo(false, "no unavailable state on option in disabled group (bug 759666)");
|
||||
// testStates("listitem-disabledgroup",
|
||||
// STATE_UNAVAILABLE, 0,
|
||||
// STATE_SELECTABLE | STATE_SELECTED | STATE_FOCUSABLE,
|
||||
// EXT_STATE_ACTIVE);
|
||||
|
||||
testStates("listbox-disabled",
|
||||
STATE_UNAVAILABLE, 0,
|
||||
STATE_FOCUSABLE);
|
||||
|
||||
todo(false, "no unavailable state on option in disabled select (bug 759666)");
|
||||
// testStates("listitem-disabledlistbox",
|
||||
// STATE_UNAVAILABLE, 0,
|
||||
// STATE_SELECTABLE | STATE_SELECTED | STATE_FOCUSABLE,
|
||||
// EXT_STATE_ACTIVE);
|
||||
|
||||
// open combobox
|
||||
gQueue = new eventQueue();
|
||||
gQueue.push(new openComboboxNCheckStates("combobox"));
|
||||
gQueue.invoke(); // Will call SimpleTest.finish();
|
||||
gQueue.invoke(); // Will call */SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
@ -113,6 +145,11 @@
|
|||
title="Expose active state on current item of selectable widgets">
|
||||
Mozilla Bug 689847
|
||||
</a>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=756983"
|
||||
title="Isolate focusable and unavailable states from State()">
|
||||
Mozilla Bug 756983
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
|
@ -124,10 +161,19 @@
|
|||
</select>
|
||||
|
||||
<select id="listbox" name="component" size="3">
|
||||
<option>Build</option>
|
||||
<option>Disability Access APIs</option>
|
||||
<option>General</option>
|
||||
<option>UI</option>
|
||||
<option id="listitem-active">Build</option>
|
||||
<option id="listitem">Disability Access APIs</option>
|
||||
<option id="listitem-disabled" disabled>General</option>
|
||||
<optgroup id="listgroup" label="group">
|
||||
<option>option</option>
|
||||
</optgroup>
|
||||
<optgroup id="listgroup-disabled" disabled label="group2">
|
||||
<option id="listitem-disabledgroup">UI</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
|
||||
<select id="listbox-disabled" size="3" disabled>
|
||||
<option id="listitem-disabledlistbox">option</option>
|
||||
</select>
|
||||
|
||||
</body>
|
||||
|
|
|
@ -651,10 +651,18 @@ SettingsListener.observe('language.current', 'en-US', function(value) {
|
|||
});
|
||||
});
|
||||
|
||||
['ril.data.apn', 'ril.data.user', 'ril.data.passwd'].forEach(function(key) {
|
||||
let strPrefs = ['ril.data.apn', 'ril.data.user', 'ril.data.passwd',
|
||||
'ril.data.mmsc', 'ril.data.mmsproxy'];
|
||||
strPrefs.forEach(function(key) {
|
||||
SettingsListener.observe(key, false, function(value) {
|
||||
Services.prefs.setCharPref(key, value);
|
||||
});
|
||||
});
|
||||
|
||||
['ril.data.mmsport'].forEach(function(key) {
|
||||
SettingsListener.observe(key, false, function(value) {
|
||||
Services.prefs.setIntPref(key, value);
|
||||
});
|
||||
});
|
||||
})();
|
||||
|
||||
|
|
|
@ -174,6 +174,9 @@
|
|||
@BINPATH@/components/dom_indexeddb.xpt
|
||||
@BINPATH@/components/dom_offline.xpt
|
||||
@BINPATH@/components/dom_json.xpt
|
||||
#ifdef MOZ_B2G_RIL
|
||||
@BINPATH@/components/dom_mms.xpt
|
||||
#endif
|
||||
@BINPATH@/components/dom_power.xpt
|
||||
@BINPATH@/components/dom_range.xpt
|
||||
@BINPATH@/components/dom_settings.xpt
|
||||
|
@ -425,6 +428,8 @@
|
|||
@BINPATH@/components/NetworkManager.js
|
||||
@BINPATH@/components/RadioInterfaceLayer.manifest
|
||||
@BINPATH@/components/RadioInterfaceLayer.js
|
||||
@BINPATH@/components/MmsService.manifest
|
||||
@BINPATH@/components/MmsService.js
|
||||
@BINPATH@/components/RILContentHelper.js
|
||||
@BINPATH@/components/SmsDatabaseService.manifest
|
||||
@BINPATH@/components/SmsDatabaseService.js
|
||||
|
|
|
@ -15,10 +15,6 @@ if test "$OS_ARCH" = "WINNT"; then
|
|||
fi
|
||||
fi
|
||||
|
||||
if (test "$OS_TARGET" = "WINNT" -o "$OS_TARGET" = "Darwin"); then
|
||||
MOZ_WEBAPP_RUNTIME=1
|
||||
fi
|
||||
|
||||
MOZ_CHROME_FILE_FORMAT=omni
|
||||
MOZ_SAFE_BROWSING=1
|
||||
MOZ_SERVICES_SYNC=1
|
||||
|
@ -44,3 +40,4 @@ MAR_CHANNEL_ID=firefox-mozilla-central
|
|||
MOZ_PROFILE_MIGRATOR=1
|
||||
MOZ_EXTENSION_MANAGER=1
|
||||
MOZ_APP_STATIC_INI=1
|
||||
MOZ_WEBAPP_RUNTIME=1
|
||||
|
|
|
@ -179,6 +179,9 @@
|
|||
@BINPATH@/components/dom_indexeddb.xpt
|
||||
@BINPATH@/components/dom_offline.xpt
|
||||
@BINPATH@/components/dom_json.xpt
|
||||
#ifdef MOZ_B2G_RIL
|
||||
@BINPATH@/components/dom_mms.xpt
|
||||
#endif
|
||||
@BINPATH@/components/dom_power.xpt
|
||||
@BINPATH@/components/dom_range.xpt
|
||||
@BINPATH@/components/dom_settings.xpt
|
||||
|
@ -408,6 +411,8 @@
|
|||
#ifdef MOZ_B2G_RIL
|
||||
@BINPATH@/components/RadioInterfaceLayer.manifest
|
||||
@BINPATH@/components/RadioInterfaceLayer.js
|
||||
@BINPATH@/components/MmsService.manifest
|
||||
@BINPATH@/components/MmsService.js
|
||||
@BINPATH@/components/RILContentHelper.js
|
||||
@BINPATH@/components/SmsDatabaseService.manifest
|
||||
@BINPATH@/components/SmsDatabaseService.js
|
||||
|
|
|
@ -32,6 +32,8 @@ let WebappsInstaller = {
|
|||
let shell = new WinNativeApp(aData);
|
||||
#elifdef XP_MACOSX
|
||||
let shell = new MacNativeApp(aData);
|
||||
#elifdef XP_UNIX
|
||||
let shell = new LinuxNativeApp(aData);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
|
@ -48,8 +50,8 @@ let WebappsInstaller = {
|
|||
}
|
||||
|
||||
/**
|
||||
* This function implements the common constructor for both
|
||||
* the Windows and Mac native app shells. It reads and parses
|
||||
* This function implements the common constructor for
|
||||
* the Windows, Mac and Linux native app shells. It reads and parses
|
||||
* the data from the app manifest and stores it in the NativeApp
|
||||
* object. It's meant to be called as NativeApp.call(this, aData)
|
||||
* from the platform-specific constructor.
|
||||
|
@ -113,6 +115,8 @@ function NativeApp(aData) {
|
|||
"registryDir": this.profileFolder.path,
|
||||
"app": app
|
||||
};
|
||||
|
||||
this.processFolder = Services.dirsvc.get("CurProcD", Ci.nsIFile);
|
||||
}
|
||||
|
||||
#ifdef XP_WIN
|
||||
|
@ -188,12 +192,16 @@ WinNativeApp.prototype = {
|
|||
|
||||
// The ${InstallDir} format is as follows:
|
||||
// host of the app origin + ";" +
|
||||
// protocol + ";" +
|
||||
// port (-1 for default port)
|
||||
// protocol
|
||||
// + ";" + port (only if port is not default)
|
||||
this.installDir = Services.dirsvc.get("AppData", Ci.nsIFile);
|
||||
this.installDir.append(this.launchURI.host + ";" +
|
||||
this.launchURI.scheme + ";" +
|
||||
this.launchURI.port);
|
||||
let installDirLeaf = this.launchURI.scheme
|
||||
+ ";"
|
||||
+ this.launchURI.host;
|
||||
if (this.launchURI.port != -1) {
|
||||
installDirLeaf += ";" + this.launchURI.port;
|
||||
}
|
||||
this.installDir.append(installDirLeaf);
|
||||
|
||||
this.uninstallDir = this.installDir.clone();
|
||||
this.uninstallDir.append("uninstall");
|
||||
|
@ -207,8 +215,6 @@ WinNativeApp.prototype = {
|
|||
this.iconFile.append("default");
|
||||
this.iconFile.append("default.ico");
|
||||
|
||||
this.processFolder = Services.dirsvc.get("CurProcD", Ci.nsIFile);
|
||||
|
||||
this.desktopShortcut = Services.dirsvc.get("Desk", Ci.nsILocalFile);
|
||||
this.desktopShortcut.append(this.appNameAsFilename + ".lnk");
|
||||
this.desktopShortcut.followLinks = false;
|
||||
|
@ -218,8 +224,7 @@ WinNativeApp.prototype = {
|
|||
this.startMenuShortcut.followLinks = false;
|
||||
|
||||
this.uninstallSubkeyStr = this.launchURI.scheme + "://" +
|
||||
this.launchURI.host + ":" +
|
||||
this.launchURI.port;
|
||||
this.launchURI.hostPort;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -482,8 +487,6 @@ MacNativeApp.prototype = {
|
|||
|
||||
this.iconFile = this.resourcesDir.clone();
|
||||
this.iconFile.append("appicon.icns");
|
||||
|
||||
this.processFolder = Services.dirsvc.get("CurProcD", Ci.nsIFile);
|
||||
},
|
||||
|
||||
install: function() {
|
||||
|
@ -640,6 +643,154 @@ MacNativeApp.prototype = {
|
|||
|
||||
}
|
||||
|
||||
#elifdef XP_UNIX
|
||||
|
||||
function LinuxNativeApp(aData) {
|
||||
NativeApp.call(this, aData);
|
||||
this._init();
|
||||
}
|
||||
|
||||
LinuxNativeApp.prototype = {
|
||||
_init: function() {
|
||||
// The ${InstallDir} and desktop entry filename format is as follows:
|
||||
// host of the app origin + ";" +
|
||||
// protocol
|
||||
// + ";" + port (only if port is not default)
|
||||
|
||||
this.uniqueName = this.launchURI.scheme + ";" + this.launchURI.host;
|
||||
if (this.launchURI.port != -1)
|
||||
this.uniqueName += ";" + this.launchURI.port;
|
||||
|
||||
this.installDir = Services.dirsvc.get("Home", Ci.nsIFile);
|
||||
this.installDir.append("." + this.uniqueName);
|
||||
|
||||
this.iconFile = this.installDir.clone();
|
||||
this.iconFile.append(this.uniqueName + ".png");
|
||||
|
||||
this.webapprt = this.installDir.clone();
|
||||
this.webapprt.append("webapprt-stub");
|
||||
|
||||
let env = Cc["@mozilla.org/process/environment;1"]
|
||||
.getService(Ci.nsIEnvironment);
|
||||
let xdg_data_home_env = env.get("XDG_DATA_HOME");
|
||||
if (xdg_data_home_env != "") {
|
||||
this.desktopINI = Cc["@mozilla.org/file/local;1"]
|
||||
.createInstance(Ci.nsILocalFile);
|
||||
this.desktopINI.initWithPath(xdg_data_home_env);
|
||||
}
|
||||
else {
|
||||
this.desktopINI = Services.dirsvc.get("Home", Ci.nsIFile);
|
||||
this.desktopINI.append(".local");
|
||||
this.desktopINI.append("share");
|
||||
}
|
||||
|
||||
this.desktopINI.append("applications");
|
||||
this.desktopINI.append("owa-" + this.uniqueName + ".desktop");
|
||||
},
|
||||
|
||||
install: function() {
|
||||
this._removeInstallation();
|
||||
|
||||
try {
|
||||
this._createDirectoryStructure();
|
||||
this._copyPrebuiltFiles();
|
||||
this._createConfigFiles();
|
||||
} catch (ex) {
|
||||
this._removeInstallation();
|
||||
throw(ex);
|
||||
}
|
||||
|
||||
getIconForApp(this, function() {});
|
||||
},
|
||||
|
||||
_removeInstallation: function() {
|
||||
try {
|
||||
if (this.installDir.exists())
|
||||
this.installDir.remove(true);
|
||||
|
||||
if (this.desktopINI.exists())
|
||||
this.desktopINI.remove(false);
|
||||
} catch(ex) {
|
||||
}
|
||||
},
|
||||
|
||||
_createDirectoryStructure: function() {
|
||||
this.installDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0755);
|
||||
},
|
||||
|
||||
_copyPrebuiltFiles: function() {
|
||||
let webapprtPre = this.processFolder.clone();
|
||||
webapprtPre.append(this.webapprt.leafName);
|
||||
webapprtPre.copyTo(this.installDir, this.webapprt.leafName);
|
||||
},
|
||||
|
||||
_createConfigFiles: function() {
|
||||
// ${InstallDir}/webapp.json
|
||||
let configJson = this.installDir.clone();
|
||||
configJson.append("webapp.json");
|
||||
writeToFile(configJson, JSON.stringify(this.webappJson), function() {});
|
||||
|
||||
// ${InstallDir}/webapp.ini
|
||||
let webappINI = this.installDir.clone();
|
||||
webappINI.append("webapp.ini");
|
||||
|
||||
let factory = Cc["@mozilla.org/xpcom/ini-processor-factory;1"]
|
||||
.getService(Ci.nsIINIParserFactory);
|
||||
|
||||
let writer = factory.createINIParser(webappINI).QueryInterface(Ci.nsIINIParserWriter);
|
||||
writer.setString("Webapp", "Name", this.appName);
|
||||
writer.setString("Webapp", "Profile", this.uniqueName);
|
||||
writer.setString("WebappRT", "InstallDir", this.processFolder.path);
|
||||
writer.writeFile();
|
||||
|
||||
// $XDG_DATA_HOME/applications/owa-<webappuniquename>.desktop
|
||||
this.desktopINI.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0755);
|
||||
|
||||
writer = factory.createINIParser(this.desktopINI).QueryInterface(Ci.nsIINIParserWriter);
|
||||
writer.setString("Desktop Entry", "Name", this.appName);
|
||||
writer.setString("Desktop Entry", "Comment", this.shortDescription);
|
||||
writer.setString("Desktop Entry", "Exec", '"'+this.webapprt.path+'"');
|
||||
writer.setString("Desktop Entry", "Icon", this.iconFile.path);
|
||||
writer.setString("Desktop Entry", "Type", "Application");
|
||||
writer.setString("Desktop Entry", "Terminal", "false");
|
||||
writer.writeFile();
|
||||
},
|
||||
|
||||
/**
|
||||
* This variable specifies if the icon retrieval process should
|
||||
* use a temporary file in the system or a binary stream. This
|
||||
* is accessed by a common function in WebappsIconHelpers.js and
|
||||
* is different for each platform.
|
||||
*/
|
||||
useTmpForIcon: false,
|
||||
|
||||
/**
|
||||
* Process the icon from the imageStream as retrieved from
|
||||
* the URL by getIconForApp().
|
||||
*
|
||||
* @param aMimeType ahe icon mimetype
|
||||
* @param aImageStream the stream for the image data
|
||||
* @param aCallback a callback function to be called
|
||||
* after the process finishes
|
||||
*/
|
||||
processIcon: function(aMimeType, aImageStream, aCallback) {
|
||||
let iconStream;
|
||||
try {
|
||||
let imgTools = Cc["@mozilla.org/image/tools;1"]
|
||||
.createInstance(Ci.imgITools);
|
||||
let imgContainer = { value: null };
|
||||
|
||||
imgTools.decodeImageData(aImageStream, aMimeType, imgContainer);
|
||||
iconStream = imgTools.encodeImage(imgContainer.value, "image/png");
|
||||
} catch (e) {
|
||||
throw("processIcon - Failure converting icon (" + e + ")");
|
||||
}
|
||||
|
||||
let outputStream = FileUtils.openSafeFileOutputStream(this.iconFile);
|
||||
NetUtil.asyncCopy(iconStream, outputStream);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Helper Functions */
|
||||
|
|
|
@ -6413,6 +6413,9 @@ MOZ_ARG_DISABLE_BOOL(webapp-runtime,
|
|||
[ --disable-webapp-runtime Disable Web App Runtime],
|
||||
MOZ_WEBAPP_RUNTIME=,
|
||||
MOZ_WEBAPP_RUNTIME=1)
|
||||
if test "$MOZ_WIDGET_TOOLKIT" != "windows" -a "$MOZ_WIDGET_TOOLKIT" != "cocoa" -a "$MOZ_WIDGET_TOOLKIT" != "gtk2"; then
|
||||
MOZ_WEBAPP_RUNTIME=
|
||||
fi
|
||||
if test "$OS_ARCH" = "WINNT" -a -z "$MAKENSISU" -a -n "$CROSS_COMPILE"; then
|
||||
MOZ_WEBAPP_RUNTIME=
|
||||
fi
|
||||
|
|
|
@ -116,6 +116,15 @@ nsInProcessTabChildGlobal::Init()
|
|||
this,
|
||||
nsnull,
|
||||
mCx);
|
||||
|
||||
// Set the location information for the new global, so that tools like
|
||||
// about:memory may use that information.
|
||||
JSObject *global;
|
||||
nsIURI* docURI = mOwner->OwnerDoc()->GetDocumentURI();
|
||||
if (mGlobal && NS_SUCCEEDED(mGlobal->GetJSObject(&global)) && docURI) {
|
||||
xpc::SetLocationForGlobal(global, docURI);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -118,7 +118,8 @@ static const PRInt32 MAX_VIDEO_HEIGHT = 3000;
|
|||
void ScaleDisplayByAspectRatio(nsIntSize& aDisplay, float aAspectRatio);
|
||||
|
||||
// The amount of virtual memory reserved for thread stacks.
|
||||
#if defined(XP_WIN) || defined(XP_MACOSX) || defined(LINUX)
|
||||
#if (defined(XP_WIN) || defined(XP_MACOSX) || defined(LINUX)) && \
|
||||
!defined(MOZ_ASAN)
|
||||
#define MEDIA_THREAD_STACK_SIZE (128 * 1024)
|
||||
#else
|
||||
// All other platforms use their system defaults.
|
||||
|
|
|
@ -55,6 +55,7 @@ DIRS += \
|
|||
power \
|
||||
settings \
|
||||
sms \
|
||||
mms \
|
||||
src \
|
||||
locales \
|
||||
network \
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
# You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DEPTH = ../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
relativesrcdir = dom/mms
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
PARALLEL_DIRS = interfaces src
|
||||
|
||||
ifdef MOZ_B2G_RIL
|
||||
ifdef ENABLE_TESTS
|
||||
XPCSHELL_TESTS = tests
|
||||
endif
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
|
@ -0,0 +1,19 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
# You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
XPIDL_MODULE = dom_mms
|
||||
|
||||
XPIDLSRCS = \
|
||||
nsIMmsService.idl \
|
||||
nsIWapPushApplication.idl \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
|
@ -0,0 +1,11 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
[scriptable, uuid(217ddd76-75db-4210-955d-8806cd8d87f9)]
|
||||
interface nsIMmsService : nsISupports
|
||||
{
|
||||
boolean hasSupport();
|
||||
};
|
|
@ -0,0 +1,31 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
/**
|
||||
* Handle WAP Push notifications.
|
||||
*/
|
||||
[scriptable, uuid(fd6f7f6b-a67e-4892-930d-fca864df8fe7)]
|
||||
interface nsIWapPushApplication : nsISupports
|
||||
{
|
||||
/**
|
||||
* Receive WAP Push message.
|
||||
*
|
||||
* @param aData
|
||||
* An array containing raw PDU data.
|
||||
* @param aLength
|
||||
* Length of aData.
|
||||
* @param aOffset
|
||||
* Start offset of aData containing message body of the Push PDU.
|
||||
* @param options
|
||||
* An object containing various attributes from lower transport layer.
|
||||
*/
|
||||
[implicit_jscontext]
|
||||
void receiveWapPush([array, size_is(aLength)] in octet aData,
|
||||
in unsigned long aLength,
|
||||
in unsigned long aOffset,
|
||||
in jsval aOptions);
|
||||
};
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
# You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = \
|
||||
$(srcdir) \
|
||||
$(NULL)
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
ifdef MOZ_B2G_RIL
|
||||
EXTRA_COMPONENTS = \
|
||||
ril/MmsService.js \
|
||||
ril/MmsService.manifest \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_JS_MODULES = \
|
||||
ril/mms_consts.js \
|
||||
ril/MmsPduHelper.jsm \
|
||||
ril/wap_consts.js \
|
||||
ril/WapPushManager.js \
|
||||
ril/WspPduHelper.jsm \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,480 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
Cu.import("resource://gre/modules/FileUtils.jsm");
|
||||
Cu.import("resource://gre/modules/NetUtil.jsm");
|
||||
|
||||
const RIL_MMSSERVICE_CONTRACTID = "@mozilla.org/mms/rilmmsservice;1";
|
||||
const RIL_MMSSERVICE_CID = Components.ID("{217ddd76-75db-4210-955d-8806cd8d87f9}");
|
||||
|
||||
const DEBUG = false;
|
||||
|
||||
const kNetworkInterfaceStateChangedTopic = "network-interface-state-changed";
|
||||
const kXpcomShutdownObserverTopic = "xpcom-shutdown";
|
||||
|
||||
// File modes for saving MMS attachments.
|
||||
const FILE_OPEN_MODE = FileUtils.MODE_CREATE
|
||||
| FileUtils.MODE_WRONLY
|
||||
| FileUtils.MODE_TRUNCATE;
|
||||
|
||||
// Size of each segment in a nsIStorageStream. Must be a power of two.
|
||||
const STORAGE_STREAM_SEGMENT_SIZE = 4096;
|
||||
|
||||
// HTTP status codes:
|
||||
// @see http://tools.ietf.org/html/rfc2616#page-39
|
||||
const HTTP_STATUS_OK = 200;
|
||||
|
||||
const CONFIG_SEND_REPORT_NEVER = 0;
|
||||
const CONFIG_SEND_REPORT_DEFAULT_NO = 1;
|
||||
const CONFIG_SEND_REPORT_DEFAULT_YES = 2;
|
||||
const CONFIG_SEND_REPORT_ALWAYS = 3;
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gpps",
|
||||
"@mozilla.org/network/protocol-proxy-service;1",
|
||||
"nsIProtocolProxyService");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "MMS", function () {
|
||||
let MMS = {};
|
||||
Cu.import("resource://gre/modules/MmsPduHelper.jsm", MMS);
|
||||
return MMS;
|
||||
});
|
||||
|
||||
/**
|
||||
* MmsService
|
||||
*/
|
||||
function MmsService() {
|
||||
Services.obs.addObserver(this, kXpcomShutdownObserverTopic, false);
|
||||
Services.obs.addObserver(this, kNetworkInterfaceStateChangedTopic, false);
|
||||
}
|
||||
MmsService.prototype = {
|
||||
|
||||
classID: RIL_MMSSERVICE_CID,
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIMmsService,
|
||||
Ci.nsIWapPushApplication,
|
||||
Ci.nsIObserver,
|
||||
Ci.nsIProtocolProxyFilter]),
|
||||
|
||||
/**
|
||||
* Whether or not should we enable X-Mms-Report-Allowed in M-NotifyResp.ind
|
||||
* and M-Acknowledge.ind PDU.
|
||||
*/
|
||||
confSendDeliveryReport: CONFIG_SEND_REPORT_DEFAULT_YES,
|
||||
|
||||
proxyInfo: null,
|
||||
MMSC: null,
|
||||
|
||||
/** MMS proxy filter reference count. */
|
||||
proxyFilterRefCount: 0,
|
||||
|
||||
/**
|
||||
* Calculate Whether or not should we enable X-Mms-Report-Allowed.
|
||||
*
|
||||
* @param config
|
||||
* Current config value.
|
||||
* @param wish
|
||||
* Sender wish. Could be undefined, false, or true.
|
||||
*/
|
||||
getReportAllowed: function getReportAllowed(config, wish) {
|
||||
if ((config == CONFIG_SEND_REPORT_DEFAULT_NO)
|
||||
|| (config == CONFIG_SEND_REPORT_DEFAULT_YES)) {
|
||||
if (wish != null) {
|
||||
config += (wish ? 1 : -1);
|
||||
}
|
||||
}
|
||||
return config >= CONFIG_SEND_REPORT_DEFAULT_YES;
|
||||
},
|
||||
|
||||
/**
|
||||
* Acquire referece-counted MMS proxy filter.
|
||||
*/
|
||||
acquireProxyFilter: function acquireProxyFilter() {
|
||||
if (!this.proxyFilterRefCount) {
|
||||
debug("Register proxy filter");
|
||||
gpps.registerFilter(this, 0);
|
||||
}
|
||||
this.proxyFilterRefCount++;
|
||||
},
|
||||
|
||||
/**
|
||||
* Release referece-counted MMS proxy filter.
|
||||
*/
|
||||
releaseProxyFilter: function releaseProxyFilter() {
|
||||
this.proxyFilterRefCount--;
|
||||
if (this.proxyFilterRefCount <= 0) {
|
||||
this.proxyFilterRefCount = 0;
|
||||
|
||||
debug("Unregister proxy filter");
|
||||
gpps.unregisterFilter(this);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Send MMS request to MMSC.
|
||||
*
|
||||
* @param method
|
||||
* "GET" or "POST".
|
||||
* @param url
|
||||
* Target url string.
|
||||
* @param istream [optional]
|
||||
* An nsIInputStream instance as data source to be sent.
|
||||
* @param callback
|
||||
* A callback function that takes two arguments: one for http status,
|
||||
* the other for wrapped PDU data for further parsing.
|
||||
*/
|
||||
sendMmsRequest: function sendMmsRequest(method, url, istream, callback) {
|
||||
let that = this;
|
||||
function releaseProxyFilterAndCallback(status, data) {
|
||||
// Always release proxy filter before callback.
|
||||
that.releaseProxyFilter(false);
|
||||
if (callback) {
|
||||
callback(status, data);
|
||||
}
|
||||
}
|
||||
|
||||
this.acquireProxyFilter();
|
||||
|
||||
try {
|
||||
let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
|
||||
.createInstance(Ci.nsIXMLHttpRequest);
|
||||
|
||||
// Basic setups
|
||||
xhr.open(method, url, true);
|
||||
xhr.responseType = "arraybuffer";
|
||||
if (istream) {
|
||||
xhr.setRequestHeader("Content-Type", "application/vnd.wap.mms-message");
|
||||
xhr.setRequestHeader("Content-Length", istream.available());
|
||||
} else {
|
||||
xhr.setRequestHeader("Content-Length", 0);
|
||||
}
|
||||
|
||||
// Setup event listeners
|
||||
xhr.onerror = function () {
|
||||
debug("xhr error, response headers: " + xhr.getAllResponseHeaders());
|
||||
releaseProxyFilterAndCallback(xhr.status, null);
|
||||
};
|
||||
xhr.onreadystatechange = function () {
|
||||
if (xhr.readyState != Ci.nsIXMLHttpRequest.DONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
let data = null;
|
||||
switch (xhr.status) {
|
||||
case HTTP_STATUS_OK: {
|
||||
debug("xhr success, response headers: " + xhr.getAllResponseHeaders());
|
||||
|
||||
let array = new Uint8Array(xhr.response);
|
||||
if (false) {
|
||||
for (let begin = 0; begin < array.length; begin += 20) {
|
||||
debug("res: " + JSON.stringify(array.subarray(begin, begin + 20)));
|
||||
}
|
||||
}
|
||||
|
||||
data = {array: array, offset: 0};
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
debug("xhr done, but status = " + xhr.status);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
releaseProxyFilterAndCallback(xhr.status, data);
|
||||
}
|
||||
|
||||
// Send request
|
||||
xhr.send(istream);
|
||||
} catch (e) {
|
||||
debug("xhr error, can't send: " + e.message);
|
||||
releaseProxyFilterAndCallback(0, null);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Send M-NotifyResp.ind back to MMSC.
|
||||
*
|
||||
* @param tid
|
||||
* X-Mms-Transaction-ID of the message.
|
||||
* @param status
|
||||
* X-Mms-Status of the response.
|
||||
* @param ra
|
||||
* X-Mms-Report-Allowed of the response.
|
||||
*
|
||||
* @see OMA-TS-MMS_ENC-V1_3-20110913-A section 6.2
|
||||
*/
|
||||
sendNotificationResponse: function sendNotificationResponse(tid, status, ra) {
|
||||
debug("sendNotificationResponse: tid = " + tid + ", status = " + status
|
||||
+ ", reportAllowed = " + ra);
|
||||
|
||||
let headers = {};
|
||||
|
||||
// Mandatory fields
|
||||
headers["x-mms-message-type"] = MMS.MMS_PDU_TYPE_NOTIFYRESP_IND;
|
||||
headers["x-mms-transaction-id"] = tid;
|
||||
headers["x-mms-mms-version"] = MMS.MMS_VERSION;
|
||||
headers["x-mms-status"] = status;
|
||||
// Optional fields
|
||||
headers["x-mms-report-allowed"] = ra;
|
||||
|
||||
let istream = MMS.PduHelper.compose(null, {headers: headers});
|
||||
this.sendMmsRequest("POST", this.MMSC, istream);
|
||||
},
|
||||
|
||||
/**
|
||||
* @param file
|
||||
* A nsIFile object indicating where to save the data.
|
||||
* @param data
|
||||
* An array of raw octets.
|
||||
* @param callback
|
||||
* Callback function when I/O is done.
|
||||
*
|
||||
* @return An nsIRequest representing the copy operation returned by
|
||||
* NetUtil.asyncCopy().
|
||||
*/
|
||||
saveContentToFile: function saveContentToFile(file, data, callback) {
|
||||
// Write to a StorageStream for NetUtil.asyncCopy()
|
||||
let sstream = Cc["@mozilla.org/storagestream;1"]
|
||||
.createInstance(Ci.nsIStorageStream);
|
||||
sstream.init(STORAGE_STREAM_SEGMENT_SIZE, data.length, null);
|
||||
let bostream = Cc["@mozilla.org/binaryoutputstream;1"]
|
||||
.createInstance(Ci.nsIBinaryOutputStream);
|
||||
bostream.setOutputStream(sstream.getOutputStream(0));
|
||||
bostream.writeByteArray(data, data.length);
|
||||
bostream.close();
|
||||
|
||||
// Write message body to file
|
||||
let ofstream = FileUtils.openSafeFileOutputStream(file, FILE_OPEN_MODE);
|
||||
return NetUtil.asyncCopy(sstream.newInputStream(0), ofstream, callback);
|
||||
},
|
||||
|
||||
/**
|
||||
* @param msg
|
||||
* A MMS message object.
|
||||
* @param callback
|
||||
* A callback function that accepts one argument as retrieved message.
|
||||
*/
|
||||
saveMessageContent: function saveMessageContent(msg, callback) {
|
||||
function saveCallback(obj, counter, status) {
|
||||
obj.saved = Components.isSuccessCode(status);
|
||||
debug("saveMessageContent: " + obj.file.path + ", saved: " + obj.saved);
|
||||
|
||||
// The async copy callback may not be invoked in order, so we only
|
||||
// callback after all of them were done.
|
||||
counter.count++;
|
||||
if (counter.count >= counter.max) {
|
||||
if (callback) {
|
||||
callback(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let tid = msg.headers["x-mms-transaction-id"];
|
||||
if (msg.parts) {
|
||||
let counter = {max: msg.parts.length, count: 0};
|
||||
|
||||
msg.parts.forEach((function (part, index) {
|
||||
part.file = FileUtils.getFile("ProfD", ["mms", tid, index], true);
|
||||
if (!part.content) {
|
||||
saveCallback(part, counter, Cr.NS_ERROR_NOT_AVAILABLE);
|
||||
} else {
|
||||
this.saveContentToFile(part.file, part.content,
|
||||
saveCallback.bind(null, part, counter));
|
||||
}
|
||||
}).bind(this));
|
||||
} else if (msg.content) {
|
||||
msg.file = FileUtils.getFile("ProfD", ["mms", tid, "content"], true);
|
||||
this.saveContentToFile(msg.file, msg.content,
|
||||
saveCallback.bind(null, msg, {max: 1, count: 0}));
|
||||
} else {
|
||||
// Nothing to save here.
|
||||
if (callback) {
|
||||
callback(msg);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @param data
|
||||
* A wrapped object containing raw PDU data.
|
||||
* @param options
|
||||
* Additional options to be passed to corresponding PDU handler.
|
||||
*
|
||||
* @return true if incoming data parsed successfully and passed to PDU
|
||||
* handler; false otherwise.
|
||||
*/
|
||||
parseStreamAndDispatch: function parseStreamAndDispatch(data, options) {
|
||||
let msg = MMS.PduHelper.parse(data, null);
|
||||
if (!msg) {
|
||||
return false;
|
||||
}
|
||||
debug("parseStreamAndDispatch: msg = " + JSON.stringify(msg));
|
||||
|
||||
switch (msg.type) {
|
||||
case MMS.MMS_PDU_TYPE_NOTIFICATION_IND:
|
||||
this.handleNotificationIndication(msg, options);
|
||||
break;
|
||||
case MMS.MMS_PDU_TYPE_RETRIEVE_CONF:
|
||||
this.handleRetrieveConfirmation(msg, options);
|
||||
break;
|
||||
default:
|
||||
debug("Unsupported X-MMS-Message-Type: " + msg.type);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle incoming M-Notification.ind PDU.
|
||||
*
|
||||
* @param msg
|
||||
* The MMS message object.
|
||||
*/
|
||||
handleNotificationIndication: function handleNotificationIndication(msg) {
|
||||
function callback(status, retr) {
|
||||
let tid = msg.headers["x-mms-transaction-id"];
|
||||
|
||||
// For X-Mms-Report-Allowed
|
||||
let wish = msg.headers["x-mms-delivery-report"];
|
||||
// `The absence of the field does not indicate any default value.`
|
||||
// So we go checking the same field in retrieved message instead.
|
||||
if ((wish == null) && retr) {
|
||||
wish = retr.headers["x-mms-delivery-report"];
|
||||
}
|
||||
let ra = this.getReportAllowed(this.confSendDeliveryReport, wish);
|
||||
|
||||
this.sendNotificationResponse(tid, status, ra);
|
||||
}
|
||||
|
||||
function retrCallback(error, retr) {
|
||||
callback.call(this, MMS.translatePduErrorToStatus(error), retr);
|
||||
}
|
||||
|
||||
let url = msg.headers["x-mms-content-location"].uri;
|
||||
this.sendMmsRequest("GET", url, null, (function (status, data) {
|
||||
if (!data) {
|
||||
callback.call(this, MMS.MMS_PDU_STATUS_DEFERRED, null);
|
||||
} else if (!this.parseStreamAndDispatch(data, retrCallback.bind(this))) {
|
||||
callback.call(this, MMS.MMS_PDU_STATUS_UNRECOGNISED, null);
|
||||
}
|
||||
}).bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle incoming M-Retrieve.conf PDU.
|
||||
*
|
||||
* @param msg
|
||||
* The MMS message object.
|
||||
* @param callback
|
||||
* A callback function that accepts one argument as retrieved message.
|
||||
*/
|
||||
handleRetrieveConfirmation: function handleRetrieveConfirmation(msg, callback) {
|
||||
function callbackIfValid(status, msg) {
|
||||
if (callback) {
|
||||
callback(status, msg)
|
||||
}
|
||||
}
|
||||
|
||||
// Fix default header field values.
|
||||
if (msg.headers["x-mms-delivery-report"] == null) {
|
||||
msg.headers["x-mms-delivery-report"] = false;
|
||||
}
|
||||
|
||||
let status = msg.headers["x-mms-retrieve-status"];
|
||||
if ((status != null) && (status != MMS.MMS_PDU_ERROR_OK)) {
|
||||
callbackIfValid(status, msg);
|
||||
return;
|
||||
}
|
||||
|
||||
this.saveMessageContent(msg, callbackIfValid.bind(null, MMS.MMS_PDU_ERROR_OK));
|
||||
},
|
||||
|
||||
/**
|
||||
* Update proxyInfo & MMSC from preferences.
|
||||
*
|
||||
* @param enabled
|
||||
* Enable or disable MMS proxy.
|
||||
*/
|
||||
updateProxyInfo: function updateProxyInfo(enabled) {
|
||||
try {
|
||||
if (enabled) {
|
||||
this.MMSC = Services.prefs.getCharPref("ril.data.mmsc");
|
||||
this.proxyInfo = gpps.newProxyInfo("http",
|
||||
Services.prefs.getCharPref("ril.data.mmsproxy"),
|
||||
Services.prefs.getIntPref("ril.data.mmsport"),
|
||||
Ci.nsIProxyInfo.TRANSPARENT_PROXY_RESOLVES_HOST,
|
||||
-1, null);
|
||||
debug("updateProxyInfo: "
|
||||
+ JSON.stringify({MMSC: this.MMSC, proxyInfo: this.proxyInfo}));
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
// Failed to refresh proxy info from settings. Fallback to disable.
|
||||
}
|
||||
|
||||
this.MMSC = null;
|
||||
this.proxyInfo = null;
|
||||
},
|
||||
|
||||
// nsIMmsService
|
||||
|
||||
hasSupport: function hasSupport() {
|
||||
return true;
|
||||
},
|
||||
|
||||
// nsIWapPushApplication
|
||||
|
||||
receiveWapPush: function receiveWapPush(array, length, offset, options) {
|
||||
this.parseStreamAndDispatch({array: array, offset: offset});
|
||||
},
|
||||
|
||||
// nsIObserver
|
||||
|
||||
observe: function observe(subject, topic, data) {
|
||||
switch (topic) {
|
||||
case kNetworkInterfaceStateChangedTopic: {
|
||||
let iface = subject.QueryInterface(Ci.nsINetworkInterface);
|
||||
if ((iface.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE)
|
||||
|| (iface.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS)) {
|
||||
this.updateProxyInfo(iface.state == Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kXpcomShutdownObserverTopic: {
|
||||
Services.obs.removeObserver(this, kXpcomShutdownObserverTopic);
|
||||
Services.obs.removeObserver(this, kNetworkInterfaceStateChangedTopic);
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// nsIProtocolProxyFilter
|
||||
|
||||
applyFilter: function applyFilter(service, uri, proxyInfo) {
|
||||
if (uri.prePath == this.MMSC) {
|
||||
debug("applyFilter: match " + uri.spec);
|
||||
return this.proxyInfo;
|
||||
}
|
||||
|
||||
return proxyInfo;
|
||||
},
|
||||
};
|
||||
|
||||
const NSGetFactory = XPCOMUtils.generateNSGetFactory([MmsService]);
|
||||
|
||||
let debug;
|
||||
if (DEBUG) {
|
||||
debug = function (s) {
|
||||
dump("-@- MmsService: " + s + "\n");
|
||||
};
|
||||
} else {
|
||||
debug = function (s) {};
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
# MmsService.js
|
||||
component {217ddd76-75db-4210-955d-8806cd8d87f9} MmsService.js
|
||||
contract @mozilla.org/mms/rilmmsservice;1 {217ddd76-75db-4210-955d-8806cd8d87f9}
|
||||
category profile-after-change MmsService @mozilla.org/mms/rilmmsservice;1
|
|
@ -0,0 +1,92 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
Cu.import("resource://gre/modules/WspPduHelper.jsm");
|
||||
|
||||
const DEBUG = false; // set to true to see debug messages
|
||||
|
||||
/**
|
||||
* Helpers for WAP PDU processing.
|
||||
*/
|
||||
let WapPushManager = {
|
||||
|
||||
/**
|
||||
* Parse raw PDU data and deliver to a proper target.
|
||||
*
|
||||
* @param data
|
||||
* A wrapped object containing raw PDU data.
|
||||
* @param options
|
||||
* Extra context for decoding.
|
||||
*/
|
||||
processMessage: function processMessage(data, options) {
|
||||
try {
|
||||
PduHelper.parse(data, true, options);
|
||||
debug("options: " + JSON.stringify(options));
|
||||
} catch (ex) {
|
||||
debug("Failed to parse sessionless WSP PDU: " + ex.message);
|
||||
return;
|
||||
}
|
||||
|
||||
let appid = options.headers["x-wap-application-id"];
|
||||
if (!appid) {
|
||||
debug("Push message doesn't contains X-Wap-Application-Id.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (appid == "x-wap-application:mms.ua") {
|
||||
let mmsService = Cc["@mozilla.org/mms/rilmmsservice;1"]
|
||||
.getService(Ci.nsIMmsService);
|
||||
mmsService.QueryInterface(Ci.nsIWapPushApplication)
|
||||
.receiveWapPush(data.array, data.array.length, data.offset, options);
|
||||
} else {
|
||||
debug("No WAP Push application registered for " + appid);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @param array
|
||||
* A Uint8Array or an octet array representing raw PDU data.
|
||||
* @param length
|
||||
* Length of the array.
|
||||
* @param offset
|
||||
* Offset of the array that a raw PDU data begins.
|
||||
* @param options
|
||||
* WDP bearer information.
|
||||
*/
|
||||
receiveWdpPDU: function receiveWdpPDU(array, length, offset, options) {
|
||||
if ((options.bearer == null) || !options.sourceAddress
|
||||
|| (options.sourcePort == null) || !array) {
|
||||
debug("Incomplete WDP PDU");
|
||||
return;
|
||||
}
|
||||
|
||||
if (options.destinationPort != WDP_PORT_PUSH) {
|
||||
debug("Not WAP Push port: " + options.destinationPort);
|
||||
return;
|
||||
}
|
||||
|
||||
this.processMessage({array: array, offset: offset}, options);
|
||||
},
|
||||
};
|
||||
|
||||
let debug;
|
||||
if (DEBUG) {
|
||||
debug = function (s) {
|
||||
dump("-*- WapPushManager: " + s + "\n");
|
||||
};
|
||||
} else {
|
||||
debug = function (s) {};
|
||||
}
|
||||
|
||||
const EXPORTED_SYMBOLS = ALL_CONST_SYMBOLS.concat([
|
||||
"WapPushManager",
|
||||
]);
|
||||
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,62 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// Encoded X-Mms-Message-Type values
|
||||
// @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.3.30
|
||||
const MMS_PDU_TYPE_SEND_REQ = 128;
|
||||
const MMS_PDU_TYPE_SEND_CONF = 129;
|
||||
const MMS_PDU_TYPE_NOTIFICATION_IND = 130;
|
||||
const MMS_PDU_TYPE_NOTIFYRESP_IND = 131;
|
||||
const MMS_PDU_TYPE_RETRIEVE_CONF = 132;
|
||||
const MMS_PDU_TYPE_ACKNOWLEDGE_IND = 133;
|
||||
const MMS_PDU_TYPE_DELIVERY_IND = 134;
|
||||
const MMS_PDU_TYPE_READ_REC_IND = 135;
|
||||
const MMS_PDU_TYPE_READ_ORIG_IND = 136;
|
||||
const MMS_PDU_TYPE_FORWARD_REQ = 137;
|
||||
const MMS_PDU_TYPE_FORWARD_CONF = 138;
|
||||
const MMS_PDU_TYPE_MBOX_STORE_REQ = 139;
|
||||
const MMS_PDU_TYPE_MBOX_STORE_CONF = 140;
|
||||
const MMS_PDU_TYPE_MBOX_VIEW_REQ = 141;
|
||||
const MMS_PDU_TYPE_MBOX_VIEW_CONF = 142;
|
||||
const MMS_PDU_TYPE_MBOX_UPLOAD_REQ = 143;
|
||||
const MMS_PDU_TYPE_MBOX_UPLOAD_CONF = 144;
|
||||
const MMS_PDU_TYPE_MBOX_DELETE_REQ = 145;
|
||||
const MMS_PDU_TYPE_MBOX_DELETE_CONF = 146;
|
||||
const MMS_PDU_TYPE_MBOX_DESCR = 147;
|
||||
const MMS_PDU_TYPE_DELETE_REQ = 148;
|
||||
const MMS_PDU_TYPE_DELETE_CONF = 149;
|
||||
const MMS_PDU_TYPE_CANCEL_REQ = 150;
|
||||
const MMS_PDU_TYPE_CANCEL_CONF = 151;
|
||||
|
||||
// MMS version 1.3
|
||||
// @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.3.34
|
||||
const MMS_VERSION = (0x01 << 4) | 0x03;
|
||||
|
||||
// X-Mms-Retrieve-Status values
|
||||
// @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.3.50
|
||||
const MMS_PDU_ERROR_OK = 128;
|
||||
const MMS_PDU_ERROR_TRANSIENT_FAILURE = 192;
|
||||
const MMS_PDU_ERROR_TRANSIENT_MESSAGE_NOT_FOUND = 193;
|
||||
const MMS_PDU_ERROR_TRANSIENT_NETWORK_PROBLEM = 194;
|
||||
const MMS_PDU_ERROR_PERMANENT_FAILURE = 224;
|
||||
const MMS_PDU_ERROR_PERMANENT_SERVICE_DENIED = 225;
|
||||
const MMS_PDU_ERROR_PERMANENT_MESSAGE_NOT_FOUND = 226;
|
||||
const MMS_PDU_ERROR_PERMANENT_CONTENT_UNSUPPORTED = 227;
|
||||
|
||||
// X-Mms-Status values
|
||||
// @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.3.54
|
||||
const MMS_PDU_STATUS_EXPIRED = 128;
|
||||
const MMS_PDU_STATUS_RETRIEVED = 129;
|
||||
const MMS_PDU_STATUS_REJECTED = 130;
|
||||
const MMS_PDU_STATUS_DEFERRED = 131;
|
||||
const MMS_PDU_STATUS_UNRECOGNISED = 132;
|
||||
const MMS_PDU_STATUS_INDETERMINATE = 133;
|
||||
const MMS_PDU_STATUS_FORWARDED = 134;
|
||||
const MMS_PDU_STATUS_UNREACHABLE = 135;
|
||||
|
||||
const ALL_CONST_SYMBOLS = Object.keys(this);
|
||||
|
||||
// Allow this file to be imported via Components.utils.import().
|
||||
const EXPORTED_SYMBOLS = ALL_CONST_SYMBOLS;
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
// WSP PDU Type Assignments
|
||||
// @see WAP-230-WSP-20010705-a Appendix A. Assigned Numbers.
|
||||
const WSP_PDU_TYPE_PUSH = 0x06;
|
||||
|
||||
// Registered WDP Port Numbers
|
||||
// @see WAP-259-WDP-20010614-a Appendix B. Port Number Definitions.
|
||||
const WDP_PORT_PUSH = 2948;
|
||||
|
||||
// Bearer Type Assignments
|
||||
// @see WAP-259-WDP-20010614-a Appendix C. Network Bearer Table.
|
||||
const WDP_BEARER_GSM_SMS_GSM_MSISDN = 0x03;
|
||||
|
||||
const ALL_CONST_SYMBOLS = Object.keys(this);
|
||||
|
||||
const EXPORTED_SYMBOLS = ALL_CONST_SYMBOLS;
|
||||
|
|
@ -0,0 +1,164 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
|
||||
|
||||
let subscriptLoader = Cc["@mozilla.org/moz/jssubscript-loader;1"]
|
||||
.getService(Ci.mozIJSSubScriptLoader);
|
||||
|
||||
/**
|
||||
* Test whether specified function throws exception with expected
|
||||
* result.
|
||||
*
|
||||
* @param func
|
||||
* Function to be tested.
|
||||
* @param exception
|
||||
* Expected class name of thrown exception. Use null for no throws.
|
||||
* @param stack
|
||||
* Optional stack object to be printed. null for Components#stack#caller.
|
||||
*/
|
||||
function do_check_throws(func, result, stack)
|
||||
{
|
||||
if (!stack)
|
||||
stack = Components.stack.caller;
|
||||
|
||||
try {
|
||||
func();
|
||||
} catch (ex) {
|
||||
if (ex.name == result) {
|
||||
return;
|
||||
}
|
||||
do_throw("expected result " + result + ", caught " + ex, stack);
|
||||
}
|
||||
|
||||
if (result) {
|
||||
do_throw("expected result " + result + ", none thrown", stack);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal test function for comparing results.
|
||||
*
|
||||
* @param func
|
||||
* A function under test. It should accept an arguement and return the
|
||||
* result.
|
||||
* @param data
|
||||
* Input data for `func`.
|
||||
* @param expect
|
||||
* Expected result.
|
||||
*/
|
||||
function wsp_test_func(func, data, expect) {
|
||||
let result_str = JSON.stringify(func(data));
|
||||
let expect_str = JSON.stringify(expect);
|
||||
if (result_str !== expect_str) {
|
||||
do_throw("expect decoded value: '" + expect_str + "', got '" + result_str + "'");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test customized WSP PDU decoding.
|
||||
*
|
||||
* @param func
|
||||
* Decoding func under test. It should return a decoded value if invoked.
|
||||
* @param input
|
||||
* Array of octets as test data.
|
||||
* @param expect
|
||||
* Expected decoded value, use null if expecting errors instead.
|
||||
* @param exception
|
||||
* Expected class name of thrown exception. Use null for no throws.
|
||||
*/
|
||||
function wsp_decode_test_ex(func, input, expect, exception) {
|
||||
let data = {array: input, offset: 0};
|
||||
do_check_throws(wsp_test_func.bind(null, func, data, expect), exception);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test default WSP PDU decoding.
|
||||
*
|
||||
* @param target
|
||||
* Target decoding object, ie. TextValue.
|
||||
* @param input
|
||||
* Array of octets as test data.
|
||||
* @param expect
|
||||
* Expected decoded value, use null if expecting errors instead.
|
||||
* @param exception
|
||||
* Expected class name of thrown exception. Use null for no throws.
|
||||
*/
|
||||
function wsp_decode_test(target, input, expect, exception) {
|
||||
let func = function decode_func(data) {
|
||||
return target.decode(data);
|
||||
};
|
||||
|
||||
wsp_decode_test_ex(func, input, expect, exception);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test customized WSP PDU encoding.
|
||||
*
|
||||
* @param func
|
||||
* Encoding func under test. It should return an encoded octet array if
|
||||
* invoked.
|
||||
* @param input
|
||||
* An object to be encoded.
|
||||
* @param expect
|
||||
* Expected encoded octet array, use null if expecting errors instead.
|
||||
* @param exception
|
||||
* Expected class name of thrown exception. Use null for no throws.
|
||||
*/
|
||||
function wsp_encode_test_ex(func, input, expect, exception) {
|
||||
let data = {array: [], offset: 0};
|
||||
do_check_throws(wsp_test_func.bind(null, func.bind(null, data), input,
|
||||
expect), exception);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test default WSP PDU encoding.
|
||||
*
|
||||
* @param target
|
||||
* Target decoding object, ie. TextValue.
|
||||
* @param input
|
||||
* An object to be encoded.
|
||||
* @param expect
|
||||
* Expected encoded octet array, use null if expecting errors instead.
|
||||
* @param exception
|
||||
* Expected class name of thrown exception. Use null for no throws.
|
||||
*/
|
||||
function wsp_encode_test(target, input, expect, exception) {
|
||||
let func = function encode_func(data, input) {
|
||||
target.encode(data, input);
|
||||
|
||||
// Remove extra space consumed during encoding.
|
||||
while (data.array.length > data.offset) {
|
||||
data.array.pop();
|
||||
}
|
||||
|
||||
return data.array;
|
||||
}
|
||||
|
||||
wsp_encode_test_ex(func, input, expect, exception);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param str
|
||||
* A string.
|
||||
* @param noAppendNull
|
||||
* True to omit terminating NUL octet. Default false.
|
||||
*
|
||||
* @return A number array of char codes of characters in `str`.
|
||||
*/
|
||||
function strToCharCodeArray(str, noAppendNull) {
|
||||
let result = [];
|
||||
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
result.push(str.charCodeAt(i));
|
||||
}
|
||||
if (!noAppendNull) {
|
||||
result.push(0);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
@ -0,0 +1,552 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
let MMS = {};
|
||||
subscriptLoader.loadSubScript("resource://gre/modules/MmsPduHelper.jsm", MMS);
|
||||
MMS.debug = do_print;
|
||||
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
//
|
||||
// Test target: BooleanValue
|
||||
//
|
||||
|
||||
//// BooleanValue.decode ////
|
||||
|
||||
add_test(function test_BooleanValue_decode() {
|
||||
for (let i = 0; i < 256; i++) {
|
||||
if (i == 128) {
|
||||
wsp_decode_test(MMS.BooleanValue, [128], true);
|
||||
} else if (i == 129) {
|
||||
wsp_decode_test(MMS.BooleanValue, [129], false);
|
||||
} else {
|
||||
wsp_decode_test(MMS.BooleanValue, [i], null, "CodeError");
|
||||
}
|
||||
}
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//// BooleanValue.encode ////
|
||||
|
||||
add_test(function test_BooleanValue_encode() {
|
||||
wsp_encode_test(MMS.BooleanValue, true, [128]);
|
||||
wsp_encode_test(MMS.BooleanValue, false, [129]);
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: Address
|
||||
//
|
||||
|
||||
//// Address.decode ////
|
||||
|
||||
add_test(function test_Address_decode() {
|
||||
// Test for PLMN address
|
||||
wsp_decode_test(MMS.Address, strToCharCodeArray("+123.456-789/TYPE=PLMN"),
|
||||
{address: "+123.456-789", type: "PLMN"});
|
||||
wsp_decode_test(MMS.Address, strToCharCodeArray("123456789/TYPE=PLMN"),
|
||||
{address: "123456789", type: "PLMN"});
|
||||
// Test for IPv4
|
||||
wsp_decode_test(MMS.Address, strToCharCodeArray("1.2.3.4/TYPE=IPv4"),
|
||||
{address: "1.2.3.4", type: "IPv4"});
|
||||
// Test for IPv6
|
||||
wsp_decode_test(MMS.Address,
|
||||
strToCharCodeArray("1111:AAAA:bbbb:CdEf:1ABC:2cde:3Def:0000/TYPE=IPv6"),
|
||||
{address: "1111:AAAA:bbbb:CdEf:1ABC:2cde:3Def:0000", type: "IPv6"}
|
||||
);
|
||||
// Test for other device-address
|
||||
wsp_decode_test(MMS.Address, strToCharCodeArray("+H-e.l%l_o/TYPE=W0r1d_"),
|
||||
{address: "+H-e.l%l_o", type: "W0r1d_"});
|
||||
// Test for num-shortcode
|
||||
wsp_decode_test(MMS.Address, strToCharCodeArray("+123"),
|
||||
{address: "+123", type: "num"});
|
||||
wsp_decode_test(MMS.Address, strToCharCodeArray("*123"),
|
||||
{address: "*123", type: "num"});
|
||||
wsp_decode_test(MMS.Address, strToCharCodeArray("#123"),
|
||||
{address: "#123", type: "num"});
|
||||
// Test for alphanum-shortcode
|
||||
wsp_decode_test(MMS.Address, strToCharCodeArray("H0wD0Y0uTurnTh1s0n"),
|
||||
{address: "H0wD0Y0uTurnTh1s0n", type: "alphanum"});
|
||||
// Test for other unknown typed sequence
|
||||
wsp_decode_test(MMS.Address, strToCharCodeArray("Joe User <joe@user.org>"),
|
||||
{address: "Joe User <joe@user.org>", type: "unknown"});
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: HeaderField
|
||||
//
|
||||
|
||||
//// HeaderField.decode ////
|
||||
|
||||
add_test(function test_HeaderField_decode() {
|
||||
wsp_decode_test(MMS.HeaderField, [65, 0, 66, 0], {name: "a", value: "B"});
|
||||
wsp_decode_test(MMS.HeaderField, [0x80 | 0x27, 128],
|
||||
{name: "x-mms-stored", value: true});
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//// HeaderField.encode ////
|
||||
|
||||
add_test(function test_HeaderField_encode() {
|
||||
// Test for MmsHeader
|
||||
wsp_encode_test(MMS.HeaderField, {name: "X-Mms-Message-Type",
|
||||
value: MMS.MMS_PDU_TYPE_SEND_REQ},
|
||||
[0x80 | 0x0C, MMS.MMS_PDU_TYPE_SEND_REQ]);
|
||||
// Test for ApplicationHeader
|
||||
wsp_encode_test(MMS.HeaderField, {name: "a", value: "B"}, [97, 0, 66, 0]);
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: MmsHeader
|
||||
//
|
||||
|
||||
//// MmsHeader.decode ////
|
||||
|
||||
add_test(function test_MmsHeader_decode() {
|
||||
wsp_decode_test(MMS.MmsHeader, [0x80 | 0x00], null, "NotWellKnownEncodingError");
|
||||
wsp_decode_test(MMS.MmsHeader, [0x80 | 0x27, 128],
|
||||
{name: "x-mms-stored", value: true});
|
||||
wsp_decode_test(MMS.MmsHeader, [0x80 | 0x27, 255], null);
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//// MmsHeader.encode ////
|
||||
|
||||
add_test(function test_MmsHeader_encode() {
|
||||
// Test for empty header name:
|
||||
wsp_encode_test(MMS.MmsHeader, {name: undefined, value: null}, null, "CodeError");
|
||||
wsp_encode_test(MMS.MmsHeader, {name: null, value: null}, null, "CodeError");
|
||||
wsp_encode_test(MMS.MmsHeader, {name: "", value: null}, null, "CodeError");
|
||||
// Test for non-well-known header name:
|
||||
wsp_encode_test(MMS.MmsHeader, {name: "X-No-Such-Field", value: null},
|
||||
null, "NotWellKnownEncodingError");
|
||||
// Test for normal header
|
||||
wsp_encode_test(MMS.MmsHeader, {name: "X-Mms-Message-Type",
|
||||
value: MMS.MMS_PDU_TYPE_SEND_REQ},
|
||||
[0x80 | 0x0C, MMS.MMS_PDU_TYPE_SEND_REQ]);
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: ContentClassValue
|
||||
//
|
||||
|
||||
//// ContentClassValue.decode ////
|
||||
|
||||
add_test(function test_ContentClassValue_decode() {
|
||||
for (let i = 0; i < 256; i++) {
|
||||
if ((i >= 128) && (i <= 135)) {
|
||||
wsp_decode_test(MMS.ContentClassValue, [i], i);
|
||||
} else {
|
||||
wsp_decode_test(MMS.ContentClassValue, [i], null, "CodeError");
|
||||
}
|
||||
}
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: ContentLocationValue
|
||||
//
|
||||
|
||||
//// ContentLocationValue.decode ////
|
||||
|
||||
add_test(function test_ContentLocationValue_decode() {
|
||||
// Test for MMS_PDU_TYPE_MBOX_DELETE_CONF & MMS_PDU_TYPE_DELETE_CONF
|
||||
wsp_decode_test_ex(function (data) {
|
||||
data.array[0] = data.array.length - 1;
|
||||
|
||||
let options = {};
|
||||
options["x-mms-message-type"] = /*MMS.MMS_PDU_TYPE_MBOX_DELETE_CONF*/146;
|
||||
return MMS.ContentLocationValue.decode(data, options);
|
||||
}, [0, 0x80 | 0x00].concat(strToCharCodeArray("http://no.such.com/path")),
|
||||
{statusCount: 0, uri: "http://no.such.com/path"}
|
||||
);
|
||||
wsp_decode_test_ex(function (data) {
|
||||
data.array[0] = data.array.length - 1;
|
||||
|
||||
let options = {};
|
||||
options["x-mms-message-type"] = /*MMS.MMS_PDU_TYPE_DELETE_CONF*/149;
|
||||
return MMS.ContentLocationValue.decode(data, options);
|
||||
}, [0, 0x80 | 0x00].concat(strToCharCodeArray("http://no.such.com/path")),
|
||||
{statusCount: 0, uri: "http://no.such.com/path"}
|
||||
);
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: ElementDescriptorValue
|
||||
//
|
||||
|
||||
//// ElementDescriptorValue.decode ////
|
||||
|
||||
add_test(function test_ElementDescriptorValue_decode() {
|
||||
wsp_decode_test(MMS.ElementDescriptorValue, [2, 97, 0], {contentReference: "a"});
|
||||
wsp_decode_test(MMS.ElementDescriptorValue, [4, 97, 0, 0x80 | 0x02, 0x80],
|
||||
{contentReference: "a", params: {type: 0}});
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: Parameter
|
||||
//
|
||||
|
||||
//// Parameter.decodeParameterName ////
|
||||
|
||||
add_test(function test_Parameter_decodeParameterName() {
|
||||
wsp_decode_test_ex(function (data) {
|
||||
return MMS.Parameter.decodeParameterName(data);
|
||||
}, [0x80 | 0x02], "type"
|
||||
);
|
||||
wsp_decode_test_ex(function (data) {
|
||||
return MMS.Parameter.decodeParameterName(data);
|
||||
}, strToCharCodeArray("type"), "type"
|
||||
);
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//// Parameter.decode ////
|
||||
|
||||
add_test(function test_Parameter_decode() {
|
||||
wsp_decode_test(MMS.Parameter, [0x80 | 0x02, 0x80 | 0x00], {name: "type", value: 0});
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//// Parameter.decodeMultiple ////
|
||||
|
||||
add_test(function test_Parameter_decodeMultiple() {
|
||||
// FIXME: The following test case falls because Parameter-value decoding of
|
||||
// "type" parameters utilies WSP.ConstrainedEncoding, which in turn
|
||||
// utilies WSP.TextString, and TextString is not matual exclusive to
|
||||
// each other.
|
||||
//wsp_decode_test_ex(function (data) {
|
||||
// return MMS.Parameter.decodeMultiple(data, data.array.length);
|
||||
// }, [0x80 | 0x02, 0x80 | 0x00].concat(strToCharCodeArray("good")).concat([0x80 | 0x01]),
|
||||
// {type: 0, good: 1}
|
||||
//);
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: EncodedStringValue
|
||||
//
|
||||
|
||||
//// EncodedStringValue.decode ////
|
||||
|
||||
add_test(function test_EncodedStringValue_decode() {
|
||||
// Test for normal TextString
|
||||
wsp_decode_test(MMS.EncodedStringValue, strToCharCodeArray("Hello"), "Hello");
|
||||
// Test for non-well-known charset
|
||||
wsp_decode_test(MMS.EncodedStringValue, [1, 0x80], null, "NotWellKnownEncodingError");
|
||||
// Test for utf-8
|
||||
let (entry = MMS.WSP.WSP_WELL_KNOWN_CHARSETS["utf-8"]) {
|
||||
// "Mozilla" in full width.
|
||||
let str = "\uff2d\uff4f\uff5a\uff49\uff4c\uff4c\uff41";
|
||||
|
||||
let conv = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
|
||||
.createInstance(Ci.nsIScriptableUnicodeConverter);
|
||||
conv.charset = entry.converter;
|
||||
|
||||
let raw;
|
||||
try {
|
||||
let raw = conv.convertToByteArray(str).concat([0]);
|
||||
if (raw[0] >= 128) {
|
||||
wsp_decode_test(MMS.EncodedStringValue,
|
||||
[raw.length + 2, 0x80 | entry.number, 127].concat(raw), str);
|
||||
} else {
|
||||
wsp_decode_test(MMS.EncodedStringValue,
|
||||
[raw.length + 1, 0x80 | entry.number].concat(raw), str);
|
||||
}
|
||||
} catch (e) {
|
||||
do_print("Can't convert test string to byte array with " + entry.converter);
|
||||
}
|
||||
}
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: ExpiryValue
|
||||
//
|
||||
|
||||
//// ExpiryValue.decode ////
|
||||
|
||||
add_test(function test_ExpiryValue_decode() {
|
||||
// Test for Absolute-token Date-value
|
||||
wsp_decode_test(MMS.ExpiryValue, [3, 128, 1, 0x80], new Date(0x80 * 1000));
|
||||
// Test for Relative-token Delta-seconds-value
|
||||
wsp_decode_test(MMS.ExpiryValue, [3, 129, 0x80], 0);
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: PreviouslySentByValue
|
||||
//
|
||||
|
||||
//// PreviouslySentByValue.decode ////
|
||||
|
||||
add_test(function test_PreviouslySentByValue_decode() {
|
||||
wsp_decode_test(MMS.PreviouslySentByValue, [3, 0x80 | 0x03, 65, 0],
|
||||
{forwardedCount: 3, originator: {address: "A",
|
||||
type: "alphanum"}});
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: PreviouslySentDateValue
|
||||
//
|
||||
|
||||
//// PreviouslySentDateValue.decode ////
|
||||
|
||||
add_test(function test_PreviouslySentDateValue_decode() {
|
||||
wsp_decode_test(MMS.PreviouslySentDateValue, [3, 0x80 | 0x03, 1, 4],
|
||||
{forwardedCount: 3, timestamp: new Date(4 * 1000)});
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: FromValue
|
||||
//
|
||||
|
||||
//// FromValue.decode ////
|
||||
|
||||
add_test(function test_FromValue_decode() {
|
||||
// Test for Insert-address-token:
|
||||
wsp_decode_test(MMS.FromValue, [1, 129], null);
|
||||
// Test for Address-present-token:
|
||||
let (addr = strToCharCodeArray("+123/TYPE=PLMN")) {
|
||||
wsp_decode_test(MMS.FromValue, [addr.length + 2, 128].concat(addr),
|
||||
{address: "+123", type: "PLMN"});
|
||||
}
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: MessageClassValue
|
||||
//
|
||||
|
||||
//// MessageClassValue.decode ////
|
||||
|
||||
add_test(function test_MessageClassValue_decode() {
|
||||
wsp_decode_test(MMS.MessageClassValue, [65, 0], "A");
|
||||
wsp_decode_test(MMS.MessageClassValue, [128], "personal");
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: ClassIdentifier
|
||||
//
|
||||
|
||||
//// ClassIdentifier.decode ////
|
||||
|
||||
add_test(function test_ClassIdentifier_decode() {
|
||||
let (IDs = ["personal", "advertisement", "informational", "auto"]) {
|
||||
for (let i = 0; i < 256; i++) {
|
||||
if ((i >= 128) && (i <= 131)) {
|
||||
wsp_decode_test(MMS.ClassIdentifier, [i], IDs[i - 128]);
|
||||
} else {
|
||||
wsp_decode_test(MMS.ClassIdentifier, [i], null, "CodeError");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: MessageTypeValue
|
||||
//
|
||||
|
||||
//// MessageTypeValue.decode ////
|
||||
|
||||
add_test(function test_MessageTypeValue_decode() {
|
||||
for (let i = 0; i < 256; i++) {
|
||||
if ((i >= 128) && (i <= 151)) {
|
||||
wsp_decode_test(MMS.MessageTypeValue, [i], i);
|
||||
} else {
|
||||
wsp_decode_test(MMS.MessageTypeValue, [i], null, "CodeError");
|
||||
}
|
||||
}
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//// MessageTypeValue.encode ////
|
||||
|
||||
add_test(function test_MessageTypeValue_encode() {
|
||||
for (let i = 0; i < 256; i++) {
|
||||
if ((i >= 128) && (i <= 151)) {
|
||||
wsp_encode_test(MMS.MessageTypeValue, i, [i]);
|
||||
} else {
|
||||
wsp_encode_test(MMS.MessageTypeValue, i, null, "CodeError");
|
||||
}
|
||||
}
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: MmFlagsValue
|
||||
//
|
||||
|
||||
//// MmFlagsValue.decode ////
|
||||
|
||||
add_test(function test_MmFlagsValue_decode() {
|
||||
for (let i = 0; i < 256; i++) {
|
||||
if ((i >= 128) && (i <= 130)) {
|
||||
wsp_decode_test(MMS.MmFlagsValue, [3, i, 65, 0], {type: i, text: "A"});
|
||||
} else {
|
||||
wsp_decode_test(MMS.MmFlagsValue, [3, i, 65, 0], null, "CodeError");
|
||||
}
|
||||
}
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: MmStateValue
|
||||
//
|
||||
|
||||
//// MmStateValue.decode ////
|
||||
|
||||
add_test(function test_MmStateValue_decode() {
|
||||
for (let i = 0; i < 256; i++) {
|
||||
if ((i >= 128) && (i <= 132)) {
|
||||
wsp_decode_test(MMS.MmStateValue, [i, 0], i);
|
||||
} else {
|
||||
wsp_decode_test(MMS.MmStateValue, [i, 0], null, "CodeError");
|
||||
}
|
||||
}
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: PriorityValue
|
||||
//
|
||||
|
||||
//// PriorityValue.decode ////
|
||||
|
||||
add_test(function test_PriorityValue_decode() {
|
||||
for (let i = 0; i < 256; i++) {
|
||||
if ((i >= 128) && (i <= 130)) {
|
||||
wsp_decode_test(MMS.PriorityValue, [i], i);
|
||||
} else {
|
||||
wsp_decode_test(MMS.PriorityValue, [i], null, "CodeError");
|
||||
}
|
||||
}
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: RecommendedRetrievalModeValue
|
||||
//
|
||||
|
||||
//// RecommendedRetrievalModeValue.decode ////
|
||||
|
||||
add_test(function test_RecommendedRetrievalModeValue_decode() {
|
||||
for (let i = 0; i < 256; i++) {
|
||||
if (i == 128) {
|
||||
wsp_decode_test(MMS.RecommendedRetrievalModeValue, [i], i);
|
||||
} else {
|
||||
wsp_decode_test(MMS.RecommendedRetrievalModeValue, [i], null, "CodeError");
|
||||
}
|
||||
}
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: ReplyChargingValue
|
||||
//
|
||||
|
||||
//// ReplyChargingValue.decode ////
|
||||
|
||||
add_test(function test_ReplyChargingValue_decode() {
|
||||
for (let i = 0; i < 256; i++) {
|
||||
if ((i >= 128) && (i <= 131)) {
|
||||
wsp_decode_test(MMS.ReplyChargingValue, [i], i);
|
||||
} else {
|
||||
wsp_decode_test(MMS.ReplyChargingValue, [i], null, "CodeError");
|
||||
}
|
||||
}
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: RetrieveStatusValue
|
||||
//
|
||||
|
||||
//// RetrieveStatusValue.decode ////
|
||||
|
||||
add_test(function test_RetrieveStatusValue_decode() {
|
||||
for (let i = 0; i < 256; i++) {
|
||||
if ((i == 128)
|
||||
|| ((i >= 192) && (i <= 194))
|
||||
|| ((i >= 224) && (i <= 227))) {
|
||||
wsp_decode_test(MMS.RetrieveStatusValue, [i], i);
|
||||
} else if ((i >= 195) && (i <= 223)) {
|
||||
wsp_decode_test(MMS.RetrieveStatusValue, [i], 192);
|
||||
} else {
|
||||
wsp_decode_test(MMS.RetrieveStatusValue, [i], 224);
|
||||
}
|
||||
}
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: StatusValue
|
||||
//
|
||||
|
||||
//// StatusValue.decode ////
|
||||
|
||||
add_test(function test_StatusValue_decode() {
|
||||
for (let i = 0; i < 256; i++) {
|
||||
if ((i >= 128) && (i <= 135)) {
|
||||
wsp_decode_test(MMS.StatusValue, [i], i);
|
||||
} else {
|
||||
wsp_decode_test(MMS.StatusValue, [i], null, "CodeError");
|
||||
}
|
||||
}
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//// StatusValue.encode ////
|
||||
|
||||
add_test(function test_StatusValue_encode() {
|
||||
for (let i = 0; i < 256; i++) {
|
||||
if ((i >= 128) && (i <= 135)) {
|
||||
wsp_encode_test(MMS.StatusValue, i, [i]);
|
||||
} else {
|
||||
wsp_encode_test(MMS.StatusValue, i, null, "CodeError");
|
||||
}
|
||||
}
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
|
@ -0,0 +1,918 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
let WSP = {};
|
||||
subscriptLoader.loadSubScript("resource://gre/modules/WspPduHelper.jsm", WSP);
|
||||
WSP.debug = do_print;
|
||||
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
//
|
||||
// Test target: ensureHeader
|
||||
//
|
||||
|
||||
add_test(function test_ensureHeader() {
|
||||
do_check_throws(function () {
|
||||
WSP.ensureHeader({}, "no-such-property");
|
||||
}, "FatalCodeError"
|
||||
);
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: skipValue()
|
||||
//
|
||||
|
||||
add_test(function test_skipValue() {
|
||||
// Test for zero-valued first octet:
|
||||
wsp_decode_test_ex(function (data) {
|
||||
return WSP.skipValue(data);
|
||||
}, [0], null
|
||||
);
|
||||
// Test first octet < 31
|
||||
wsp_decode_test_ex(function (data) {
|
||||
return WSP.skipValue(data);
|
||||
}, [1, 2], [2]
|
||||
);
|
||||
// Test first octet = 31
|
||||
wsp_decode_test_ex(function (data) {
|
||||
return WSP.skipValue(data);
|
||||
}, [31, 0], null
|
||||
);
|
||||
wsp_decode_test_ex(function (data) {
|
||||
return WSP.skipValue(data);
|
||||
}, [31, 1, 2], [2]
|
||||
);
|
||||
// Test first octet <= 127
|
||||
wsp_decode_test_ex(function (data) {
|
||||
return WSP.skipValue(data);
|
||||
}, strToCharCodeArray("Hello world!"), "Hello world!"
|
||||
);
|
||||
// Test first octet >= 128
|
||||
wsp_decode_test_ex(function (data) {
|
||||
return WSP.skipValue(data);
|
||||
}, [0x80 | 0x01], 0x01
|
||||
);
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: Octet
|
||||
//
|
||||
|
||||
//// Octet.decode ////
|
||||
|
||||
add_test(function test_Octet_decode() {
|
||||
wsp_decode_test(WSP.Octet, [1], 1);
|
||||
wsp_decode_test(WSP.Octet, [], null, "RangeError");
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//// Octet.decodeMultiple ////
|
||||
|
||||
add_test(function test_Octet_decodeMultiple() {
|
||||
wsp_decode_test_ex(function (data) {
|
||||
return WSP.Octet.decodeMultiple(data, 3);
|
||||
}, [0, 1, 2], [0, 1, 2], null
|
||||
);
|
||||
wsp_decode_test_ex(function (data) {
|
||||
return WSP.Octet.decodeMultiple(data, 3);
|
||||
}, new Uint8Array([0, 1, 2]), new Uint8Array([0, 1, 2]), null
|
||||
);
|
||||
wsp_decode_test_ex(function (data) {
|
||||
return WSP.Octet.decodeMultiple(data, 4);
|
||||
}, [0, 1, 2], null, "RangeError"
|
||||
);
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//// Octet.decodeEqualTo ////
|
||||
|
||||
add_test(function test_Octet_decodeEqualTo() {
|
||||
wsp_decode_test_ex(function (data) {
|
||||
return WSP.Octet.decodeEqualTo(data, 1);
|
||||
}, [1], 1, null
|
||||
);
|
||||
wsp_decode_test_ex(function (data) {
|
||||
return WSP.Octet.decodeEqualTo(data, 2);
|
||||
}, [1], null, "CodeError"
|
||||
);
|
||||
wsp_decode_test_ex(function (data) {
|
||||
return WSP.Octet.decodeEqualTo(data, 2);
|
||||
}, [], null, "RangeError"
|
||||
);
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//// Octet.encode ////
|
||||
|
||||
add_test(function test_Octet_encode() {
|
||||
for (let i = 0; i < 256; i++) {
|
||||
wsp_encode_test(WSP.Octet, i, [i]);
|
||||
}
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: Text
|
||||
//
|
||||
|
||||
//// Text.decode ////
|
||||
|
||||
add_test(function test_Text_decode() {
|
||||
for (let i = 0; i < 256; i++) {
|
||||
if (i == 0) {
|
||||
wsp_decode_test(WSP.Text, [0], null, "NullCharError");
|
||||
} else if ((i < WSP.CTLS) || (i == WSP.DEL)) {
|
||||
wsp_decode_test(WSP.Text, [i], null, "CodeError");
|
||||
} else {
|
||||
wsp_decode_test(WSP.Text, [i], String.fromCharCode(i));
|
||||
}
|
||||
}
|
||||
// Test \r\n(SP|HT)* sequence:
|
||||
wsp_decode_test(WSP.Text, strToCharCodeArray("\r\n \t \t \t", true), " ");
|
||||
wsp_decode_test(WSP.Text, strToCharCodeArray("\r\n \t \t \t"), " ");
|
||||
wsp_decode_test(WSP.Text, strToCharCodeArray("\r\n \t \t \tA"), " ");
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//// Text.encode ////
|
||||
|
||||
add_test(function test_Text_encode() {
|
||||
for (let i = 0; i < 256; i++) {
|
||||
if ((i < WSP.CTLS) || (i == WSP.DEL)) {
|
||||
wsp_encode_test(WSP.Text, String.fromCharCode(i), null, "CodeError");
|
||||
} else {
|
||||
wsp_encode_test(WSP.Text, String.fromCharCode(i), [i]);
|
||||
}
|
||||
}
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: NullTerminatedTexts
|
||||
//
|
||||
|
||||
//// NullTerminatedTexts.decode ////
|
||||
|
||||
add_test(function test_NullTerminatedTexts_decode() {
|
||||
// Test incompleted string:
|
||||
wsp_decode_test(WSP.NullTerminatedTexts, strToCharCodeArray(" ", true), null, "RangeError");
|
||||
// Test control char:
|
||||
wsp_decode_test(WSP.NullTerminatedTexts, strToCharCodeArray(" \n"), null, "CodeError");
|
||||
// Test normal string:
|
||||
wsp_decode_test(WSP.NullTerminatedTexts, strToCharCodeArray(""), "");
|
||||
wsp_decode_test(WSP.NullTerminatedTexts, strToCharCodeArray("oops"), "oops");
|
||||
// Test \r\n(SP|HT)* sequence:
|
||||
wsp_decode_test(WSP.NullTerminatedTexts, strToCharCodeArray("A\r\n \t \t \tB"), "A B");
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//// NullTerminatedTexts.encode ////
|
||||
|
||||
add_test(function test_NullTerminatedTexts_encode() {
|
||||
wsp_encode_test(WSP.NullTerminatedTexts, "", [0]);
|
||||
wsp_encode_test(WSP.NullTerminatedTexts, "Hello, World!",
|
||||
strToCharCodeArray("Hello, World!"));
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: Token
|
||||
//
|
||||
|
||||
let TOKEN_SEPS = "()<>@,;:\\\"/[]?={} \t";
|
||||
|
||||
//// Token.decode ////
|
||||
|
||||
add_test(function test_Token_decode() {
|
||||
for (let i = 0; i < 256; i++) {
|
||||
if (i == 0) {
|
||||
wsp_decode_test(WSP.Token, [i], null, "NullCharError");
|
||||
} else if ((i < WSP.CTLS) || (i >= WSP.ASCIIS)
|
||||
|| (TOKEN_SEPS.indexOf(String.fromCharCode(i)) >= 0)) {
|
||||
wsp_decode_test(WSP.Token, [i], null, "CodeError");
|
||||
} else {
|
||||
wsp_decode_test(WSP.Token, [i], String.fromCharCode(i));
|
||||
}
|
||||
}
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//// Token.encode ////
|
||||
|
||||
add_test(function test_Token_encode() {
|
||||
for (let i = 0; i < 256; i++) {
|
||||
if ((i < WSP.CTLS) || (i >= WSP.ASCIIS)
|
||||
|| (TOKEN_SEPS.indexOf(String.fromCharCode(i)) >= 0)) {
|
||||
wsp_encode_test(WSP.Token, String.fromCharCode(i), null, "CodeError");
|
||||
} else {
|
||||
wsp_encode_test(WSP.Token, String.fromCharCode(i), [i]);
|
||||
}
|
||||
}
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: URIC
|
||||
//
|
||||
|
||||
//// URIC.decode ////
|
||||
|
||||
add_test(function test_URIC_decode() {
|
||||
let uric = "!#$%&'()*+,-./0123456789:;=?@ABCDEFGHIJKLMN"
|
||||
+ "OPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~";
|
||||
for (let i = 0; i < 256; i++) {
|
||||
if (i == 0) {
|
||||
wsp_decode_test(WSP.URIC, [i], null, "NullCharError");
|
||||
} else if (uric.indexOf(String.fromCharCode(i)) >= 0) {
|
||||
wsp_decode_test(WSP.URIC, [i], String.fromCharCode(i));
|
||||
} else {
|
||||
wsp_decode_test(WSP.URIC, [i], null, "CodeError");
|
||||
}
|
||||
}
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: TextString
|
||||
//
|
||||
|
||||
//// TextString.decode ////
|
||||
|
||||
add_test(function test_TextString_decode() {
|
||||
// Test quoted string
|
||||
wsp_decode_test(WSP.TextString, [127, 128, 0], String.fromCharCode(128));
|
||||
// Test illegal quoted string
|
||||
wsp_decode_test(WSP.TextString, [127, 32, 0], null, "CodeError");
|
||||
// Test illegal unquoted string
|
||||
wsp_decode_test(WSP.TextString, [128, 0], null, "CodeError");
|
||||
// Test normal string
|
||||
wsp_decode_test(WSP.TextString, [32, 0], " ");
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//// TextString.encode ////
|
||||
|
||||
add_test(function test_TextString_encode() {
|
||||
// Test quoted string
|
||||
wsp_encode_test(WSP.TextString, String.fromCharCode(128), [127, 128, 0]);
|
||||
// Test normal string
|
||||
wsp_encode_test(WSP.TextString, "Mozilla", strToCharCodeArray("Mozilla"));
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: TokenText
|
||||
//
|
||||
|
||||
//// TokenText.decode ////
|
||||
|
||||
add_test(function test_TokenText_decode() {
|
||||
wsp_decode_test(WSP.TokenText, [65], null, "RangeError");
|
||||
wsp_decode_test(WSP.TokenText, [0], "");
|
||||
wsp_decode_test(WSP.TokenText, [65, 0], "A");
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//// TokenText.encode ////
|
||||
|
||||
add_test(function test_TokenText_encode() {
|
||||
wsp_encode_test(WSP.TokenText, "B2G", strToCharCodeArray("B2G"));
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: QuotedString
|
||||
//
|
||||
|
||||
//// QuotedString.decode ////
|
||||
|
||||
add_test(function test_QuotedString_decode() {
|
||||
// Test non-quoted string
|
||||
wsp_decode_test(WSP.QuotedString, [32, 0], null, "CodeError");
|
||||
// Test incompleted string
|
||||
wsp_decode_test(WSP.QuotedString, [34, 32], null, "RangeError");
|
||||
wsp_decode_test(WSP.QuotedString, [34, 32, 0], " ");
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: ShortInteger
|
||||
//
|
||||
|
||||
//// ShortInteger.decode ////
|
||||
|
||||
add_test(function test_ShortInteger_decode() {
|
||||
for (let i = 0; i < 256; i++) {
|
||||
if (i & 0x80) {
|
||||
wsp_decode_test(WSP.ShortInteger, [i], i & 0x7F);
|
||||
} else {
|
||||
wsp_decode_test(WSP.ShortInteger, [i], null, "CodeError");
|
||||
}
|
||||
}
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//// ShortInteger.encode ////
|
||||
|
||||
add_test(function test_ShortInteger_encode() {
|
||||
for (let i = 0; i < 256; i++) {
|
||||
if (i & 0x80) {
|
||||
wsp_encode_test(WSP.ShortInteger, i, null, "CodeError");
|
||||
} else {
|
||||
wsp_encode_test(WSP.ShortInteger, i, [0x80 | i]);
|
||||
}
|
||||
}
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: LongInteger
|
||||
//
|
||||
|
||||
//// LongInteger.decode ////
|
||||
|
||||
function LongInteger_testcases(target) {
|
||||
// Test LongInteger of zero octet
|
||||
wsp_decode_test(target, [0, 0], null, "CodeError");
|
||||
wsp_decode_test(target, [1, 0x80], 0x80);
|
||||
wsp_decode_test(target, [2, 0x80, 2], 0x8002);
|
||||
wsp_decode_test(target, [3, 0x80, 2, 3], 0x800203);
|
||||
wsp_decode_test(target, [4, 0x80, 2, 3, 4], 0x80020304);
|
||||
wsp_decode_test(target, [5, 0x80, 2, 3, 4, 5], 0x8002030405);
|
||||
wsp_decode_test(target, [6, 0x80, 2, 3, 4, 5, 6], 0x800203040506);
|
||||
// Test LongInteger of more than 6 octets
|
||||
wsp_decode_test(target, [7, 0x80, 2, 3, 4, 5, 6, 7], [0x80, 2, 3, 4, 5, 6, 7]);
|
||||
// Test LongInteger of more than 30 octets
|
||||
wsp_decode_test(target, [31], null, "CodeError");
|
||||
}
|
||||
add_test(function test_LongInteger_decode() {
|
||||
LongInteger_testcases(WSP.LongInteger);
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: UintVar
|
||||
//
|
||||
|
||||
//// UintVar.decode ////
|
||||
|
||||
add_test(function test_UintVar_decode() {
|
||||
wsp_decode_test(WSP.UintVar, [0x80], null, "RangeError");
|
||||
// Test up to max 53 bits integer
|
||||
wsp_decode_test(WSP.UintVar, [0x7F], 0x7F);
|
||||
wsp_decode_test(WSP.UintVar, [0xFF, 0x7F], 0x3FFF);
|
||||
wsp_decode_test(WSP.UintVar, [0xFF, 0xFF, 0x7F], 0x1FFFFF);
|
||||
wsp_decode_test(WSP.UintVar, [0xFF, 0xFF, 0xFF, 0x7F], 0xFFFFFFF);
|
||||
wsp_decode_test(WSP.UintVar, [0xFF, 0xFF, 0xFF, 0xFF, 0x7F], 0x7FFFFFFFF);
|
||||
wsp_decode_test(WSP.UintVar, [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F], 0x3FFFFFFFFFF);
|
||||
wsp_decode_test(WSP.UintVar, [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F], 0x1FFFFFFFFFFFF);
|
||||
wsp_decode_test(WSP.UintVar, [0x8F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F], 0x1FFFFFFFFFFFFF);
|
||||
wsp_decode_test(WSP.UintVar, [0x01, 0x02], 1);
|
||||
wsp_decode_test(WSP.UintVar, [0x80, 0x01, 0x02], 1);
|
||||
wsp_decode_test(WSP.UintVar, [0x80, 0x80, 0x80, 0x01, 0x2], 1);
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: ConstrainedEncoding (decodeAlternatives)
|
||||
//
|
||||
|
||||
//// ConstrainedEncoding.decode ////
|
||||
|
||||
add_test(function test_ConstrainedEncoding_decode() {
|
||||
wsp_decode_test(WSP.ConstrainedEncoding, [0x80], 0);
|
||||
wsp_decode_test(WSP.ConstrainedEncoding, [32, 0], " ");
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: ValueLength
|
||||
//
|
||||
|
||||
//// ValueLength.decode ////
|
||||
|
||||
add_test(function test_ValueLength_decode() {
|
||||
for (let i = 0; i < 256; i++) {
|
||||
if (i < 31) {
|
||||
wsp_decode_test(WSP.ValueLength, [i, 0x8F, 0x7F], i);
|
||||
} else if (i == 31) {
|
||||
wsp_decode_test(WSP.ValueLength, [i, 0x8F, 0x7F], 0x7FF);
|
||||
} else {
|
||||
wsp_decode_test(WSP.ValueLength, [i, 0x8F, 0x7F], null, "CodeError");
|
||||
}
|
||||
}
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: NoValue
|
||||
//
|
||||
|
||||
//// NoValue.decode ////
|
||||
|
||||
add_test(function test_NoValue_decode() {
|
||||
wsp_decode_test(WSP.NoValue, [0], null);
|
||||
for (let i = 1; i < 256; i++) {
|
||||
wsp_decode_test(WSP.NoValue, [i], null, "CodeError");
|
||||
}
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: TextValue
|
||||
//
|
||||
|
||||
//// TextValue.decode ////
|
||||
|
||||
add_test(function test_TextValue_decode() {
|
||||
wsp_decode_test(WSP.TextValue, [0], null);
|
||||
wsp_decode_test(WSP.TextValue, [65, 0], "A");
|
||||
wsp_decode_test(WSP.TextValue, [32, 0], null, "CodeError");
|
||||
wsp_decode_test(WSP.TextValue, [34, 32, 0], " ");
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: IntegerValue
|
||||
//
|
||||
|
||||
//// IntegerValue.decode ////
|
||||
|
||||
add_test(function test_IntegerValue_decode() {
|
||||
for (let i = 128; i < 256; i++) {
|
||||
wsp_decode_test(WSP.IntegerValue, [i], i & 0x7F);
|
||||
}
|
||||
|
||||
LongInteger_testcases(WSP.IntegerValue);
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: DateValue
|
||||
//
|
||||
|
||||
//// DateValue.decode ////
|
||||
|
||||
add_test(function test_DateValue_decode() {
|
||||
wsp_decode_test(WSP.DateValue, [0, 0], null, "CodeError");
|
||||
wsp_decode_test(WSP.DateValue, [1, 0x80], new Date(0x80 * 1000));
|
||||
wsp_decode_test(WSP.DateValue, [31], null, "CodeError");
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: DeltaSecondsValue
|
||||
//
|
||||
// DeltaSecondsValue is only an alias of IntegerValue.
|
||||
|
||||
//
|
||||
// Test target: QValue
|
||||
//
|
||||
|
||||
//// QValue.decode ////
|
||||
|
||||
add_test(function test_QValue_decode() {
|
||||
wsp_decode_test(WSP.QValue, [0], null, "CodeError");
|
||||
wsp_decode_test(WSP.QValue, [1], 0);
|
||||
wsp_decode_test(WSP.QValue, [100], 0.99);
|
||||
wsp_decode_test(WSP.QValue, [101], 0.001);
|
||||
wsp_decode_test(WSP.QValue, [0x88, 0x4B], 0.999);
|
||||
wsp_decode_test(WSP.QValue, [0x88, 0x4C], null, "CodeError");
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: VersionValue
|
||||
//
|
||||
|
||||
//// VersionValue.decode ////
|
||||
|
||||
add_test(function test_VersionValue_decode() {
|
||||
for (let major = 1; major < 8; major++) {
|
||||
let version = (major << 4) | 0x0F;
|
||||
wsp_decode_test(WSP.VersionValue, [0x80 | version], version);
|
||||
wsp_decode_test(WSP.VersionValue, [major + 0x30, 0], version);
|
||||
|
||||
for (let minor = 0; minor < 15; minor++) {
|
||||
version = (major << 4) | minor;
|
||||
wsp_decode_test(WSP.VersionValue, [0x80 | version], version);
|
||||
if (minor >= 10) {
|
||||
wsp_decode_test(WSP.VersionValue, [major + 0x30, 0x2E, 0x31, (minor - 10) + 0x30, 0], version);
|
||||
} else {
|
||||
wsp_decode_test(WSP.VersionValue, [major + 0x30, 0x2E, minor + 0x30, 0], version);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: UriValue
|
||||
//
|
||||
|
||||
//// UriValue.decode ////
|
||||
|
||||
add_test(function test_UriValue_decode() {
|
||||
wsp_decode_test(WSP.UriValue, [97], null, "RangeError");
|
||||
wsp_decode_test(WSP.UriValue, [0], "");
|
||||
wsp_decode_test(WSP.UriValue, [65, 0], "A");
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: Parameter
|
||||
//
|
||||
|
||||
//// Parameter.decodeTypedParameter ////
|
||||
|
||||
add_test(function test_Parameter_decodeTypedParameter() {
|
||||
// Test for array-typed return value from IntegerValue
|
||||
wsp_decode_test_ex(function (data) {
|
||||
return WSP.Parameter.decodeTypedParameter(data);
|
||||
}, [7, 0, 0, 0, 0, 0, 0, 0], null, "CodeError"
|
||||
);
|
||||
// Test for number-typed return value from IntegerValue
|
||||
wsp_decode_test_ex(function (data) {
|
||||
return WSP.Parameter.decodeTypedParameter(data);
|
||||
}, [1, 0, 0], {name: "q", value: null}
|
||||
);
|
||||
// Test for NotWellKnownEncodingError
|
||||
wsp_decode_test_ex(function (data) {
|
||||
return WSP.Parameter.decodeTypedParameter(data);
|
||||
}, [1, 0xFF], null, "NotWellKnownEncodingError"
|
||||
);
|
||||
// Test for parameter specific decoder
|
||||
wsp_decode_test_ex(function (data) {
|
||||
return WSP.Parameter.decodeTypedParameter(data);
|
||||
}, [1, 0, 100], {name: "q", value: 0.99}
|
||||
);
|
||||
// Test for TextValue
|
||||
wsp_decode_test_ex(function (data) {
|
||||
return WSP.Parameter.decodeTypedParameter(data);
|
||||
}, [1, 0x10, 48, 46, 57, 57, 0], {name: "secure", value: "0.99"}
|
||||
);
|
||||
// Test for TextString
|
||||
wsp_decode_test_ex(function (data) {
|
||||
return WSP.Parameter.decodeTypedParameter(data);
|
||||
}, [1, 0x19, 60, 115, 109, 105, 108, 62, 0], {name: "start", value: "<smil>"}
|
||||
);
|
||||
// Test for skipValue
|
||||
wsp_decode_test_ex(function (data) {
|
||||
return WSP.Parameter.decodeTypedParameter(data);
|
||||
}, [1, 0x19, 128], null
|
||||
);
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//// Parameter.decodeUntypedParameter ////
|
||||
|
||||
add_test(function test_Parameter_decodeUntypedParameter() {
|
||||
wsp_decode_test_ex(function (data) {
|
||||
return WSP.Parameter.decodeUntypedParameter(data);
|
||||
}, [1], null, "CodeError"
|
||||
);
|
||||
wsp_decode_test_ex(function (data) {
|
||||
return WSP.Parameter.decodeUntypedParameter(data);
|
||||
}, [65, 0, 0], {name: "a", value: null}
|
||||
);
|
||||
// Test for IntegerValue
|
||||
wsp_decode_test_ex(function (data) {
|
||||
return WSP.Parameter.decodeUntypedParameter(data);
|
||||
}, [65, 0, 1, 0], {name: "a", value: 0}
|
||||
);
|
||||
// Test for TextValue
|
||||
wsp_decode_test_ex(function (data) {
|
||||
return WSP.Parameter.decodeUntypedParameter(data);
|
||||
}, [65, 0, 66, 0], {name: "a", value: "B"}
|
||||
);
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//// Parameter.decode ////
|
||||
|
||||
add_test(function test_Parameter_decode() {
|
||||
wsp_decode_test_ex(function (data) {
|
||||
return WSP.Parameter.decode(data);
|
||||
}, [1, 0x19, 60, 115, 109, 105, 108, 62, 0], {name: "start", value: "<smil>"}
|
||||
);
|
||||
wsp_decode_test_ex(function (data) {
|
||||
return WSP.Parameter.decode(data);
|
||||
}, [65, 0, 66, 0], {name: "a", value: "B"}
|
||||
);
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//// Parameter.decodeMultiple ////
|
||||
|
||||
add_test(function test_Parameter_decodeMultiple() {
|
||||
wsp_decode_test_ex(function (data) {
|
||||
return WSP.Parameter.decodeMultiple(data, 13);
|
||||
}, [1, 0x19, 60, 115, 109, 105, 108, 62, 0, 65, 0, 66, 0], {start: "<smil>", a: "B"}
|
||||
);
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: Header
|
||||
//
|
||||
|
||||
//// Header.decode ////
|
||||
|
||||
add_test(function test_Header_decode() {
|
||||
wsp_decode_test(WSP.Header, [0x34 | 0x80, 0x80], {name: "push-flag", value: 0});
|
||||
wsp_decode_test(WSP.Header, [65, 0, 66, 0], {name: "a", value: "B"});
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: WellKnownHeader
|
||||
//
|
||||
|
||||
//// WellKnownHeader.decode ////
|
||||
|
||||
add_test(function test_WellKnownHeader_decode() {
|
||||
wsp_decode_test(WSP.WellKnownHeader, [0xFF], null, "NotWellKnownEncodingError");
|
||||
let (entry = WSP.WSP_HEADER_FIELDS["push-flag"]) {
|
||||
// Test for Short-Integer
|
||||
wsp_decode_test(WSP.WellKnownHeader, [entry.number | 0x80, 0x80],
|
||||
{name: entry.name, value: 0});
|
||||
// Test for NoValue
|
||||
wsp_decode_test(WSP.WellKnownHeader, [entry.number | 0x80, 0],
|
||||
{name: entry.name, value: null});
|
||||
// Test for TokenText
|
||||
wsp_decode_test(WSP.WellKnownHeader, [entry.number | 0x80, 65, 0],
|
||||
{name: entry.name, value: "A"});
|
||||
// Test for QuotedString
|
||||
wsp_decode_test(WSP.WellKnownHeader, [entry.number | 0x80, 34, 128, 0],
|
||||
{name: entry.name, value: String.fromCharCode(128)});
|
||||
// Test for skipValue
|
||||
wsp_decode_test(WSP.WellKnownHeader, [entry.number | 0x80, 2, 0, 0], null);
|
||||
}
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: ApplicationHeader
|
||||
//
|
||||
|
||||
//// ApplicationHeader.decode ////
|
||||
|
||||
add_test(function test_ApplicationHeader_decode() {
|
||||
wsp_decode_test(WSP.ApplicationHeader, [5, 0, 66, 0], null, "CodeError");
|
||||
wsp_decode_test(WSP.ApplicationHeader, [65, 0, 66, 0], {name: "a", value: "B"});
|
||||
// Test for skipValue
|
||||
wsp_decode_test(WSP.ApplicationHeader, [65, 0, 2, 0, 0], null);
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//// ApplicationHeader.encode ////
|
||||
|
||||
add_test(function test_ApplicationHeader_encode() {
|
||||
// Test invalid header name string:
|
||||
wsp_encode_test(WSP.ApplicationHeader, {name: undefined, value: "asdf"}, null, "CodeError");
|
||||
wsp_encode_test(WSP.ApplicationHeader, {name: null, value: "asdf"}, null, "CodeError");
|
||||
wsp_encode_test(WSP.ApplicationHeader, {name: "", value: "asdf"}, null, "CodeError");
|
||||
wsp_encode_test(WSP.ApplicationHeader, {name: "a b", value: "asdf"}, null, "CodeError");
|
||||
// Test value string:
|
||||
wsp_encode_test(WSP.ApplicationHeader, {name: "asdf", value: undefined},
|
||||
strToCharCodeArray("asdf").concat([0]));
|
||||
wsp_encode_test(WSP.ApplicationHeader, {name: "asdf", value: null},
|
||||
strToCharCodeArray("asdf").concat([0]));
|
||||
wsp_encode_test(WSP.ApplicationHeader, {name: "asdf", value: ""},
|
||||
strToCharCodeArray("asdf").concat([0]));
|
||||
wsp_encode_test(WSP.ApplicationHeader, {name: "asdf", value: "fdsa"},
|
||||
strToCharCodeArray("asdf").concat(strToCharCodeArray("fdsa")));
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: FieldName
|
||||
//
|
||||
|
||||
//// FieldName.decode ////
|
||||
|
||||
add_test(function test_FieldName_decode() {
|
||||
wsp_decode_test(WSP.FieldName, [0], "");
|
||||
wsp_decode_test(WSP.FieldName, [65, 0], "a");
|
||||
wsp_decode_test(WSP.FieldName, [97, 0], "a");
|
||||
let (entry = WSP.WSP_HEADER_FIELDS["content-length"]) {
|
||||
wsp_decode_test(WSP.FieldName, [entry.number | 0x80], entry.name);
|
||||
}
|
||||
wsp_decode_test(WSP.FieldName, [0xFF], null, "NotWellKnownEncodingError");
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: AcceptCharsetValue
|
||||
//
|
||||
|
||||
//// AcceptCharsetValue.decode ////
|
||||
|
||||
add_test(function test_AcceptCharsetValue_decode() {
|
||||
wsp_decode_test(WSP.AcceptCharsetValue, [0xFF], null, "CodeError");
|
||||
// Test for Any-Charset
|
||||
wsp_decode_test(WSP.AcceptCharsetValue, [128], {charset: "*"});
|
||||
// Test for Constrained-Charset
|
||||
wsp_decode_test(WSP.AcceptCharsetValue, [65, 0], {charset: "A"});
|
||||
let (entry = WSP.WSP_WELL_KNOWN_CHARSETS["utf-8"]) {
|
||||
wsp_decode_test(WSP.AcceptCharsetValue, [entry.number | 0x80], {charset: entry.name});
|
||||
}
|
||||
// Test for Accept-Charset-General-Form
|
||||
wsp_decode_test(WSP.AcceptCharsetValue, [1, 128], {charset: "*"});
|
||||
let (entry = WSP.WSP_WELL_KNOWN_CHARSETS["utf-8"]) {
|
||||
wsp_decode_test(WSP.AcceptCharsetValue, [2, 1, entry.number], {charset: entry.name});
|
||||
wsp_decode_test(WSP.AcceptCharsetValue, [1, entry.number | 0x80], {charset: entry.name});
|
||||
}
|
||||
wsp_decode_test(WSP.AcceptCharsetValue, [3, 65, 0, 100], {charset: "A", q: 0.99});
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: WellKnownCharset
|
||||
//
|
||||
|
||||
//// WellKnownCharset.decode ////
|
||||
|
||||
add_test(function test_WellKnownCharset_decode() {
|
||||
wsp_decode_test(WSP.WellKnownCharset, [0xFF], null, "NotWellKnownEncodingError");
|
||||
// Test for Any-Charset
|
||||
wsp_decode_test(WSP.WellKnownCharset, [128], {charset: "*"});
|
||||
// Test for number-typed return value from IntegerValue
|
||||
wsp_decode_test(WSP.WellKnownCharset, [1, 3], {charset: "ansi_x3.4-1968"});
|
||||
// Test for array-typed return value from IntegerValue
|
||||
wsp_decode_test(WSP.WellKnownCharset, [7, 0, 0, 0, 0, 0, 0, 0, 3], null, "CodeError");
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: ContentTypeValue
|
||||
//
|
||||
|
||||
//// ContentTypeValue.decodeConstrainedMedia ////
|
||||
|
||||
add_test(function test_ContentTypeValue_decodeConstrainedMedia() {
|
||||
// Test for string-typed return value from ConstrainedEncoding
|
||||
wsp_decode_test_ex(function (data) {
|
||||
return WSP.ContentTypeValue.decodeConstrainedMedia(data);
|
||||
}, [65, 0], {media: "a", params: null}
|
||||
);
|
||||
// Test for number-typed return value from ConstrainedEncoding
|
||||
wsp_decode_test_ex(function (data) {
|
||||
return WSP.ContentTypeValue.decodeConstrainedMedia(data);
|
||||
}, [0x33 | 0x80], {media: "application/vnd.wap.multipart.related", params: null}
|
||||
);
|
||||
// Test for NotWellKnownEncodingError
|
||||
wsp_decode_test_ex(function (data) {
|
||||
return WSP.ContentTypeValue.decodeConstrainedMedia(data);
|
||||
}, [0x80], null, "NotWellKnownEncodingError"
|
||||
);
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//// ContentTypeValue.decodeMedia ////
|
||||
|
||||
add_test(function test_ContentTypeValue_decodeMedia() {
|
||||
// Test for NullTerminatedTexts
|
||||
wsp_decode_test_ex(function (data) {
|
||||
return WSP.ContentTypeValue.decodeMedia(data);
|
||||
}, [65, 0], "a"
|
||||
);
|
||||
// Test for IntegerValue
|
||||
wsp_decode_test_ex(function (data) {
|
||||
return WSP.ContentTypeValue.decodeMedia(data);
|
||||
}, [0x3E | 0x80], "application/vnd.wap.mms-message"
|
||||
);
|
||||
wsp_decode_test_ex(function (data) {
|
||||
return WSP.ContentTypeValue.decodeMedia(data);
|
||||
}, [0x80], null, "NotWellKnownEncodingError"
|
||||
);
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//// ContentTypeValue.decodeMediaType ////
|
||||
|
||||
add_test(function test_ContentTypeValue_decodeMediaType() {
|
||||
wsp_decode_test_ex(function (data) {
|
||||
return WSP.ContentTypeValue.decodeMediaType(data, 1);
|
||||
}, [0x3E | 0x80],
|
||||
{media: "application/vnd.wap.mms-message", params: null}
|
||||
);
|
||||
wsp_decode_test_ex(function (data) {
|
||||
return WSP.ContentTypeValue.decodeMediaType(data, 14);
|
||||
}, [0x3E | 0x80, 1, 0x19, 60, 115, 109, 105, 108, 62, 0, 65, 0, 66, 0],
|
||||
{media: "application/vnd.wap.mms-message", params: {start: "<smil>", a: "B"}}
|
||||
);
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//// ContentTypeValue.decodeContentGeneralForm ////
|
||||
|
||||
add_test(function test_ContentTypeValue_decodeContentGeneralForm() {
|
||||
wsp_decode_test_ex(function (data) {
|
||||
return WSP.ContentTypeValue.decodeContentGeneralForm(data);
|
||||
}, [14, 0x3E | 0x80, 1, 0x19, 60, 115, 109, 105, 108, 62, 0, 65, 0, 66, 0],
|
||||
{media: "application/vnd.wap.mms-message", params: {start: "<smil>", a: "B"}}
|
||||
);
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//// ContentTypeValue.decode ////
|
||||
|
||||
add_test(function test_ContentTypeValue_decode() {
|
||||
wsp_decode_test(WSP.ContentTypeValue,
|
||||
[14, 0x3E | 0x80, 1, 0x19, 60, 115, 109, 105, 108, 62, 0, 65, 0, 66, 0],
|
||||
{media: "application/vnd.wap.mms-message", params: {start: "<smil>", a: "B"}}
|
||||
);
|
||||
|
||||
wsp_decode_test(WSP.ContentTypeValue, [0x33 | 0x80],
|
||||
{media: "application/vnd.wap.multipart.related", params: null}
|
||||
);
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: ApplicationIdValue
|
||||
//
|
||||
|
||||
//// ApplicationIdValue.decode ////
|
||||
|
||||
add_test(function test_ApplicationIdValue_decode() {
|
||||
wsp_decode_test(WSP.ApplicationIdValue, [0], "");
|
||||
wsp_decode_test(WSP.ApplicationIdValue, [65, 0], "A");
|
||||
wsp_decode_test(WSP.ApplicationIdValue, [97, 0], "a");
|
||||
let (entry = WSP.OMNA_PUSH_APPLICATION_IDS["x-wap-application:mms.ua"]) {
|
||||
wsp_decode_test(WSP.ApplicationIdValue, [entry.number | 0x80], entry.urn);
|
||||
wsp_decode_test(WSP.ApplicationIdValue, [1, entry.number], entry.urn);
|
||||
}
|
||||
wsp_decode_test(WSP.ApplicationIdValue, [0xFF], null, "NotWellKnownEncodingError");
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
//
|
||||
// Test target: PduHelper
|
||||
//
|
||||
|
||||
//// PduHelper.parseHeaders ////
|
||||
|
||||
add_test(function test_PduHelper_parseHeaders() {
|
||||
wsp_decode_test_ex(function (data) {
|
||||
return WSP.PduHelper.parseHeaders(data, data.array.length);
|
||||
}, [0x80 | 0x05, 2, 0x23, 0x28, 0x80 | 0x2F, 0x80 | 0x04],
|
||||
{"age": 9000, "x-wap-application-id": "x-wap-application:mms.ua"}
|
||||
);
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
[DEFAULT]
|
||||
head = header_helpers.js
|
||||
tail =
|
||||
|
||||
[test_wsp_pdu_helper.js]
|
||||
[test_mms_pdu_helper.js]
|
|
@ -37,6 +37,30 @@ LocationCallback(GpsLocation* location)
|
|||
callback->Update(somewhere);
|
||||
}
|
||||
|
||||
static void
|
||||
StatusCallback(GpsStatus* status)
|
||||
{}
|
||||
|
||||
static void
|
||||
SvStatusCallback(GpsSvStatus* sv_info)
|
||||
{}
|
||||
|
||||
static void
|
||||
NmeaCallback(GpsUtcTime timestamp, const char* nmea, int length)
|
||||
{}
|
||||
|
||||
static void
|
||||
SetCapabilitiesCallback(uint32_t capabilities)
|
||||
{}
|
||||
|
||||
static void
|
||||
AcquireWakelockCallback()
|
||||
{}
|
||||
|
||||
static void
|
||||
ReleaseWakelockCallback()
|
||||
{}
|
||||
|
||||
typedef void *(*pthread_func)(void *);
|
||||
|
||||
/** Callback for creating a thread that can call into the JS codes.
|
||||
|
@ -57,16 +81,23 @@ CreateThreadCallback(const char* name, void (*start)(void *), void* arg)
|
|||
return thread;
|
||||
}
|
||||
|
||||
static void
|
||||
RequestUtcTimeCallback()
|
||||
{}
|
||||
|
||||
static GpsCallbacks gCallbacks = {
|
||||
sizeof(GpsCallbacks),
|
||||
LocationCallback,
|
||||
NULL, /* StatusCallback */
|
||||
NULL, /* SvStatusCallback */
|
||||
NULL, /* NmeaCallback */
|
||||
NULL, /* SetCapabilitiesCallback */
|
||||
NULL, /* AcquireWakelockCallback */
|
||||
NULL, /* ReleaseWakelockCallback */
|
||||
StatusCallback,
|
||||
SvStatusCallback,
|
||||
NmeaCallback,
|
||||
SetCapabilitiesCallback,
|
||||
AcquireWakelockCallback,
|
||||
ReleaseWakelockCallback,
|
||||
CreateThreadCallback,
|
||||
#ifdef GPS_CAPABILITY_ON_DEMAND_TIME
|
||||
RequestUtcTimeCallback,
|
||||
#endif
|
||||
};
|
||||
|
||||
GonkGPSGeolocationProvider::GonkGPSGeolocationProvider()
|
||||
|
|
|
@ -70,6 +70,12 @@ XPCOMUtils.defineLazyServiceGetter(this, "gSettingsService",
|
|||
"@mozilla.org/settingsService;1",
|
||||
"nsISettingsService");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "WAP", function () {
|
||||
let WAP = {};
|
||||
Cu.import("resource://gre/modules/WapPushManager.js", WAP);
|
||||
return WAP;
|
||||
});
|
||||
|
||||
function convertRILCallState(state) {
|
||||
switch (state) {
|
||||
case RIL.CALL_STATE_ACTIVE:
|
||||
|
@ -173,7 +179,9 @@ function RadioInterfaceLayer() {
|
|||
Services.obs.addObserver(this, kMozSettingsChangedObserverTopic, false);
|
||||
|
||||
this._sentSmsEnvelopes = {};
|
||||
|
||||
this.portAddressedSmsApps = {};
|
||||
this.portAddressedSmsApps[WAP.WDP_PORT_PUSH] = this.handleSmsWdpPortPush.bind(this);
|
||||
}
|
||||
RadioInterfaceLayer.prototype = {
|
||||
|
||||
|
@ -583,10 +591,39 @@ RadioInterfaceLayer.prototype = {
|
|||
ppmm.sendAsyncMessage("RIL:CallError", message);
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle WDP port push PDU. Constructor WDP bearer information and deliver
|
||||
* to WapPushManager.
|
||||
*
|
||||
* @param message
|
||||
* A SMS message.
|
||||
*/
|
||||
handleSmsWdpPortPush: function handleSmsWdpPortPush(message) {
|
||||
if (message.encoding != RIL.PDU_DCS_MSG_CODING_8BITS_ALPHABET) {
|
||||
debug("Got port addressed SMS but not encoded in 8-bit alphabet. Drop!");
|
||||
return;
|
||||
}
|
||||
|
||||
let options = {
|
||||
bearer: WAP.WDP_BEARER_GSM_SMS_GSM_MSISDN,
|
||||
sourceAddress: message.sender,
|
||||
sourcePort: message.header.originatorPort,
|
||||
destinationAddress: this.radioState.icc.MSISDN,
|
||||
destinationPort: message.header.destinationPort,
|
||||
};
|
||||
WAP.WapPushManager.receiveWdpPDU(message.fullData, message.fullData.length,
|
||||
0, options);
|
||||
},
|
||||
|
||||
portAddressedSmsApps: null,
|
||||
handleSmsReceived: function handleSmsReceived(message) {
|
||||
debug("handleSmsReceived: " + JSON.stringify(message));
|
||||
|
||||
// FIXME: Bug 737202 - Typed arrays become normal arrays when sent to/from workers
|
||||
if (message.encoding == RIL.PDU_DCS_MSG_CODING_8BITS_ALPHABET) {
|
||||
message.fullData = new Uint8Array(message.fullData);
|
||||
}
|
||||
|
||||
// Dispatch to registered handler if application port addressing is
|
||||
// available. Note that the destination port can possibly be zero when
|
||||
// representing a UDP/TCP port.
|
||||
|
|
|
@ -99,7 +99,7 @@ frontend::CompileScript(JSContext *cx, JSObject *scopeChain, StackFrame *callerF
|
|||
if (!parser.init())
|
||||
return NULL;
|
||||
|
||||
SharedContext sc(cx, /* inFunction = */ false);
|
||||
SharedContext sc(cx, scopeChain, /* fun = */ NULL, /* funbox = */ NULL);
|
||||
|
||||
TreeContext tc(&parser, &sc);
|
||||
if (!tc.init())
|
||||
|
@ -118,14 +118,13 @@ frontend::CompileScript(JSContext *cx, JSObject *scopeChain, StackFrame *callerF
|
|||
JS_ASSERT_IF(globalObj, JSCLASS_HAS_GLOBAL_FLAG_AND_SLOTS(globalObj->getClass()));
|
||||
|
||||
GlobalScope globalScope(cx, globalObj);
|
||||
bce.sc->setScopeChain(scopeChain);
|
||||
bce.globalScope = &globalScope;
|
||||
if (!SetStaticLevel(bce.sc, staticLevel))
|
||||
if (!SetStaticLevel(&sc, staticLevel))
|
||||
return NULL;
|
||||
|
||||
/* If this is a direct call to eval, inherit the caller's strictness. */
|
||||
if (callerFrame && callerFrame->isScriptFrame() && callerFrame->script()->strictModeCode)
|
||||
bce.sc->setInStrictMode();
|
||||
sc.setInStrictMode();
|
||||
|
||||
#ifdef DEBUG
|
||||
bool savedCallerFun;
|
||||
|
@ -165,10 +164,8 @@ frontend::CompileScript(JSContext *cx, JSObject *scopeChain, StackFrame *callerF
|
|||
* Inline this->statements to emit as we go to save AST space. We must
|
||||
* generate our script-body blockid since we aren't calling Statements.
|
||||
*/
|
||||
uint32_t bodyid;
|
||||
if (!GenerateBlockId(bce.sc, bodyid))
|
||||
if (!GenerateBlockId(&sc, sc.bodyid))
|
||||
return NULL;
|
||||
bce.sc->bodyid = bodyid;
|
||||
|
||||
ParseNode *pn;
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
|
@ -201,7 +198,7 @@ frontend::CompileScript(JSContext *cx, JSObject *scopeChain, StackFrame *callerF
|
|||
|
||||
if (!AnalyzeFunctions(bce.parser))
|
||||
return NULL;
|
||||
bce.sc->functionList = NULL;
|
||||
tc.functionList = NULL;
|
||||
|
||||
if (!EmitTree(cx, &bce, pn))
|
||||
return NULL;
|
||||
|
@ -266,7 +263,8 @@ frontend::CompileFunctionBody(JSContext *cx, JSFunction *fun,
|
|||
if (!parser.init())
|
||||
return false;
|
||||
|
||||
SharedContext funsc(cx, /* inFunction = */ true);
|
||||
JS_ASSERT(fun);
|
||||
SharedContext funsc(cx, /* scopeChain = */ NULL, fun, /* funbox = */ NULL);
|
||||
|
||||
TreeContext funtc(&parser, &funsc);
|
||||
if (!funtc.init())
|
||||
|
@ -277,7 +275,6 @@ frontend::CompileFunctionBody(JSContext *cx, JSFunction *fun,
|
|||
if (!funbce.init())
|
||||
return false;
|
||||
|
||||
funsc.setFunction(fun);
|
||||
funsc.bindings.transfer(cx, bindings);
|
||||
fun->setArgCount(funsc.bindings.numArgs());
|
||||
if (!GenerateBlockId(&funsc, funsc.bodyid))
|
||||
|
|
|
@ -83,7 +83,8 @@ BytecodeEmitter::BytecodeEmitter(Parser *parser, SharedContext *sc, unsigned lin
|
|||
typesetCount(0),
|
||||
noScriptRval(noScriptRval),
|
||||
needScriptGlobal(needScriptGlobal),
|
||||
hasSingletons(false)
|
||||
hasSingletons(false),
|
||||
inForInit(false)
|
||||
{
|
||||
memset(&prolog, 0, sizeof prolog);
|
||||
memset(&main, 0, sizeof main);
|
||||
|
@ -660,7 +661,7 @@ LookupCompileTimeConstant(JSContext *cx, BytecodeEmitter *bce, JSAtom *atom, Val
|
|||
*/
|
||||
constp->setMagic(JS_NO_CONSTANT);
|
||||
do {
|
||||
if (bce->sc->inFunction || bce->parser->compileAndGo) {
|
||||
if (bce->sc->inFunction() || bce->parser->compileAndGo) {
|
||||
/* XXX this will need revising if 'const' becomes block-scoped. */
|
||||
StmtInfo *stmt = LexicalLookup(bce->sc, atom, NULL);
|
||||
if (stmt)
|
||||
|
@ -679,7 +680,7 @@ LookupCompileTimeConstant(JSContext *cx, BytecodeEmitter *bce, JSAtom *atom, Val
|
|||
* with object or catch variable; nor can prop's value be changed,
|
||||
* nor can prop be deleted.
|
||||
*/
|
||||
if (bce->sc->inFunction) {
|
||||
if (bce->sc->inFunction()) {
|
||||
if (bce->sc->bindings.hasBinding(cx, atom))
|
||||
break;
|
||||
} else {
|
||||
|
@ -997,7 +998,7 @@ static int
|
|||
AdjustBlockSlot(JSContext *cx, BytecodeEmitter *bce, int slot)
|
||||
{
|
||||
JS_ASSERT((unsigned) slot < bce->maxStackDepth);
|
||||
if (bce->sc->inFunction) {
|
||||
if (bce->sc->inFunction()) {
|
||||
slot += bce->sc->bindings.numVars();
|
||||
if ((unsigned) slot >= SLOTNO_LIMIT) {
|
||||
ReportCompileErrorNumber(cx, bce->tokenStream(), NULL, JSREPORT_ERROR,
|
||||
|
@ -1220,7 +1221,7 @@ BindNameToSlot(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
* Don't generate upvars on the left side of a for loop. See
|
||||
* bug 470758.
|
||||
*/
|
||||
if (bce->sc->inForInit)
|
||||
if (bce->inForInit)
|
||||
return JS_TRUE;
|
||||
|
||||
JS_ASSERT(caller->isScriptFrame());
|
||||
|
@ -1564,7 +1565,13 @@ BytecodeEmitter::needsImplicitThis()
|
|||
{
|
||||
if (!parser->compileAndGo)
|
||||
return true;
|
||||
if (!sc->inFunction) {
|
||||
|
||||
if (sc->inFunction()) {
|
||||
for (const FunctionBox *funbox = this->sc->funbox(); funbox; funbox = funbox->parent) {
|
||||
if (funbox->inWith)
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
JSObject *scope = sc->scopeChain();
|
||||
while (scope) {
|
||||
if (scope->isWith())
|
||||
|
@ -1572,10 +1579,7 @@ BytecodeEmitter::needsImplicitThis()
|
|||
scope = scope->enclosingScope();
|
||||
}
|
||||
}
|
||||
for (const FunctionBox *funbox = this->sc->funbox; funbox; funbox = funbox->parent) {
|
||||
if (funbox->inWith)
|
||||
return true;
|
||||
}
|
||||
|
||||
for (StmtInfo *stmt = sc->topStmt; stmt; stmt = stmt->down) {
|
||||
if (stmt->type == STMT_WITH)
|
||||
return true;
|
||||
|
@ -1650,11 +1654,11 @@ EmitXMLName(JSContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce)
|
|||
JS_ASSERT(op == JSOP_XMLNAME || op == JSOP_CALLXMLNAME);
|
||||
|
||||
ParseNode *pn2 = pn->pn_kid;
|
||||
bool oldInForInit = bce->sc->inForInit;
|
||||
bce->sc->inForInit = false;
|
||||
bool oldInForInit = bce->inForInit;
|
||||
bce->inForInit = false;
|
||||
if (!EmitTree(cx, bce, pn2))
|
||||
return false;
|
||||
bce->sc->inForInit = oldInForInit;
|
||||
bce->inForInit = oldInForInit;
|
||||
if (NewSrcNote2(cx, bce, SRC_PCBASE, bce->offset() - pn2->pn_offset) < 0)
|
||||
return false;
|
||||
|
||||
|
@ -2630,7 +2634,7 @@ MaybeEmitVarDecl(JSContext *cx, BytecodeEmitter *bce, JSOp prologOp, ParseNode *
|
|||
}
|
||||
|
||||
if (JOF_OPTYPE(pn->getOp()) == JOF_ATOM &&
|
||||
(!bce->sc->inFunction || bce->sc->funIsHeavyweight()))
|
||||
(!bce->sc->inFunction() || bce->sc->funIsHeavyweight()))
|
||||
{
|
||||
bce->switchToProlog();
|
||||
if (!UpdateLineNumberNotes(cx, bce, pn->pn_pos.begin.lineno))
|
||||
|
@ -2640,7 +2644,7 @@ MaybeEmitVarDecl(JSContext *cx, BytecodeEmitter *bce, JSOp prologOp, ParseNode *
|
|||
bce->switchToMain();
|
||||
}
|
||||
|
||||
if (bce->sc->inFunction &&
|
||||
if (bce->sc->inFunction() &&
|
||||
JOF_OPTYPE(pn->getOp()) == JOF_LOCAL &&
|
||||
!pn->isLet() &&
|
||||
bce->shouldNoteClosedName(pn))
|
||||
|
@ -3343,11 +3347,11 @@ EmitVariables(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, VarEmitOption
|
|||
return JS_FALSE;
|
||||
}
|
||||
|
||||
bool oldInForInit = bce->sc->inForInit;
|
||||
bce->sc->inForInit = false;
|
||||
bool oldInForInit = bce->inForInit;
|
||||
bce->inForInit = false;
|
||||
if (!EmitTree(cx, bce, pn3))
|
||||
return JS_FALSE;
|
||||
bce->sc->inForInit = oldInForInit;
|
||||
bce->inForInit = oldInForInit;
|
||||
} else if (letNotes) {
|
||||
/* JSOP_ENTERLETx expects at least 1 slot to have been pushed. */
|
||||
if (Emit1(cx, bce, JSOP_UNDEFINED) < 0)
|
||||
|
@ -4402,7 +4406,7 @@ EmitLexicalScope(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
(stmtInfo.down
|
||||
? stmtInfo.down->type == STMT_BLOCK &&
|
||||
(!stmtInfo.down->down || stmtInfo.down->down->type != STMT_FOR_IN_LOOP)
|
||||
: !bce->sc->inFunction))
|
||||
: !bce->sc->inFunction()))
|
||||
{
|
||||
/* There must be no source note already output for the next op. */
|
||||
JS_ASSERT(bce->noteCount() == 0 ||
|
||||
|
@ -4496,10 +4500,10 @@ EmitForIn(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
|
|||
if (pn1) {
|
||||
ParseNode *decl = letDecl ? pn1->pn_expr : pn1;
|
||||
JS_ASSERT(decl->isKind(PNK_VAR) || decl->isKind(PNK_LET));
|
||||
bce->sc->inForInit = true;
|
||||
bce->inForInit = true;
|
||||
if (!EmitVariables(cx, bce, decl, DefineVars))
|
||||
return false;
|
||||
bce->sc->inForInit = false;
|
||||
bce->inForInit = false;
|
||||
}
|
||||
|
||||
/* Compile the object expression to the right of 'in'. */
|
||||
|
@ -4639,7 +4643,7 @@ EmitNormalFor(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
|
|||
/* No initializer: emit an annotated nop for the decompiler. */
|
||||
op = JSOP_NOP;
|
||||
} else {
|
||||
bce->sc->inForInit = true;
|
||||
bce->inForInit = true;
|
||||
#if JS_HAS_DESTRUCTURING
|
||||
if (pn3->isKind(PNK_ASSIGN)) {
|
||||
JS_ASSERT(pn3->isOp(JSOP_NOP));
|
||||
|
@ -4662,7 +4666,7 @@ EmitNormalFor(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
|
|||
op = JSOP_NOP;
|
||||
}
|
||||
}
|
||||
bce->sc->inForInit = false;
|
||||
bce->inForInit = false;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -4792,7 +4796,7 @@ EmitFunc(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
* comments in EmitStatementList.
|
||||
*/
|
||||
JS_ASSERT(pn->isOp(JSOP_NOP));
|
||||
JS_ASSERT(bce->sc->inFunction);
|
||||
JS_ASSERT(bce->sc->inFunction());
|
||||
return EmitFunctionDefNop(cx, bce, pn->pn_index);
|
||||
}
|
||||
|
||||
|
@ -4800,20 +4804,18 @@ EmitFunc(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
fun->kind() == JSFUN_INTERPRETED);
|
||||
|
||||
{
|
||||
SharedContext sc(cx, /* inFunction = */ true);
|
||||
FunctionBox *funbox = pn->pn_funbox;
|
||||
SharedContext sc(cx, /* scopeChain = */ NULL, fun, funbox);
|
||||
BytecodeEmitter bce2(bce->parser, &sc, pn->pn_pos.begin.lineno,
|
||||
/* noScriptRval = */ false, /* needsScriptGlobal = */ false);
|
||||
if (!bce2.init())
|
||||
return false;
|
||||
|
||||
FunctionBox *funbox = pn->pn_funbox;
|
||||
bce2.sc->cxFlags = funbox->cxFlags;
|
||||
sc.cxFlags = funbox->cxFlags;
|
||||
if (bce->sc->funMightAliasLocals())
|
||||
bce2.sc->setFunMightAliasLocals(); // inherit funMightAliasLocals from parent
|
||||
sc.setFunMightAliasLocals(); // inherit funMightAliasLocals from parent
|
||||
|
||||
bce2.sc->bindings.transfer(cx, &funbox->bindings);
|
||||
bce2.sc->setFunction(fun);
|
||||
bce2.sc->funbox = funbox;
|
||||
sc.bindings.transfer(cx, &funbox->bindings);
|
||||
bce2.parent = bce;
|
||||
bce2.globalScope = bce->globalScope;
|
||||
|
||||
|
@ -4824,7 +4826,7 @@ EmitFunc(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
* below.
|
||||
*/
|
||||
JS_ASSERT(bce->sc->staticLevel < JS_BITMASK(16) - 1);
|
||||
bce2.sc->staticLevel = bce->sc->staticLevel + 1;
|
||||
sc.staticLevel = bce->sc->staticLevel + 1;
|
||||
|
||||
/* We measured the max scope depth when we parsed the function. */
|
||||
if (!EmitFunctionScript(cx, &bce2, pn->pn_body))
|
||||
|
@ -4851,7 +4853,7 @@ EmitFunc(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
* invocation of the emitter and calls to EmitTree for function
|
||||
* definitions can be scheduled before generating the rest of code.
|
||||
*/
|
||||
if (!bce->sc->inFunction) {
|
||||
if (!bce->sc->inFunction()) {
|
||||
JS_ASSERT(!bce->sc->topStmt);
|
||||
JS_ASSERT(pn->pn_cookie.isFree());
|
||||
if (pn->pn_cookie.isFree()) {
|
||||
|
@ -5137,7 +5139,7 @@ EmitStatement(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
*/
|
||||
bool wantval = false;
|
||||
JSBool useful = JS_FALSE;
|
||||
if (bce->sc->inFunction) {
|
||||
if (bce->sc->inFunction()) {
|
||||
JS_ASSERT(!bce->noScriptRval);
|
||||
} else {
|
||||
useful = wantval = !bce->noScriptRval;
|
||||
|
@ -5326,13 +5328,13 @@ EmitCallOrNew(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
|
|||
* JSOP_NEW bytecode with a two-byte immediate telling how many args
|
||||
* were pushed on the operand stack.
|
||||
*/
|
||||
bool oldInForInit = bce->sc->inForInit;
|
||||
bce->sc->inForInit = false;
|
||||
bool oldInForInit = bce->inForInit;
|
||||
bce->inForInit = false;
|
||||
for (ParseNode *pn3 = pn2->pn_next; pn3; pn3 = pn3->pn_next) {
|
||||
if (!EmitTree(cx, bce, pn3))
|
||||
return false;
|
||||
}
|
||||
bce->sc->inForInit = oldInForInit;
|
||||
bce->inForInit = oldInForInit;
|
||||
if (NewSrcNote2(cx, bce, SRC_PCBASE, bce->offset() - off) < 0)
|
||||
return false;
|
||||
|
||||
|
@ -5812,12 +5814,12 @@ EmitUnary(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
if (op == JSOP_TYPEOF && !pn2->isKind(PNK_NAME))
|
||||
op = JSOP_TYPEOFEXPR;
|
||||
|
||||
bool oldInForInit = bce->sc->inForInit;
|
||||
bce->sc->inForInit = false;
|
||||
bool oldInForInit = bce->inForInit;
|
||||
bce->inForInit = false;
|
||||
if (!EmitTree(cx, bce, pn2))
|
||||
return false;
|
||||
|
||||
bce->sc->inForInit = oldInForInit;
|
||||
bce->inForInit = oldInForInit;
|
||||
return Emit1(cx, bce, op) >= 0;
|
||||
}
|
||||
|
||||
|
@ -5825,7 +5827,7 @@ static bool
|
|||
EmitDefaults(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
||||
{
|
||||
JS_ASSERT(pn->isKind(PNK_ARGSBODY));
|
||||
uint16_t ndefaults = bce->sc->funbox->ndefaults;
|
||||
uint16_t ndefaults = bce->sc->funbox()->ndefaults;
|
||||
JSFunction *fun = bce->sc->fun();
|
||||
unsigned nformal = fun->nargs - fun->hasRest();
|
||||
EMIT_UINT16_IMM_OP(JSOP_ACTUALSFILLED, nformal - ndefaults);
|
||||
|
@ -6074,7 +6076,7 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
|
||||
#if JS_HAS_GENERATORS
|
||||
case PNK_YIELD:
|
||||
JS_ASSERT(bce->sc->inFunction);
|
||||
JS_ASSERT(bce->sc->inFunction());
|
||||
if (pn->pn_kid) {
|
||||
if (!EmitTree(cx, bce, pn->pn_kid))
|
||||
return JS_FALSE;
|
||||
|
@ -6219,8 +6221,8 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
* possibly including a let (a = b) ... expression. We must clear
|
||||
* inForInit to avoid mis-compiling such beasts.
|
||||
*/
|
||||
bool oldInForInit = bce->sc->inForInit;
|
||||
bce->sc->inForInit = false;
|
||||
bool oldInForInit = bce->inForInit;
|
||||
bce->inForInit = false;
|
||||
#endif
|
||||
|
||||
/* Binary operators that evaluate both operands unconditionally. */
|
||||
|
@ -6229,7 +6231,7 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
if (!EmitTree(cx, bce, pn->pn_right))
|
||||
return JS_FALSE;
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
bce->sc->inForInit = oldInForInit;
|
||||
bce->inForInit = oldInForInit;
|
||||
#endif
|
||||
if (Emit1(cx, bce, pn->getOp()) < 0)
|
||||
return JS_FALSE;
|
||||
|
@ -6244,11 +6246,11 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
} else {
|
||||
JSOp op = pn->getOp();
|
||||
JS_ASSERT(op == JSOP_BINDXMLNAME || op == JSOP_SETXMLNAME);
|
||||
bool oldInForInit = bce->sc->inForInit;
|
||||
bce->sc->inForInit = false;
|
||||
bool oldInForInit = bce->inForInit;
|
||||
bce->inForInit = false;
|
||||
if (!EmitTree(cx, bce, pn->pn_kid))
|
||||
return false;
|
||||
bce->sc->inForInit = oldInForInit;
|
||||
bce->inForInit = oldInForInit;
|
||||
if (Emit1(cx, bce, op) < 0)
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -127,6 +127,8 @@ struct BytecodeEmitter
|
|||
|
||||
bool hasSingletons:1; /* script contains singleton initializer JSOP_OBJECT */
|
||||
|
||||
bool inForInit:1; /* emitting init expr of for; exclude 'in' */
|
||||
|
||||
BytecodeEmitter(Parser *parser, SharedContext *sc, unsigned lineno,
|
||||
bool noScriptRval, bool needScriptGlobal);
|
||||
bool init();
|
||||
|
@ -163,7 +165,7 @@ struct BytecodeEmitter
|
|||
}
|
||||
|
||||
bool checkSingletonContext() {
|
||||
if (!parser->compileAndGo || sc->inFunction)
|
||||
if (!parser->compileAndGo || sc->inFunction())
|
||||
return false;
|
||||
for (StmtInfo *stmt = sc->topStmt; stmt; stmt = stmt->down) {
|
||||
if (STMT_IS_LOOP(stmt))
|
||||
|
|
|
@ -173,9 +173,9 @@ Parser::newObjectBox(JSObject *obj)
|
|||
FunctionBox::FunctionBox(ObjectBox* traceListHead, JSObject *obj, ParseNode *fn, TreeContext *tc)
|
||||
: ObjectBox(traceListHead, obj),
|
||||
node(fn),
|
||||
siblings(tc->sc->functionList),
|
||||
siblings(tc->functionList),
|
||||
kids(NULL),
|
||||
parent(tc->sc->funbox),
|
||||
parent(tc->sc->inFunction() ? tc->sc->funbox() : NULL),
|
||||
bindings(tc->sc->context),
|
||||
level(tc->sc->staticLevel),
|
||||
ndefaults(0),
|
||||
|
@ -192,7 +192,7 @@ FunctionBox::FunctionBox(ObjectBox* traceListHead, JSObject *obj, ParseNode *fn,
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (!tc->sc->inFunction) {
|
||||
if (!tc->sc->inFunction()) {
|
||||
JSObject *scope = tc->sc->scopeChain();
|
||||
while (scope) {
|
||||
if (scope->isWith())
|
||||
|
@ -221,7 +221,7 @@ Parser::newFunctionBox(JSObject *obj, ParseNode *fn, TreeContext *tc)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
traceListHead = tc->sc->functionList = funbox;
|
||||
traceListHead = tc->functionList = funbox;
|
||||
|
||||
return funbox;
|
||||
}
|
||||
|
@ -267,11 +267,10 @@ Parser::parse(JSObject *chain)
|
|||
* an object lock before it finishes generating bytecode into a script
|
||||
* protected from the GC by a root or a stack frame reference.
|
||||
*/
|
||||
SharedContext globalsc(context, /* inFunction = */ false);
|
||||
SharedContext globalsc(context, chain, /* fun = */ NULL, /* funbox = */ NULL);
|
||||
TreeContext globaltc(this, &globalsc);
|
||||
if (!globaltc.init())
|
||||
return NULL;
|
||||
globalsc.setScopeChain(chain);
|
||||
if (!GenerateBlockId(&globalsc, globalsc.bodyid))
|
||||
return NULL;
|
||||
|
||||
|
@ -432,7 +431,7 @@ ReportBadReturn(JSContext *cx, Parser *parser, ParseNode *pn, unsigned flags, un
|
|||
static JSBool
|
||||
CheckFinalReturn(JSContext *cx, Parser *parser, ParseNode *pn)
|
||||
{
|
||||
JS_ASSERT(parser->tc->sc->inFunction);
|
||||
JS_ASSERT(parser->tc->sc->inFunction());
|
||||
return HasFinalReturn(pn) == ENDS_IN_RETURN ||
|
||||
ReportBadReturn(cx, parser, pn, JSREPORT_WARNING | JSREPORT_STRICT,
|
||||
JSMSG_NO_RETURN_VALUE, JSMSG_ANON_NO_RETURN_VALUE);
|
||||
|
@ -505,7 +504,7 @@ static bool
|
|||
CheckStrictParameters(JSContext *cx, Parser *parser)
|
||||
{
|
||||
SharedContext *sc = parser->tc->sc;
|
||||
JS_ASSERT(sc->inFunction);
|
||||
JS_ASSERT(sc->inFunction());
|
||||
|
||||
if (!sc->needStrictChecks() || sc->bindings.numArgs() == 0)
|
||||
return true;
|
||||
|
@ -574,7 +573,7 @@ BindLocalVariable(JSContext *cx, SharedContext *sc, ParseNode *pn, BindingKind k
|
|||
ParseNode *
|
||||
Parser::functionBody(FunctionBodyType type)
|
||||
{
|
||||
JS_ASSERT(tc->sc->inFunction);
|
||||
JS_ASSERT(tc->sc->inFunction());
|
||||
|
||||
StmtInfo stmtInfo(context);
|
||||
PushStatement(tc->sc, &stmtInfo, STMT_BLOCK, -1);
|
||||
|
@ -734,7 +733,7 @@ Parser::functionBody(FunctionBodyType type)
|
|||
bool
|
||||
Parser::checkForArgumentsAndRest()
|
||||
{
|
||||
JS_ASSERT(!tc->sc->inFunction);
|
||||
JS_ASSERT(!tc->sc->inFunction());
|
||||
if (callerFrame && callerFrame->isFunctionFrame() && callerFrame->fun()->hasRest()) {
|
||||
PropertyName *arguments = context->runtime->atomState.argumentsAtom;
|
||||
for (AtomDefnRange r = tc->lexdeps->all(); !r.empty(); r.popFront()) {
|
||||
|
@ -992,7 +991,7 @@ static JSBool
|
|||
BindDestructuringArg(JSContext *cx, BindData *data, JSAtom *atom, Parser *parser)
|
||||
{
|
||||
TreeContext *tc = parser->tc;
|
||||
JS_ASSERT(tc->sc->inFunction);
|
||||
JS_ASSERT(tc->sc->inFunction());
|
||||
|
||||
/*
|
||||
* NB: Check tc->decls rather than tc->sc->bindings, because destructuring
|
||||
|
@ -1048,7 +1047,7 @@ Parser::newFunction(TreeContext *tc, JSAtom *atom, FunctionSyntaxKind kind)
|
|||
tc = tc->parent;
|
||||
|
||||
RootedObject parent(context);
|
||||
parent = tc->sc->inFunction ? NULL : tc->sc->scopeChain();
|
||||
parent = tc->sc->inFunction() ? NULL : tc->sc->scopeChain();
|
||||
|
||||
RootedFunction fun(context);
|
||||
fun = js_NewFunction(context, NULL, NULL, 0,
|
||||
|
@ -1080,31 +1079,17 @@ MatchOrInsertSemicolon(JSContext *cx, TokenStream *ts)
|
|||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static FunctionBox *
|
||||
EnterFunction(ParseNode *fn, Parser *parser, JSAtom *funAtom = NULL,
|
||||
FunctionSyntaxKind kind = Expression)
|
||||
static bool
|
||||
EnterFunction(SharedContext *outersc, SharedContext *funsc)
|
||||
{
|
||||
TreeContext *funtc = parser->tc;
|
||||
TreeContext *outertc = funtc->parent;
|
||||
JSFunction *fun = parser->newFunction(outertc, funAtom, kind);
|
||||
if (!fun)
|
||||
return NULL;
|
||||
/* Initialize non-default members of funsc. */
|
||||
funsc->blockidGen = outersc->blockidGen;
|
||||
if (!GenerateBlockId(funsc, funsc->bodyid))
|
||||
return false;
|
||||
if (!SetStaticLevel(funsc, outersc->staticLevel + 1))
|
||||
return false;
|
||||
|
||||
/* Create box for fun->object early to protect against last-ditch GC. */
|
||||
FunctionBox *funbox = parser->newFunctionBox(fun, fn, outertc);
|
||||
if (!funbox)
|
||||
return NULL;
|
||||
|
||||
/* Initialize non-default members of funtc->sc. */
|
||||
funtc->sc->blockidGen = outertc->sc->blockidGen;
|
||||
if (!GenerateBlockId(funtc->sc, funtc->sc->bodyid))
|
||||
return NULL;
|
||||
funtc->sc->setFunction(fun);
|
||||
funtc->sc->funbox = funbox;
|
||||
if (!SetStaticLevel(funtc->sc, outertc->sc->staticLevel + 1))
|
||||
return NULL;
|
||||
|
||||
return funbox;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -1293,7 +1278,7 @@ Parser::functionArguments(ParseNode **listp, bool &hasRest)
|
|||
return false;
|
||||
argsbody->setOp(JSOP_NOP);
|
||||
argsbody->makeEmpty();
|
||||
tc->sc->funbox->node->pn_body = argsbody;
|
||||
tc->sc->funbox()->node->pn_body = argsbody;
|
||||
|
||||
if (!tokenStream.matchToken(TOK_RP)) {
|
||||
bool hasDefaults = false;
|
||||
|
@ -1418,7 +1403,7 @@ Parser::functionArguments(ParseNode **listp, bool &hasRest)
|
|||
uint16_t slot;
|
||||
if (!tc->sc->bindings.addArgument(context, name, &slot))
|
||||
return false;
|
||||
if (!DefineArg(tc->sc->funbox->node, name, slot, this))
|
||||
if (!DefineArg(tc->sc->funbox()->node, name, slot, this))
|
||||
return false;
|
||||
|
||||
if (tokenStream.matchToken(TOK_ASSIGN)) {
|
||||
|
@ -1430,10 +1415,10 @@ Parser::functionArguments(ParseNode **listp, bool &hasRest)
|
|||
ParseNode *def_expr = assignExprWithoutYield(JSMSG_YIELD_IN_DEFAULT);
|
||||
if (!def_expr)
|
||||
return false;
|
||||
ParseNode *arg = tc->sc->funbox->node->pn_body->last();
|
||||
ParseNode *arg = tc->sc->funbox()->node->pn_body->last();
|
||||
arg->pn_dflags |= PND_DEFAULT;
|
||||
arg->pn_expr = def_expr;
|
||||
tc->sc->funbox->ndefaults++;
|
||||
tc->sc->funbox()->ndefaults++;
|
||||
} else if (!hasRest && hasDefaults) {
|
||||
reportErrorNumber(NULL, JSREPORT_ERROR, JSMSG_NONDEFAULT_FORMAL_AFTER_DEFAULT);
|
||||
return false;
|
||||
|
@ -1552,7 +1537,7 @@ Parser::functionDef(HandlePropertyName funName, FunctionType type, FunctionSynta
|
|||
* when BytecodeEmitter.cpp's BindNameToSlot can optimize a JSOP_NAME
|
||||
* into a JSOP_GETLOCAL bytecode).
|
||||
*/
|
||||
if (bodyLevel && tc->sc->inFunction) {
|
||||
if (bodyLevel && tc->sc->inFunction()) {
|
||||
/*
|
||||
* Define a local in the outer function so that BindNameToSlot
|
||||
* can properly optimize accesses. Note that we need a local
|
||||
|
@ -1581,21 +1566,27 @@ Parser::functionDef(HandlePropertyName funName, FunctionType type, FunctionSynta
|
|||
|
||||
TreeContext *outertc = tc;
|
||||
|
||||
RootedFunction fun(context, newFunction(outertc, funName, kind));
|
||||
if (!fun)
|
||||
return NULL;
|
||||
|
||||
/* Create box for fun->object early to protect against last-ditch GC. */
|
||||
FunctionBox *funbox = newFunctionBox(fun, pn, outertc);
|
||||
if (!funbox)
|
||||
return NULL;
|
||||
|
||||
/* Initialize early for possible flags mutation via destructuringExpr. */
|
||||
SharedContext funsc(context, /* inFunction = */ true);
|
||||
SharedContext funsc(context, /* scopeChain = */ NULL, fun, funbox);
|
||||
TreeContext funtc(this, &funsc);
|
||||
if (!funtc.init())
|
||||
return NULL;
|
||||
|
||||
FunctionBox *funbox = EnterFunction(pn, this, funName, kind);
|
||||
if (!funbox)
|
||||
if (!EnterFunction(outertc->sc, &funsc))
|
||||
return NULL;
|
||||
|
||||
if (outertc->sc->inStrictMode())
|
||||
funsc.setInStrictMode(); // inherit strict mode from parent
|
||||
|
||||
RootedFunction fun(context, funbox->function());
|
||||
|
||||
/* Now parse formal argument list and compute fun->nargs. */
|
||||
ParseNode *prelude = NULL;
|
||||
bool hasRest;
|
||||
|
@ -1757,14 +1748,14 @@ Parser::functionDef(HandlePropertyName funName, FunctionType type, FunctionSynta
|
|||
}
|
||||
}
|
||||
|
||||
funbox->kids = funsc.functionList;
|
||||
funbox->kids = funtc.functionList;
|
||||
|
||||
pn->pn_funbox = funbox;
|
||||
pn->setOp(op);
|
||||
pn->pn_body->append(body);
|
||||
pn->pn_body->pn_pos = body->pn_pos;
|
||||
|
||||
JS_ASSERT_IF(!outertc->sc->inFunction && bodyLevel && kind == Statement,
|
||||
JS_ASSERT_IF(!outertc->sc->inFunction() && bodyLevel && kind == Statement,
|
||||
pn->pn_cookie.isFree());
|
||||
|
||||
pn->pn_blockid = outertc->sc->blockid();
|
||||
|
@ -2123,7 +2114,7 @@ OuterLet(SharedContext *sc, StmtInfo *stmt, JSAtom *atom)
|
|||
static bool
|
||||
BindFunctionLocal(JSContext *cx, BindData *data, MultiDeclRange &mdl, SharedContext *sc)
|
||||
{
|
||||
JS_ASSERT(sc->inFunction);
|
||||
JS_ASSERT(sc->inFunction());
|
||||
|
||||
ParseNode *pn = data->pn;
|
||||
JSAtom *name = pn->pn_atom;
|
||||
|
@ -2146,7 +2137,7 @@ BindFunctionLocal(JSContext *cx, BindData *data, MultiDeclRange &mdl, SharedCont
|
|||
}
|
||||
|
||||
if (kind == ARGUMENT) {
|
||||
JS_ASSERT(sc->inFunction);
|
||||
JS_ASSERT(sc->inFunction());
|
||||
JS_ASSERT(!mdl.empty() && mdl.front()->kind() == Definition::ARG);
|
||||
} else {
|
||||
JS_ASSERT(kind == VARIABLE || kind == CONSTANT);
|
||||
|
@ -2299,7 +2290,7 @@ BindVarOrConst(JSContext *cx, BindData *data, JSAtom *atom, Parser *parser)
|
|||
if (data->op == JSOP_DEFCONST)
|
||||
pn->pn_dflags |= PND_CONST;
|
||||
|
||||
if (tc->sc->inFunction)
|
||||
if (tc->sc->inFunction())
|
||||
return BindFunctionLocal(cx, data, mdl, tc->sc);
|
||||
|
||||
return true;
|
||||
|
@ -2355,7 +2346,7 @@ NoteLValue(JSContext *cx, ParseNode *pn, SharedContext *sc, unsigned dflag = PND
|
|||
* mode, we must have a binding for it in the scope chain; we ensure this
|
||||
* happens by making such functions heavyweight.
|
||||
*/
|
||||
if (sc->inFunction && pn->pn_atom == sc->fun()->atom)
|
||||
if (sc->inFunction() && pn->pn_atom == sc->fun()->atom)
|
||||
sc->setFunIsHeavyweight();
|
||||
}
|
||||
|
||||
|
@ -2691,7 +2682,7 @@ ParseNode *
|
|||
Parser::returnOrYield(bool useAssignExpr)
|
||||
{
|
||||
TokenKind tt = tokenStream.currentToken().type;
|
||||
if (!tc->sc->inFunction) {
|
||||
if (!tc->sc->inFunction()) {
|
||||
reportErrorNumber(NULL, JSREPORT_ERROR, JSMSG_BAD_RETURN_OR_YIELD,
|
||||
(tt == TOK_RETURN) ? js_return_str : js_yield_str);
|
||||
return NULL;
|
||||
|
@ -3160,7 +3151,7 @@ Parser::forStatement()
|
|||
* expressions involving an 'in' operator are illegal in the init
|
||||
* clause of an ordinary for loop.
|
||||
*/
|
||||
tc->sc->inForInit = true;
|
||||
tc->inForInit = true;
|
||||
if (tt == TOK_VAR || tt == TOK_CONST) {
|
||||
forDecl = true;
|
||||
tokenStream.consumeKnownToken(tt);
|
||||
|
@ -3183,7 +3174,7 @@ Parser::forStatement()
|
|||
else {
|
||||
pn1 = expr();
|
||||
}
|
||||
tc->sc->inForInit = false;
|
||||
tc->inForInit = false;
|
||||
if (!pn1)
|
||||
return NULL;
|
||||
}
|
||||
|
@ -3201,7 +3192,7 @@ Parser::forStatement()
|
|||
* We can be sure that it's a for/in loop if there's still an 'in'
|
||||
* keyword here, even if JavaScript recognizes 'in' as an operator,
|
||||
* as we've excluded 'in' from being parsed in RelExpr by setting
|
||||
* tc->sc->inForInit.
|
||||
* tc->inForInit.
|
||||
*/
|
||||
ParseNode *forHead; /* initialized by both branches. */
|
||||
StmtInfo letStmt(context); /* used if blockObj != NULL. */
|
||||
|
@ -4264,7 +4255,7 @@ Parser::variables(ParseNodeKind kind, StaticBlockObject *blockObj, VarContext va
|
|||
if (!CheckDestructuring(context, &data, pn2, this))
|
||||
return NULL;
|
||||
bool ignored;
|
||||
if (tc->sc->inForInit && matchInOrOf(&ignored)) {
|
||||
if (tc->inForInit && matchInOrOf(&ignored)) {
|
||||
tokenStream.ungetToken();
|
||||
pn->append(pn2);
|
||||
continue;
|
||||
|
@ -4471,8 +4462,8 @@ BEGIN_EXPR_PARSER(relExpr1)
|
|||
* Uses of the in operator in shiftExprs are always unambiguous,
|
||||
* so unset the flag that prohibits recognizing it.
|
||||
*/
|
||||
bool oldInForInit = tc->sc->inForInit;
|
||||
tc->sc->inForInit = false;
|
||||
bool oldInForInit = tc->inForInit;
|
||||
tc->inForInit = false;
|
||||
|
||||
ParseNode *pn = shiftExpr1i();
|
||||
while (pn &&
|
||||
|
@ -4488,7 +4479,7 @@ BEGIN_EXPR_PARSER(relExpr1)
|
|||
pn = ParseNode::newBinaryOrAppend(kind, op, pn, shiftExpr1n(), this);
|
||||
}
|
||||
/* Restore previous state of inForInit flag. */
|
||||
tc->sc->inForInit |= oldInForInit;
|
||||
tc->inForInit |= oldInForInit;
|
||||
|
||||
return pn;
|
||||
}
|
||||
|
@ -4582,10 +4573,10 @@ Parser::condExpr1()
|
|||
* where it's unambiguous, even if we might be parsing the init of a
|
||||
* for statement.
|
||||
*/
|
||||
bool oldInForInit = tc->sc->inForInit;
|
||||
tc->sc->inForInit = false;
|
||||
bool oldInForInit = tc->inForInit;
|
||||
tc->inForInit = false;
|
||||
ParseNode *thenExpr = assignExpr();
|
||||
tc->sc->inForInit = oldInForInit;
|
||||
tc->inForInit = oldInForInit;
|
||||
if (!thenExpr)
|
||||
return NULL;
|
||||
|
||||
|
@ -5007,7 +4998,7 @@ GenexpGuard::maybeNoteGenerator(ParseNode *pn)
|
|||
TreeContext *tc = parser->tc;
|
||||
if (tc->yieldCount > 0) {
|
||||
tc->sc->setFunIsGenerator();
|
||||
if (!tc->sc->inFunction) {
|
||||
if (!tc->sc->inFunction()) {
|
||||
parser->reportErrorNumber(NULL, JSREPORT_ERROR, JSMSG_BAD_RETURN_OR_YIELD,
|
||||
js_yield_str);
|
||||
return false;
|
||||
|
@ -5112,9 +5103,9 @@ CompExprTransplanter::transplant(ParseNode *pn)
|
|||
|
||||
funbox->level = tc->sc->staticLevel + funcLevel;
|
||||
if (++funcLevel == 1 && genexp) {
|
||||
FunctionBox *parent = tc->sc->funbox;
|
||||
FunctionBox *parent = tc->sc->funbox();
|
||||
|
||||
FunctionBox **funboxp = &tc->parent->sc->functionList;
|
||||
FunctionBox **funboxp = &tc->parent->functionList;
|
||||
while (*funboxp != funbox)
|
||||
funboxp = &(*funboxp)->siblings;
|
||||
*funboxp = funbox->siblings;
|
||||
|
@ -5499,13 +5490,22 @@ Parser::generatorExpr(ParseNode *kid)
|
|||
|
||||
{
|
||||
TreeContext *outertc = tc;
|
||||
SharedContext gensc(context, /* inFunction = */ true);
|
||||
|
||||
RootedFunction fun(context, newFunction(outertc, /* atom = */ NULL, Expression));
|
||||
if (!fun)
|
||||
return NULL;
|
||||
|
||||
/* Create box for fun->object early to protect against last-ditch GC. */
|
||||
FunctionBox *funbox = newFunctionBox(fun, genfn, outertc);
|
||||
if (!funbox)
|
||||
return NULL;
|
||||
|
||||
SharedContext gensc(context, /* scopeChain = */ NULL, fun, funbox);
|
||||
TreeContext gentc(this, &gensc);
|
||||
if (!gentc.init())
|
||||
return NULL;
|
||||
|
||||
FunctionBox *funbox = EnterFunction(genfn, this);
|
||||
if (!funbox)
|
||||
if (!EnterFunction(outertc->sc, &gensc))
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
|
@ -5874,10 +5874,10 @@ Parser::bracketedExpr()
|
|||
* where it's unambiguous, even if we might be parsing the init of a
|
||||
* for statement.
|
||||
*/
|
||||
bool oldInForInit = tc->sc->inForInit;
|
||||
tc->sc->inForInit = false;
|
||||
bool oldInForInit = tc->inForInit;
|
||||
tc->inForInit = false;
|
||||
ParseNode *pn = expr();
|
||||
tc->sc->inForInit = oldInForInit;
|
||||
tc->inForInit = oldInForInit;
|
||||
return pn;
|
||||
}
|
||||
|
||||
|
@ -6477,12 +6477,11 @@ Parser::parseXMLText(JSObject *chain, bool allowList)
|
|||
* lightweight function activation, or if its scope chain doesn't match
|
||||
* the one passed to us.
|
||||
*/
|
||||
SharedContext xmlsc(context, /* inFunction = */ false);
|
||||
SharedContext xmlsc(context, chain, /* fun = */ NULL, /* funbox = */ NULL);
|
||||
TreeContext xmltc(this, &xmlsc);
|
||||
if (!xmltc.init())
|
||||
return NULL;
|
||||
JS_ASSERT(!xmlsc.inStrictMode());
|
||||
xmlsc.setScopeChain(chain);
|
||||
|
||||
/* Set XML-only mode to turn off special treatment of {expr} in XML. */
|
||||
tokenStream.setXMLOnlyMode();
|
||||
|
|
|
@ -160,14 +160,15 @@ MarkExtensibleScopeDescendants(JSContext *context, FunctionBox *funbox, bool has
|
|||
bool
|
||||
frontend::AnalyzeFunctions(Parser *parser)
|
||||
{
|
||||
SharedContext *sc = parser->tc->sc;
|
||||
if (!sc->functionList)
|
||||
TreeContext *tc = parser->tc;
|
||||
SharedContext *sc = tc->sc;
|
||||
if (!tc->functionList)
|
||||
return true;
|
||||
if (!MarkExtensibleScopeDescendants(sc->context, sc->functionList, false))
|
||||
if (!MarkExtensibleScopeDescendants(sc->context, tc->functionList, false))
|
||||
return false;
|
||||
bool isDirectEval = !!parser->callerFrame;
|
||||
bool isHeavyweight = false;
|
||||
SetFunctionKinds(sc->functionList, &isHeavyweight, sc->inFunction, isDirectEval);
|
||||
SetFunctionKinds(tc->functionList, &isHeavyweight, sc->inFunction(), isDirectEval);
|
||||
if (isHeavyweight)
|
||||
sc->setFunIsHeavyweight();
|
||||
return true;
|
||||
|
|
|
@ -16,24 +16,23 @@
|
|||
namespace js {
|
||||
|
||||
inline
|
||||
SharedContext::SharedContext(JSContext *cx, bool inFunction)
|
||||
SharedContext::SharedContext(JSContext *cx, JSObject *scopeChain, JSFunction *fun,
|
||||
FunctionBox *funbox)
|
||||
: context(cx),
|
||||
bodyid(0),
|
||||
blockidGen(0),
|
||||
topStmt(NULL),
|
||||
topScopeStmt(NULL),
|
||||
blockChain(cx),
|
||||
fun_(cx),
|
||||
scopeChain_(cx),
|
||||
fun_(cx, fun),
|
||||
funbox_(funbox),
|
||||
scopeChain_(cx, scopeChain),
|
||||
staticLevel(0),
|
||||
funbox(NULL),
|
||||
functionList(NULL),
|
||||
bindings(cx),
|
||||
bindingsRoot(cx, &bindings),
|
||||
inFunction(inFunction),
|
||||
inForInit(false),
|
||||
cxFlags(cx)
|
||||
{
|
||||
JS_ASSERT((fun && !scopeChain_) || (!fun && !funbox));
|
||||
}
|
||||
|
||||
inline unsigned
|
||||
|
@ -70,6 +69,7 @@ TreeContext::TreeContext(Parser *prs, SharedContext *sc)
|
|||
blockNode(NULL),
|
||||
decls(prs->context),
|
||||
yieldNode(NULL),
|
||||
functionList(NULL),
|
||||
parserTC(&prs->tc),
|
||||
lexdeps(prs->context),
|
||||
parent(prs->tc),
|
||||
|
@ -77,6 +77,7 @@ TreeContext::TreeContext(Parser *prs, SharedContext *sc)
|
|||
funcStmts(NULL),
|
||||
hasReturnExpr(false),
|
||||
hasReturnVoid(false),
|
||||
inForInit(false),
|
||||
inDeclDestructuring(false)
|
||||
{
|
||||
prs->tc = this;
|
||||
|
|
|
@ -43,8 +43,7 @@ bool
|
|||
frontend::GenerateBlockId(SharedContext *sc, uint32_t &blockid)
|
||||
{
|
||||
if (sc->blockidGen == JS_BIT(20)) {
|
||||
JS_ReportErrorNumber(sc->context, js_GetErrorMessage, NULL,
|
||||
JSMSG_NEED_DIET, "program");
|
||||
JS_ReportErrorNumber(sc->context, js_GetErrorMessage, NULL, JSMSG_NEED_DIET, "program");
|
||||
return false;
|
||||
}
|
||||
blockid = sc->blockidGen++;
|
||||
|
|
|
@ -61,10 +61,6 @@ class ContextFlags {
|
|||
//
|
||||
bool bindingsAccessedDynamically:1;
|
||||
|
||||
// The |fun*| flags are only relevant if |inFunction| is true. Due to
|
||||
// sloppiness, however, some are set in cases where |inFunction| is
|
||||
// false.
|
||||
|
||||
// The function needs Call object per call.
|
||||
bool funIsHeavyweight:1;
|
||||
|
||||
|
@ -145,67 +141,61 @@ struct SharedContext {
|
|||
chain when in head of let block/expr) */
|
||||
|
||||
private:
|
||||
RootedFunction fun_; /* function to store argument and variable
|
||||
names when inFunction is set */
|
||||
RootedObject scopeChain_; /* scope chain object for the script */
|
||||
const RootedFunction fun_; /* function to store argument and variable
|
||||
names when it's a function's context */
|
||||
FunctionBox *const funbox_; /* null or box for function we're compiling
|
||||
if inFunction() is true and not in
|
||||
js::frontend::CompileFunctionBody */
|
||||
|
||||
const RootedObject scopeChain_; /* scope chain object for the script */
|
||||
|
||||
public:
|
||||
unsigned staticLevel; /* static compilation unit nesting level */
|
||||
|
||||
FunctionBox *funbox; /* null or box for function we're compiling
|
||||
if inFunction is set and not in
|
||||
js::frontend::CompileFunctionBody */
|
||||
FunctionBox *functionList;
|
||||
|
||||
Bindings bindings; /* bindings in this code, including
|
||||
arguments if we're compiling a function */
|
||||
Bindings::AutoRooter bindingsRoot; /* root for stack allocated bindings. */
|
||||
|
||||
const bool inFunction:1; /* parsing/emitting inside function body */
|
||||
|
||||
bool inForInit:1; /* parsing/emitting init expr of for; exclude 'in' */
|
||||
|
||||
ContextFlags cxFlags;
|
||||
|
||||
inline SharedContext(JSContext *cx, bool inFunction);
|
||||
// If it's function code, fun must be non-NULL and scopeChain must be NULL.
|
||||
// If it's global code, fun and funbox must be NULL.
|
||||
inline SharedContext(JSContext *cx, JSObject *scopeChain, JSFunction *fun, FunctionBox *funbox);
|
||||
|
||||
bool inStrictMode() const { return cxFlags.inStrictMode; }
|
||||
bool bindingsAccessedDynamically() const { return cxFlags.bindingsAccessedDynamically; }
|
||||
bool funIsHeavyweight() const { return cxFlags.funIsHeavyweight; }
|
||||
bool funIsGenerator() const { return cxFlags.funIsGenerator; }
|
||||
bool funMightAliasLocals() const { return cxFlags.funMightAliasLocals; }
|
||||
bool funHasExtensibleScope() const { return cxFlags.funHasExtensibleScope; }
|
||||
bool funArgumentsHasLocalBinding() const { return cxFlags.funArgumentsHasLocalBinding; }
|
||||
bool funDefinitelyNeedsArgsObj() const { return cxFlags.funDefinitelyNeedsArgsObj; }
|
||||
// In theory, |fun*| flags are only relevant if |inFunction()| is true.
|
||||
// However, we get and set in some cases where |inFunction()| is false,
|
||||
// which is why |INFUNC| doesn't appear in all of the fun* and setFun*
|
||||
// functions below.
|
||||
#define INFUNC JS_ASSERT(inFunction())
|
||||
|
||||
void setInStrictMode() { cxFlags.inStrictMode = true; }
|
||||
void setBindingsAccessedDynamically() { cxFlags.bindingsAccessedDynamically = true; }
|
||||
void setFunIsHeavyweight() { cxFlags.funIsHeavyweight = true; }
|
||||
void setFunIsGenerator() { cxFlags.funIsGenerator = true; }
|
||||
void setFunMightAliasLocals() { cxFlags.funMightAliasLocals = true; }
|
||||
void setFunHasExtensibleScope() { cxFlags.funHasExtensibleScope = true; }
|
||||
void setFunArgumentsHasLocalBinding() { cxFlags.funArgumentsHasLocalBinding = true; }
|
||||
bool inStrictMode() const { return cxFlags.inStrictMode; }
|
||||
bool bindingsAccessedDynamically() const { return cxFlags.bindingsAccessedDynamically; }
|
||||
bool funIsHeavyweight() const { INFUNC; return cxFlags.funIsHeavyweight; }
|
||||
bool funIsGenerator() const { INFUNC; return cxFlags.funIsGenerator; }
|
||||
bool funMightAliasLocals() const { return cxFlags.funMightAliasLocals; }
|
||||
bool funHasExtensibleScope() const { return cxFlags.funHasExtensibleScope; }
|
||||
bool funArgumentsHasLocalBinding() const { INFUNC; return cxFlags.funArgumentsHasLocalBinding; }
|
||||
bool funDefinitelyNeedsArgsObj() const { INFUNC; return cxFlags.funDefinitelyNeedsArgsObj; }
|
||||
|
||||
void setInStrictMode() { cxFlags.inStrictMode = true; }
|
||||
void setBindingsAccessedDynamically() { cxFlags.bindingsAccessedDynamically = true; }
|
||||
void setFunIsHeavyweight() { cxFlags.funIsHeavyweight = true; }
|
||||
void setFunIsGenerator() { INFUNC; cxFlags.funIsGenerator = true; }
|
||||
void setFunMightAliasLocals() { cxFlags.funMightAliasLocals = true; }
|
||||
void setFunHasExtensibleScope() { cxFlags.funHasExtensibleScope = true; }
|
||||
void setFunArgumentsHasLocalBinding() { INFUNC; cxFlags.funArgumentsHasLocalBinding = true; }
|
||||
void setFunDefinitelyNeedsArgsObj() { JS_ASSERT(cxFlags.funArgumentsHasLocalBinding);
|
||||
cxFlags.funDefinitelyNeedsArgsObj = true; }
|
||||
INFUNC; cxFlags.funDefinitelyNeedsArgsObj = true; }
|
||||
|
||||
#undef INFUNC
|
||||
|
||||
unsigned argumentsLocalSlot() const;
|
||||
|
||||
JSFunction *fun() const {
|
||||
JS_ASSERT(inFunction);
|
||||
return fun_;
|
||||
}
|
||||
void setFunction(JSFunction *fun) {
|
||||
JS_ASSERT(inFunction);
|
||||
fun_ = fun;
|
||||
}
|
||||
JSObject *scopeChain() const {
|
||||
JS_ASSERT(!inFunction);
|
||||
return scopeChain_;
|
||||
}
|
||||
void setScopeChain(JSObject *scopeChain) {
|
||||
JS_ASSERT(!inFunction);
|
||||
scopeChain_ = scopeChain;
|
||||
}
|
||||
bool inFunction() const { return !!fun_; }
|
||||
|
||||
JSFunction *fun() const { JS_ASSERT(inFunction()); return fun_; }
|
||||
FunctionBox *funbox() const { JS_ASSERT(inFunction()); return funbox_; }
|
||||
JSObject *scopeChain() const { JS_ASSERT(!inFunction()); return scopeChain_; }
|
||||
|
||||
unsigned blockid();
|
||||
|
||||
|
@ -239,6 +229,7 @@ struct TreeContext { /* tree context for semantic checks */
|
|||
ParseNode *yieldNode; /* parse node for a yield expression that might
|
||||
be an error if we turn out to be inside a
|
||||
generator expression */
|
||||
FunctionBox *functionList;
|
||||
|
||||
private:
|
||||
TreeContext **parserTC; /* this points to the Parser's active tc
|
||||
|
@ -263,6 +254,8 @@ struct TreeContext { /* tree context for semantic checks */
|
|||
bool hasReturnExpr:1; /* function has 'return <expr>;' */
|
||||
bool hasReturnVoid:1; /* function has 'return;' */
|
||||
|
||||
bool inForInit:1; /* parsing init expr of for; exclude 'in' */
|
||||
|
||||
// Set when parsing a declaration-like destructuring pattern. This flag
|
||||
// causes PrimaryExpr to create PN_NAME parse nodes for variable references
|
||||
// which are not hooked into any definition's use chain, added to any tree
|
||||
|
|
|
@ -1246,7 +1246,7 @@ JSScript::NewScriptFromEmitter(JSContext *cx, BytecodeEmitter *bce)
|
|||
script->mainOffset = prologLength;
|
||||
PodCopy<jsbytecode>(script->code, bce->prologBase(), prologLength);
|
||||
PodCopy<jsbytecode>(script->main(), bce->base(), mainLength);
|
||||
nfixed = bce->sc->inFunction ? bce->sc->bindings.numVars() : 0;
|
||||
nfixed = bce->sc->inFunction() ? bce->sc->bindings.numVars() : 0;
|
||||
JS_ASSERT(nfixed < SLOTNO_LIMIT);
|
||||
script->nfixed = uint16_t(nfixed);
|
||||
InitAtomMap(cx, bce->atomIndices.getMap(), script->atoms);
|
||||
|
@ -1309,7 +1309,7 @@ JSScript::NewScriptFromEmitter(JSContext *cx, BytecodeEmitter *bce)
|
|||
script->debugMode = true;
|
||||
#endif
|
||||
|
||||
if (bce->sc->inFunction) {
|
||||
if (bce->sc->inFunction()) {
|
||||
if (bce->sc->funArgumentsHasLocalBinding()) {
|
||||
// This must precede the script->bindings.transfer() call below.
|
||||
script->setArgumentsHasLocalBinding(bce->sc->argumentsLocalSlot());
|
||||
|
@ -1318,9 +1318,6 @@ JSScript::NewScriptFromEmitter(JSContext *cx, BytecodeEmitter *bce)
|
|||
} else {
|
||||
JS_ASSERT(!bce->sc->funDefinitelyNeedsArgsObj());
|
||||
}
|
||||
} else {
|
||||
JS_ASSERT(!bce->sc->funArgumentsHasLocalBinding());
|
||||
JS_ASSERT(!bce->sc->funDefinitelyNeedsArgsObj());
|
||||
}
|
||||
|
||||
if (nClosedArgs)
|
||||
|
@ -1331,7 +1328,7 @@ JSScript::NewScriptFromEmitter(JSContext *cx, BytecodeEmitter *bce)
|
|||
script->bindings.transfer(cx, &bce->sc->bindings);
|
||||
|
||||
fun = NULL;
|
||||
if (bce->sc->inFunction) {
|
||||
if (bce->sc->inFunction()) {
|
||||
JS_ASSERT(!bce->noScriptRval);
|
||||
JS_ASSERT(!bce->needScriptGlobal);
|
||||
|
||||
|
@ -1362,10 +1359,6 @@ JSScript::NewScriptFromEmitter(JSContext *cx, BytecodeEmitter *bce)
|
|||
script->globalObject = fun->getParent() ? &fun->getParent()->global() : NULL;
|
||||
|
||||
} else {
|
||||
// It'd be nice to JS_ASSERT(!bce->sc->funIsHeavyweight()) here, but
|
||||
// Parser.cpp is sloppy and sometimes applies it to non-functions.
|
||||
JS_ASSERT(!bce->sc->funIsGenerator());
|
||||
|
||||
/*
|
||||
* Initialize script->object, if necessary, so that the debugger has a
|
||||
* valid holder object.
|
||||
|
|
|
@ -238,7 +238,7 @@ UnwrapObject(JSObject *obj, bool stopAtOuter = true, unsigned *flagsp = NULL);
|
|||
JS_FRIEND_API(JSObject *)
|
||||
UnwrapObjectChecked(JSContext *cx, JSObject *obj);
|
||||
|
||||
bool
|
||||
JS_FRIEND_API(bool)
|
||||
IsCrossCompartmentWrapper(const JSObject *obj);
|
||||
|
||||
void
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2008 the V8 project authors. All rights reserved.
|
||||
// Copyright 2012 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
|
@ -78,7 +78,7 @@ BenchmarkSuite.suites = [];
|
|||
// Scores are not comparable across versions. Bump the version if
|
||||
// you're making changes that will affect that scores, e.g. if you add
|
||||
// a new benchmark or change an existing one.
|
||||
BenchmarkSuite.version = '6';
|
||||
BenchmarkSuite.version = '7';
|
||||
|
||||
|
||||
// To make the benchmark results predictable, we replace Math.random
|
||||
|
|
|
@ -1406,7 +1406,7 @@ function rng_seed_int(x) {
|
|||
|
||||
// Mix in the current time (w/milliseconds) into the pool
|
||||
function rng_seed_time() {
|
||||
// Use pre-computed date to avoid making the benchmark
|
||||
// Use pre-computed date to avoid making the benchmark
|
||||
// results dependent on the current date.
|
||||
rng_seed_int(1122926989487);
|
||||
}
|
||||
|
|
|
@ -134,7 +134,7 @@ function sc_rempropBang(sym, key) {
|
|||
/*** META ((export #t)) */
|
||||
function sc_any2String(o) {
|
||||
return jsstring2string(sc_toDisplayString(o));
|
||||
}
|
||||
}
|
||||
|
||||
/*** META ((export #t)
|
||||
(peephole (infix 2 2 "==="))
|
||||
|
@ -923,7 +923,7 @@ function sc_dualAppendBang(l1, l2) {
|
|||
tmp.cdr = l2;
|
||||
return l1;
|
||||
}
|
||||
|
||||
|
||||
/*** META ((export #t)) */
|
||||
function sc_appendBang() {
|
||||
var res = null;
|
||||
|
@ -1163,7 +1163,7 @@ sc_Char.readable2char = {
|
|||
"us": "\037",
|
||||
"sp": "\040",
|
||||
"del": "\177"};
|
||||
|
||||
|
||||
sc_Char.prototype.toString = function() {
|
||||
return this.val;
|
||||
};
|
||||
|
@ -1533,7 +1533,7 @@ function sc_mapBang(proc, l1) {
|
|||
}
|
||||
return l1_orig;
|
||||
}
|
||||
|
||||
|
||||
/*** META ((export #t)) */
|
||||
function sc_forEach(proc, l1) {
|
||||
if (l1 === undefined)
|
||||
|
@ -1871,7 +1871,7 @@ function sc_jsNew(c) {
|
|||
evalStr += ", arguments[" + i + "]";
|
||||
evalStr +=")";
|
||||
return eval(evalStr);
|
||||
}
|
||||
}
|
||||
|
||||
// ======================== RegExp ====================
|
||||
/*** META ((export #t)) */
|
||||
|
@ -1883,9 +1883,9 @@ function sc_pregexp(re) {
|
|||
function sc_pregexpMatch(re, s) {
|
||||
var reg = (re instanceof RegExp) ? re : sc_pregexp(re);
|
||||
var tmp = reg.exec(sc_string2jsstring(s));
|
||||
|
||||
|
||||
if (tmp == null) return false;
|
||||
|
||||
|
||||
var res = null;
|
||||
for (var i = tmp.length-1; i >= 0; i--) {
|
||||
if (tmp[i] !== null) {
|
||||
|
@ -1896,7 +1896,7 @@ function sc_pregexpMatch(re, s) {
|
|||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/*** META ((export #t)) */
|
||||
function sc_pregexpReplace(re, s1, s2) {
|
||||
var reg;
|
||||
|
@ -1914,7 +1914,7 @@ function sc_pregexpReplace(re, s1, s2) {
|
|||
|
||||
return jss1.replace(reg, jss2);
|
||||
}
|
||||
|
||||
|
||||
/*** META ((export pregexp-replace*)) */
|
||||
function sc_pregexpReplaceAll(re, s1, s2) {
|
||||
var reg;
|
||||
|
@ -1945,7 +1945,7 @@ function sc_pregexpSplit(re, s) {
|
|||
|
||||
return sc_vector2list(tmp);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* =========================================================================== */
|
||||
/* Other library stuff */
|
||||
|
@ -2136,7 +2136,7 @@ sc_ErrorInputPort.prototype.getNextChar = function() {
|
|||
sc_ErrorInputPort.prototype.isCharReady = function() {
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* .............. String port ..........................*/
|
||||
|
||||
|
@ -2200,7 +2200,7 @@ sc_Tokenizer.prototype.readToken = function() {
|
|||
};
|
||||
sc_Tokenizer.prototype.nextToken = function() {
|
||||
var port = this.port;
|
||||
|
||||
|
||||
function isNumberChar(c) {
|
||||
return (c >= "0" && c <= "9");
|
||||
};
|
||||
|
@ -2280,7 +2280,7 @@ sc_Tokenizer.prototype.nextToken = function() {
|
|||
else
|
||||
return new sc_Token(12/*NUMBER*/, res - 0);
|
||||
};
|
||||
|
||||
|
||||
function skipWhitespaceAndComments() {
|
||||
var done = false;
|
||||
while (!done) {
|
||||
|
@ -2299,7 +2299,7 @@ sc_Tokenizer.prototype.nextToken = function() {
|
|||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
function readDot() {
|
||||
if (isWhitespace(port.peekChar()))
|
||||
return new sc_Token(10/*DOT*/);
|
||||
|
@ -2429,7 +2429,7 @@ sc_Reader.prototype.read = function() {
|
|||
|
||||
while (true) {
|
||||
var token = tokenizer.peekToken();
|
||||
|
||||
|
||||
switch (token.type) {
|
||||
case 2/*CLOSE_PAR*/:
|
||||
case 4/*CLOSE_BRACE*/:
|
||||
|
@ -2491,7 +2491,7 @@ sc_Reader.prototype.read = function() {
|
|||
else
|
||||
throw "bad reference: " + nb;
|
||||
};
|
||||
|
||||
|
||||
var tokenizer = this.tokenizer;
|
||||
|
||||
var token = tokenizer.readToken();
|
||||
|
@ -2499,7 +2499,7 @@ sc_Reader.prototype.read = function() {
|
|||
// handle error
|
||||
if (token.type === 13/*ERROR*/)
|
||||
throw token.val;
|
||||
|
||||
|
||||
switch (token.type) {
|
||||
case 1/*OPEN_PAR*/:
|
||||
case 3/*OPEN_BRACE*/:
|
||||
|
@ -2550,7 +2550,7 @@ function sc_peekChar(port) {
|
|||
port = SC_DEFAULT_IN; // THREAD: shared var...
|
||||
var t = port.peekChar();
|
||||
return t === SC_EOF_OBJECT? t: new sc_Char(t);
|
||||
}
|
||||
}
|
||||
/*** META ((export #t)
|
||||
(type bool))
|
||||
*/
|
||||
|
@ -2722,7 +2722,7 @@ sc_StringOutputPort.prototype.close = function() {
|
|||
function sc_getOutputString(sp) {
|
||||
return sc_jsstring2string(sp.res);
|
||||
}
|
||||
|
||||
|
||||
|
||||
function sc_ErrorOutputPort() {
|
||||
}
|
||||
|
@ -2852,7 +2852,7 @@ function sc_newline(p) {
|
|||
p = SC_DEFAULT_OUT;
|
||||
p.appendJSString("\n");
|
||||
}
|
||||
|
||||
|
||||
/* ------------------ write-char ---------------------------------------------------*/
|
||||
|
||||
/*** META ((export #t)) */
|
||||
|
@ -2927,7 +2927,7 @@ sc_Pair.prototype.sc_toWriteCircleString = function(symb, inList) {
|
|||
}
|
||||
|
||||
var res = "";
|
||||
|
||||
|
||||
if (this[symb] !== undefined) { // implies > 0
|
||||
this[symb + "use"] = true;
|
||||
if (inList)
|
||||
|
@ -2939,10 +2939,10 @@ sc_Pair.prototype.sc_toWriteCircleString = function(symb, inList) {
|
|||
|
||||
if (!inList)
|
||||
res += "(";
|
||||
|
||||
|
||||
// print car
|
||||
res += sc_genToWriteCircleString(this.car, symb);
|
||||
|
||||
|
||||
if (sc_isPair(this.cdr)) {
|
||||
res += " " + this.cdr.sc_toWriteCircleString(symb, true);
|
||||
} else if (this.cdr !== null) {
|
||||
|
@ -3072,7 +3072,7 @@ function sc_format(s, args) {
|
|||
p.appendJSString(arguments[j].toString(2));
|
||||
i += 2; j++;
|
||||
break;
|
||||
|
||||
|
||||
case 37:
|
||||
case 110:
|
||||
// %, n
|
||||
|
@ -3186,7 +3186,7 @@ function sc_isEqual(o1, o2) {
|
|||
function sc_number2symbol(x, radix) {
|
||||
return sc_SYMBOL_PREFIX + sc_number2jsstring(x, radix);
|
||||
}
|
||||
|
||||
|
||||
/*** META ((export number->string integer->string)) */
|
||||
var sc_number2string = sc_number2jsstring;
|
||||
|
||||
|
|
|
@ -0,0 +1,387 @@
|
|||
/**
|
||||
* Copyright 2012 the V8 project authors. All rights reserved.
|
||||
* Copyright 2009 Oliver Hunt <http://nerget.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
var NavierStokes = new BenchmarkSuite('NavierStokes', 1484000,
|
||||
[new Benchmark('NavierStokes',
|
||||
runNavierStokes,
|
||||
setupNavierStokes,
|
||||
tearDownNavierStokes)]);
|
||||
|
||||
var solver = null;
|
||||
|
||||
function runNavierStokes()
|
||||
{
|
||||
solver.update();
|
||||
}
|
||||
|
||||
function setupNavierStokes()
|
||||
{
|
||||
solver = new FluidField(null);
|
||||
solver.setResolution(128, 128);
|
||||
solver.setIterations(20);
|
||||
solver.setDisplayFunction(function(){});
|
||||
solver.setUICallback(prepareFrame);
|
||||
solver.reset();
|
||||
}
|
||||
|
||||
function tearDownNavierStokes()
|
||||
{
|
||||
solver = null;
|
||||
}
|
||||
|
||||
function addPoints(field) {
|
||||
var n = 64;
|
||||
for (var i = 1; i <= n; i++) {
|
||||
field.setVelocity(i, i, n, n);
|
||||
field.setDensity(i, i, 5);
|
||||
field.setVelocity(i, n - i, -n, -n);
|
||||
field.setDensity(i, n - i, 20);
|
||||
field.setVelocity(128 - i, n + i, -n, -n);
|
||||
field.setDensity(128 - i, n + i, 30);
|
||||
}
|
||||
}
|
||||
|
||||
var framesTillAddingPoints = 0;
|
||||
var framesBetweenAddingPoints = 5;
|
||||
|
||||
function prepareFrame(field)
|
||||
{
|
||||
if (framesTillAddingPoints == 0) {
|
||||
addPoints(field);
|
||||
framesTillAddingPoints = framesBetweenAddingPoints;
|
||||
framesBetweenAddingPoints++;
|
||||
} else {
|
||||
framesTillAddingPoints--;
|
||||
}
|
||||
}
|
||||
|
||||
// Code from Oliver Hunt (http://nerget.com/fluidSim/pressure.js) starts here.
|
||||
function FluidField(canvas) {
|
||||
function addFields(x, s, dt)
|
||||
{
|
||||
for (var i=0; i<size ; i++ ) x[i] += dt*s[i];
|
||||
}
|
||||
|
||||
function set_bnd(b, x)
|
||||
{
|
||||
if (b===1) {
|
||||
for (var i = 1; i <= width; i++) {
|
||||
x[i] = x[i + rowSize];
|
||||
x[i + (height+1) *rowSize] = x[i + height * rowSize];
|
||||
}
|
||||
|
||||
for (var j = 1; i <= height; i++) {
|
||||
x[j * rowSize] = -x[1 + j * rowSize];
|
||||
x[(width + 1) + j * rowSize] = -x[width + j * rowSize];
|
||||
}
|
||||
} else if (b === 2) {
|
||||
for (var i = 1; i <= width; i++) {
|
||||
x[i] = -x[i + rowSize];
|
||||
x[i + (height + 1) * rowSize] = -x[i + height * rowSize];
|
||||
}
|
||||
|
||||
for (var j = 1; j <= height; j++) {
|
||||
x[j * rowSize] = x[1 + j * rowSize];
|
||||
x[(width + 1) + j * rowSize] = x[width + j * rowSize];
|
||||
}
|
||||
} else {
|
||||
for (var i = 1; i <= width; i++) {
|
||||
x[i] = x[i + rowSize];
|
||||
x[i + (height + 1) * rowSize] = x[i + height * rowSize];
|
||||
}
|
||||
|
||||
for (var j = 1; j <= height; j++) {
|
||||
x[j * rowSize] = x[1 + j * rowSize];
|
||||
x[(width + 1) + j * rowSize] = x[width + j * rowSize];
|
||||
}
|
||||
}
|
||||
var maxEdge = (height + 1) * rowSize;
|
||||
x[0] = 0.5 * (x[1] + x[rowSize]);
|
||||
x[maxEdge] = 0.5 * (x[1 + maxEdge] + x[height * rowSize]);
|
||||
x[(width+1)] = 0.5 * (x[width] + x[(width + 1) + rowSize]);
|
||||
x[(width+1)+maxEdge] = 0.5 * (x[width + maxEdge] + x[(width + 1) + height * rowSize]);
|
||||
}
|
||||
|
||||
function lin_solve(b, x, x0, a, c)
|
||||
{
|
||||
if (a === 0 && c === 1) {
|
||||
for (var j=1 ; j<=height; j++) {
|
||||
var currentRow = j * rowSize;
|
||||
++currentRow;
|
||||
for (var i = 0; i < width; i++) {
|
||||
x[currentRow] = x0[currentRow];
|
||||
++currentRow;
|
||||
}
|
||||
}
|
||||
set_bnd(b, x);
|
||||
} else {
|
||||
var invC = 1 / c;
|
||||
for (var k=0 ; k<iterations; k++) {
|
||||
for (var j=1 ; j<=height; j++) {
|
||||
var lastRow = (j - 1) * rowSize;
|
||||
var currentRow = j * rowSize;
|
||||
var nextRow = (j + 1) * rowSize;
|
||||
var lastX = x[currentRow];
|
||||
++currentRow;
|
||||
for (var i=1; i<=width; i++)
|
||||
lastX = x[currentRow] = (x0[currentRow] + a*(lastX+x[++currentRow]+x[++lastRow]+x[++nextRow])) * invC;
|
||||
}
|
||||
set_bnd(b, x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function diffuse(b, x, x0, dt)
|
||||
{
|
||||
var a = 0;
|
||||
lin_solve(b, x, x0, a, 1 + 4*a);
|
||||
}
|
||||
|
||||
function lin_solve2(x, x0, y, y0, a, c)
|
||||
{
|
||||
if (a === 0 && c === 1) {
|
||||
for (var j=1 ; j <= height; j++) {
|
||||
var currentRow = j * rowSize;
|
||||
++currentRow;
|
||||
for (var i = 0; i < width; i++) {
|
||||
x[currentRow] = x0[currentRow];
|
||||
y[currentRow] = y0[currentRow];
|
||||
++currentRow;
|
||||
}
|
||||
}
|
||||
set_bnd(1, x);
|
||||
set_bnd(2, y);
|
||||
} else {
|
||||
var invC = 1/c;
|
||||
for (var k=0 ; k<iterations; k++) {
|
||||
for (var j=1 ; j <= height; j++) {
|
||||
var lastRow = (j - 1) * rowSize;
|
||||
var currentRow = j * rowSize;
|
||||
var nextRow = (j + 1) * rowSize;
|
||||
var lastX = x[currentRow];
|
||||
var lastY = y[currentRow];
|
||||
++currentRow;
|
||||
for (var i = 1; i <= width; i++) {
|
||||
lastX = x[currentRow] = (x0[currentRow] + a * (lastX + x[currentRow] + x[lastRow] + x[nextRow])) * invC;
|
||||
lastY = y[currentRow] = (y0[currentRow] + a * (lastY + y[++currentRow] + y[++lastRow] + y[++nextRow])) * invC;
|
||||
}
|
||||
}
|
||||
set_bnd(1, x);
|
||||
set_bnd(2, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function diffuse2(x, x0, y, y0, dt)
|
||||
{
|
||||
var a = 0;
|
||||
lin_solve2(x, x0, y, y0, a, 1 + 4 * a);
|
||||
}
|
||||
|
||||
function advect(b, d, d0, u, v, dt)
|
||||
{
|
||||
var Wdt0 = dt * width;
|
||||
var Hdt0 = dt * height;
|
||||
var Wp5 = width + 0.5;
|
||||
var Hp5 = height + 0.5;
|
||||
for (var j = 1; j<= height; j++) {
|
||||
var pos = j * rowSize;
|
||||
for (var i = 1; i <= width; i++) {
|
||||
var x = i - Wdt0 * u[++pos];
|
||||
var y = j - Hdt0 * v[pos];
|
||||
if (x < 0.5)
|
||||
x = 0.5;
|
||||
else if (x > Wp5)
|
||||
x = Wp5;
|
||||
var i0 = x | 0;
|
||||
var i1 = i0 + 1;
|
||||
if (y < 0.5)
|
||||
y = 0.5;
|
||||
else if (y > Hp5)
|
||||
y = Hp5;
|
||||
var j0 = y | 0;
|
||||
var j1 = j0 + 1;
|
||||
var s1 = x - i0;
|
||||
var s0 = 1 - s1;
|
||||
var t1 = y - j0;
|
||||
var t0 = 1 - t1;
|
||||
var row1 = j0 * rowSize;
|
||||
var row2 = j1 * rowSize;
|
||||
d[pos] = s0 * (t0 * d0[i0 + row1] + t1 * d0[i0 + row2]) + s1 * (t0 * d0[i1 + row1] + t1 * d0[i1 + row2]);
|
||||
}
|
||||
}
|
||||
set_bnd(b, d);
|
||||
}
|
||||
|
||||
function project(u, v, p, div)
|
||||
{
|
||||
var h = -0.5 / Math.sqrt(width * height);
|
||||
for (var j = 1 ; j <= height; j++ ) {
|
||||
var row = j * rowSize;
|
||||
var previousRow = (j - 1) * rowSize;
|
||||
var prevValue = row - 1;
|
||||
var currentRow = row;
|
||||
var nextValue = row + 1;
|
||||
var nextRow = (j + 1) * rowSize;
|
||||
for (var i = 1; i <= width; i++ ) {
|
||||
div[++currentRow] = h * (u[++nextValue] - u[++prevValue] + v[++nextRow] - v[++previousRow]);
|
||||
p[currentRow] = 0;
|
||||
}
|
||||
}
|
||||
set_bnd(0, div);
|
||||
set_bnd(0, p);
|
||||
|
||||
lin_solve(0, p, div, 1, 4 );
|
||||
var wScale = 0.5 * width;
|
||||
var hScale = 0.5 * height;
|
||||
for (var j = 1; j<= height; j++ ) {
|
||||
var prevPos = j * rowSize - 1;
|
||||
var currentPos = j * rowSize;
|
||||
var nextPos = j * rowSize + 1;
|
||||
var prevRow = (j - 1) * rowSize;
|
||||
var currentRow = j * rowSize;
|
||||
var nextRow = (j + 1) * rowSize;
|
||||
|
||||
for (var i = 1; i<= width; i++) {
|
||||
u[++currentPos] -= wScale * (p[++nextPos] - p[++prevPos]);
|
||||
v[currentPos] -= hScale * (p[++nextRow] - p[++prevRow]);
|
||||
}
|
||||
}
|
||||
set_bnd(1, u);
|
||||
set_bnd(2, v);
|
||||
}
|
||||
|
||||
function dens_step(x, x0, u, v, dt)
|
||||
{
|
||||
addFields(x, x0, dt);
|
||||
diffuse(0, x0, x, dt );
|
||||
advect(0, x, x0, u, v, dt );
|
||||
}
|
||||
|
||||
function vel_step(u, v, u0, v0, dt)
|
||||
{
|
||||
addFields(u, u0, dt );
|
||||
addFields(v, v0, dt );
|
||||
var temp = u0; u0 = u; u = temp;
|
||||
var temp = v0; v0 = v; v = temp;
|
||||
diffuse2(u,u0,v,v0, dt);
|
||||
project(u, v, u0, v0);
|
||||
var temp = u0; u0 = u; u = temp;
|
||||
var temp = v0; v0 = v; v = temp;
|
||||
advect(1, u, u0, u0, v0, dt);
|
||||
advect(2, v, v0, u0, v0, dt);
|
||||
project(u, v, u0, v0 );
|
||||
}
|
||||
var uiCallback = function(d,u,v) {};
|
||||
|
||||
function Field(dens, u, v) {
|
||||
// Just exposing the fields here rather than using accessors is a measurable win during display (maybe 5%)
|
||||
// but makes the code ugly.
|
||||
this.setDensity = function(x, y, d) {
|
||||
dens[(x + 1) + (y + 1) * rowSize] = d;
|
||||
}
|
||||
this.getDensity = function(x, y) {
|
||||
return dens[(x + 1) + (y + 1) * rowSize];
|
||||
}
|
||||
this.setVelocity = function(x, y, xv, yv) {
|
||||
u[(x + 1) + (y + 1) * rowSize] = xv;
|
||||
v[(x + 1) + (y + 1) * rowSize] = yv;
|
||||
}
|
||||
this.getXVelocity = function(x, y) {
|
||||
return u[(x + 1) + (y + 1) * rowSize];
|
||||
}
|
||||
this.getYVelocity = function(x, y) {
|
||||
return v[(x + 1) + (y + 1) * rowSize];
|
||||
}
|
||||
this.width = function() { return width; }
|
||||
this.height = function() { return height; }
|
||||
}
|
||||
function queryUI(d, u, v)
|
||||
{
|
||||
for (var i = 0; i < size; i++)
|
||||
u[i] = v[i] = d[i] = 0.0;
|
||||
uiCallback(new Field(d, u, v));
|
||||
}
|
||||
|
||||
this.update = function () {
|
||||
queryUI(dens_prev, u_prev, v_prev);
|
||||
vel_step(u, v, u_prev, v_prev, dt);
|
||||
dens_step(dens, dens_prev, u, v, dt);
|
||||
displayFunc(new Field(dens, u, v));
|
||||
}
|
||||
this.setDisplayFunction = function(func) {
|
||||
displayFunc = func;
|
||||
}
|
||||
|
||||
this.iterations = function() { return iterations; }
|
||||
this.setIterations = function(iters) {
|
||||
if (iters > 0 && iters <= 100)
|
||||
iterations = iters;
|
||||
}
|
||||
this.setUICallback = function(callback) {
|
||||
uiCallback = callback;
|
||||
}
|
||||
var iterations = 10;
|
||||
var visc = 0.5;
|
||||
var dt = 0.1;
|
||||
var dens;
|
||||
var dens_prev;
|
||||
var u;
|
||||
var u_prev;
|
||||
var v;
|
||||
var v_prev;
|
||||
var width;
|
||||
var height;
|
||||
var rowSize;
|
||||
var size;
|
||||
var displayFunc;
|
||||
function reset()
|
||||
{
|
||||
rowSize = width + 2;
|
||||
size = (width+2)*(height+2);
|
||||
dens = new Array(size);
|
||||
dens_prev = new Array(size);
|
||||
u = new Array(size);
|
||||
u_prev = new Array(size);
|
||||
v = new Array(size);
|
||||
v_prev = new Array(size);
|
||||
for (var i = 0; i < size; i++)
|
||||
dens_prev[i] = u_prev[i] = v_prev[i] = dens[i] = u[i] = v[i] = 0;
|
||||
}
|
||||
this.reset = reset;
|
||||
this.setResolution = function (hRes, wRes)
|
||||
{
|
||||
var res = wRes * hRes;
|
||||
if (res > 0 && res < 1000000 && (wRes != width || hRes != height)) {
|
||||
width = wRes;
|
||||
height = hRes;
|
||||
reset();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
this.setResolution(64, 64);
|
||||
}
|
|
@ -33,7 +33,7 @@
|
|||
// the popularity of the pages where it occurs and the number of times
|
||||
// it is executed while loading each page. Furthermore the literal
|
||||
// letters in the data are encoded using ROT13 in a way that does not
|
||||
// affect how the regexps match their input. Finally the strings are
|
||||
// affect how the regexps match their input. Finally the strings are
|
||||
// scrambled to exercise the regexp engine on different input strings.
|
||||
|
||||
|
||||
|
@ -47,7 +47,7 @@ function RegExpSetup() {
|
|||
regExpBenchmark = new RegExpBenchmark();
|
||||
RegExpRun(); // run once to get system initialized
|
||||
}
|
||||
|
||||
|
||||
function RegExpRun() {
|
||||
regExpBenchmark.run();
|
||||
}
|
||||
|
@ -1759,6 +1759,6 @@ function RegExpBenchmark() {
|
|||
runBlock11();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.run = run;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
// Copyright 2008 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
load('base.js');
|
||||
load('navier-stokes.js');
|
||||
|
||||
var success = true;
|
||||
|
||||
function PrintResult(name, result) {
|
||||
print(name + ': ' + result);
|
||||
}
|
||||
|
||||
|
||||
function PrintError(name, error) {
|
||||
PrintResult(name, error);
|
||||
success = false;
|
||||
}
|
||||
|
||||
|
||||
function PrintScore(score) {
|
||||
if (success) {
|
||||
print('----');
|
||||
print('Score (version ' + BenchmarkSuite.version + '): ' + score);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BenchmarkSuite.RunSuites({ NotifyResult: PrintResult,
|
||||
NotifyError: PrintError,
|
||||
NotifyScore: PrintScore });
|
|
@ -34,6 +34,7 @@ load('raytrace.js');
|
|||
load('earley-boyer.js');
|
||||
load('regexp.js');
|
||||
load('splay.js');
|
||||
load('navier-stokes.js');
|
||||
|
||||
var success = true;
|
||||
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
<!DOCTYPE html>
|
||||
<html class="reftest-wait">
|
||||
<head>
|
||||
<script>
|
||||
|
||||
function frameDoc() { return document.getElementById("f").contentDocument; }
|
||||
|
||||
function arm() {
|
||||
// Create an element in the iframe.
|
||||
var div = frameDoc().createElement("div");
|
||||
|
||||
// Force a wrapper to be created for .style.
|
||||
var style = div.style;
|
||||
style.color = "green";
|
||||
|
||||
// Adopt the element out of the iframe, leaving the |style| behind.
|
||||
document.adoptNode(div);
|
||||
}
|
||||
|
||||
function boom()
|
||||
{
|
||||
// Create an orphan.
|
||||
arm();
|
||||
|
||||
// Force an iteration over all the wrappers in frameDoc's scope, causing
|
||||
// us to notice the orphan.
|
||||
frameDoc().write("2");
|
||||
|
||||
// All done.
|
||||
document.documentElement.removeAttribute("class");
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body onload="boom();"><iframe id="f" src="data:text/html,1"></iframe></body>
|
||||
</html>
|
|
@ -37,5 +37,6 @@ load 648206-1.html
|
|||
load 705875.html
|
||||
load 720305-1.html
|
||||
load 723465.html
|
||||
load 751995.html
|
||||
asserts(0-1) load 752038.html # We may hit bug 645229 here.
|
||||
load 754311.html
|
||||
|
|
|
@ -1729,6 +1729,80 @@ XPCWrappedNative::ReparentWrapperIfFound(XPCCallContext& ccx,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
XPCWrappedNative*
|
||||
XPCWrappedNative::GetParentWrapper()
|
||||
{
|
||||
XPCWrappedNative *wrapper = nsnull;
|
||||
JSObject *parent = js::GetObjectParent(mFlatJSObject);
|
||||
if (parent && IS_WN_WRAPPER(parent)) {
|
||||
wrapper = static_cast<XPCWrappedNative*>(js::GetObjectPrivate(parent));
|
||||
}
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
// Orphans are sad little things - If only we could treat them better. :-(
|
||||
//
|
||||
// When a wrapper gets reparented to another scope (for example, when calling
|
||||
// adoptNode), it's entirely possible that it previously served as the parent for
|
||||
// other wrappers (via PreCreate hooks). When it moves, the old mFlatJSObject is
|
||||
// replaced by a cross-compartment wrapper. Its descendants really _should_ move
|
||||
// too, but we have no way of locating them short of a compartment-wide sweep
|
||||
// (which we believe to be prohibitively expensive).
|
||||
//
|
||||
// So we just leave them behind. In practice, the only time this turns out to
|
||||
// be a problem is during subsequent wrapper reparenting. When this happens, we
|
||||
// call into the below fixup code at the last minute and straighten things out
|
||||
// before proceeding.
|
||||
//
|
||||
// See bug 751995 for more information.
|
||||
|
||||
bool
|
||||
XPCWrappedNative::IsOrphan()
|
||||
{
|
||||
JSObject *parent = js::GetObjectParent(mFlatJSObject);
|
||||
|
||||
// If there's no parent, we've presumably got a global, which can't be an
|
||||
// orphan by definition.
|
||||
if (!parent)
|
||||
return false;
|
||||
|
||||
// If our parent is a cross-compartment wrapper, it has left us behind.
|
||||
return js::IsCrossCompartmentWrapper(parent);
|
||||
}
|
||||
|
||||
// Recursively fix up orphans on the parent chain of a wrapper. Note that this
|
||||
// can cause a wrapper to move even if IsOrphan() is false, since its parent
|
||||
// might be an orphan, and fixing the parent causes this wrapper to become an
|
||||
// orphan.
|
||||
nsresult
|
||||
XPCWrappedNative::RescueOrphans(XPCCallContext& ccx)
|
||||
{
|
||||
// Even if we're not an orphan at the moment, one of our ancestors might
|
||||
// be. If so, we need to recursively rescue up the parent chain.
|
||||
nsresult rv;
|
||||
XPCWrappedNative *parentWrapper = GetParentWrapper();
|
||||
if (parentWrapper && parentWrapper->IsOrphan()) {
|
||||
rv = parentWrapper->RescueOrphans(ccx);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// Now that we know our parent is in the right place, determine if we've
|
||||
// been orphaned. If not, we have nothing to do.
|
||||
if (!IsOrphan())
|
||||
return NS_OK;
|
||||
|
||||
// We've been orphaned. Find where our parent went, and follow it.
|
||||
JSObject *parentGhost = js::GetObjectParent(mFlatJSObject);
|
||||
JSObject *realParent = js::UnwrapObject(parentGhost);
|
||||
nsRefPtr<XPCWrappedNative> ignored;
|
||||
return ReparentWrapperIfFound(ccx,
|
||||
XPCWrappedNativeScope::
|
||||
FindInJSObjectScope(ccx, parentGhost),
|
||||
XPCWrappedNativeScope::
|
||||
FindInJSObjectScope(ccx, realParent),
|
||||
realParent, mIdentity, getter_AddRefs(ignored));
|
||||
}
|
||||
|
||||
#define IS_TEAROFF_CLASS(clazz) \
|
||||
((clazz) == &XPC_WN_Tearoff_JSClass)
|
||||
|
||||
|
|
|
@ -1547,6 +1547,19 @@ MoveWrapper(XPCCallContext& ccx, XPCWrappedNative *wrapper,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// For performance reasons, we wait to fix up orphaned wrappers (wrappers
|
||||
// whose parents have moved to another scope) until right before they
|
||||
// threaten to confuse us.
|
||||
//
|
||||
// If this wrapper is an orphan, reunite it with its parent. If, following
|
||||
// that, the wrapper is no longer in the old scope, then we don't need to
|
||||
// reparent it.
|
||||
MOZ_ASSERT(wrapper->GetScope() == oldScope);
|
||||
nsresult rv = wrapper->RescueOrphans(ccx);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (wrapper->GetScope() != oldScope)
|
||||
return NS_OK;
|
||||
|
||||
nsISupports *identity = wrapper->GetIdentityObject();
|
||||
nsCOMPtr<nsIClassInfo> info(do_QueryInterface(identity));
|
||||
|
||||
|
@ -1571,9 +1584,9 @@ MoveWrapper(XPCCallContext& ccx, XPCWrappedNative *wrapper,
|
|||
return NS_OK;
|
||||
|
||||
JSObject *newParent = oldScope->GetGlobalJSObject();
|
||||
nsresult rv = sciWrapper.GetCallback()->PreCreate(identity, ccx,
|
||||
newParent,
|
||||
&newParent);
|
||||
rv = sciWrapper.GetCallback()->PreCreate(identity, ccx,
|
||||
newParent,
|
||||
&newParent);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
|
|
|
@ -2704,6 +2704,15 @@ public:
|
|||
nsISupports* aCOMObj,
|
||||
XPCWrappedNative** aWrapper);
|
||||
|
||||
// Returns the wrapper corresponding to the parent of our mFlatJSObject.
|
||||
//
|
||||
// If the parent does not have a WN, or if there is no parent, null is
|
||||
// returned.
|
||||
XPCWrappedNative *GetParentWrapper();
|
||||
|
||||
bool IsOrphan();
|
||||
nsresult RescueOrphans(XPCCallContext& ccx);
|
||||
|
||||
void FlatJSObjectFinalized();
|
||||
|
||||
void SystemIsBeingShutDown();
|
||||
|
|
|
@ -14,8 +14,9 @@ interface nsIDOMNode;
|
|||
interface nsIDOMNodeList;
|
||||
interface nsIDOMFontFaceList;
|
||||
interface nsIDOMRange;
|
||||
interface nsIDOMCSSStyleSheet;
|
||||
|
||||
[scriptable, uuid(983475e4-6bdf-4741-a733-76e9a8d119b9)]
|
||||
[scriptable, uuid(f7a37305-a963-4a2a-b951-2c97a6b27fb4)]
|
||||
interface inIDOMUtils : nsISupports
|
||||
{
|
||||
// CSS utilities
|
||||
|
@ -51,4 +52,13 @@ interface inIDOMUtils : nsISupports
|
|||
void removePseudoClassLock(in nsIDOMElement aElement, in DOMString aPseudoClass);
|
||||
bool hasPseudoClassLock(in nsIDOMElement aElement, in DOMString aPseudoClass);
|
||||
void clearPseudoClassLocks(in nsIDOMElement aElement);
|
||||
|
||||
/**
|
||||
* Parse CSS and update the style sheet in place.
|
||||
*
|
||||
* @param DOMCSSStyleSheet aSheet
|
||||
* @param DOMString aInput
|
||||
* The new source string for the style sheet.
|
||||
*/
|
||||
void parseStyleSheet(in nsIDOMCSSStyleSheet aSheet, in DOMString aInput);
|
||||
};
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "nsIAtom.h"
|
||||
#include "nsRange.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "nsCSSStyleSheet.h"
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -424,3 +425,13 @@ inDOMUtils::ClearPseudoClassLocks(nsIDOMElement *aElement)
|
|||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
inDOMUtils::ParseStyleSheet(nsIDOMCSSStyleSheet *aSheet,
|
||||
const nsAString& aInput)
|
||||
{
|
||||
nsRefPtr<nsCSSStyleSheet> sheet = do_QueryObject(aSheet);
|
||||
NS_ENSURE_ARG_POINTER(sheet);
|
||||
|
||||
return sheet->ParseSheet(aInput);
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@ _CHROME_FILES =\
|
|||
GentiumPlus-R.woff \
|
||||
test_bug708874.xul \
|
||||
test_bug708874.css \
|
||||
test_bug727834.xul \
|
||||
test_bug727834.css \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_CHROME_FILES)
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
body {
|
||||
padding-top: 100px;
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
<?xml version="1.0"?>
|
||||
<!--
|
||||
vim: set ts=2 et sw=2 tw=80:
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
|
||||
<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
|
||||
<?xml-stylesheet type="text/css" href="test_bug727834.css"?>
|
||||
<window title="Mozilla Bug 727834"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
onload="RunTests();">
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
|
||||
<script type="application/javascript"><![CDATA[
|
||||
/** Test for Bug 727834 - Add an API to (re)parse a style sheet in place **/
|
||||
|
||||
function RunTests() {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
let DOMUtils = Components.classes["@mozilla.org/inspector/dom-utils;1"]
|
||||
.getService(Components.interfaces.inIDOMUtils);
|
||||
let body = document.querySelector("body");
|
||||
let testSheet = document.styleSheets[2];
|
||||
let rule = document.styleSheets[2].cssRules[0];
|
||||
|
||||
is(testSheet.cssRules.length, 1,
|
||||
"style sheet has 1 rule");
|
||||
is(rule.style.paddingTop, "100px",
|
||||
"original first rule has padding-top 100px");
|
||||
is(window.getComputedStyle(body).paddingTop, "100px",
|
||||
"original first rule applies");
|
||||
|
||||
DOMUtils.parseStyleSheet(testSheet,
|
||||
"@import url(test_bug727834.css); body{background: red;}");
|
||||
|
||||
is(testSheet.cssRules.length, 2,
|
||||
"style sheet now has 2 rules");
|
||||
is(window.getComputedStyle(body).backgroundColor, "rgb(255, 0, 0)",
|
||||
"background is now red");
|
||||
|
||||
let exceptionName;
|
||||
try {
|
||||
rule.style.paddingLeft = "100px";
|
||||
} catch (ex) {
|
||||
exceptionName = ex.name;
|
||||
} finally {
|
||||
is(exceptionName, "NS_ERROR_NOT_AVAILABLE",
|
||||
"original rule is not available for modification anymore");
|
||||
}
|
||||
is(window.getComputedStyle(body).paddingLeft, "0px",
|
||||
"original rule does not apply to document");
|
||||
|
||||
rule = testSheet.cssRules[0];
|
||||
|
||||
is(rule.parentStyleSheet, testSheet,
|
||||
"rule's parent style sheet is not null");
|
||||
|
||||
DOMUtils.parseStyleSheet(testSheet,
|
||||
"body{background: lime;}");
|
||||
|
||||
is(testSheet.cssRules.length, 1,
|
||||
"style sheet now has 1 rule");
|
||||
is(window.getComputedStyle(body).backgroundColor, "rgb(0, 255, 0)",
|
||||
"background is now lime");
|
||||
is(rule.parentStyleSheet, null,
|
||||
"detached rule's parent style sheet is null");
|
||||
|
||||
SimpleTest.executeSoon(function () {
|
||||
DOMUtils.parseStyleSheet(testSheet,
|
||||
"@import url(test_bug727834.css); body{background: blue;}");
|
||||
|
||||
is(testSheet.cssRules.length, 2,
|
||||
"style sheet now has 2 rules");
|
||||
is(window.getComputedStyle(body).backgroundColor, "rgb(0, 0, 255)",
|
||||
"background is now blue");
|
||||
is(testSheet.cssRules[0].parentStyleSheet, testSheet,
|
||||
"parent style sheet is the test sheet");
|
||||
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}
|
||||
]]></script>
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=727834">
|
||||
Mozilla Bug 727834 - Add an API to (re)parse a style sheet in place
|
||||
</a>
|
||||
</body>
|
||||
</window>
|
|
@ -1751,6 +1751,17 @@ nsCSSStyleSheet::InsertRule(const nsAString& aRule,
|
|||
return InsertRuleInternal(aRule, aIndex, aReturn);
|
||||
}
|
||||
|
||||
static bool
|
||||
RuleHasPendingChildSheet(css::Rule *cssRule)
|
||||
{
|
||||
nsCOMPtr<nsIDOMCSSImportRule> importRule(do_QueryInterface(cssRule));
|
||||
NS_ASSERTION(importRule, "Rule which has type IMPORT_RULE and does not implement nsIDOMCSSImportRule!");
|
||||
nsCOMPtr<nsIDOMCSSStyleSheet> childSheet;
|
||||
importRule->GetStyleSheet(getter_AddRefs(childSheet));
|
||||
nsRefPtr<nsCSSStyleSheet> cssSheet = do_QueryObject(childSheet);
|
||||
return cssSheet != nsnull && !cssSheet->IsComplete();
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsCSSStyleSheet::InsertRuleInternal(const nsAString& aRule,
|
||||
PRUint32 aIndex,
|
||||
|
@ -1871,23 +1882,16 @@ nsCSSStyleSheet::InsertRuleInternal(const nsAString& aRule,
|
|||
NS_ENSURE_SUCCESS(result, result);
|
||||
}
|
||||
|
||||
// We don't notify immediately for @import rules, but rather when
|
||||
// the sheet the rule is importing is loaded
|
||||
bool notify = true;
|
||||
if (type == css::Rule::IMPORT_RULE) {
|
||||
nsCOMPtr<nsIDOMCSSImportRule> importRule(do_QueryInterface(cssRule));
|
||||
NS_ASSERTION(importRule, "Rule which has type IMPORT_RULE and does not implement nsIDOMCSSImportRule!");
|
||||
nsCOMPtr<nsIDOMCSSStyleSheet> childSheet;
|
||||
importRule->GetStyleSheet(getter_AddRefs(childSheet));
|
||||
if (!childSheet) {
|
||||
notify = false;
|
||||
}
|
||||
if (type == css::Rule::IMPORT_RULE && RuleHasPendingChildSheet(cssRule)) {
|
||||
// We don't notify immediately for @import rules, but rather when
|
||||
// the sheet the rule is importing is loaded (see StyleSheetLoaded)
|
||||
continue;
|
||||
}
|
||||
if (mDocument && notify) {
|
||||
if (mDocument) {
|
||||
mDocument->StyleRuleAdded(this, cssRule);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
*aReturn = aIndex;
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -2058,6 +2062,9 @@ nsCSSStyleSheet::StyleSheetLoaded(nsCSSStyleSheet* aSheet,
|
|||
bool aWasAlternate,
|
||||
nsresult aStatus)
|
||||
{
|
||||
if (aSheet->GetParentSheet() == nsnull) {
|
||||
return NS_OK; // ignore if sheet has been detached already (see parseSheet)
|
||||
}
|
||||
NS_ASSERTION(this == aSheet->GetParentSheet(),
|
||||
"We are being notified of a sheet load for a sheet that is not our child!");
|
||||
|
||||
|
@ -2072,6 +2079,72 @@ nsCSSStyleSheet::StyleSheetLoaded(nsCSSStyleSheet* aSheet,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsCSSStyleSheet::ParseSheet(const nsAString& aInput)
|
||||
{
|
||||
// Not doing this if the sheet is not complete!
|
||||
if (!mInner->mComplete) {
|
||||
return NS_ERROR_DOM_INVALID_ACCESS_ERR;
|
||||
}
|
||||
|
||||
// Hold strong ref to the CSSLoader in case the document update
|
||||
// kills the document
|
||||
nsRefPtr<css::Loader> loader;
|
||||
if (mDocument) {
|
||||
loader = mDocument->CSSLoader();
|
||||
NS_ASSERTION(loader, "Document with no CSS loader!");
|
||||
} else {
|
||||
loader = new css::Loader();
|
||||
}
|
||||
|
||||
nsCSSParser parser(loader, this);
|
||||
|
||||
mozAutoDocUpdate updateBatch(mDocument, UPDATE_STYLE, true);
|
||||
|
||||
nsresult rv = WillDirty();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// detach existing rules (including child sheets via import rules)
|
||||
int ruleCount;
|
||||
while ((ruleCount = mInner->mOrderedRules.Count()) != 0) {
|
||||
nsRefPtr<css::Rule> rule = mInner->mOrderedRules.ObjectAt(ruleCount - 1);
|
||||
mInner->mOrderedRules.RemoveObjectAt(ruleCount - 1);
|
||||
rule->SetStyleSheet(nsnull);
|
||||
if (mDocument) {
|
||||
mDocument->StyleRuleRemoved(this, rule);
|
||||
}
|
||||
}
|
||||
|
||||
// nuke child sheets list and current namespace map
|
||||
for (nsCSSStyleSheet* child = mInner->mFirstChild; child; child = child->mNext) {
|
||||
NS_ASSERTION(child->mParent == this, "Child sheet is not parented to this!");
|
||||
child->mParent = nsnull;
|
||||
child->mDocument = nsnull;
|
||||
}
|
||||
mInner->mFirstChild = nsnull;
|
||||
mInner->mNameSpaceMap = nsnull;
|
||||
|
||||
// allow unsafe rules if the style sheet's principal is the system principal
|
||||
bool allowUnsafeRules = nsContentUtils::IsSystemPrincipal(mInner->mPrincipal);
|
||||
rv = parser.ParseSheet(aInput, mInner->mSheetURI, mInner->mBaseURI,
|
||||
mInner->mPrincipal, 1, allowUnsafeRules);
|
||||
DidDirty(); // we are always 'dirty' here since we always remove rules first
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// notify document of all new rules
|
||||
if (mDocument) {
|
||||
for (PRInt32 index = 0; index < mInner->mOrderedRules.Count(); ++index) {
|
||||
nsRefPtr<css::Rule> rule = mInner->mOrderedRules.ObjectAt(index);
|
||||
if (rule->GetType() == css::Rule::IMPORT_RULE &&
|
||||
RuleHasPendingChildSheet(rule)) {
|
||||
continue; // notify when loaded (see StyleSheetLoaded)
|
||||
}
|
||||
mDocument->StyleRuleAdded(this, rule);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* virtual */ nsIURI*
|
||||
nsCSSStyleSheet::GetOriginalURI() const
|
||||
{
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче