Merge the last green PGO changeset of mozilla-inbound to mozilla-central

This commit is contained in:
Ehsan Akhgari 2012-06-04 11:31:44 -04:00
Родитель 10d862efb8 2f22631c76
Коммит 624a77c0c9
116 изменённых файлов: 8067 добавлений и 625 удалений

Просмотреть файл

@ -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 \

22
dom/mms/Makefile.in Normal file
Просмотреть файл

@ -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);
};

30
dom/mms/src/Makefile.in Normal file
Просмотреть файл

@ -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;

387
js/src/v8/navier-stokes.js Normal file
Просмотреть файл

@ -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
{

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше