Merge mozilla-central into mozilla-inbound

This commit is contained in:
Ehsan Akhgari 2012-07-05 11:13:45 -04:00
commit 4951d76b67
96 changed files with 2912 additions and 249 deletions

View File

@ -1023,7 +1023,7 @@ pref("services.sync.prefs.sync.xpinstall.whitelist.required", true);
pref("devtools.errorconsole.enabled", false);
// Developer toolbar and GCLI preferences
pref("devtools.toolbar.enabled", false);
pref("devtools.toolbar.enabled", true);
pref("devtools.toolbar.visible", false);
pref("devtools.gcli.allowSet", false);
pref("devtools.commands.dir", "");

View File

@ -519,7 +519,6 @@
autocheck="false"
hidden="true"
label="&devToolbarMenu.label;"
accesskey="&devToolbarMenu.accesskey;"
key="key_devToolbar"
command="Tools:DevToolbar"/>
<menuitem id="webConsole"

View File

@ -225,13 +225,6 @@
#endif
<key id="key_openAddons" key="&addons.commandkey;" command="Tools:Addons" modifiers="accel,shift"/>
<key id="key_errorConsole" key="&errorConsoleCmd.commandkey;" oncommand="toJavaScriptConsole();" modifiers="accel,shift" disabled="true"/>
<key id="key_devToolbar" key="&devToolbar.commandkey;" command="Tools:DevToolbar"
#ifdef XP_MACOSX
modifiers="accel,alt"
#else
modifiers="accel,shift"
#endif
/>
<key id="key_webConsole" key="&webConsoleCmd.commandkey;" oncommand="HUDConsoleUI.toggleHUD();"
#ifdef XP_MACOSX
modifiers="accel,alt"

View File

@ -6868,6 +6868,10 @@ FocusManager.prototype._checkShow = function() {
* available inputs
*/
FocusManager.prototype._shouldShowTooltip = function() {
if (!this._hasFocus) {
return { visible: false, reason: '!hasFocus' };
}
if (eagerHelper.value === Eagerness.NEVER) {
return { visible: false, reason: 'eagerHelper !== NEVER' };
}
@ -6896,6 +6900,10 @@ FocusManager.prototype._shouldShowTooltip = function() {
* available inputs
*/
FocusManager.prototype._shouldShowOutput = function() {
if (!this._hasFocus) {
return { visible: false, reason: '!hasFocus' };
}
if (this._recentOutput) {
return { visible: true, reason: 'recentOutput' };
}

View File

@ -179,6 +179,9 @@ DeveloperToolbar.prototype._onload = function DT_onload()
scratchpad: null
});
this.display.focusManager.addMonitoredElement(this.outputPanel._frame);
this.display.focusManager.addMonitoredElement(this._element);
this.display.onVisibilityChange.add(this.outputPanel._visibilityChanged, this.outputPanel);
this.display.onVisibilityChange.add(this.tooltipPanel._visibilityChanged, this.tooltipPanel);
this.display.onOutput.add(this.outputPanel._outputChanged, this.outputPanel);
@ -187,7 +190,6 @@ DeveloperToolbar.prototype._onload = function DT_onload()
this._chromeWindow.getBrowser().tabContainer.addEventListener("TabClose", this, false);
this._chromeWindow.getBrowser().addEventListener("load", this, true);
this._chromeWindow.getBrowser().addEventListener("beforeunload", this, true);
this._chromeWindow.addEventListener("resize", this, false);
this._initErrorsCount(this._chromeWindow.getBrowser().selectedTab);
@ -307,11 +309,13 @@ DeveloperToolbar.prototype.destroy = function DT_destroy()
this._chromeWindow.getBrowser().tabContainer.removeEventListener("TabSelect", this, false);
this._chromeWindow.getBrowser().removeEventListener("load", this, true);
this._chromeWindow.getBrowser().removeEventListener("beforeunload", this, true);
this._chromeWindow.removeEventListener("resize", this, false);
let tabs = this._chromeWindow.getBrowser().tabs;
Array.prototype.forEach.call(tabs, this._stopErrorsCount, this);
this.display.focusManager.removeMonitoredElement(this.outputPanel._frame);
this.display.focusManager.removeMonitoredElement(this._element);
this.display.onVisibilityChange.remove(this.outputPanel._visibilityChanged, this.outputPanel);
this.display.onVisibilityChange.remove(this.tooltipPanel._visibilityChanged, this.tooltipPanel);
this.display.onOutput.remove(this.outputPanel._outputChanged, this.outputPanel);
@ -368,9 +372,6 @@ DeveloperToolbar.prototype.handleEvent = function DT_handleEvent(aEvent)
}
}
}
else if (aEvent.type == "resize") {
this.outputPanel._resize();
}
else if (aEvent.type == "TabClose") {
this._stopErrorsCount(aEvent.target);
}
@ -812,7 +813,7 @@ TooltipPanel.prototype._resize = function TP_resize()
}
let offset = 10 + Math.floor(this._dimensions.start * AVE_CHAR_WIDTH);
this._frame.style.marginLeft = offset + "px";
this._panel.style.marginLeft = offset + "px";
/*
// Bug 744906: UX review - Not sure if we want this code to fatten connector

View File

@ -40,6 +40,6 @@ function runTest() {
}
function getLeftMargin() {
let style = DeveloperToolbar.tooltipPanel._frame.style.marginLeft;
let style = DeveloperToolbar.tooltipPanel._panel.style.marginLeft;
return parseInt(style.slice(0, -2), 10);
}

View File

@ -237,8 +237,6 @@ These should match what Safari and other Apple applications use on OS X Lion. --
<!ENTITY devToolbarCloseButton.tooltiptext "Close Developer Toolbar">
<!ENTITY devToolbarMenu.label "Developer Toolbar">
<!ENTITY devToolbarMenu.accesskey "v">
<!ENTITY devToolbar.commandkey "v">
<!ENTITY webConsoleButton.label "Web Console">
<!ENTITY inspectorButton.label "Inspector">

View File

@ -2398,6 +2398,7 @@ html|*#gcli-output-frame {
#gcli-tooltip {
border-width: 0;
background-color: transparent;
-moz-appearance: none;
margin-bottom: -2px;
}

View File

@ -31,7 +31,7 @@
margin-top: -1px;
margin-left: 8px;
width: 20px;
height: 0;
height: 10px;
border-left: 1px solid hsl(210,11%,10%);
border-right: 1px solid hsl(210,11%,10%);
background-color: hsl(210,11%,16%);

View File

@ -3139,6 +3139,7 @@ html|*#gcli-output-frame {
#gcli-tooltip {
border-width: 0;
background-color: transparent;
-moz-appearance: none;
margin-bottom: -2px;
}

View File

@ -32,10 +32,11 @@
margin-top: -1px;
margin-left: 8px;
width: 20px;
height: 0;
height: 10px;
border-left: 1px solid hsl(210,11%,10%);
border-right: 1px solid hsl(210,11%,10%);
background-color: hsl(210,11%,16%);
background-image: url(background-noise-toolbar.png);
}
.gcli-tt-description,

View File

@ -3073,6 +3073,7 @@ html|*#gcli-output-frame {
#gcli-tooltip {
border-width: 0;
background-color: transparent;
-moz-appearance: none;
margin-bottom: -2px;
}

View File

@ -921,6 +921,7 @@ GK_ATOM(statedatasource, "statedatasource")
GK_ATOM(staticHint, "staticHint")
GK_ATOM(statusbar, "statusbar")
GK_ATOM(statustext, "statustext")
GK_ATOM(step, "step")
GK_ATOM(stop, "stop")
GK_ATOM(stretch, "stretch")
GK_ATOM(strike, "strike")

View File

@ -1901,6 +1901,7 @@ nsEventStateManager::FireContextClick()
type == NS_FORM_INPUT_URL ||
type == NS_FORM_INPUT_PASSWORD ||
type == NS_FORM_INPUT_FILE ||
type == NS_FORM_INPUT_NUMBER ||
type == NS_FORM_TEXTAREA);
}
else if (tag == nsGkAtoms::applet ||

View File

@ -53,6 +53,7 @@ enum InputElementTypes {
NS_FORM_INPUT_HIDDEN,
NS_FORM_INPUT_RESET,
NS_FORM_INPUT_IMAGE,
NS_FORM_INPUT_NUMBER,
NS_FORM_INPUT_PASSWORD,
NS_FORM_INPUT_RADIO,
NS_FORM_INPUT_SEARCH,
@ -229,6 +230,8 @@ nsIFormControl::IsSingleLineTextControl(bool aExcludePassword, PRUint32 aType)
aType == NS_FORM_INPUT_SEARCH ||
aType == NS_FORM_INPUT_TEL ||
aType == NS_FORM_INPUT_URL ||
// TODO: this is temporary until bug 635240 is fixed.
aType == NS_FORM_INPUT_NUMBER ||
(!aExcludePassword && aType == NS_FORM_INPUT_PASSWORD);
}

View File

@ -178,6 +178,7 @@ ShouldBeInElements(nsIFormControl* aFormControl)
case NS_FORM_INPUT_TEXT :
case NS_FORM_INPUT_TEL :
case NS_FORM_INPUT_URL :
case NS_FORM_INPUT_NUMBER :
case NS_FORM_SELECT :
case NS_FORM_TEXTAREA :
case NS_FORM_FIELDSET :

View File

@ -87,9 +87,12 @@
#include "mozilla/LookAndFeel.h"
#include "mozilla/Util.h" // DebugOnly
#include "mozilla/Preferences.h"
#include "nsIIDNService.h"
#include <limits>
using namespace mozilla;
using namespace mozilla::dom;
@ -119,6 +122,7 @@ static const nsAttrValue::EnumTable kInputTypeTable[] = {
{ "hidden", NS_FORM_INPUT_HIDDEN },
{ "reset", NS_FORM_INPUT_RESET },
{ "image", NS_FORM_INPUT_IMAGE },
{ "number", NS_FORM_INPUT_NUMBER },
{ "password", NS_FORM_INPUT_PASSWORD },
{ "radio", NS_FORM_INPUT_RADIO },
{ "search", NS_FORM_INPUT_SEARCH },
@ -130,7 +134,7 @@ static const nsAttrValue::EnumTable kInputTypeTable[] = {
};
// Default type is 'text'.
static const nsAttrValue::EnumTable* kInputDefaultType = &kInputTypeTable[12];
static const nsAttrValue::EnumTable* kInputDefaultType = &kInputTypeTable[13];
static const PRUint8 NS_INPUT_AUTOCOMPLETE_OFF = 0;
static const PRUint8 NS_INPUT_AUTOCOMPLETE_ON = 1;
@ -146,6 +150,9 @@ static const nsAttrValue::EnumTable kInputAutocompleteTable[] = {
// Default autocomplete value is "".
static const nsAttrValue::EnumTable* kInputDefaultAutocomplete = &kInputAutocompleteTable[0];
const double nsHTMLInputElement::kDefaultStepBase = 0;
const double nsHTMLInputElement::kStepAny = 0;
#define NS_INPUT_ELEMENT_STATE_IID \
{ /* dc3b3d14-23e2-4479-b513-7b369343e3a0 */ \
0xdc3b3d14, \
@ -522,6 +529,7 @@ nsHTMLInputElement::nsHTMLInputElement(already_AddRefed<nsINodeInfo> aNodeInfo,
, mInhibitRestoration(aFromParser & FROM_PARSER_FRAGMENT)
, mCanShowValidUI(true)
, mCanShowInvalidUI(true)
, mHasRange(false)
{
mInputData.mState = new nsTextEditorState(this);
@ -646,6 +654,7 @@ nsHTMLInputElement::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const
case NS_FORM_INPUT_PASSWORD:
case NS_FORM_INPUT_TEL:
case NS_FORM_INPUT_URL:
case NS_FORM_INPUT_NUMBER:
if (mValueChanged) {
// We don't have our default value anymore. Set our value on
// the clone.
@ -809,6 +818,15 @@ nsHTMLInputElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
UpdatePatternMismatchValidityState();
} else if (aName == nsGkAtoms::multiple) {
UpdateTypeMismatchValidityState();
} else if (aName == nsGkAtoms::max) {
UpdateHasRange();
UpdateRangeOverflowValidityState();
} else if (aName == nsGkAtoms::min) {
UpdateHasRange();
UpdateRangeUnderflowValidityState();
UpdateStepMismatchValidityState();
} else if (aName == nsGkAtoms::step) {
UpdateStepMismatchValidityState();
}
UpdateState(aNotify);
@ -836,6 +854,8 @@ NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLInputElement, Autocomplete, autocomplete,
NS_IMPL_BOOL_ATTR(nsHTMLInputElement, Autofocus, autofocus)
//NS_IMPL_BOOL_ATTR(nsHTMLInputElement, Checked, checked)
NS_IMPL_BOOL_ATTR(nsHTMLInputElement, Disabled, disabled)
NS_IMPL_STRING_ATTR(nsHTMLInputElement, Max, max)
NS_IMPL_STRING_ATTR(nsHTMLInputElement, Min, min)
NS_IMPL_ACTION_ATTR(nsHTMLInputElement, FormAction, formaction)
NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLInputElement, FormEnctype, formenctype,
kFormDefaultEnctype->tag)
@ -849,6 +869,7 @@ NS_IMPL_STRING_ATTR(nsHTMLInputElement, Name, name)
NS_IMPL_BOOL_ATTR(nsHTMLInputElement, ReadOnly, readonly)
NS_IMPL_BOOL_ATTR(nsHTMLInputElement, Required, required)
NS_IMPL_URI_ATTR(nsHTMLInputElement, Src, src)
NS_IMPL_STRING_ATTR(nsHTMLInputElement, Step, step)
NS_IMPL_INT_ATTR(nsHTMLInputElement, TabIndex, tabindex)
NS_IMPL_STRING_ATTR(nsHTMLInputElement, UseMap, usemap)
//NS_IMPL_STRING_ATTR(nsHTMLInputElement, Value, value)
@ -972,6 +993,20 @@ nsHTMLInputElement::IsValueEmpty() const
return value.IsEmpty();
}
double
nsHTMLInputElement::GetValueAsDouble() const
{
double doubleValue;
nsAutoString stringValue;
PRInt32 ec;
GetValueInternal(stringValue);
doubleValue = stringValue.ToDouble(&ec);
return NS_FAILED(ec) ? std::numeric_limits<double>::quiet_NaN()
: doubleValue;
}
NS_IMETHODIMP
nsHTMLInputElement::SetValue(const nsAString& aValue)
{
@ -1026,6 +1061,148 @@ nsHTMLInputElement::GetList(nsIDOMHTMLElement** aValue)
return NS_OK;
}
void
nsHTMLInputElement::SetValue(double aValue)
{
nsAutoString value;
value.AppendFloat(aValue);
SetValue(value);
}
NS_IMETHODIMP
nsHTMLInputElement::GetValueAsNumber(double* aValueAsNumber)
{
*aValueAsNumber = DoesValueAsNumberApply() ? GetValueAsDouble()
: std::numeric_limits<double>::quiet_NaN();
return NS_OK;
}
NS_IMETHODIMP
nsHTMLInputElement::SetValueAsNumber(double aValueAsNumber)
{
if (!DoesValueAsNumberApply()) {
return NS_ERROR_DOM_INVALID_STATE_ERR;
}
SetValue(aValueAsNumber);
return NS_OK;
}
double
nsHTMLInputElement::GetStepBase() const
{
if (!HasAttr(kNameSpaceID_None, nsGkAtoms::min)) {
return kDefaultStepBase;
}
nsAutoString minStr;
GetAttr(kNameSpaceID_None, nsGkAtoms::min, minStr);
PRInt32 ec;
double stepBase = minStr.ToDouble(&ec);
return NS_FAILED(ec) ? kDefaultStepBase : stepBase;
}
nsresult
nsHTMLInputElement::ApplyStep(PRInt32 aStep)
{
if (!DoStepDownStepUpApply()) {
return NS_ERROR_DOM_INVALID_STATE_ERR;
}
double step = GetStep();
if (step == kStepAny) {
return NS_ERROR_DOM_INVALID_STATE_ERR;
}
double value = GetValueAsDouble();
if (value != value) { // NaN
return NS_OK;
}
// TODO: refactorize with GetMin(), see bug 636634.
double min = std::numeric_limits<double>::quiet_NaN();
if (HasAttr(kNameSpaceID_None, nsGkAtoms::min)) {
nsAutoString minStr;
GetAttr(kNameSpaceID_None, nsGkAtoms::min, minStr);
PRInt32 ec;
double minTmp = minStr.ToDouble(&ec);
if (!NS_FAILED(ec)) {
min = minTmp;
}
}
// TODO: refactorize with GetMax(), see bug 636634.
double max = std::numeric_limits<double>::quiet_NaN();
if (HasAttr(kNameSpaceID_None, nsGkAtoms::max)) {
nsAutoString maxStr;
GetAttr(kNameSpaceID_None, nsGkAtoms::max, maxStr);
PRInt32 ec;
double maxTmp = maxStr.ToDouble(&ec);
if (!NS_FAILED(ec)) {
// "max - (max - stepBase) % step" is the nearest valid value to max.
max = maxTmp - NS_floorModulo(maxTmp - GetStepBase(), step);
}
}
// Cases where we are clearly going in the wrong way.
// We don't use ValidityState because we can be higher than the maximal
// allowed value and still not suffer from range overflow in the case of
// of the value specified in @max isn't in the step.
if ((value <= min && aStep < 0) ||
(value >= max && aStep > 0)) {
return NS_OK;
}
if (GetValidityState(VALIDITY_STATE_STEP_MISMATCH) &&
value != min && value != max) {
if (aStep > 0) {
value -= NS_floorModulo(value - GetStepBase(), step);
} else if (aStep < 0) {
value -= NS_floorModulo(value - GetStepBase(), step);
value += step;
}
}
value += aStep * step;
// When stepUp() is called and the value is below min, we should clamp on
// min unless stepUp() moves us higher than min.
if (GetValidityState(VALIDITY_STATE_RANGE_UNDERFLOW) && aStep > 0 &&
value <= min) {
MOZ_ASSERT(min == min); // min can't be NaN if we are here!
value = min;
// Same goes for stepDown() and max.
} else if (GetValidityState(VALIDITY_STATE_RANGE_OVERFLOW) && aStep < 0 &&
value >= max) {
MOZ_ASSERT(max == max); // max can't be NaN if we are here!
value = max;
// If we go down, we want to clamp on min.
} else if (aStep < 0 && min == min) {
value = NS_MAX(value, min);
// If we go up, we want to clamp on max.
} else if (aStep > 0 && max == max) {
value = NS_MIN(value, max);
}
SetValue(value);
return NS_OK;
}
NS_IMETHODIMP
nsHTMLInputElement::StepDown(PRInt32 n, PRUint8 optional_argc)
{
return ApplyStep(optional_argc ? -n : -1);
}
NS_IMETHODIMP
nsHTMLInputElement::StepUp(PRInt32 n, PRUint8 optional_argc)
{
return ApplyStep(optional_argc ? n : 1);
}
NS_IMETHODIMP
nsHTMLInputElement::MozGetFileNameArray(PRUint32 *aLength, PRUnichar ***aFileNames)
{
@ -1097,6 +1274,12 @@ nsHTMLInputElement::MozSetFileNameArray(const PRUnichar **aFileNames, PRUint32 a
NS_IMETHODIMP
nsHTMLInputElement::MozIsTextField(bool aExcludePassword, bool* aResult)
{
// TODO: temporary until bug 635240 is fixed.
if (mType == NS_FORM_INPUT_NUMBER) {
*aResult = false;
return NS_OK;
}
*aResult = IsSingleLineTextControl(aExcludePassword);
return NS_OK;
@ -2174,7 +2357,8 @@ nsHTMLInputElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
if (aVisitor.mEvent->message == NS_KEY_PRESS &&
(keyEvent->keyCode == NS_VK_RETURN ||
keyEvent->keyCode == NS_VK_ENTER) &&
IsSingleLineTextControl(false, mType)) {
(IsSingleLineTextControl(false, mType) ||
mType == NS_FORM_INPUT_NUMBER)) {
FireChangeEventIfNeeded();
rv = MaybeSubmitForm(aVisitor.mPresContext);
NS_ENSURE_SUCCESS(rv, rv);
@ -2422,6 +2606,8 @@ nsHTMLInputElement::HandleTypeChange(PRUint8 aNewType)
}
}
UpdateHasRange();
// Do not notify, it will be done after if needed.
UpdateAllValidityStates(false);
}
@ -2450,6 +2636,15 @@ nsHTMLInputElement::SanitizeValue(nsAString& aValue)
aValue = nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(aValue);
}
break;
case NS_FORM_INPUT_NUMBER:
{
PRInt32 ec;
PromiseFlatString(aValue).ToDouble(&ec);
if (NS_FAILED(ec)) {
aValue.Truncate();
}
}
break;
}
}
@ -2467,6 +2662,11 @@ nsHTMLInputElement::ParseAttribute(PRInt32 aNamespaceID,
bool success = aResult.ParseEnumValue(aValue, kInputTypeTable, false);
if (success) {
newType = aResult.GetEnumValue();
if (newType == NS_FORM_INPUT_NUMBER &&
!Preferences::GetBool("dom.experimental_forms", false)) {
newType = kInputDefaultType->value;
aResult.SetTo(newType, &aValue);
}
} else {
newType = kInputDefaultType->value;
}
@ -3068,6 +3268,7 @@ nsHTMLInputElement::SaveState()
case NS_FORM_INPUT_TEL:
case NS_FORM_INPUT_URL:
case NS_FORM_INPUT_HIDDEN:
case NS_FORM_INPUT_NUMBER:
{
if (mValueChanged) {
inputState = new nsHTMLInputElementState();
@ -3216,6 +3417,14 @@ nsHTMLInputElement::IntrinsicState() const
state |= NS_EVENT_STATE_MOZ_SUBMITINVALID;
}
// :in-range and :out-of-range only apply if the element currently has a range.
if (mHasRange) {
state |= (GetValidityState(VALIDITY_STATE_RANGE_OVERFLOW) ||
GetValidityState(VALIDITY_STATE_RANGE_UNDERFLOW))
? NS_EVENT_STATE_OUTOFRANGE
: NS_EVENT_STATE_INRANGE;
}
return state;
}
@ -3245,6 +3454,7 @@ nsHTMLInputElement::RestoreState(nsPresState* aState)
case NS_FORM_INPUT_TEL:
case NS_FORM_INPUT_URL:
case NS_FORM_INPUT_HIDDEN:
case NS_FORM_INPUT_NUMBER:
{
SetValueInternal(inputState->GetValue(), false, true);
break;
@ -3469,6 +3679,7 @@ nsHTMLInputElement::GetValueMode() const
case NS_FORM_INPUT_TEL:
case NS_FORM_INPUT_EMAIL:
case NS_FORM_INPUT_URL:
case NS_FORM_INPUT_NUMBER:
return VALUE_MODE_VALUE;
default:
NS_NOTYETIMPLEMENTED("Unexpected input type in GetValueMode()");
@ -3512,6 +3723,7 @@ nsHTMLInputElement::DoesReadOnlyApply() const
case NS_FORM_INPUT_TEL:
case NS_FORM_INPUT_EMAIL:
case NS_FORM_INPUT_URL:
case NS_FORM_INPUT_NUMBER:
return true;
default:
NS_NOTYETIMPLEMENTED("Unexpected input type in DoesReadOnlyApply()");
@ -3547,6 +3759,7 @@ nsHTMLInputElement::DoesRequiredApply() const
case NS_FORM_INPUT_TEL:
case NS_FORM_INPUT_EMAIL:
case NS_FORM_INPUT_URL:
case NS_FORM_INPUT_NUMBER:
return true;
default:
NS_NOTYETIMPLEMENTED("Unexpected input type in DoesRequiredApply()");
@ -3561,9 +3774,83 @@ nsHTMLInputElement::DoesRequiredApply() const
bool
nsHTMLInputElement::DoesPatternApply() const
{
// TODO: temporary until bug 635240 is fixed.
if (mType == NS_FORM_INPUT_NUMBER) {
return false;
}
return IsSingleLineTextControl(false);
}
bool
nsHTMLInputElement::DoesMinMaxApply() const
{
switch (mType)
{
case NS_FORM_INPUT_NUMBER:
// TODO:
// case NS_FORM_INPUT_RANGE:
// All date/time types.
return true;
#ifdef DEBUG
case NS_FORM_INPUT_RESET:
case NS_FORM_INPUT_SUBMIT:
case NS_FORM_INPUT_IMAGE:
case NS_FORM_INPUT_BUTTON:
case NS_FORM_INPUT_HIDDEN:
case NS_FORM_INPUT_RADIO:
case NS_FORM_INPUT_CHECKBOX:
case NS_FORM_INPUT_FILE:
case NS_FORM_INPUT_TEXT:
case NS_FORM_INPUT_PASSWORD:
case NS_FORM_INPUT_SEARCH:
case NS_FORM_INPUT_TEL:
case NS_FORM_INPUT_EMAIL:
case NS_FORM_INPUT_URL:
return false;
default:
NS_NOTYETIMPLEMENTED("Unexpected input type in DoesRequiredApply()");
return false;
#else // DEBUG
default:
return false;
#endif // DEBUG
}
}
double
nsHTMLInputElement::GetStep() const
{
NS_ASSERTION(mType == NS_FORM_INPUT_NUMBER,
"We can't be there if type!=number!");
// NOTE: should be defaultStep * defaultStepScaleFactor,
// which is 1 for type=number.
double step = 1;
if (HasAttr(kNameSpaceID_None, nsGkAtoms::step)) {
nsAutoString stepStr;
GetAttr(kNameSpaceID_None, nsGkAtoms::step, stepStr);
if (stepStr.LowerCaseEqualsLiteral("any")) {
// The element can't suffer from step mismatch if there is no step.
return kStepAny;
}
PRInt32 ec;
// NOTE: should be multiplied by defaultStepScaleFactor,
// which is 1 for type=number.
step = stepStr.ToDouble(&ec);
if (NS_FAILED(ec) || step <= 0) {
// NOTE: we should use defaultStep * defaultStepScaleFactor,
// which is 1 for type=number.
step = 1;
}
}
return step;
}
// nsIConstraintValidation
NS_IMETHODIMP
@ -3694,6 +3981,76 @@ nsHTMLInputElement::HasPatternMismatch() const
return !nsContentUtils::IsPatternMatching(value, pattern, doc);
}
bool
nsHTMLInputElement::IsRangeOverflow() const
{
nsAutoString maxStr;
if (!DoesMinMaxApply() ||
!GetAttr(kNameSpaceID_None, nsGkAtoms::max, maxStr)) {
return false;
}
PRInt32 ec;
double max = maxStr.ToDouble(&ec);
if (NS_FAILED(ec)) {
return false;
}
double value = GetValueAsDouble();
// value can be NaN when value="".
if (value != value) {
return false;
}
return value > max;
}
bool
nsHTMLInputElement::IsRangeUnderflow() const
{
nsAutoString minStr;
if (!DoesMinMaxApply() ||
!GetAttr(kNameSpaceID_None, nsGkAtoms::min, minStr)) {
return false;
}
PRInt32 ec;
double min = minStr.ToDouble(&ec);
if (NS_FAILED(ec)) {
return false;
}
double value = GetValueAsDouble();
// value can be NaN when value="".
if (value != value) {
return false;
}
return value < min;
}
bool
nsHTMLInputElement::HasStepMismatch() const
{
if (!DoesStepApply()) {
return false;
}
double value = GetValueAsDouble();
if (value != value) {
// The element can't suffer from step mismatch if it's value isn't a number.
return false;
}
double step = GetStep();
if (step == kStepAny) {
return false;
}
// Value has to be an integral multiple of step.
return fmod(value - GetStepBase(), step) != 0;
}
void
nsHTMLInputElement::UpdateTooLongValidityState()
{
@ -3772,6 +4129,24 @@ nsHTMLInputElement::UpdatePatternMismatchValidityState()
SetValidityState(VALIDITY_STATE_PATTERN_MISMATCH, HasPatternMismatch());
}
void
nsHTMLInputElement::UpdateRangeOverflowValidityState()
{
SetValidityState(VALIDITY_STATE_RANGE_OVERFLOW, IsRangeOverflow());
}
void
nsHTMLInputElement::UpdateRangeUnderflowValidityState()
{
SetValidityState(VALIDITY_STATE_RANGE_UNDERFLOW, IsRangeUnderflow());
}
void
nsHTMLInputElement::UpdateStepMismatchValidityState()
{
SetValidityState(VALIDITY_STATE_STEP_MISMATCH, HasStepMismatch());
}
void
nsHTMLInputElement::UpdateAllValidityStates(bool aNotify)
{
@ -3780,6 +4155,9 @@ nsHTMLInputElement::UpdateAllValidityStates(bool aNotify)
UpdateValueMissingValidityState();
UpdateTypeMismatchValidityState();
UpdatePatternMismatchValidityState();
UpdateRangeOverflowValidityState();
UpdateRangeUnderflowValidityState();
UpdateStepMismatchValidityState();
if (validBefore != IsValid()) {
UpdateState(aNotify);
@ -3887,6 +4265,95 @@ nsHTMLInputElement::GetValidationMessage(nsAString& aValidationMessage,
aValidationMessage = message;
break;
}
case VALIDITY_STATE_RANGE_OVERFLOW:
{
nsXPIDLString message;
nsAutoString maxStr;
GetAttr(kNameSpaceID_None, nsGkAtoms::max, maxStr);
// We want to show the double as parsed so we parse it and change maxStr.
PRInt32 ec;
double max = maxStr.ToDouble(&ec);
NS_ASSERTION(NS_SUCCEEDED(ec), "max must be a number at this point!");
maxStr.Truncate();
maxStr.AppendFloat(max);
const PRUnichar* params[] = { maxStr.get() };
rv = nsContentUtils::FormatLocalizedString(nsContentUtils::eDOM_PROPERTIES,
"FormValidationRangeOverflow",
params, message);
aValidationMessage = message;
break;
}
case VALIDITY_STATE_RANGE_UNDERFLOW:
{
nsXPIDLString message;
nsAutoString minStr;
GetAttr(kNameSpaceID_None, nsGkAtoms::min, minStr);
// We want to show the double as parsed so we parse it and change minStr.
PRInt32 ec;
double min = minStr.ToDouble(&ec);
NS_ASSERTION(NS_SUCCEEDED(ec), "min must be a number at this point!");
minStr.Truncate();
minStr.AppendFloat(min);
const PRUnichar* params[] = { minStr.get() };
rv = nsContentUtils::FormatLocalizedString(nsContentUtils::eDOM_PROPERTIES,
"FormValidationRangeUnderflow",
params, message);
aValidationMessage = message;
break;
}
case VALIDITY_STATE_STEP_MISMATCH:
{
nsXPIDLString message;
double value = GetValueAsDouble();
NS_ASSERTION(value == value, "The element can't suffer from a step "
"mismatch if its value is NaN");
double step = GetStep();
NS_ASSERTION(step != kStepAny, "The element can't suffer from a step "
"mismatch if @step is 'any'");
PRInt32 ec;
nsAutoString minStr;
GetAttr(kNameSpaceID_None, nsGkAtoms::min, minStr);
double min = minStr.ToDouble(&ec);
if (NS_FAILED(ec)) {
min = 0.f;
}
double valueLow = value - fmod(value - min, step);
double valueHigh = value + step - fmod(value - min, step);
nsAutoString maxStr;
GetAttr(kNameSpaceID_None, nsGkAtoms::max, maxStr);
double max = maxStr.ToDouble(&ec);
if (NS_FAILED(ec) || valueHigh <= max) {
nsAutoString valueLowStr, valueHighStr;
valueLowStr.AppendFloat(valueLow);
valueHighStr.AppendFloat(valueHigh);
const PRUnichar* params[] = { valueLowStr.get(), valueHighStr.get() };
rv = nsContentUtils::FormatLocalizedString(nsContentUtils::eDOM_PROPERTIES,
"FormValidationStepMismatch",
params, message);
} else {
nsAutoString valueLowStr;
valueLowStr.AppendFloat(valueLow);
const PRUnichar* params[] = { valueLowStr.get() };
rv = nsContentUtils::FormatLocalizedString(nsContentUtils::eDOM_PROPERTIES,
"FormValidationStepMismatchWithoutMax",
params, message);
}
aValidationMessage = message;
break;
}
default:
rv = nsIConstraintValidation::GetValidationMessage(aValidationMessage, aType);
}
@ -4313,3 +4780,33 @@ nsHTMLInputElement::UpdateValidityUIBits(bool aIsFocused)
}
}
void
nsHTMLInputElement::UpdateHasRange()
{
mHasRange = false;
if (mType != NS_FORM_INPUT_NUMBER) {
return;
}
// <input type=number> has a range if min or max is a valid float number.
nsAutoString tmpStr;
if (GetAttr(kNameSpaceID_None, nsGkAtoms::min, tmpStr)) {
PRInt32 ec;
tmpStr.ToDouble(&ec);
if (NS_SUCCEEDED(ec)) {
mHasRange = true;
return;
}
}
if (GetAttr(kNameSpaceID_None, nsGkAtoms::max, tmpStr)) {
PRInt32 ec;
tmpStr.ToDouble(&ec);
if (NS_SUCCEEDED(ec)) {
mHasRange = true;
return;
}
}
}

View File

@ -216,10 +216,16 @@ public:
bool IsValueMissing() const;
bool HasTypeMismatch() const;
bool HasPatternMismatch() const;
bool IsRangeOverflow() const;
bool IsRangeUnderflow() const;
bool HasStepMismatch() const;
void UpdateTooLongValidityState();
void UpdateValueMissingValidityState();
void UpdateTypeMismatchValidityState();
void UpdatePatternMismatchValidityState();
void UpdateRangeOverflowValidityState();
void UpdateRangeUnderflowValidityState();
void UpdateStepMismatchValidityState();
void UpdateAllValidityStates(bool aNotify);
void UpdateBarredFromConstraintValidation();
nsresult GetValidationMessage(nsAString& aValidationMessage,
@ -463,6 +469,26 @@ protected:
*/
bool DoesPatternApply() const;
/**
* Returns if the min and max attributes apply for the current type.
*/
bool DoesMinMaxApply() const;
/**
* Returns if the step attribute apply for the current type.
*/
bool DoesStepApply() const { return DoesMinMaxApply(); }
/**
* Returns if stepDown and stepUp methods apply for the current type.
*/
bool DoStepDownStepUpApply() const { return DoesStepApply(); }
/**
* Returns if valueAsNumber attribute applies for the current type.
*/
bool DoesValueAsNumberApply() const { return DoesMinMaxApply(); }
/**
* Returns if the maxlength attribute applies for the current type.
*/
@ -533,6 +559,50 @@ protected:
*/
nsIRadioGroupContainer* GetRadioGroupContainer() const;
/**
* Returns the input element's value as a double-precision float.
* Returns NaN if the current element's value is not a floating point number.
*
* @return the input element's value as a double-precision float.
*/
double GetValueAsDouble() const;
/**
* Sets the value of the element to the string representation of the double.
*
* @param aValue The double that will be used to set the value.
*/
void SetValue(double aValue);
/**
* Update the HAS_RANGE bit field value.
*/
void UpdateHasRange();
/**
* Returns the current step value.
* Returns kStepAny if the current step is "any" string.
*
* @return the current step value.
*/
double GetStep() const;
/**
* Return the base used to compute if a value matches step.
* Basically, it's the min attribute if present and a default value otherwise.
*
* @return The step base.
*/
double GetStepBase() const;
/**
* Apply a step change from stepUp or stepDown by multiplying aStep by the
* current step value.
*
* @param aStep The value used to be multiplied against the step value.
*/
nsresult ApplyStep(PRInt32 aStep);
nsCOMPtr<nsIControllers> mControllers;
/*
@ -578,6 +648,11 @@ protected:
*/
nsString mFocusedValue;
// Default step base value when a type do not have specific one.
static const double kDefaultStepBase;
// Float alue returned by GetStep() when the step attribute is set to 'any'.
static const double kStepAny;
/**
* The type of this input (<input type=...>) as an integer.
* @see nsIFormControl.h (specifically NS_FORM_INPUT_*)
@ -596,6 +671,7 @@ protected:
bool mInhibitRestoration : 1;
bool mCanShowValidUI : 1;
bool mCanShowInvalidUI : 1;
bool mHasRange : 1;
private:
struct nsFilePickerFilter {

View File

@ -72,10 +72,14 @@ nsIConstraintValidation::GetValidationMessage(nsAString& aValidationMessage)
GetValidationMessage(aValidationMessage, VALIDITY_STATE_TYPE_MISMATCH);
} else if (GetValidityState(VALIDITY_STATE_PATTERN_MISMATCH)) {
GetValidationMessage(aValidationMessage, VALIDITY_STATE_PATTERN_MISMATCH);
} else if (GetValidityState(VALIDITY_STATE_RANGE_OVERFLOW)) {
GetValidationMessage(aValidationMessage, VALIDITY_STATE_RANGE_OVERFLOW);
} else if (GetValidityState(VALIDITY_STATE_RANGE_UNDERFLOW)) {
GetValidationMessage(aValidationMessage, VALIDITY_STATE_RANGE_UNDERFLOW);
} else if (GetValidityState(VALIDITY_STATE_STEP_MISMATCH)) {
GetValidationMessage(aValidationMessage, VALIDITY_STATE_STEP_MISMATCH);
} else {
// TODO: The other messages have not been written
// because related constraint validation are not implemented yet.
// We should not be here.
// There should not be other validity states.
return NS_ERROR_UNEXPECTED;
}
} else {

View File

@ -42,6 +42,12 @@ _TEST_FILES = \
test_option_disabled.html \
test_meter_element.html \
test_meter_pseudo-classes.html \
test_max_attribute.html \
test_min_attribute.html \
test_step_attribute.html \
test_stepup_stepdown.html \
test_valueasnumber_attribute.html \
test_experimental_forms_pref.html \
$(NULL)
libs:: $(_TEST_FILES)

View File

@ -0,0 +1,43 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=764481
-->
<head>
<title>Test for Bug 764481</title>
<script type="application/javascript" src="/MochiKit/packed.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=764481">Mozilla Bug 764481</a>
<p id="display"></p>
<div id="content" style="display: none" >
</div>
<pre id="test">
<script type="application/javascript">
var input = document.createElement("input");
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({'set': [["dom.experimental_forms", false]]}, function() {
input.type = "number";
is(input.type, "text", "input type shouldn't be number when the experimental forms are disabled");
is(input.getAttribute('type'), "number", "input 'type' attribute should not change");
SpecialPowers.pushPrefEnv({'set': [["dom.experimental_forms",true]]}, function() {
// Change the type of input to text and then back to number,
// so that nsHTMLInputElement::ParseAttribute gets called with the pref enabled.
input.type = "text";
input.type = "number";
is(input.type, "number", "input type should be number when the experimental forms are enabled");
is(input.getAttribute('type'), "number", "input 'type' attribute should not change");
SimpleTest.finish();
});
});
</script>
</pre>
</body>
</html>

View File

@ -17,6 +17,8 @@
// TODO: maybe make those reflections be tested against all input types.
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({'set': [["dom.experimental_forms", true]]}, function() {
// .accept
reflectString({
element: document.createElement("input"),
@ -111,7 +113,10 @@ reflectUnsignedInt({
// TODO: list (HTMLElement)
// .max
todo("max" in document.createElement("input"), "max isn't implemented yet");
reflectString({
element: document.createElement('input'),
attribute: 'max',
});
// .maxLength
reflectInt({
@ -121,7 +126,10 @@ reflectInt({
});
// .min
todo("min" in document.createElement("input"), "min isn't implemented yet");
reflectString({
element: document.createElement('input'),
attribute: 'min',
});
// .multiple
reflectBoolean({
@ -173,7 +181,10 @@ reflectUnsignedInt({
// TODO: src (URL)
// .step
todo("step" in document.createElement("input"), "step isn't implemented yet");
reflectString({
element: document.createElement('input'),
attribute: 'step',
});
// .type
reflectLimitedEnumerated({
@ -181,11 +192,11 @@ reflectLimitedEnumerated({
attribute: "type",
validValues: [ "hidden", "text", "search", "tel", "url", "email", "password",
"checkbox", "radio", "file", "submit", "image", "reset",
"button" ],
"button", "number" ],
invalidValues: [ "this-is-probably-a-wrong-type", "", "tulip" ],
defaultValue: "text",
unsupportedValues: [ "datetime", "date", "month", "week", "time",
"datetime-local", "number", "range", "color" ]
"datetime-local", "range", "color" ]
});
// .defaultValue
@ -201,9 +212,9 @@ reflectString({
todo("valueAsDate" in document.createElement("input"),
"valueAsDate isn't implemented yet");
// .valueAsNumber
todo("valueAsNumber" in document.createElement("input"),
"valueAsNumber isn't implemented yet");
// Deeper check will be done with bug 763305.
is('valueAsNumber' in document.createElement("input"), true,
"valueAsNumber should be available");
// .selectedOption
todo("selectedOption" in document.createElement("input"),
@ -221,6 +232,9 @@ reflectUnsignedInt({
// .validationMessage doesn't reflect a content attribute.
// .labels doesn't reflect a content attribute.
SimpleTest.finish();
});
</script>
</pre>
</body>

View File

@ -0,0 +1,168 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=635499
-->
<head>
<title>Test for Bug 635499</title>
<script type="application/javascript" src="/MochiKit/packed.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=635499">Mozilla Bug 635499</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 635499 **/
var types = [
[ 'hidden', false ],
[ 'text', false ],
[ 'search', false ],
[ 'tel', false ],
[ 'url', false ],
[ 'email', false ],
[ 'password', false ],
[ 'datetime', true, true ],
[ 'date', true, true ],
[ 'month', true, true ],
[ 'week', true, true ],
[ 'time', true, true ],
[ 'datetime-local', true, true ],
[ 'number', true ],
[ 'range', true, true ],
[ 'color', false, true ],
[ 'checkbox', false ],
[ 'radio', false ],
[ 'file', false ],
[ 'submit', false ],
[ 'image', false ],
[ 'reset', false ],
[ 'button', false ],
];
var input = document.createElement("input");
document.getElementById('content').appendChild(input);
function checkValidity(aElement, aValidity, aApply, aRangeApply)
{
aValidity = aApply ? aValidity : true;
is(aElement.validity.valid, aValidity,
"element validity should be " + aValidity);
is(aElement.validity.rangeOverflow, !aValidity,
"element overflow status should be " + !aValidity);
is(aElement.validationMessage, aValidity
? "" : "Please select a value that is lower than " + aElement.max + ".",
"validation message");
is(aElement.mozMatchesSelector(":valid"), aElement.willValidate && aValidity,
(aElement.willValidate && aValidity) ? ":valid should apply" : "valid shouldn't apply");
is(aElement.mozMatchesSelector(":invalid"), aElement.willValidate && !aValidity,
(aElement.wil && aValidity) ? ":invalid shouldn't apply" : "valid should apply");
if (!aRangeApply) {
ok(!aElement.mozMatchesSelector(":in-range"), ":in-range should not match");
ok(!aElement.mozMatchesSelector(":out-of-range"),
":out-of-range should not match");
} else {
is(aElement.mozMatchesSelector(":in-range"), aValidity,
":in-range matches status should be " + aValidity);
is(aElement.mozMatchesSelector(":out-of-range"), !aValidity,
":out-of-range matches status should be " + !aValidity);
}
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({'set': [["dom.experimental_forms", true]]}, function() {
for each (var data in types) {
input.type = data[0];
var apply = data[1];
if (data[2]) {
todo_is(input.type, data[0], data[0] + " isn't implemented yet");
continue;
}
checkValidity(input, true, apply, false);
input.max = '2';
checkValidity(input, true, apply, apply);
if (input.type == 'url') {
input.value = 'http://mozilla.org';
checkValidity(input, true, apply, apply);
} else if (input.type == 'email') {
input.value = 'foo@bar.com';
checkValidity(input, true, apply, apply);
} else if (input.type == 'file') {
// Need privileges to set a filename with .value.
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var dirSvc = Components.classes["@mozilla.org/file/directory_service;1"]
.getService(Components.interfaces.nsIProperties);
var file = dirSvc.get("ProfD", Components.interfaces.nsIFile);
file.append('635499_file');
var outStream = Components.
classes["@mozilla.org/network/file-output-stream;1"].
createInstance(Components.interfaces.nsIFileOutputStream);
outStream.init(file, 0x02 | 0x08 | 0x20, // write, create, truncate
0666, 0);
outStream.write("foo", 3);
outStream.close();
input.value = file.path;
checkValidity(input, true, apply, apply);
file.remove(false);
} else {
input.value = '1';
checkValidity(input, true, apply, apply);
input.value = '2';
checkValidity(input, true, apply, apply);
input.value = 'foo';
checkValidity(input, true, apply, apply);
input.value = '3';
checkValidity(input, false, apply, apply);
input.max = '5';
checkValidity(input, true, apply, apply);
input.value = '42';
checkValidity(input, false, apply, apply);
}
input.max = '';
checkValidity(input, true, apply, false);
input.max = 'foo';
checkValidity(input, true, apply, false);
// Check that we correctly convert input.max to a double in validationMessage.
if (input.type == 'number') {
input.max = "4.333333333333333333333333333333333331";
input.value = "5";
is(input.validationMessage,
"Please select a value that is lower than 4.33333333333333.",
"validation message");
}
// Cleaning up,
input.removeAttribute('max');
input.value = '';
}
SimpleTest.finish();
});
</script>
</pre>
</body>
</html>

View File

@ -0,0 +1,168 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=635553
-->
<head>
<title>Test for Bug 635553</title>
<script type="application/javascript" src="/MochiKit/packed.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=635499">Mozilla Bug 635499</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 635553 **/
var types = [
[ 'hidden', false ],
[ 'text', false ],
[ 'search', false ],
[ 'tel', false ],
[ 'url', false ],
[ 'email', false ],
[ 'password', false ],
[ 'datetime', true, true ],
[ 'date', true, true ],
[ 'month', true, true ],
[ 'week', true, true ],
[ 'time', true, true ],
[ 'datetime-local', true, true ],
[ 'number', true ],
[ 'range', true, true ],
[ 'color', false, true ],
[ 'checkbox', false ],
[ 'radio', false ],
[ 'file', false ],
[ 'submit', false ],
[ 'image', false ],
[ 'reset', false ],
[ 'button', false ],
];
var input = document.createElement("input");
document.getElementById('content').appendChild(input);
function checkValidity(aElement, aValidity, aApply, aRangeApply)
{
aValidity = aApply ? aValidity : true;
is(aElement.validity.valid, aValidity,
"element validity should be " + aValidity);
is(aElement.validity.rangeUnderflow, !aValidity,
"element underflow status should be " + !aValidity);
is(aElement.validationMessage, aValidity
? "" : "Please select a value that is higher than " + aElement.min + ".",
"validation message");
is(aElement.mozMatchesSelector(":valid"), aElement.willValidate && aValidity,
(aElement.willValidate && aValidity) ? ":valid should apply" : "valid shouldn't apply");
is(aElement.mozMatchesSelector(":invalid"), aElement.willValidate && !aValidity,
(aElement.wil && aValidity) ? ":invalid shouldn't apply" : "valid should apply");
if (!aRangeApply) {
ok(!aElement.mozMatchesSelector(":in-range"), ":in-range should not match");
ok(!aElement.mozMatchesSelector(":out-of-range"),
":out-of-range should not match");
} else {
is(aElement.mozMatchesSelector(":in-range"), aValidity,
":in-range matches status should be " + aValidity);
is(aElement.mozMatchesSelector(":out-of-range"), !aValidity,
":out-of-range matches status should be " + !aValidity);
}
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({'set': [["dom.experimental_forms", true]]}, function() {
for each (var data in types) {
input.type = data[0];
var apply = data[1];
if (data[2]) {
todo_is(input.type, data[0], data[0] + " isn't implemented yet");
continue;
}
checkValidity(input, true, apply, false);
input.min = '0';
checkValidity(input, true, apply, apply);
if (input.type == 'url') {
input.value = 'http://mozilla.org';
checkValidity(input, true, apply, apply);
} else if (input.type == 'email') {
input.value = 'foo@bar.com';
checkValidity(input, true, apply, apply);
} else if (input.type == 'file') {
// Need privileges to set a filename with .value.
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var dirSvc = Components.classes["@mozilla.org/file/directory_service;1"]
.getService(Components.interfaces.nsIProperties);
var file = dirSvc.get("ProfD", Components.interfaces.nsIFile);
file.append('635499_file');
var outStream = Components.
classes["@mozilla.org/network/file-output-stream;1"].
createInstance(Components.interfaces.nsIFileOutputStream);
outStream.init(file, 0x02 | 0x08 | 0x20, // write, create, truncate
0666, 0);
outStream.write("foo", 3);
outStream.close();
input.value = file.path;
checkValidity(input, true, apply, apply);
file.remove(false);
} else {
input.value = '1';
checkValidity(input, true, apply, apply);
input.value = '0';
checkValidity(input, true, apply, apply);
input.value = 'foo';
checkValidity(input, true, apply, apply);
input.value = '-1';
checkValidity(input, false, apply, apply);
input.min = '-1';
checkValidity(input, true, apply, apply);
input.value = '-42';
checkValidity(input, false, apply, apply);
}
input.min = '';
checkValidity(input, true, apply, false);
input.min = 'foo';
checkValidity(input, true, apply, false);
// Check that we correctly convert input.min to a double in validationMessage.
if (input.type == 'number') {
input.min = "4.333333333333333333333333333333333331";
input.value = "2";
is(input.validationMessage,
"Please select a value that is higher than 4.33333333333333.",
"validation message");
}
// Cleaning up,
input.removeAttribute('min');
input.value = '';
}
SimpleTest.finish();
});
</script>
</pre>
</body>
</html>

View File

@ -44,12 +44,10 @@ var gInputTestData = [
['image', false],
['radio', false],
['submit', false],
// TODO: the next states are not yet implemented but we can't use a todo for
// them as the check will success so the test will fail (todo _has_ to fail).
// The tests are not failing because the unvalid states fallback to 'text'.
['search', true],
['email', true],
['url', true],
['number', false],
];
/**
@ -58,7 +56,6 @@ var gInputTestData = [
*/
var gInputTodoData = [
/* type expected result */
['number', false],
['range', false],
['color', false],
['date', false],
@ -105,6 +102,8 @@ function checkMozIsTextFieldValueTodo(aInput, aResult)
"mozIsTextField(true) should return " + aResult);
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({'set': [["dom.experimental_forms", true]]}, function() {
// Check if the method is defined for the correct elements.
for each (data in gElementTestData) {
checkMozIsTextFieldDefined(data[0], data[1]);
@ -123,6 +122,9 @@ for each (data in gInputTodoData) {
checkMozIsTextFieldValueTodo(input, data[1]);
}
SimpleTest.finish();
});
</script>
</pre>
</body>

View File

@ -261,11 +261,13 @@ var input = document.getElementById('i');
// and |invalidTypes| are the ones which do not accept it.
var validTypes = Array('text', 'password', 'search', 'tel', 'email', 'url');
var barredTypes = Array('hidden', 'reset', 'button', 'submit', 'image');
var invalidTypes = Array('checkbox', 'radio', 'file');
var invalidTypes = Array('checkbox', 'radio', 'file', 'number');
// TODO: 'datetime', 'date', 'month', 'week', 'time', 'datetime-local',
// 'number', 'range', ande 'color' do not accept the @pattern too but are
// not implemented yet.
// 'range', and 'color' do not accept the @pattern too but are not
// implemented yet.
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({'set': [["dom.experimental_forms", true]]}, function() {
for each (type in validTypes) {
input.type = type;
completeValidityCheck(input, false);
@ -282,6 +284,9 @@ for each (type in invalidTypes) {
completeValidityCheck(input, true);
}
SimpleTest.finish();
});
</script>
</pre>
</body>

View File

@ -162,6 +162,8 @@ function checkInputRequiredValidity(type)
element.value = 'foo@bar.com';
} else if (element.type == 'url') {
element.value = 'http://mozilla.org/';
} else if (element.type == 'number') {
element.value = '42';
} else {
element.value = 'foo';
}
@ -369,9 +371,10 @@ for each (type in typeRequireNotApply) {
}
// Now, checking for all types which accept the required attribute.
// TODO: check 'datetime', 'date', 'month', 'week', 'time', 'datetime-local'
// and 'number' when they will be implemented.
var typeRequireApply = ["text", "password", "search", "tel", "email", "url"];
// TODO: check 'datetime', 'date', 'month', 'week', 'time' and 'datetime-local'
// when they will be implemented.
var typeRequireApply = ["text", "password", "search", "tel", "email", "url",
"number"];
for each (type in typeRequireApply) {
checkInputRequiredValidity(type);

View File

@ -0,0 +1,259 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=635553
-->
<head>
<title>Test for Bug 635553</title>
<script type="application/javascript" src="/MochiKit/packed.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=635499">Mozilla Bug 635499</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 635553 **/
var types = [
[ 'hidden', false ],
[ 'text', false ],
[ 'search', false ],
[ 'tel', false ],
[ 'url', false ],
[ 'email', false ],
[ 'password', false ],
[ 'datetime', true, true ],
[ 'date', true, true ],
[ 'month', true, true ],
[ 'week', true, true ],
[ 'time', true, true ],
[ 'datetime-local', true, true ],
[ 'number', true ],
[ 'range', true, true ],
[ 'color', false, true ],
[ 'checkbox', false ],
[ 'radio', false ],
[ 'file', false ],
[ 'submit', false ],
[ 'image', false ],
[ 'reset', false ],
[ 'button', false ],
];
var input = document.createElement("input");
document.getElementById('content').appendChild(input);
function checkValidity(aElement, aValidity, aApply)
{
aValidity = aApply ? aValidity : true;
is(aElement.validity.valid, aValidity,
"element validity should be " + aValidity);
is(aElement.validity.stepMismatch, !aValidity,
"element step mismatch status should be " + !aValidity);
if (aValidity) {
is(aElement.validationMessage, "", "There should be no validation message.");
} else {
var value = parseFloat(aElement.value);
var min = parseFloat(aElement.min);
if (isNaN(min)) min = 0;
var step = parseFloat(aElement.step);
if (isNaN(step) || step <= 0) step = 1;
var modulo = (value - min) % step;
is(aElement.validationMessage, "Please select a valid value. " +
"The two nearest valid values are " + (value - modulo) + " and " +
(value - modulo + step) + ".", "There should be a validation message.");
}
is(aElement.mozMatchesSelector(":valid"), aElement.willValidate && aValidity,
(aElement.willValidate && aValidity) ? ":valid should apply" : "valid shouldn't apply");
is(aElement.mozMatchesSelector(":invalid"), aElement.willValidate && !aValidity,
(aElement.wil && aValidity) ? ":invalid shouldn't apply" : "valid should apply");
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({'set': [["dom.experimental_forms", true]]}, function() {
for each (var data in types) {
input.type = data[0];
var apply = data[1];
if (data[2]) {
todo_is(input.type, data[0], data[0] + " isn't implemented yet");
continue;
}
checkValidity(input, true, apply);
input.step = '0';
checkValidity(input, true, apply);
if (input.type == 'url') {
input.value = 'http://mozilla.org';
checkValidity(input, true, apply);
} else if (input.type == 'email') {
input.value = 'foo@bar.com';
checkValidity(input, true, apply);
} else if (input.type == 'file') {
// Need privileges to set a filename with .value.
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var dirSvc = Components.classes["@mozilla.org/file/directory_service;1"]
.getService(Components.interfaces.nsIProperties);
var file = dirSvc.get("ProfD", Components.interfaces.nsIFile);
file.append('635499_file');
var outStream = Components.
classes["@mozilla.org/network/file-output-stream;1"].
createInstance(Components.interfaces.nsIFileOutputStream);
outStream.init(file, 0x02 | 0x08 | 0x20, // write, create, truncate
0666, 0);
outStream.write("foo", 3);
outStream.close();
input.value = file.path;
checkValidity(input, true, apply);
file.remove(false);
} else {
// When step=0, the allowed step is 1.
input.value = '1.2';
checkValidity(input, false, apply);
input.value = '1';
checkValidity(input, true, apply);
input.value = '0';
checkValidity(input, true, apply);
// When step is NaN, the allowed step value is 1.
input.step = 'foo';
input.value = '1';
checkValidity(input, true, apply);
input.value = '1.5';
checkValidity(input, false, apply);
// When step is negative, the allowed step value is 1.
input.step = '-0.1';
checkValidity(input, false, apply);
input.value = '1';
checkValidity(input, true, apply);
// When step is missing, the allowed step value is 1.
input.removeAttribute('step');
input.value = '1.5';
checkValidity(input, false, apply);
input.value = '1';
checkValidity(input, true, apply);
// When step is 'any', all values are fine wrt to step.
input.step = 'any';
checkValidity(input, true, apply);
input.step = 'aNy';
input.value = '1337';
checkValidity(input, true, apply);
input.step = 'AnY';
input.value = '0.1';
checkValidity(input, true, apply);
input.step = 'ANY';
input.value = '-13.37';
checkValidity(input, true, apply);
// When min is set to a valid float, there is a step base.
input.min = '1';
input.step = '2';
input.value = '3';
checkValidity(input, true, apply);
input.value = '2';
checkValidity(input, false, apply);
input.removeAttribute('step'); // step = 1
input.min = '0.5';
input.value = '5.5';
checkValidity(input, true, apply);
input.value = '1';
checkValidity(input, false, apply);
input.min = '-0.1';
input.step = '1';
input.value = '0.9';
checkValidity(input, true, apply);
input.value = '0.1';
checkValidity(input, false, apply);
// When min is set to NaN, there is no step base (step base=0 actually).
input.min = 'foo';
input.step = '1';
input.value = '1';
checkValidity(input, true, apply);
input.value = '0.5';
checkValidity(input, false, apply);
input.min = '';
input.value = '1';
checkValidity(input, true, apply);
input.value = '0.5';
checkValidity(input, false, apply);
input.removeAttribute('min');
// If value isn't a number, the element isn't invalid.
input.value = '';
checkValidity(input, true, apply);
// Regular situations.
input.step = '2';
input.value = '1.5';
checkValidity(input, false, apply);
input.value = '42.0';
checkValidity(input, true, apply);
input.step = '0.1';
input.value = '-0.1';
checkValidity(input, true, apply);
}
if (input.type == 'number') {
// Check that when the higher value is higher than max, we don't show it.
input.step = '2';
input.min = '1';
input.max = '10.9';
input.value = '10';
is(input.validationMessage, "Please select a valid value. " +
"The nearest valid value is 9.",
"The validation message should not include the higher value.");
input.removeAttribute('min');
input.removeAttribute('max');
}
// Cleaning up,
input.removeAttribute('step');
input.value = '';
}
SimpleTest.finish();
});
</script>
</pre>
</body>
</html>

View File

@ -0,0 +1,353 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=636627
-->
<head>
<title>Test for Bug 636627</title>
<script type="application/javascript" src="/MochiKit/packed.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=636627">Mozilla Bug 636627</a>
<p id="display"></p>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 636627 **/
/**
* This test is testing stepDown() and stepUp().
*/
function checkPresence()
{
var input = document.createElement('input');
is('stepDown' in input, true, 'stepDown() should be an input function');
is('stepUp' in input, true, 'stepUp() should be an input function');
}
function checkAvailability()
{
var testData =
[
["text", false],
["password", false],
["search", false],
["telephone", false],
["email", false],
["url", false],
["hidden", false],
["checkbox", false],
["radio", false],
["file", false],
["submit", false],
["image", false],
["reset", false],
["button", false],
["number", true],
// The next types have not been implemented but will fallback to "text"
// which has the same value.
["color", false],
];
var todoList =
[
["datetime", true],
["date", true],
["month", true],
["week", true],
["time", true],
["datetime-local", true],
["range", true],
];
var element = document.createElement("input");
element.setAttribute('value', '0');
for each (data in testData) {
var exceptionCaught = false;
element.type = data[0];
try {
element.stepDown();
} catch (e) {
exceptionCaught = true;
}
is(exceptionCaught, !data[1], "stepDown() availability is not correct");
exceptionCaught = false;
try {
element.stepUp();
} catch (e) {
exceptionCaught = true;
}
is(exceptionCaught, !data[1], "stepUp() availability is not correct");
}
for each (data in todoList) {
var exceptionCaught = false;
element.type = data[0];
try {
element.stepDown();
} catch (e) {
exceptionCaught = true;
}
todo_is(exceptionCaught, !data[1],
"stepDown() availability is not correct");
exceptionCaught = false;
try {
element.stepUp();
} catch (e) {
exceptionCaught = true;
}
todo_is(exceptionCaught, !data[1],
"stepUp() availability is not correct");
}
}
function checkStepDownForNumber()
{
// This testData is very similar to the one in checkStepUpForNumber
// with some changes relative to stepDown.
var testData = [
/* Initial value | step | min | max | stepDown arg | final value | exception */
// Regular case.
[ '1', null, null, null, null, '0', false ],
// Argument testing.
[ '1', null, null, null, 1, '0', false ],
[ '9', null, null, null, 9, '0', false ],
[ '1', null, null, null, -1, '2', false ],
[ '1', null, null, null, 0, '1', false ],
// Float values are rounded to integer (1.1 -> 1).
[ '1', null, null, null, 1.1, '0', false ],
// With step values.
[ '1', '0.5', null, null, null, '0.5', false ],
[ null, '0.5', null, null, null, '0', false ],
[ null, '0.5', null, null, null, '-0.5', false ],
[ '1', '0.25', null, null, 4, '0', false ],
// step = 0 isn't allowed (-> step = 1).
[ '1', '0', null, null, null, '0', false ],
// step < 0 isn't allowed (-> step = 1).
[ '1', '-1', null, null, null, '0', false ],
// step = NaN isn't allowed (-> step = 1).
[ '1', 'foo', null, null, null, '0', false ],
// Min values testing.
[ '1', '1', 'foo', null, null, '0', false ],
[ '1', null, '-10', null, null, '0', false ],
[ '1', null, '0', null, null, '0', false ],
[ '1', null, '10', null, null, '1', false ],
[ '1', null, '2', null, null, '1', false ],
[ '1', null, '1', null, null, '1', false ],
// Max values testing.
[ '1', '1', null, 'foo', null, '0', false ],
[ '1', null, null, '10', null, '0', false ],
[ '1', null, null, '0', null, '0', false ],
[ '1', null, null, '-10', null, '-10', false ],
[ '1', null, null, '1', null, '0', false ],
[ '5', null, null, '3', '3', '2', false ],
[ '5', '2', null, '3', '2', '2', false ],
[ '-3', '5', '-10', '-3', null, '-5', false ],
// Step mismatch.
[ '1', '2', '-2', null, null, '0', false ],
[ '3', '2', '-2', null, null, '2', false ],
[ '3', '2', '-2', null, '2', '0', false ],
[ '3', '2', '-2', null, '-2', '6', false ],
[ '1', '2', null, null, null, '0', false ],
[ '1', '2', '-2', null, null, '0', false ],
[ '1', '3', null, null, null, '0', false ],
[ '2', '3', null, null, null, '0', false ],
[ '2', '3', '1', null, null, '1', false ],
[ '5', '3', '1', null, null, '4', false ],
[ '3', '2', null, null, null, '2', false ],
[ '5', '2', null, null, null, '4', false ],
[ '6', '2', '1', null, null, '5', false ],
[ '8', '3', '1', null, null, '7', false ],
[ '9', '2', '-10', null, null, '8', false ],
[ '7', '3', '-10', null, null, '5', false ],
[ '-2', '3', '-10', null, null, '-4', false ],
// Clamping.
[ '0', '2', '-1', null, null, '-1', false ],
[ '10', '2', '0', '4', '10', '0', false ],
[ '10', '2', '0', '4', '5', '0', false ],
// value = "" (NaN).
[ '', null, null, null, null, '', false ],
// With step = 'any'.
[ '0', 'any', null, null, 1, null, true ],
[ '0', 'ANY', null, null, 1, null, true ],
[ '0', 'AnY', null, null, 1, null, true ],
[ '0', 'aNy', null, null, 1, null, true ],
];
var element = document.createElement("input");
element.type = 'number';
for each (var data in testData) {
if (data[0] != null) {
element.value = data[0];
}
if (data[1] != null) {
element.step = data[1];
}
if (data[2] != null) {
element.min = data[2];
}
if (data[3] != null) {
element.max = data[3];
}
var exceptionCaught = false;
try {
if (data[4] != null) {
element.stepDown(data[4]);
} else {
element.stepDown();
}
is(element.value, data[5], "The value should be " + data[5]);
} catch (e) {
exceptionCaught = true;
is(element.value, data[0], e.name + "The value should not have changed");
is(e.name, 'InvalidStateError',
"It should be a InvalidStateError exception.");
} finally {
is(exceptionCaught, data[6], "exception status should be " + data[6]);
}
element.removeAttribute('step');
element.removeAttribute('min');
element.removeAttribute('max');
}
}
function checkStepUpForNumber()
{
// This testData is very similar to the one in checkStepDownForNumber
// with some changes relative to stepUp.
var testData = [
/* Initial value | step | min | max | stepUp arg | final value | exception */
// Regular case.
[ '1', null, null, null, null, '2', false ],
// Argument testing.
[ '1', null, null, null, 1, '2', false ],
[ '9', null, null, null, 9, '18', false ],
[ '1', null, null, null, -1, '0', false ],
[ '1', null, null, null, 0, '1', false ],
// Float values are rounded to integer (1.1 -> 1).
[ '1', null, null, null, 1.1, '2', false ],
// With step values.
[ '1', '0.5', null, null, null, '1.5', false ],
[ null, '0.5', null, null, null, '2', false ],
[ null, '0.5', null, null, null, '2.5', false ],
[ '1', '0.25', null, null, 4, '2', false ],
// step = 0 isn't allowed (-> step = 1).
[ '1', '0', null, null, null, '2', false ],
// step < 0 isn't allowed (-> step = 1).
[ '1', '-1', null, null, null, '2', false ],
// step = NaN isn't allowed (-> step = 1).
[ '1', 'foo', null, null, null, '2', false ],
// Min values testing.
[ '1', '1', 'foo', null, null, '2', false ],
[ '1', null, '-10', null, null, '2', false ],
[ '1', null, '0', null, null, '2', false ],
[ '1', null, '10', null, null, '10', false ],
[ '1', null, '2', null, null, '2', false ],
[ '1', null, '1', null, null, '2', false ],
[ '0', null, '4', null, '5', '5', false ],
[ '0', '2', '5', null, '3', '5', false ],
// Max values testing.
[ '1', '1', null, 'foo', null, '2', false ],
[ '1', null, null, '10', null, '2', false ],
[ '1', null, null, '0', null, '1', false ],
[ '1', null, null, '-10', null, '1', false ],
[ '1', null, null, '1', null, '1', false ],
[ '-3', '5', '-10', '-3', null, '-3', false ],
// Step mismatch.
[ '1', '2', '0', null, null, '2', false ],
[ '1', '2', '0', null, '2', '4', false ],
[ '8', '2', null, '9', null, '8', false ],
[ '-3', '2', null, null, null, '-2', false ],
[ '9', '3', '-10', null, null, '11', false ],
[ '7', '3', '-10', null, null, '8', false ],
[ '7', '3', '5', null, null, '8', false ],
[ '9', '4', '3', null, null, '11', false ],
[ '-2', '3', '-6', null, null, '0', false ],
[ '7', '3', '6', null, null, '9', false ],
// Clamping.
[ '1', '2', '0', '3', null, '2', false ],
[ '0', '5', '1', '8', '10', '6', false ],
[ '-9', '3', '-8', '-1', '5', '-2', false ],
[ '-9', '3', '8', '15', '15', '14', false ],
[ '-1', '3', '-1', '4', '3', '2', false ],
[ '-3', '2', null, '-2', null, '-2', false ],
[ '-3', '2', null, '-1', null, '-2', false ],
// value = "" (NaN).
[ '', null, null, null, null, '', false ],
// With step = 'any'.
[ '0', 'any', null, null, 1, null, true ],
[ '0', 'ANY', null, null, 1, null, true ],
[ '0', 'AnY', null, null, 1, null, true ],
[ '0', 'aNy', null, null, 1, null, true ],
];
var element = document.createElement("input");
element.type = 'number';
for each (var data in testData) {
if (data[0] != null) {
element.value = data[0];
}
if (data[1] != null) {
element.step = data[1];
}
if (data[2] != null) {
element.min = data[2];
}
if (data[3] != null) {
element.max = data[3];
}
var exceptionCaught = false;
try {
if (data[4] != null) {
element.stepUp(data[4]);
} else {
element.stepUp();
}
is(element.value, data[5], "The value should be " + data[5]);
} catch (e) {
exceptionCaught = true;
is(element.value, data[0], e.name + "The value should not have changed");
is(e.name, 'InvalidStateError',
"It should be a InvalidStateError exception.");
} finally {
is(exceptionCaught, data[6], "exception status should be " + data[6]);
}
element.removeAttribute('step');
element.removeAttribute('min');
element.removeAttribute('max');
}
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({'set': [["dom.experimental_forms", true]]}, function() {
checkPresence();
checkAvailability();
checkStepDownForNumber();
checkStepUpForNumber();
SimpleTest.finish();
});
</script>
</pre>
</body>
</html>

View File

@ -285,6 +285,8 @@ function checkValidityStateObjectAliveWithoutElement(element)
ok(v.valid, "When the element is not alive, it should be valid");
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({'set': [["dom.experimental_forms", true]]}, function() {
checkConstraintValidationAPIExist(document.getElementById('f'));
checkConstraintValidationAPIExist(document.getElementById('i'));
checkConstraintValidationAPIExist(document.getElementById('b'));
@ -339,6 +341,9 @@ checkValidityStateObjectAliveWithoutElement("textarea");
checkValidityStateObjectAliveWithoutElement("output");
checkValidityStateObjectAliveWithoutElement("object");
SimpleTest.finish();
});
</script>
</pre>
</body>

View File

@ -0,0 +1,181 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=636737
-->
<head>
<title>Test for Bug 636737</title>
<script type="application/javascript" src="/MochiKit/packed.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=636737">Mozilla Bug 636737</a>
<p id="display"></p>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 636737 **/
/**
* This test is checking .valueAsNumber.
*/
// Global variable used by all functions.
var element = document.createElement("input");
function checkAvailability()
{
var testData =
[
["text", false],
["password", false],
["search", false],
["telephone", false],
["email", false],
["url", false],
["hidden", false],
["checkbox", false],
["radio", false],
["file", false],
["submit", false],
["image", false],
["reset", false],
["button", false],
["number", true],
// The next types have not been implemented but will fallback to "text"
// which has the same value.
["color", false],
];
var todoList =
[
["datetime", true],
["date", true],
["month", true],
["week", true],
["time", true],
["datetime-local", true],
["range", true],
];
for each (data in testData) {
var exceptionCatched = false;
element.type = data[0];
try {
element.valueAsNumber;
} catch (e) {
exceptionCatched = true;
}
is(exceptionCatched, false,
"valueAsNumber shouldn't throw exception on getting");
exceptionCatched = false;
try {
element.valueAsNumber = 42;
} catch (e) {
exceptionCatched = true;
}
is(exceptionCatched, !data[1], "valueAsNumber for " + data[0] +
" availability is not correct");
}
for each (data in todoList) {
var exceptionCatched = false;
element.type = data[0];
try {
element.valueAsNumber;
} catch (e) {
exceptionCatched = true;
}
is(exceptionCatched, false,
"valueAsNumber shouldn't throw exception on getting");
exceptionCatched = false;
try {
element.valueAsNumber = 42;
} catch (e) {
exceptionCatched = true;
}
todo_is(exceptionCatched, !data[1],
"valueAsNumber for " + data[0] + " availability is not correct");
}
}
function checkGet()
{
var testData =
[
["42", 42],
["-42", -42], // should work for negative values
["42.1234", 42.1234],
["123.12345678912345", 123.12345678912345], // double precision
["1e2", 100], // e should be usable
["2e1", 20],
["1e-1", 0.1], // value after e can be negative
["1E2", 100], // E can be used instead of e
["e", null],
["e2", null],
["1e0.1", null],
["", null], // the empty string is not a number
["foo", null],
["42,13", null], // comma can't be used as a decimal separator
];
element.type = "number";
for each (data in testData) {
element.value = data[0];
if (data[1] != null) {
is(element.valueAsNumber, data[1], "valueAsNumber should return the " +
"floating point representation of the value");
} else {
ok(isNaN(element.valueAsNumber), "valueAsNumber should return NaN " +
"when the element value is not a number");
}
}
}
function checkSet()
{
var testData =
[
[42, "42"],
[-42, "-42"], // should work for negative values
[42.1234, "42.1234"],
[123.123456789123, "123.123456789123"], // double precision
[1e2, "100"], // e should be usable
[2e1, "20"],
[1e-1, "0.1"], // value after e can be negative
[1E2, "100"], // E can be used instead of e
["", null], // the empty string is not a number
["foo", null],
];
element.type = "number";
for each (data in testData) {
element.valueAsNumber = data[0];
if (data[1] != null) {
is(element.value, data[1],
"valueAsNumber should be able to set the value");
} else {
element.valueAsNumber = testData[0];
isnot(element.value, data[1],
"valueAsNumber should not set the value if it's not a number");
}
}
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({'set': [["dom.experimental_forms", true]]}, function() {
checkAvailability();
checkGet();
checkSet();
SimpleTest.finish();
});
</script>
</pre>
</body>
</html>

View File

@ -25,12 +25,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=549475
var inputTypes =
[
"text", "password", "search", "tel", "hidden", "checkbox", "radio",
"submit", "image", "reset", "button", "email", "url"
"submit", "image", "reset", "button", "email", "url", "number",
];
var todoTypes =
[
"number", "range", "color",
"range", "color",
"date", "month", "week", "time", "datetime", "datetime-local",
];
@ -60,8 +60,7 @@ function sanitizeValue(aType, aValue)
// TODO: write the sanitize algorithm.
return "";
case "number":
// TODO: write the sanitize algorithm.
return "";
return (parseFloat(aValue) + "" === aValue) ? aValue : "";
case "range":
// TODO: write the sanitize algorithm.
return "";
@ -77,11 +76,17 @@ function checkSanitizing(element)
{
var testData =
[
// For text, password, search, tel, email:
"\n\rfoo\n\r",
"foo\n\rbar",
" foo ",
" foo\n\r bar ",
// For url:
"\r\n foobar \n\r",
// For number:
"42",
"13.37",
"1.234567898765432",
];
for each (value in testData) {
@ -126,6 +131,8 @@ function checkSanitizing(element)
}
}
var pref = SpecialPowers.getBoolPref("dom.experimental_forms");
SpecialPowers.setBoolPref("dom.experimental_forms", true);
for each (type in inputTypes) {
var form = document.forms[0];
var element = document.createElement("input");
@ -161,6 +168,8 @@ for each (type in todoTypes) {
form.removeChild(element);
}
SpecialPowers.setBoolPref("dom.experimental_forms", pref);
</script>
</pre>
</body>

View File

@ -2584,6 +2584,37 @@ nsDocShell::AddSessionStorage(nsIPrincipal* aPrincipal,
return NS_OK;
}
static PLDHashOperator
CloneSessionStorages(nsCStringHashKey::KeyType aKey, nsIDOMStorage* aStorage,
void* aUserArg)
{
nsIDocShell *docShell = static_cast<nsIDocShell*>(aUserArg);
nsCOMPtr<nsPIDOMStorage> pistorage = do_QueryInterface(aStorage);
if (pistorage) {
nsCOMPtr<nsIDOMStorage> storage = pistorage->Clone();
docShell->AddSessionStorage(pistorage->Principal(), storage);
}
return PL_DHASH_NEXT;
}
NS_IMETHODIMP
nsDocShell::CloneSessionStoragesTo(nsIDocShell* aDocShell)
{
aDocShell->ClearSessionStorages();
mStorages.EnumerateRead(CloneSessionStorages, aDocShell);
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::ClearSessionStorages()
{
mStorages.Clear();
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::GetCurrentDocumentChannel(nsIChannel** aResult)
{

View File

@ -39,7 +39,7 @@ interface nsIWebBrowserPrint;
interface nsIVariant;
interface nsIPrivacyTransitionObserver;
[scriptable, uuid(6f60ac96-fa2c-41a5-92b4-29aaadbd7a7b)]
[scriptable, builtinclass, uuid(89ea9f32-18ec-413b-9e2c-ce9a4c851b1c)]
interface nsIDocShell : nsISupports
{
/**
@ -434,6 +434,19 @@ interface nsIDocShell : nsISupports
*/
void addSessionStorage(in nsIPrincipal principal, in nsIDOMStorage storage);
/**
* Clones all session storage objects and attaches them to the given docshell.
* Useful when duplicating tabs and their states.
*
* @param docShell the docshell to clone the sessionstorage objects to
*/
void cloneSessionStoragesTo(in nsIDocShell docShell);
/**
* Removes all WebApps session storage objects attached to the docshell.
*/
void clearSessionStorages();
/**
* Gets the channel for the currently loaded document, if any.
* For a new document load, this will be the channel of the previous document

View File

@ -20,7 +20,7 @@ interface nsIDOMValidityState;
* http://www.whatwg.org/specs/web-apps/current-work/
*/
[scriptable, uuid(ac2e2b14-b987-452c-a071-5823b2406b85)]
[scriptable, uuid(c12471c8-155f-4368-9e8b-13a231e85f3b)]
interface nsIDOMHTMLInputElement : nsIDOMHTMLElement
{
attribute DOMString accept;
@ -44,7 +44,9 @@ interface nsIDOMHTMLInputElement : nsIDOMHTMLElement
attribute boolean indeterminate;
readonly attribute nsIDOMHTMLElement list;
attribute DOMString max;
attribute long maxLength;
attribute DOMString min;
attribute boolean multiple;
attribute DOMString name;
@ -53,6 +55,7 @@ interface nsIDOMHTMLInputElement : nsIDOMHTMLElement
attribute DOMString placeholder;
attribute boolean readOnly;
attribute boolean required;
attribute DOMString step;
attribute DOMString align;
@ -63,6 +66,10 @@ interface nsIDOMHTMLInputElement : nsIDOMHTMLElement
attribute DOMString type;
attribute DOMString defaultValue;
attribute DOMString value;
attribute double valueAsNumber;
[optional_argc] void stepDown([optional] in long n);
[optional_argc] void stepUp([optional] in long n);
// The following lines are part of the constraint validation API, see:
// http://www.whatwg.org/specs/web-apps/current-work/#the-constraint-validation-api

View File

@ -40,6 +40,14 @@ FormValidationInvalidURL=Please enter a URL.
FormValidationPatternMismatch=Please match the requested format.
# LOCALIZATION NOTE (FormValidationPatternMismatchWithTitle): %S is the (possibly truncated) title attribute value.
FormValidationPatternMismatchWithTitle=Please match the requested format: %S.
# LOCALIZATION NOTE (FormValidationRangeOverflow): %S can be a number or a date.
FormValidationRangeOverflow=Please select a value that is lower than %S.
# LOCALIZATION NOTE (FormValidationRangeUnderflow): %S can be a number or a date.
FormValidationRangeUnderflow=Please select a value that is higher than %S.
# LOCALIZATION NOTE (FormValidationStepMismatch): both %S can be a number or a date.
FormValidationStepMismatch=Please select a valid value. The two nearest valid values are %S and %S.
# LOCALIZATION NOTE (FormValidationStepMismatchWitoutMax): %S can be a number or a date. This is called instead of FormValidationStepMismatch when the second value isn't valid because it's higher than the maximum allowed value.
FormValidationStepMismatchWithoutMax=Please select a valid value. The nearest valid value is %S.
GetAttributeNodeWarning=Use of getAttributeNode() is deprecated. Use getAttribute() instead.
SetAttributeNodeWarning=Use of setAttributeNode() is deprecated. Use setAttribute() instead.
GetAttributeNodeNSWarning=Use of getAttributeNodeNS() is deprecated. Use getAttributeNS() instead.

View File

@ -9,6 +9,7 @@
#if defined(XP_UNIX)
#include "unistd.h"
#include "dirent.h"
#endif // defined(XP_UNIX)
#if defined(XP_MACOSX)
@ -264,6 +265,19 @@ static dom::ConstantSpec gLibcProperties[] =
#endif // defined(EWOULDBLOCK)
INT_CONSTANT(EXDEV),
#if defined(DT_UNKNOWN)
// Constants for |readdir|
INT_CONSTANT(DT_UNKNOWN),
INT_CONSTANT(DT_FIFO),
INT_CONSTANT(DT_CHR),
INT_CONSTANT(DT_DIR),
INT_CONSTANT(DT_BLK),
INT_CONSTANT(DT_REG),
INT_CONSTANT(DT_LNK),
INT_CONSTANT(DT_SOCK),
INT_CONSTANT(DT_WHT),
#endif // defined(DT_UNKNOWN)
// Constants used to define data structures
//
// Many data structures have different fields/sizes/etc. on
@ -274,9 +288,40 @@ static dom::ConstantSpec gLibcProperties[] =
#if defined(XP_UNIX)
// The size of |mode_t|.
{"OSFILE_SIZEOF_MODE_T", INT_TO_JSVAL(sizeof (mode_t)) },
{ "OSFILE_SIZEOF_MODE_T", INT_TO_JSVAL(sizeof (mode_t)) },
// Defining |dirent|.
// Size
{ "OSFILE_SIZEOF_DIRENT", INT_TO_JSVAL(sizeof (dirent)) },
// Offset of field |d_name|.
{ "OSFILE_OFFSETOF_DIRENT_D_NAME", INT_TO_JSVAL(offsetof (struct dirent, d_name)) },
// An upper bound to the length of field |d_name| of struct |dirent|.
// (may not be exact, depending on padding).
{ "OSFILE_SIZEOF_DIRENT_D_NAME", INT_TO_JSVAL(sizeof (struct dirent) - offsetof (struct dirent, d_name)) },
#if defined(DT_UNKNOWN)
// Position of field |d_type| in |dirent|
// Not strictly posix, but seems defined on all platforms
// except mingw32.
{ "OSFILE_OFFSETOF_DIRENT_D_TYPE", INT_TO_JSVAL(offsetof (struct dirent, d_type)) },
#endif // defined(DT_UNKNOWN)
#endif // defined(XP_UNIX)
// System configuration
// Under MacOSX, to avoid using deprecated functions that do not
// match the constants we define in this object (including
// |sizeof|/|offsetof| stuff, but not only), for a number of
// functions, we need to adapt the name of the symbols we are using,
// whenever macro _DARWIN_FEATURE_64_BIT_INODE is set. We export
// this value to be able to do so from JavaScript.
#if defined(_DARWIN_FEATURE_64_BIT_INODE)
{ "_DARWIN_FEATURE_64_BIT_INODE", INT_TO_JSVAL(1) },
#endif // defind(_DARWIN_FEATURE_64_BIT_INODE)
PROP_END
};
@ -296,6 +341,9 @@ static dom::ConstantSpec gWinProperties[] =
INT_CONSTANT(FORMAT_MESSAGE_FROM_SYSTEM),
INT_CONSTANT(FORMAT_MESSAGE_IGNORE_INSERTS),
// The max length of paths
INT_CONSTANT(MAX_PATH),
// CreateFile desired access
INT_CONSTANT(GENERIC_ALL),
INT_CONSTANT(GENERIC_EXECUTE),
@ -319,6 +367,7 @@ static dom::ConstantSpec gWinProperties[] =
INT_CONSTANT(FILE_ATTRIBUTE_DIRECTORY),
INT_CONSTANT(FILE_ATTRIBUTE_NORMAL),
INT_CONSTANT(FILE_ATTRIBUTE_READONLY),
INT_CONSTANT(FILE_ATTRIBUTE_REPARSE_POINT),
INT_CONSTANT(FILE_ATTRIBUTE_TEMPORARY),
// CreateFile error constant
@ -336,14 +385,19 @@ static dom::ConstantSpec gWinProperties[] =
// SetFilePointer error constant
INT_CONSTANT(INVALID_SET_FILE_POINTER),
// File attributes
INT_CONSTANT(FILE_ATTRIBUTE_DIRECTORY),
// MoveFile flags
INT_CONSTANT(MOVEFILE_COPY_ALLOWED),
INT_CONSTANT(MOVEFILE_REPLACE_EXISTING),
// Errors
INT_CONSTANT(ERROR_ACCESS_DENIED),
INT_CONSTANT(ERROR_FILE_EXISTS),
INT_CONSTANT(ERROR_FILE_NOT_FOUND),
INT_CONSTANT(ERROR_ACCESS_DENIED),
INT_CONSTANT(ERROR_NO_MORE_FILES),
PROP_END
};

View File

@ -3236,6 +3236,7 @@ nsWebBrowserPersist::CloneNodeWithFixedUpAttributes(
case NS_FORM_INPUT_TEXT:
case NS_FORM_INPUT_TEL:
case NS_FORM_INPUT_URL:
case NS_FORM_INPUT_NUMBER:
nodeAsInput->GetValue(valueStr);
// Avoid superfluous value="" serialization
if (valueStr.IsEmpty())

View File

@ -2005,7 +2005,7 @@ BindLet(JSContext *cx, BindData *data, JSAtom *atom, Parser *parser)
*/
bool redeclared;
jsid id = AtomToId(atom);
const Shape *shape = blockObj->addVar(cx, id, blockCount, &redeclared);
Shape *shape = blockObj->addVar(cx, id, blockCount, &redeclared);
if (!shape) {
if (redeclared)
ReportRedeclaration(cx, parser, pn, false, atom);
@ -2022,7 +2022,7 @@ static inline bool
ForEachLetDef(TreeContext *tc, StaticBlockObject &blockObj, Op op)
{
for (Shape::Range r = blockObj.lastProperty()->all(); !r.empty(); r.popFront()) {
const Shape &shape = r.front();
Shape &shape = r.front();
/* Beware the destructuring dummy slots. */
if (JSID_IS_INT(shape.propid()))

View File

@ -155,7 +155,7 @@ frontend::LexicalLookup(ContextT *ct, JSAtom *atom, int *slotp, typename Context
continue;
StaticBlockObject &blockObj = *stmt->blockObj;
const Shape *shape = blockObj.nativeLookup(ct->sc->context, AtomToId(atom));
Shape *shape = blockObj.nativeLookup(ct->sc->context, AtomToId(atom));
if (shape) {
JS_ASSERT(shape->hasShortID());

View File

@ -4376,7 +4376,7 @@ JS_NextProperty(JSContext *cx, JSObject *iterobj, jsid *idp)
{
AssertRootingUnnecessary safe(cx);
int32_t i;
const Shape *shape;
Shape *shape;
JSIdArray *ida;
AssertNoGC(cx);

View File

@ -318,7 +318,7 @@ JSObject::arrayGetOwnDataElement(JSContext *cx, size_t i, Value *vp)
if (!IndexToId(cx, this, i, &hole, &id))
return false;
const Shape *shape = nativeLookup(cx, id);
Shape *shape = nativeLookup(cx, id);
if (!shape || !shape->isDataDescriptor())
vp->setMagic(JS_ARRAY_HOLE);
else

View File

@ -542,7 +542,7 @@ ReportUsageError(JSContext *cx, JSObject *callee, const char *msg)
{
const char *usageStr = "usage";
PropertyName *usageAtom = js_Atomize(cx, usageStr, strlen(usageStr))->asPropertyName();
DebugOnly<const Shape *> shape = callee->nativeLookup(cx, NameToId(usageAtom));
DebugOnly<Shape *> shape = callee->nativeLookup(cx, NameToId(usageAtom));
JS_ASSERT(!shape->configurable());
JS_ASSERT(!shape->writable());
JS_ASSERT(shape->hasDefaultGetter());

View File

@ -1762,13 +1762,13 @@ MakeRangeGCSafe(jsid *vec, size_t len)
}
static JS_ALWAYS_INLINE void
MakeRangeGCSafe(const Shape **beg, const Shape **end)
MakeRangeGCSafe(Shape **beg, Shape **end)
{
PodZero(beg, end - beg);
}
static JS_ALWAYS_INLINE void
MakeRangeGCSafe(const Shape **vec, size_t len)
MakeRangeGCSafe(Shape **vec, size_t len)
{
PodZero(vec, len);
}
@ -1812,12 +1812,12 @@ class AutoObjectVector : public AutoVectorRooter<JSObject *>
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
};
class AutoShapeVector : public AutoVectorRooter<const Shape *>
class AutoShapeVector : public AutoVectorRooter<Shape *>
{
public:
explicit AutoShapeVector(JSContext *cx
JS_GUARD_OBJECT_NOTIFIER_PARAM)
: AutoVectorRooter<const Shape *>(cx, SHAPEVECTOR)
: AutoVectorRooter<Shape *>(cx, SHAPEVECTOR)
{
JS_GUARD_OBJECT_NOTIFIER_INIT;
}

View File

@ -768,12 +768,12 @@ TypeSet::addFilterPrimitives(JSContext *cx, TypeSet *target, FilterKind filter)
}
/* If id is a normal slotful 'own' property of an object, get its shape. */
static inline const Shape *
static inline Shape *
GetSingletonShape(JSContext *cx, JSObject *obj, jsid id)
{
if (!obj->isNative())
return NULL;
const Shape *shape = obj->nativeLookup(cx, id);
Shape *shape = obj->nativeLookup(cx, id);
if (shape && shape->hasDefaultGetter() && shape->hasSlot())
return shape;
return NULL;
@ -792,7 +792,7 @@ ScriptAnalysis::pruneTypeBarriers(JSContext *cx, uint32_t offset)
}
if (barrier->singleton) {
JS_ASSERT(barrier->type.isPrimitive(JSVAL_TYPE_UNDEFINED));
const Shape *shape = GetSingletonShape(cx, barrier->singleton, barrier->singletonId);
Shape *shape = GetSingletonShape(cx, barrier->singleton, barrier->singletonId);
if (shape && !barrier->singleton->nativeGetSlot(shape->slot()).isUndefined()) {
/*
* When we analyzed the script the singleton had an 'own'
@ -999,7 +999,7 @@ PropertyAccess(JSContext *cx, JSScript *script_, jsbytecode *pc, TypeObject *obj
* to remove the barrier after the property becomes defined,
* even if no undefined value is ever observed at pc.
*/
const Shape *shape = GetSingletonShape(cx, object->singleton, id);
Shape *shape = GetSingletonShape(cx, object->singleton, id);
if (shape && object->singleton->nativeGetSlot(shape->slot()).isUndefined())
script->analysis()->addSingletonTypeBarrier(cx, pc, target, object->singleton, id);
}
@ -2514,7 +2514,7 @@ struct types::ObjectTableKey
obj->getProto() != v.proto) {
return false;
}
const Shape *shape = obj->lastProperty();
Shape *shape = obj->lastProperty();
while (!shape->isEmptyShape()) {
if (shape->propid() != v.ids[shape->slot()])
return false;
@ -2557,7 +2557,7 @@ TypeCompartment::fixObjectType(JSContext *cx, JSObject *obj_)
return;
ObjectTypeTable::AddPtr p = objectTypeTable->lookupForAdd(obj.get());
const Shape *baseShape = obj->lastProperty();
Shape *baseShape = obj->lastProperty();
if (p) {
/* The lookup ensures the shape matches, now check that the types match. */
@ -2568,7 +2568,7 @@ TypeCompartment::fixObjectType(JSContext *cx, JSObject *obj_)
if (NumberTypes(ntype, types[i])) {
if (types[i].isPrimitive(JSVAL_TYPE_INT32)) {
types[i] = Type::DoubleType();
const Shape *shape = baseShape;
Shape *shape = baseShape;
while (!shape->isEmptyShape()) {
if (shape->slot() == i) {
Type type = Type::DoubleType();
@ -2608,7 +2608,7 @@ TypeCompartment::fixObjectType(JSContext *cx, JSObject *obj_)
return;
}
const Shape *shape = baseShape;
Shape *shape = baseShape;
while (!shape->isEmptyShape()) {
ids[shape->slot()] = shape->propid();
types[shape->slot()] = GetValueTypeForTable(cx, obj->getSlot(shape->slot()));
@ -2671,7 +2671,7 @@ TypeObject::getFromPrototypes(JSContext *cx, jsid id, TypeSet *types, bool force
}
static inline void
UpdatePropertyType(JSContext *cx, TypeSet *types, JSObject *obj, const Shape *shape, bool force)
UpdatePropertyType(JSContext *cx, TypeSet *types, JSObject *obj, Shape *shape, bool force)
{
types->setOwnProperty(cx, false);
if (!shape->writable())
@ -2715,14 +2715,14 @@ TypeObject::addProperty(JSContext *cx, jsid id, Property **pprop)
if (JSID_IS_VOID(id)) {
/* Go through all shapes on the object to get integer-valued properties. */
const Shape *shape = singleton->lastProperty();
Shape *shape = singleton->lastProperty();
while (!shape->isEmptyShape()) {
if (JSID_IS_VOID(MakeTypeId(cx, shape->propid())))
UpdatePropertyType(cx, &base->types, singleton, shape, true);
shape = shape->previous();
}
} else if (!JSID_IS_EMPTY(id) && singleton->isNative()) {
const Shape *shape = singleton->nativeLookup(cx, id);
Shape *shape = singleton->nativeLookup(cx, id);
if (shape)
UpdatePropertyType(cx, &base->types, singleton, shape, false);
}
@ -2754,7 +2754,7 @@ TypeObject::addDefiniteProperties(JSContext *cx, JSObject *obj)
/* Mark all properties of obj as definite properties of this type. */
AutoEnterTypeInference enter(cx);
const Shape *shape = obj->lastProperty();
Shape *shape = obj->lastProperty();
while (!shape->isEmptyShape()) {
jsid id = MakeTypeId(cx, shape->propid());
if (!JSID_IS_VOID(id) && obj->isFixedSlot(shape->slot()) &&
@ -2782,7 +2782,7 @@ TypeObject::matchDefiniteProperties(JSObject *obj)
unsigned slot = prop->types.definiteSlot();
bool found = false;
const Shape *shape = obj->lastProperty();
Shape *shape = obj->lastProperty();
while (!shape->isEmptyShape()) {
if (shape->slot() == slot && shape->propid() == prop->id) {
found = true;

View File

@ -1282,7 +1282,7 @@ TypeObject::getProperty(JSContext *cx, jsid id, bool assign)
continue;
}
const Shape *shape = protoWalk->nativeLookup(cx, id);
Shape *shape = protoWalk->nativeLookup(cx, id);
foundSetter = shape &&
!shape->hasDefaultSetter();

View File

@ -968,7 +968,7 @@ js::AssertValidPropertyCacheHit(JSContext *cx, JSObject *start_,
JS_ASSERT(prop);
JS_ASSERT(pobj == found);
const Shape *shape = (Shape *) prop;
Shape *shape = (Shape *) prop;
JS_ASSERT(entry->prop == shape);
}
#endif /* DEBUG && !JS_THREADSAFE */

View File

@ -163,7 +163,7 @@ ValuePropertyBearer(JSContext *cx, StackFrame *fp, const Value &v, int spindex)
}
inline bool
NativeGet(JSContext *cx, Handle<JSObject*> obj, Handle<JSObject*> pobj, const Shape *shape,
NativeGet(JSContext *cx, Handle<JSObject*> obj, Handle<JSObject*> pobj, Shape *shape,
unsigned getHow, Value *vp)
{
if (shape->isDataDescriptor() && shape->hasDefaultGetter()) {
@ -305,7 +305,7 @@ SetPropertyOperation(JSContext *cx, jsbytecode *pc, const Value &lval, const Val
* The entry predicts a set either an existing "own" property, or
* on a prototype property that has a setter.
*/
const Shape *shape = entry->prop;
Shape *shape = entry->prop;
JS_ASSERT_IF(shape->isDataDescriptor(), shape->writable());
JS_ASSERT_IF(shape->hasSlot(), entry->isOwnPropertyHit());

View File

@ -213,7 +213,7 @@ EnumerateNativeProperties(JSContext *cx, JSObject *obj_, JSObject *pobj_, unsign
Shape::Range r = pobj->lastProperty()->all();
Shape::Range::AutoRooter root(cx, &r);
for (; !r.empty(); r.popFront()) {
const Shape &shape = r.front();
Shape &shape = r.front();
if (!JSID_IS_DEFAULT_XML_NAMESPACE(shape.propid()) &&
!Enumerate(cx, obj, pobj, shape.propid(), shape.enumerable(), flags, ht, props))
@ -535,7 +535,7 @@ NativeIterator::init(JSObject *obj, unsigned flags, uint32_t slength, uint32_t k
{
this->obj.init(obj);
this->flags = flags;
this->shapes_array = (const Shape **) this->props_end;
this->shapes_array = (Shape **) this->props_end;
this->shapes_length = slength;
this->shapes_key = key;
}
@ -654,7 +654,7 @@ UpdateNativeIterator(NativeIterator *ni, JSObject *obj)
bool
GetIterator(JSContext *cx, HandleObject obj, unsigned flags, Value *vp)
{
Vector<const Shape *, 8> shapes(cx);
Vector<Shape *, 8> shapes(cx);
uint32_t key = 0;
bool keysOnly = (flags == JSITER_ENUMERATE);
@ -719,7 +719,7 @@ GetIterator(JSContext *cx, HandleObject obj, unsigned flags, Value *vp)
shapes.clear();
goto miss;
}
const Shape *shape = pobj->lastProperty();
Shape *shape = pobj->lastProperty();
key = (key + (key << 16)) ^ (uintptr_t(shape) >> 3);
if (!shapes.append((Shape *) shape))
return false;

View File

@ -33,7 +33,7 @@ struct NativeIterator {
HeapPtr<JSFlatString> *props_array;
HeapPtr<JSFlatString> *props_cursor;
HeapPtr<JSFlatString> *props_end;
const Shape **shapes_array;
Shape **shapes_array;
uint32_t shapes_length;
uint32_t shapes_key;
uint32_t flags;

View File

@ -190,7 +190,7 @@ MarkSharpObjects(JSContext *cx, HandleObject obj, JSIdArray **idap, JSSharpInfo
Value &value = valueRoot.get();
Value &setter = setterRoot.get();
if (obj2->isNative()) {
const Shape *shape = (Shape *) prop;
Shape *shape = (Shape *) prop;
hasGetter = shape->hasGetterValue();
hasSetter = shape->hasSetterValue();
if (hasGetter)
@ -476,7 +476,7 @@ obj_toSource(JSContext *cx, unsigned argc, Value *vp)
if (prop) {
bool doGet = true;
if (obj2->isNative()) {
const Shape *shape = (Shape *) prop;
Shape *shape = (Shape *) prop;
unsigned attrs = shape->attributes();
if (attrs & JSPROP_GETTER) {
doGet = false;
@ -1553,7 +1553,7 @@ DefinePropertyOnObject(JSContext *cx, HandleObject obj, HandleId id, const PropD
JS_ASSERT(obj == obj2);
Rooted<const Shape *> shape(cx, reinterpret_cast<Shape *>(current));
Rooted<Shape *> shape(cx, reinterpret_cast<Shape *>(current));
do {
if (desc.isAccessorDescriptor()) {
if (!shape->isAccessorDescriptor())
@ -2502,7 +2502,7 @@ js::NewObjectWithType(JSContext *cx, HandleTypeObject type, JSObject *parent, gc
JSObject *
js::NewReshapedObject(JSContext *cx, HandleTypeObject type, JSObject *parent,
gc::AllocKind kind, const Shape *shape)
gc::AllocKind kind, Shape *shape)
{
RootedObject res(cx, NewObjectWithType(cx, type, parent, kind));
if (!res)
@ -2517,7 +2517,7 @@ js::NewReshapedObject(JSContext *cx, HandleTypeObject type, JSObject *parent,
if (!ids.append(JSID_VOID))
return NULL;
}
const js::Shape *nshape = shape;
js::Shape *nshape = shape;
while (!nshape->isEmptyShape()) {
ids[nshape->slot()] = nshape->propid();
nshape = nshape->previous();
@ -2767,7 +2767,7 @@ JS_CopyPropertiesFrom(JSContext *cx, JSObject *target, JSObject *obj)
size_t n = shapes.length();
while (n > 0) {
const Shape *shape = shapes[--n];
Shape *shape = shapes[--n];
unsigned attrs = shape->attributes();
PropertyOp getter = shape->getter();
StrictPropertyOp setter = shape->setter();
@ -3175,7 +3175,7 @@ DefineStandardSlot(JSContext *cx, JSObject *obj, JSProtoKey key, JSAtom *atom,
JS_ASSERT(obj->isGlobal());
JS_ASSERT(obj->isNative());
const Shape *shape = obj->nativeLookup(cx, id);
Shape *shape = obj->nativeLookup(cx, id);
if (!shape) {
uint32_t slot = 2 * JSProto_LIMIT + key;
obj->setReservedSlot(slot, v);
@ -3456,7 +3456,7 @@ JSObject::updateSlotsForSpan(JSContext *cx, size_t oldSpan, size_t newSpan)
}
bool
JSObject::setLastProperty(JSContext *cx, const js::Shape *shape)
JSObject::setLastProperty(JSContext *cx, js::Shape *shape)
{
JS_ASSERT(!inDictionaryMode());
JS_ASSERT(!shape->inDictionary());
@ -3467,14 +3467,14 @@ JSObject::setLastProperty(JSContext *cx, const js::Shape *shape)
size_t newSpan = shape->slotSpan();
if (oldSpan == newSpan) {
shape_ = const_cast<js::Shape *>(shape);
shape_ = shape;
return true;
}
if (!updateSlotsForSpan(cx, oldSpan, newSpan))
return false;
shape_ = const_cast<js::Shape *>(shape);
shape_ = shape;
return true;
}
@ -3858,7 +3858,7 @@ js_FindClassObject(JSContext *cx, HandleObject start, JSProtoKey protoKey,
{
RootedId id(cx);
JSProperty *prop;
const Shape *shape;
Shape *shape;
RootedObject obj(cx);
@ -3976,7 +3976,7 @@ JSObject::freeSlot(JSContext *cx, uint32_t slot)
static bool
PurgeProtoChain(JSContext *cx, JSObject *obj_, jsid id_)
{
const Shape *shape;
Shape *shape;
RootedObject obj(cx, obj_);
RootedId id(cx, id_);
@ -4093,7 +4093,7 @@ CallAddPropertyHook(JSContext *cx, Class *clasp, HandleObject obj, HandleShape s
namespace js {
const Shape *
Shape *
DefineNativeProperty(JSContext *cx, HandleObject obj, HandleId id, const Value &value_,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
unsigned flags, int shortid, unsigned defineHow /* = 0 */)
@ -4271,7 +4271,7 @@ CallResolveOp(JSContext *cx, HandleObject obj, HandleId id, unsigned flags,
}
if (!obj->nativeEmpty()) {
if (const Shape *shape = obj->nativeLookup(cx, id)) {
if (Shape *shape = obj->nativeLookup(cx, id)) {
objp.set(obj);
*propp = (JSProperty *) shape;
}
@ -4287,7 +4287,7 @@ LookupPropertyWithFlagsInline(JSContext *cx, HandleObject obj, HandleId id, unsi
/* Search scopes starting with obj and following the prototype link. */
RootedObject current(cx, obj);
while (true) {
const Shape *shape = current->nativeLookup(cx, id);
Shape *shape = current->nativeLookup(cx, id);
if (shape) {
objp.set(current);
*propp = (JSProperty *) shape;
@ -4536,7 +4536,7 @@ js::FindIdentifierBase(JSContext *cx, HandleObject scopeChain, HandlePropertyNam
static JS_ALWAYS_INLINE JSBool
js_NativeGetInline(JSContext *cx, Handle<JSObject*> receiver, JSObject *obj, JSObject *pobj,
const Shape *shape, unsigned getHow, Value *vp)
Shape *shape, unsigned getHow, Value *vp)
{
JS_ASSERT(pobj->isNative());
@ -4559,7 +4559,7 @@ js_NativeGetInline(JSContext *cx, Handle<JSObject*> receiver, JSObject *obj, JSO
code->accessGetter = true;
}
Rooted<const Shape*> shapeRoot(cx, shape);
Rooted<Shape*> shapeRoot(cx, shape);
RootedObject pobjRoot(cx, pobj);
if (!shape->get(cx, receiver, obj, pobj, vp))
@ -4573,7 +4573,7 @@ js_NativeGetInline(JSContext *cx, Handle<JSObject*> receiver, JSObject *obj, JSO
}
JSBool
js_NativeGet(JSContext *cx, Handle<JSObject*> obj, Handle<JSObject*> pobj, const Shape *shape,
js_NativeGet(JSContext *cx, Handle<JSObject*> obj, Handle<JSObject*> pobj, Shape *shape,
unsigned getHow, Value *vp)
{
return js_NativeGetInline(cx, obj, obj, pobj, shape, getHow, vp);
@ -4581,7 +4581,7 @@ js_NativeGet(JSContext *cx, Handle<JSObject*> obj, Handle<JSObject*> pobj, const
JSBool
js_NativeSet(JSContext *cx, Handle<JSObject*> obj, Handle<JSObject*> receiver,
const Shape *shape, bool added, bool strict, Value *vp)
Shape *shape, bool added, bool strict, Value *vp)
{
AddTypePropertyId(cx, obj, shape->propid(), *vp);
@ -4606,7 +4606,7 @@ js_NativeSet(JSContext *cx, Handle<JSObject*> obj, Handle<JSObject*> receiver,
return js_ReportGetterOnlyAssignment(cx);
}
Rooted<const Shape *> shapeRoot(cx, shape);
Rooted<Shape *> shapeRoot(cx, shape);
int32_t sample = cx->runtime->propertyRemovals;
if (!shapeRoot->set(cx, obj, receiver, strict, vp))
@ -5042,7 +5042,7 @@ baseops::GetAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *a
if (!nobj->isNative())
return nobj->getGenericAttributes(cx, id, attrsp);
const Shape *shape = (Shape *)prop;
Shape *shape = (Shape *)prop;
*attrsp = shape->attributes();
return true;
}
@ -5061,7 +5061,7 @@ baseops::GetElementAttributes(JSContext *cx, HandleObject obj, uint32_t index, u
if (!nobj->isNative())
return nobj->getElementAttributes(cx, index, attrsp);
const Shape *shape = (Shape *)prop;
Shape *shape = (Shape *)prop;
*attrsp = shape->attributes();
return true;
}
@ -5098,7 +5098,7 @@ JSBool
baseops::DeleteGeneric(JSContext *cx, HandleObject obj, HandleId id, Value *rval, JSBool strict)
{
JSProperty *prop;
const Shape *shape;
Shape *shape;
rval->setBoolean(true);
@ -5166,7 +5166,7 @@ namespace js {
bool
HasDataProperty(JSContext *cx, HandleObject obj, jsid id, Value *vp)
{
if (const Shape *shape = obj->nativeLookup(cx, id)) {
if (Shape *shape = obj->nativeLookup(cx, id)) {
if (shape->hasDefaultGetter() && shape->hasSlot()) {
*vp = obj->nativeGetSlot(shape->slot());
return true;
@ -5306,7 +5306,7 @@ CheckAccess(JSContext *cx, JSObject *obj_, HandleId id, JSAccessMode mode,
{
JSBool writing;
JSProperty *prop;
const Shape *shape;
Shape *shape;
RootedObject obj(cx, obj_), pobj(cx);
@ -5528,7 +5528,7 @@ js_GetObjectSlotName(JSTracer *trc, char *buf, size_t bufsize)
JSObject *obj = (JSObject *)trc->debugPrintArg;
uint32_t slot = uint32_t(trc->debugPrintIndex);
const Shape *shape;
Shape *shape;
if (obj->isNative()) {
shape = obj->lastProperty();
while (shape && (!shape->hasSlot() || shape->slot() != slot))
@ -5562,11 +5562,11 @@ js_GetObjectSlotName(JSTracer *trc, char *buf, size_t bufsize)
}
}
static const Shape *
static Shape *
LastConfigurableShape(JSObject *obj)
{
for (Shape::Range r(obj->lastProperty()->all()); !r.empty(); r.popFront()) {
const Shape *shape = &r.front();
Shape *shape = &r.front();
if (shape->configurable())
return shape;
}
@ -5577,14 +5577,14 @@ bool
js_ClearNative(JSContext *cx, JSObject *obj)
{
/* Remove all configurable properties from obj. */
while (const Shape *shape = LastConfigurableShape(obj)) {
while (Shape *shape = LastConfigurableShape(obj)) {
if (!obj->removeProperty(cx, shape->propid()))
return false;
}
/* Set all remaining writable plain data properties to undefined. */
for (Shape::Range r(obj->lastProperty()->all()); !r.empty(); r.popFront()) {
const Shape *shape = &r.front();
Shape *shape = &r.front();
if (shape->isDataDescriptor() &&
shape->writable() &&
shape->hasDefaultSetter() &&
@ -5692,7 +5692,7 @@ js_DumpId(jsid id)
}
static void
DumpProperty(JSObject *obj, const Shape &shape)
DumpProperty(JSObject *obj, Shape &shape)
{
jsid id = shape.propid();
uint8_t attrs = shape.attributes();
@ -5795,7 +5795,7 @@ JSObject::dump()
if (obj->isNative()) {
fprintf(stderr, "properties:\n");
Vector<const Shape *, 8, SystemAllocPolicy> props;
Vector<Shape *, 8, SystemAllocPolicy> props;
for (Shape::Range r = obj->lastProperty()->all(); !r.empty(); r.popFront())
props.append(&r.front());
for (size_t i = props.length(); i-- != 0;)

View File

@ -274,10 +274,10 @@ struct JSObject : public js::ObjectImpl
* Update the last property, keeping the number of allocated slots in sync
* with the object's new slot span.
*/
bool setLastProperty(JSContext *cx, const js::Shape *shape);
bool setLastProperty(JSContext *cx, js::Shape *shape);
/* As above, but does not change the slot span. */
inline void setLastPropertyInfallible(const js::Shape *shape);
inline void setLastPropertyInfallible(js::Shape *shape);
/* Make a non-array object with the specified initial state. */
static inline JSObject *create(JSContext *cx,
@ -417,7 +417,7 @@ struct JSObject : public js::ObjectImpl
void rollbackProperties(JSContext *cx, uint32_t slotSpan);
inline void nativeSetSlot(unsigned slot, const js::Value &value);
inline void nativeSetSlotWithType(JSContext *cx, const js::Shape *shape, const js::Value &value);
inline void nativeSetSlotWithType(JSContext *cx, js::Shape *shape, const js::Value &value);
inline const js::Value &getReservedSlot(unsigned index) const;
inline js::HeapSlot &getReservedSlotRef(unsigned index);
@ -1145,12 +1145,12 @@ const unsigned DNP_SKIP_TYPE = 8; /* Don't update type information */
/*
* Return successfully added or changed shape or NULL on error.
*/
extern const Shape *
extern Shape *
DefineNativeProperty(JSContext *cx, HandleObject obj, HandleId id, const Value &value,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
unsigned flags, int shortid, unsigned defineHow = 0);
inline const Shape *
inline Shape *
DefineNativeProperty(JSContext *cx, HandleObject obj, PropertyName *name, const Value &value,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
unsigned flags, int shortid, unsigned defineHow = 0)
@ -1237,11 +1237,11 @@ const unsigned JSGET_CACHE_RESULT = 1; // from a caching interpreter opcode
*/
extern JSBool
js_NativeGet(JSContext *cx, js::Handle<JSObject*> obj, js::Handle<JSObject*> pobj,
const js::Shape *shape, unsigned getHow, js::Value *vp);
js::Shape *shape, unsigned getHow, js::Value *vp);
extern JSBool
js_NativeSet(JSContext *cx, js::Handle<JSObject*> obj, js::Handle<JSObject*> receiver,
const js::Shape *shape, bool added, bool strict, js::Value *vp);
js::Shape *shape, bool added, bool strict, js::Value *vp);
namespace js {

View File

@ -286,7 +286,7 @@ JSObject::dynamicSlotIndex(size_t slot)
}
inline void
JSObject::setLastPropertyInfallible(const js::Shape *shape)
JSObject::setLastPropertyInfallible(js::Shape *shape)
{
JS_ASSERT(!shape->inDictionary());
JS_ASSERT(shape->compartment() == compartment());
@ -294,7 +294,7 @@ JSObject::setLastPropertyInfallible(const js::Shape *shape)
JS_ASSERT(slotSpan() == shape->slotSpan());
JS_ASSERT(numFixedSlots() == shape->numFixedSlots());
shape_ = const_cast<js::Shape *>(shape);
shape_ = shape;
}
inline void
@ -315,7 +315,7 @@ JSObject::canRemoveLastProperty()
* converted to dictionary mode instead. See BaseShape comment in jsscope.h
*/
JS_ASSERT(!inDictionaryMode());
const js::Shape *previous = lastProperty()->previous();
js::Shape *previous = lastProperty()->previous();
return previous->getObjectParent() == lastProperty()->getObjectParent()
&& previous->getObjectFlags() == lastProperty()->getObjectFlags();
}
@ -958,7 +958,7 @@ JSObject::nativeSetSlot(unsigned slot, const js::Value &value)
}
inline void
JSObject::nativeSetSlotWithType(JSContext *cx, const js::Shape *shape, const js::Value &value)
JSObject::nativeSetSlotWithType(JSContext *cx, js::Shape *shape, const js::Value &value)
{
nativeSetSlot(shape->slot(), value);
js::types::AddTypePropertyId(cx, this, shape->propid(), value);
@ -1536,7 +1536,7 @@ CopyInitializerObject(JSContext *cx, HandleObject baseobj)
JSObject *
NewReshapedObject(JSContext *cx, HandleTypeObject type, JSObject *parent,
gc::AllocKind kind, const Shape *shape);
gc::AllocKind kind, Shape *shape);
/*
* As for gc::GetGCObjectKind, where numSlots is a guess at the final size of

View File

@ -423,7 +423,7 @@ ToDisassemblySource(JSContext *cx, jsval v, JSAutoByteString *bytes)
Shape::Range::AutoRooter root(cx, &r);
while (!r.empty()) {
Rooted<const Shape*> shape(cx, &r.front());
Rooted<Shape*> shape(cx, &r.front());
JSAtom *atom = JSID_IS_INT(shape->propid())
? cx->runtime->atomState.emptyAtom
: JSID_TO_ATOM(shape->propid());
@ -1762,7 +1762,7 @@ static const char *
GetLocalInSlot(SprintStack *ss, int i, int slot, JSObject *obj)
{
for (Shape::Range r(obj->lastProperty()); !r.empty(); r.popFront()) {
const Shape &shape = r.front();
Shape &shape = r.front();
if (shape.shortid() == slot) {
/* Ignore the empty destructuring dummy. */
@ -2321,7 +2321,7 @@ GetBlockNames(JSContext *cx, StaticBlockObject &blockObj, AtomVector *atoms)
unsigned i = numAtoms;
for (Shape::Range r = blockObj.lastProperty()->all(); !r.empty(); r.popFront()) {
const Shape &shape = r.front();
Shape &shape = r.front();
LOCAL_ASSERT(shape.hasShortID());
--i;
LOCAL_ASSERT((unsigned)shape.shortid() == i);

View File

@ -16,7 +16,7 @@ using namespace js;
PropertyCacheEntry *
PropertyCache::fill(JSContext *cx, JSObject *obj, unsigned scopeIndex, JSObject *pobj,
const Shape *shape)
Shape *shape)
{
JS_ASSERT(this == &JS_PROPERTY_CACHE(cx));
JS_ASSERT(!cx->runtime->gcRunning);

View File

@ -25,18 +25,18 @@ class PropertyCache;
struct PropertyCacheEntry
{
jsbytecode *kpc; /* pc of cache-testing bytecode */
const Shape *kshape; /* shape of direct (key) object */
const Shape *pshape; /* shape of owning object */
const Shape *prop; /* shape of accessed property */
jsbytecode *kpc; /* pc of cache-testing bytecode */
Shape *kshape; /* shape of direct (key) object */
Shape *pshape; /* shape of owning object */
Shape *prop; /* shape of accessed property */
friend class PropertyCache;
private:
/* Index into scope chain; inapplicable to property lookup entries. */
uint8_t scopeIndex;
uint8_t scopeIndex;
/* Index into the prototype chain from the object for this entry. */
uint8_t protoIndex;
uint8_t protoIndex;
public:
static const size_t MaxScopeIndex = 15;
@ -62,8 +62,8 @@ struct PropertyCacheEntry
*/
bool isPrototypePropertyHit() const { return scopeIndex == 0 && protoIndex == 1; }
void assign(jsbytecode *kpc, const Shape *kshape, const Shape *pshape,
const Shape *prop, unsigned scopeIndex, unsigned protoIndex) {
void assign(jsbytecode *kpc, Shape *kshape, Shape *pshape,
Shape *prop, unsigned scopeIndex, unsigned protoIndex) {
JS_ASSERT(scopeIndex <= MaxScopeIndex);
JS_ASSERT(protoIndex <= MaxProtoIndex);
@ -184,7 +184,7 @@ class PropertyCache
* not possible.
*/
PropertyCacheEntry *fill(JSContext *cx, JSObject *obj, unsigned scopeIndex,
JSObject *pobj, const js::Shape *shape);
JSObject *pobj, js::Shape *shape);
void purge(JSRuntime *rt);

View File

@ -33,7 +33,7 @@ js::PropertyCache::test(JSContext *cx, jsbytecode *pc, JSObject *&obj,
{
JS_ASSERT(this == &JS_PROPERTY_CACHE(cx));
const Shape *kshape = obj->lastProperty();
Shape *kshape = obj->lastProperty();
entry = &table[hash(pc, kshape)];
PCMETER(pctestentry = entry);
PCMETER(tests++);
@ -64,7 +64,7 @@ js::PropertyCache::testForSet(JSContext *cx, jsbytecode *pc, JSObject *obj,
{
JS_ASSERT(this == &JS_PROPERTY_CACHE(cx));
const Shape *kshape = obj->lastProperty();
Shape *kshape = obj->lastProperty();
PropertyCacheEntry *entry = &table[hash(pc, kshape)];
*entryp = entry;
PCMETER(pctestentry = entry);

View File

@ -201,7 +201,7 @@ Shape::finalize(FreeOp *fop)
#ifdef DEBUG
void
KidsPointer::checkConsistency(const Shape *aKid) const
KidsPointer::checkConsistency(Shape *aKid) const
{
if (isShape()) {
JS_ASSERT(toShape() == aKid);

View File

@ -60,7 +60,7 @@ class KidsPointer {
}
#ifdef DEBUG
void checkConsistency(const js::Shape *aKid) const;
void checkConsistency(js::Shape *aKid) const;
#endif
};

View File

@ -58,7 +58,7 @@ ShapeTable::init(JSRuntime *rt, Shape *lastProp)
hashShift = HASH_BITS - sizeLog2;
for (Shape::Range r = lastProp->all(); !r.empty(); r.popFront()) {
const Shape &shape = r.front();
Shape &shape = r.front();
Shape **spp = search(shape.propid(), true);
/*
@ -589,7 +589,7 @@ JSObject::addPropertyInternal(JSContext *cx, jsid id_,
* enforce all restrictions from ECMA-262 v5 8.12.9 [[DefineOwnProperty]].
*/
inline bool
CheckCanChangeAttrs(JSContext *cx, JSObject *obj, const Shape *shape, unsigned *attrsp)
CheckCanChangeAttrs(JSContext *cx, JSObject *obj, Shape *shape, unsigned *attrsp)
{
if (shape->configurable())
return true;
@ -880,7 +880,7 @@ JSObject::removeProperty(JSContext *cx, jsid id_)
* checks not to alter significantly the complexity of the
* delete in debug builds, see bug 534493.
*/
const Shape *aprop = self->lastProperty();
Shape *aprop = self->lastProperty();
for (int n = 50; --n >= 0 && aprop->parent; aprop = aprop->parent)
JS_ASSERT_IF(aprop != shape, self->nativeContains(cx, *aprop));
#endif
@ -1352,7 +1352,7 @@ EmptyShape::insertInitialShape(JSContext *cx, Shape *shape, JSObject *proto)
/* The new shape had better be rooted at the old one. */
#ifdef DEBUG
const Shape *nshape = shape;
Shape *nshape = shape;
while (!nshape->isEmptyShape())
nshape = nshape->previous();
JS_ASSERT(nshape == entry.shape);

View File

@ -559,16 +559,16 @@ struct Shape : public js::gc::Cell
class Range {
protected:
friend struct Shape;
const Shape *cursor;
Shape *cursor;
public:
Range(const Shape *shape) : cursor(shape) { }
Range(Shape *shape) : cursor(shape) { }
bool empty() const {
return cursor->isEmptyShape();
}
const Shape &front() const {
Shape &front() const {
JS_ASSERT(!empty());
return *cursor;
}
@ -598,7 +598,7 @@ struct Shape : public js::gc::Cell
};
};
Range all() const {
Range all() {
return Range(this);
}
@ -700,8 +700,8 @@ struct Shape : public js::gc::Cell
uint32_t aslot, unsigned aattrs, unsigned aflags,
int ashortid) const;
bool get(JSContext* cx, HandleObject receiver, JSObject *obj, JSObject *pobj, js::Value* vp) const;
bool set(JSContext* cx, HandleObject obj, HandleObject receiver, bool strict, js::Value* vp) const;
bool get(JSContext* cx, HandleObject receiver, JSObject *obj, JSObject *pobj, js::Value* vp);
bool set(JSContext* cx, HandleObject obj, HandleObject receiver, bool strict, js::Value* vp);
BaseShape *base() const { return base_; }
@ -847,20 +847,20 @@ struct Shape : public js::gc::Cell
static Shape *setExtensibleParents(JSContext *cx, Shape *shape);
bool extensibleParents() const { return !!(base()->flags & BaseShape::EXTENSIBLE_PARENTS); }
uint32_t entryCount() const {
uint32_t entryCount() {
if (hasTable())
return table().entryCount;
const js::Shape *shape = this;
js::Shape *shape = this;
uint32_t count = 0;
for (js::Shape::Range r = shape->all(); !r.empty(); r.popFront())
++count;
return count;
}
bool isBigEnoughForAShapeTable() const {
bool isBigEnoughForAShapeTable() {
JS_ASSERT(!hasTable());
const js::Shape *shape = this;
js::Shape *shape = this;
uint32_t count = 0;
for (js::Shape::Range r = shape->all(); !r.empty(); r.popFront()) {
++count;
@ -878,15 +878,15 @@ struct Shape : public js::gc::Cell
void finalize(FreeOp *fop);
void removeChild(js::Shape *child);
static inline void writeBarrierPre(const Shape *shape);
static inline void writeBarrierPost(const Shape *shape, void *addr);
static inline void writeBarrierPre(Shape *shape);
static inline void writeBarrierPost(Shape *shape, void *addr);
/*
* All weak references need a read barrier for incremental GC. This getter
* method implements the read barrier. It's used to obtain initial shapes
* from the compartment.
*/
static inline void readBarrier(const Shape *shape);
static inline void readBarrier(Shape *shape);
static inline ThingRootKind rootKind() { return THING_ROOT_SHAPE; }

View File

@ -265,7 +265,7 @@ Shape::getUserId(JSContext *cx, jsid *idp) const
}
inline bool
Shape::get(JSContext* cx, HandleObject receiver, JSObject* obj, JSObject *pobj, Value* vp) const
Shape::get(JSContext* cx, HandleObject receiver, JSObject* obj, JSObject *pobj, Value* vp)
{
JS_ASSERT(!hasDefaultGetter());
@ -274,7 +274,7 @@ Shape::get(JSContext* cx, HandleObject receiver, JSObject* obj, JSObject *pobj,
return InvokeGetterOrSetter(cx, receiver, fval, 0, 0, vp);
}
Rooted<const Shape *> self(cx, this);
Rooted<Shape *> self(cx, this);
RootedId id(cx);
if (!self->getUserId(cx, id.address()))
return false;
@ -283,7 +283,7 @@ Shape::get(JSContext* cx, HandleObject receiver, JSObject* obj, JSObject *pobj,
}
inline bool
Shape::set(JSContext* cx, HandleObject obj, HandleObject receiver, bool strict, Value* vp) const
Shape::set(JSContext* cx, HandleObject obj, HandleObject receiver, bool strict, Value* vp)
{
JS_ASSERT_IF(hasDefaultSetter(), hasGetterValue());
@ -295,7 +295,7 @@ Shape::set(JSContext* cx, HandleObject obj, HandleObject receiver, bool strict,
if (attrs & JSPROP_GETTER)
return js_ReportGetterOnlyAssignment(cx);
Rooted<const Shape *> self(cx, this);
Rooted<Shape *> self(cx, this);
RootedId id(cx);
if (!self->getUserId(cx, id.address()))
return false;
@ -379,7 +379,7 @@ EmptyShape::EmptyShape(UnownedBaseShape *base, uint32_t nfixed)
}
inline void
Shape::writeBarrierPre(const js::Shape *shape)
Shape::writeBarrierPre(Shape *shape)
{
#ifdef JSGC_INCREMENTAL
if (!shape)
@ -395,12 +395,12 @@ Shape::writeBarrierPre(const js::Shape *shape)
}
inline void
Shape::writeBarrierPost(const js::Shape *shape, void *addr)
Shape::writeBarrierPost(Shape *shape, void *addr)
{
}
inline void
Shape::readBarrier(const Shape *shape)
Shape::readBarrier(Shape *shape)
{
#ifdef JSGC_INCREMENTAL
JSCompartment *comp = shape->compartment();

View File

@ -154,13 +154,13 @@ Bindings::callObjectShape(JSContext *cx) const
* to first (i.e., the order we normally have iterate over Shapes). Choose
* the last added property in each set of dups.
*/
Vector<const Shape *> shapes(cx);
Vector<Shape *> shapes(cx);
HashSet<jsid> seen(cx);
if (!seen.init())
return NULL;
for (Shape::Range r = lastShape()->all(); !r.empty(); r.popFront()) {
const Shape &s = r.front();
Shape &s = r.front();
HashSet<jsid>::AddPtr p = seen.lookupForAdd(s.propid());
if (!p) {
if (!seen.add(p, s.propid()))
@ -205,7 +205,7 @@ Bindings::getLocalNameArray(JSContext *cx, BindingNames *namesp)
#endif
for (Shape::Range r = lastBinding->all(); !r.empty(); r.popFront()) {
const Shape &shape = r.front();
Shape &shape = r.front();
unsigned index = uint16_t(shape.shortid());
if (shape.setter() == CallObject::setArgOp) {
@ -234,7 +234,7 @@ Bindings::getLocalNameArray(JSContext *cx, BindingNames *namesp)
return true;
}
const Shape *
Shape *
Bindings::lastVariable() const
{
JS_ASSERT(lastBinding);

View File

@ -209,7 +209,7 @@ class Bindings
* Sometimes iteration order must be from oldest to youngest, however. For
* such cases, use js::Bindings::getLocalNameArray.
*/
const js::Shape *lastVariable() const;
js::Shape *lastVariable() const;
void trace(JSTracer *trc);

View File

@ -115,7 +115,7 @@ WatchpointMap::triggerWatchpoint(JSContext *cx, HandleObject obj, HandleId id, V
Value old;
old.setUndefined();
if (obj->isNative()) {
if (const Shape *shape = obj->nativeLookup(cx, id)) {
if (Shape *shape = obj->nativeLookup(cx, id)) {
if (shape->hasSlot())
old = obj->nativeGetSlot(shape->slot());
}

View File

@ -4768,7 +4768,7 @@ xml_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id, MutableHandleObj
objp.set(NULL);
*propp = NULL;
} else {
const Shape *shape =
Shape *shape =
js_AddNativeProperty(cx, obj, id, GetProperty, PutProperty,
SHAPE_INVALID_SLOT, JSPROP_ENUMERATE,
0, 0);
@ -4804,7 +4804,7 @@ xml_lookupElement(JSContext *cx, HandleObject obj, uint32_t index, MutableHandle
if (!IndexToId(cx, index, &id))
return false;
const Shape *shape =
Shape *shape =
js_AddNativeProperty(cx, obj, id, GetProperty, PutProperty, SHAPE_INVALID_SLOT,
JSPROP_ENUMERATE, 0, 0);
if (!shape)

View File

@ -160,7 +160,7 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::MIPSRegiste
loadPtr(Address(obj, JSObject::offsetOfShape()), shape);
}
Jump guardShape(RegisterID objReg, const Shape *shape) {
Jump guardShape(RegisterID objReg, Shape *shape) {
return branchPtr(NotEqual, Address(objReg, JSObject::offsetOfShape()), ImmPtr(shape));
}
@ -899,7 +899,7 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::MIPSRegiste
}
void loadObjProp(JSObject *obj, RegisterID objReg,
const js::Shape *shape,
js::Shape *shape,
RegisterID typeReg, RegisterID dataReg)
{
if (obj->isFixedSlot(shape->slot()))

View File

@ -6285,7 +6285,7 @@ mjit::Compiler::jsop_getgname(uint32_t index)
* then bake its address into the jitcode and guard against future
* reallocation of the global object's slots.
*/
const js::Shape *shape = globalObj->nativeLookup(cx, NameToId(name));
js::Shape *shape = globalObj->nativeLookup(cx, NameToId(name));
if (shape && shape->hasDefaultGetter() && shape->hasSlot()) {
HeapSlot *value = &globalObj->getSlotRef(shape->slot());
if (!value->isUndefined() &&
@ -6408,7 +6408,7 @@ mjit::Compiler::jsop_setgname(PropertyName *name, bool popGuaranteed)
types::TypeSet *types = globalObj->getType(cx)->getProperty(cx, id, false);
if (!types)
return false;
const js::Shape *shape = globalObj->nativeLookup(cx, NameToId(name));
js::Shape *shape = globalObj->nativeLookup(cx, NameToId(name));
if (shape && shape->hasDefaultSetter() &&
shape->writable() && shape->hasSlot() &&
!types->isOwnProperty(cx, globalObj->getType(cx), true)) {

View File

@ -63,7 +63,7 @@ ic::GetGlobalName(VMFrame &f, ic::GetGlobalNameIC *ic)
RecompilationMonitor monitor(f.cx);
const Shape *shape = obj.nativeLookup(f.cx, NameToId(name));
Shape *shape = obj.nativeLookup(f.cx, NameToId(name));
if (monitor.recompiled()) {
stubs::Name(f);
@ -115,14 +115,14 @@ PatchSetFallback(VMFrame &f, ic::SetGlobalNameIC *ic)
}
void
SetGlobalNameIC::patchInlineShapeGuard(Repatcher &repatcher, const Shape *shape)
SetGlobalNameIC::patchInlineShapeGuard(Repatcher &repatcher, Shape *shape)
{
JSC::CodeLocationDataLabelPtr label = fastPathStart.dataLabelPtrAtOffset(shapeOffset);
repatcher.repatch(label, shape);
}
static LookupStatus
UpdateSetGlobalName(VMFrame &f, ic::SetGlobalNameIC *ic, JSObject *obj, const Shape *shape)
UpdateSetGlobalName(VMFrame &f, ic::SetGlobalNameIC *ic, JSObject *obj, Shape *shape)
{
/* Give globals a chance to appear. */
if (!shape)
@ -159,7 +159,7 @@ ic::SetGlobalName(VMFrame &f, ic::SetGlobalNameIC *ic)
RecompilationMonitor monitor(f.cx);
const Shape *shape = obj.nativeLookup(f.cx, NameToId(name));
Shape *shape = obj.nativeLookup(f.cx, NameToId(name));
if (!monitor.recompiled()) {
LookupStatus status = UpdateSetGlobalName(f, ic, &obj, shape);

View File

@ -116,7 +116,7 @@ struct SetGlobalNameIC : public GlobalNameIC
/* SET only. */
ValueRemat vr; /* RHS value. */
void patchInlineShapeGuard(Repatcher &repatcher, const Shape *shape);
void patchInlineShapeGuard(Repatcher &repatcher, Shape *shape);
};
void JS_FASTCALL GetGlobalName(VMFrame &f, ic::GetGlobalNameIC *ic);

View File

@ -189,7 +189,7 @@ class SetPropCompiler : public PICStubCompiler
repatcher.relink(pic.slowPathCall, target);
}
LookupStatus patchInline(const Shape *shape)
LookupStatus patchInline(Shape *shape)
{
JS_ASSERT(!pic.inlinePathPatched);
JaegerSpew(JSpew_PICs, "patch setprop inline at %p\n", pic.fastPathStart.executableAddress());
@ -249,7 +249,7 @@ class SetPropCompiler : public PICStubCompiler
repatcher.relink(label.jumpAtOffset(secondGuardOffset), cs);
}
LookupStatus generateStub(const Shape *initialShape, const Shape *shape, bool adding)
LookupStatus generateStub(Shape *initialShape, Shape *shape, bool adding)
{
if (hadGC())
return Lookup_Uncacheable;
@ -465,7 +465,7 @@ class SetPropCompiler : public PICStubCompiler
/* If the property exists but is on a prototype, treat as addprop. */
if (prop && holder != obj) {
const Shape *shape = (const Shape *) prop;
Shape *shape = (Shape *) prop;
if (!holder->isNative())
return disable("non-native holder");
@ -512,7 +512,7 @@ class SetPropCompiler : public PICStubCompiler
proto = proto->getProto();
}
const Shape *initialShape = obj->lastProperty();
Shape *initialShape = obj->lastProperty();
uint32_t slots = obj->numDynamicSlots();
unsigned flags = 0;
@ -523,7 +523,7 @@ class SetPropCompiler : public PICStubCompiler
* populate the slot to satisfy the method invariant (in case we
* hit an early return below).
*/
const Shape *shape =
Shape *shape =
obj->putProperty(cx, name, getter, clasp->setProperty,
SHAPE_INVALID_SLOT, JSPROP_ENUMERATE, flags, 0);
if (!shape)
@ -575,7 +575,7 @@ class SetPropCompiler : public PICStubCompiler
return generateStub(initialShape, shape, true);
}
const Shape *shape = (const Shape *) prop;
Shape *shape = (Shape *) prop;
if (!shape->writable())
return disable("readonly");
if (shape->hasDefaultSetter()) {
@ -665,7 +665,7 @@ struct GetPropHelper {
// This field is set by |bind| and |lookup| only if they returned
// Lookup_Cacheable, otherwise it is NULL.
const Shape *shape;
Shape *shape;
GetPropHelper(JSContext *cx, JSObject *obj, PropertyName *name, IC &ic, VMFrame &f)
: cx(cx), obj(cx, obj), name(cx, name), ic(ic), f(f), holder(cx), prop(NULL), shape(NULL)
@ -687,7 +687,7 @@ struct GetPropHelper {
return ic.disable(cx, "non-native");
if (!IsCacheableProtoChain(obj, holder))
return ic.disable(cx, "non-native holder");
shape = (const Shape *)prop;
shape = (Shape *)prop;
return Lookup_Cacheable;
}
@ -708,7 +708,7 @@ struct GetPropHelper {
return ic.disable(f, "lookup failed");
if (!IsCacheableProtoChain(obj, holder))
return ic.disable(f, "non-native holder");
shape = (const Shape *)prop;
shape = (Shape *)prop;
return Lookup_Cacheable;
}
@ -984,7 +984,7 @@ class GetPropCompiler : public PICStubCompiler
return Lookup_Cacheable;
}
LookupStatus patchInline(JSObject *holder, const Shape *shape)
LookupStatus patchInline(JSObject *holder, Shape *shape)
{
spew("patch", "inline");
Repatcher repatcher(f.chunk());
@ -1019,7 +1019,7 @@ class GetPropCompiler : public PICStubCompiler
}
/* For JSPropertyOp getters. */
void generateGetterStub(Assembler &masm, const Shape *shape, jsid userid,
void generateGetterStub(Assembler &masm, Shape *shape, jsid userid,
Label start, Vector<Jump, 8> &shapeMismatches)
{
/*
@ -1126,7 +1126,7 @@ class GetPropCompiler : public PICStubCompiler
}
/* For getters backed by a JSNative. */
void generateNativeGetterStub(Assembler &masm, const Shape *shape,
void generateNativeGetterStub(Assembler &masm, Shape *shape,
Label start, Vector<Jump, 8> &shapeMismatches)
{
/*
@ -1217,7 +1217,7 @@ class GetPropCompiler : public PICStubCompiler
linkerEpilogue(linker, start, shapeMismatches);
}
LookupStatus generateStub(JSObject *holder, const Shape *shape)
LookupStatus generateStub(JSObject *holder, Shape *shape)
{
Vector<Jump, 8> shapeMismatches(cx);
@ -1562,7 +1562,7 @@ class ScopeNameCompiler : public PICStubCompiler
JS_ASSERT(getprop.holder != &scopeChain->global());
CallObjPropKind kind;
const Shape *shape = getprop.shape;
Shape *shape = getprop.shape;
if (shape->setterOp() == CallObject::setArgOp) {
kind = ARG;
} else if (shape->setterOp() == CallObject::setVarOp) {
@ -1698,7 +1698,7 @@ class ScopeNameCompiler : public PICStubCompiler
return true;
}
const Shape *shape = getprop.shape;
Shape *shape = getprop.shape;
Rooted<JSObject*> normalized(cx, obj);
if (obj->isWith() && !shape->hasDefaultGetter())
normalized = &obj->asWith().object();
@ -2257,7 +2257,7 @@ GetElementIC::attachGetProp(VMFrame &f, JSObject *obj, const Value &v, PropertyN
}
// Load the value.
const Shape *shape = getprop.shape;
Shape *shape = getprop.shape;
masm.loadObjProp(holder, holderReg, shape, typeReg, objReg);
Jump done = masm.jump();

View File

@ -841,7 +841,7 @@ Debugger::parseResumptionValue(AutoCompartment &ac, bool ok, const Value &rv, Va
/* Check that rv is {return: val} or {throw: val}. */
JSContext *cx = ac.context;
Rooted<JSObject*> obj(cx);
const Shape *shape;
Shape *shape;
jsid returnId = NameToId(cx->runtime->atomState.returnAtom);
jsid throwId = NameToId(cx->runtime->atomState.throwAtom);
bool okResumption = rv.isObject();

View File

@ -40,26 +40,26 @@ Debug_SetSlotRangeToCrashOnTouch(HeapSlot *begin, HeapSlot *end)
} // namespace js
inline const js::Shape *
inline js::Shape *
js::ObjectImpl::nativeLookup(JSContext *cx, PropertyId pid)
{
return nativeLookup(cx, pid.asId());
}
inline const js::Shape *
inline js::Shape *
js::ObjectImpl::nativeLookup(JSContext *cx, PropertyName *name)
{
return nativeLookup(cx, PropertyId(name));
}
#ifdef DEBUG
inline const js::Shape *
inline js::Shape *
js::ObjectImpl::nativeLookupNoAllocation(JSContext *cx, PropertyId pid)
{
return nativeLookupNoAllocation(cx, pid.asId());
}
inline const js::Shape *
inline js::Shape *
js::ObjectImpl::nativeLookupNoAllocation(JSContext *cx, PropertyName *name)
{
return nativeLookupNoAllocation(cx, PropertyId(name));

View File

@ -257,7 +257,7 @@ js::ObjectImpl::slotInRange(uint32_t slot, SentinelAllowed sentinel) const
*/
MOZ_NEVER_INLINE
#endif
const Shape *
Shape *
js::ObjectImpl::nativeLookup(JSContext *cx, jsid id)
{
MOZ_ASSERT(isNative());
@ -266,7 +266,7 @@ js::ObjectImpl::nativeLookup(JSContext *cx, jsid id)
}
#ifdef DEBUG
const Shape *
Shape *
js::ObjectImpl::nativeLookupNoAllocation(JSContext *cx, jsid id)
{
MOZ_ASSERT(isNative());
@ -503,7 +503,7 @@ js::GetOwnProperty(JSContext *cx, Handle<ObjectImpl*> obj, PropertyId pid_, unsi
return false;
}
const Shape *shape = obj->nativeLookup(cx, pid);
Shape *shape = obj->nativeLookup(cx, pid);
if (!shape) {
/* Not found: attempt to resolve it. */
Class *clasp = obj->getClass();

View File

@ -1138,14 +1138,14 @@ class ObjectImpl : public gc::Cell
/* Compute dynamicSlotsCount() for this object. */
inline uint32_t numDynamicSlots() const;
const Shape * nativeLookup(JSContext *cx, jsid id);
inline const Shape * nativeLookup(JSContext *cx, PropertyId pid);
inline const Shape * nativeLookup(JSContext *cx, PropertyName *name);
Shape * nativeLookup(JSContext *cx, jsid id);
inline Shape * nativeLookup(JSContext *cx, PropertyId pid);
inline Shape * nativeLookup(JSContext *cx, PropertyName *name);
#ifdef DEBUG
const Shape * nativeLookupNoAllocation(JSContext *cx, jsid id);
inline const Shape * nativeLookupNoAllocation(JSContext *cx, PropertyId pid);
inline const Shape * nativeLookupNoAllocation(JSContext *cx, PropertyName *name);
Shape * nativeLookupNoAllocation(JSContext *cx, jsid id);
inline Shape * nativeLookupNoAllocation(JSContext *cx, PropertyId pid);
inline Shape * nativeLookupNoAllocation(JSContext *cx, PropertyName *name);
#endif
inline Class *getClass() const;

View File

@ -661,7 +661,7 @@ StaticBlockObject::create(JSContext *cx)
return &obj->asStaticBlock();
}
const Shape *
Shape *
StaticBlockObject::addVar(JSContext *cx, jsid id, int index, bool *redeclared)
{
JS_ASSERT(JSID_IS_ATOM(id) || (JSID_IS_INT(id) && JSID_TO_INT(id) == index));
@ -804,7 +804,7 @@ js::XDRStaticBlockObject(XDRState<mode> *xdr, JSScript *script, StaticBlockObjec
return false;
for (Shape::Range r(obj->lastProperty()); !r.empty(); r.popFront()) {
const Shape *shape = &r.front();
Shape *shape = &r.front();
shapes[shape->shortid()] = shape;
}
@ -813,7 +813,7 @@ js::XDRStaticBlockObject(XDRState<mode> *xdr, JSScript *script, StaticBlockObjec
* properties to XDR, stored as id/shortid pairs.
*/
for (unsigned i = 0; i < count; i++) {
const Shape *shape = shapes[i];
Shape *shape = shapes[i];
JS_ASSERT(shape->hasDefaultGetter());
JS_ASSERT(unsigned(shape->shortid()) == i);
@ -866,7 +866,7 @@ js::CloneStaticBlockObject(JSContext *cx, StaticBlockObject &srcBlock,
for (Shape::Range r = srcBlock.lastProperty()->all(); !r.empty(); r.popFront())
shapes[r.front().shortid()] = &r.front();
for (const Shape **p = shapes.begin(); p != shapes.end(); ++p) {
for (Shape **p = shapes.begin(); p != shapes.end(); ++p) {
jsid id = (*p)->propid();
unsigned i = (*p)->shortid();

View File

@ -262,7 +262,7 @@ class StaticBlockObject : public BlockObject
*/
bool needsClone();
const Shape *addVar(JSContext *cx, jsid id, int index, bool *redeclared);
Shape *addVar(JSContext *cx, jsid id, int index, bool *redeclared);
};
class ClonedBlockObject : public BlockObject

View File

@ -3443,6 +3443,8 @@ nsCSSFrameConstructor::FindInputData(Element* aElement,
SIMPLE_INT_CREATE(NS_FORM_INPUT_TEL, NS_NewTextControlFrame),
SIMPLE_INT_CREATE(NS_FORM_INPUT_URL, NS_NewTextControlFrame),
SIMPLE_INT_CREATE(NS_FORM_INPUT_PASSWORD, NS_NewTextControlFrame),
// TODO: this is temporary until a frame is written: bug 635240.
SIMPLE_INT_CREATE(NS_FORM_INPUT_NUMBER, NS_NewTextControlFrame),
{ NS_FORM_INPUT_SUBMIT,
FCDATA_WITH_WRAPPING_BLOCK(0, NS_NewGfxButtonControlFrame,
nsCSSAnonBoxes::buttonContent) },

View File

@ -647,6 +647,9 @@ pref("dom.min_background_timeout_value", 1000);
pref("dom.new_bindings", true);
pref("dom.experimental_bindings", true);
// Don't use new input types
pref("dom.experimental_forms", false);
// Parsing perf prefs. For now just mimic what the old code did.
#ifndef XP_WIN
pref("content.sink.pending_event_mode", 0);

View File

@ -440,6 +440,147 @@
ctypes.ssize_t,
projector(ctypes.ssize_t, true));
/**
* Utility class, used to build a |struct| type
* from a set of field names, types and offsets.
*
* @param {string} name The name of the |struct| type.
* @param {number} size The total size of the |struct| type in bytes.
*/
function HollowStructure(name, size) {
if (!name) {
throw new TypeError("HollowStructure expects a name");
}
if (!size || size < 0) {
throw new TypeError("HollowStructure expects a (positive) size");
}
// A mapping from offsets in the struct to name/type pairs
// (or nothing if no field starts at that offset).
this.offset_to_field_info = [];
// The name of the struct
this.name = name;
// The size of the struct, in bytes
this.size = size;
// The number of paddings inserted so far.
// Used to give distinct names to padding fields.
this._paddings = 0;
}
HollowStructure.prototype = {
/**
* Add a field at a given offset.
*
* @param {number} offset The offset at which to insert the field.
* @param {string} name The name of the field.
* @param {CType|Type} type The type of the field.
*/
add_field_at: function add_field_at(offset, name, type) {
if (offset === null) {
throw new TypeError("add_field_at requires a non-null offset");
}
if (!name) {
throw new TypeError("add_field_at requires a non-null name");
}
if (!type) {
throw new TypeError("add_field_at requires a non-null type");
}
if (type instanceof Type) {
type = type.implementation;
}
if (this.offset_to_field_info[offset]) {
throw new Error("HollowStructure " + this.name +
" already has a field at offset " + offset);
}
if (offset + type.size > this.size) {
throw new Error("HollowStructure " + this.name +
" cannot place a value of type " + type +
" at offset " + offset +
" without exceeding its size of " + this.size);
}
let field = {name: name, type:type};
this.offset_to_field_info[offset] = field;
},
/**
* Create a pseudo-field that will only serve as padding.
*
* @param {number} size The number of bytes in the field.
* @return {Object} An association field-name => field-type,
* as expected by |ctypes.StructType|.
*/
_makePaddingField: function makePaddingField(size) {
let field = ({});
field["padding_" + this._paddings] =
ctypes.ArrayType(ctypes.uint8_t, size);
this._paddings++;
return field;
},
/**
* Convert this |HollowStructure| into a |Type|.
*/
getType: function getType() {
// Contents of the structure, in the format expected
// by ctypes.StructType.
let struct = [];
let i = 0;
while (i < this.size) {
let currentField = this.offset_to_field_info[i];
if (!currentField) {
// No field was specified at this offset, we need to
// introduce some padding.
// Firstly, determine how many bytes of padding
let padding_length = 1;
while (i + padding_length < this.size
&& !this.offset_to_field_info[i + padding_length]) {
++padding_length;
}
// Then add the padding
struct.push(this._makePaddingField(padding_length));
// And proceed
i += padding_length;
} else {
// We have a field at this offset.
// Firstly, ensure that we do not have two overlapping fields
for (let j = 1; j < currentField.type.size; ++j) {
let candidateField = this.offset_to_field_info[i + j];
if (candidateField) {
throw new Error("Fields " + currentField.name +
" and " + candidateField.name +
" overlap at position " + (i + j));
}
}
// Then add the field
let field = ({});
field[currentField.name] = currentField.type;
struct.push(field);
// And proceed
i += currentField.type.size;
}
}
let result = new Type(this.name, ctypes.StructType(this.name, struct));
if (result.implementation.size != this.size) {
throw new Error("Wrong size for type " + this.name +
": expected " + this.size +
", found " + result.implementation.size +
" (" + result.implementation.toSource() + ")");
}
return result;
}
};
exports.OS.Shared.HollowStructure = HollowStructure;
/**
* Declare a function through js-ctypes
*
@ -473,6 +614,10 @@
let argtypes = [];
for (let i = 3; i < arguments.length; ++i) {
let current = arguments[i];
if (!current) {
throw new TypeError("Missing type for argument " + ( i - 3 ) +
" of symbol " + symbol);
}
if (!current.implementation) {
throw new TypeError("Missing implementation for argument " + (i - 3)
+ " of symbol " + symbol

View File

@ -46,7 +46,7 @@
// Open libc
let libc;
let libc_candidates = [ "libSystem.dylib",
let libc_candidates = [ "libsystem.B.dylib",
"libc.so.6",
"libc.so" ];
for (let i = 0; i < libc_candidates.length; ++i) {
@ -150,6 +150,47 @@
Types.intn_t(OS.Constants.libc.OSFILE_SIZEOF_MODE_T),
{name: {value: "mode_t"}});
Types.DIR =
new Type("DIR",
ctypes.StructType("DIR"));
Types.null_or_DIR_ptr =
new Type("null_or_DIR*",
Types.DIR.out_ptr.implementation,
function(dir, operation) {
if (dir == null || dir.isNull()) {
return null;
}
return ctypes.CDataFinalizer(dir, _close_dir);
});
// Structure |dirent|
// Building this type is rather complicated, as its layout varies between
// variants of Unix. For this reason, we rely on a number of constants
// (computed in C from the C data structures) that give us the layout.
// The structure we compute looks like
// { int8_t[...] before_d_type; // ignored content
// int8_t d_type ;
// int8_t[...] before_d_name; // ignored content
// char[...] d_name;
// };
{
let dirent = new OS.Shared.HollowStructure("dirent",
OS.Constants.libc.OSFILE_SIZEOF_DIRENT);
dirent.add_field_at(OS.Constants.libc.OSFILE_OFFSETOF_DIRENT_D_TYPE,
"d_type", ctypes.uint8_t);
dirent.add_field_at(OS.Constants.libc.OSFILE_OFFSETOF_DIRENT_D_NAME,
"d_name", ctypes.ArrayType(ctypes.char, OS.Constants.libc.OSFILE_SIZEOF_DIRENT_D_NAME));
// We now have built |dirent|.
Types.dirent = dirent.getType();
LOG("dirent is: " + Types.dirent.implementation.toSource());
}
Types.null_or_dirent_ptr =
new Type("null_of_dirent",
Types.dirent.out_ptr.implementation);
// Declare libc functions as functions of |OS.Unix.File|
// Finalizer-related functions
@ -163,6 +204,16 @@
return fd.dispose();
};
let _close_dir =
libc.declare("closedir", ctypes.default_abi,
/*return */ctypes.int,
/*dirp*/ Types.DIR.in_ptr.implementation);
UnixFile.closedir = function closedir(fd) {
// Detach the finalizer and call |_close_dir|.
return fd.dispose();
};
UnixFile.free =
libc.declare("free", ctypes.default_abi,
/*return*/ ctypes.void_t,
@ -284,6 +335,12 @@
/*offset*/ Types.off_t,
/*whence*/ Types.int);
UnixFile.mkdir =
declareFFI("mkdir", ctypes.default_abi,
/*return*/ Types.int,
/*path*/ Types.string,
/*mode*/ Types.int);
UnixFile.mkstemp =
declareFFI("mkstemp", ctypes.default_abi,
/*return*/ Types.null_or_string,
@ -296,6 +353,11 @@
/*oflags*/Types.int,
/*mode*/ Types.int);
UnixFile.opendir =
declareFFI("opendir", ctypes.default_abi,
/*return*/ Types.null_or_DIR_ptr,
/*path*/ Types.string);
UnixFile.pread =
declareFFI("pread", ctypes.default_abi,
/*return*/ Types.negativeone_or_ssize_t,
@ -319,12 +381,33 @@
/*buf*/ Types.char.out_ptr,
/*nbytes*/Types.size_t);
if (OS.Constants.libc._DARWIN_FEATURE_64_BIT_INODE) {
// Special case for MacOS X 10.5+
// Symbol name "readdir" still exists but is used for a
// deprecated function that does not match the
// constants of |OS.Constants.libc|.
UnixFile.readdir =
declareFFI("readdir$INODE64", ctypes.default_abi,
/*return*/Types.null_or_dirent_ptr,
/*dir*/ Types.DIR.in_ptr); // For MacOS X
} else {
UnixFile.readdir =
declareFFI("readdir", ctypes.default_abi,
/*return*/Types.null_or_dirent_ptr,
/*dir*/ Types.DIR.in_ptr); // Other Unices
}
UnixFile.rename =
declareFFI("rename", ctypes.default_abi,
/*return*/ Types.negativeone_or_nothing,
/*old*/ Types.string,
/*new*/ Types.string);
UnixFile.rmdir =
declareFFI("rmdir", ctypes.default_abi,
/*return*/ Types.int,
/*path*/ Types.string);
UnixFile.splice =
declareFFI("splice", ctypes.default_abi,
/*return*/ Types.long,

View File

@ -590,6 +590,112 @@
} // End of definition of copy/move
/**
* Iterate on one directory.
*
* This iterator will not enter subdirectories.
*
* @param {string} path The directory upon which to iterate.
* @param {*=} options Ignored in this implementation.
*
* @throws {File.Error} If |path| does not represent a directory or
* if the directory cannot be iterated.
* @constructor
*/
File.DirectoryIterator = function DirectoryIterator(path, options) {
let dir = throw_on_null("DirectoryIterator", UnixFile.opendir(path));
this._dir = dir;
this._path = path;
};
File.DirectoryIterator.prototype = {
__iterator__: function __iterator__() {
return this;
},
/**
* Return the next entry in the directory, if any such entry is
* available.
*
* Skip special directories "." and "..".
*
* @return {File.Entry} The next entry in the directory.
* @throws {StopIteration} Once all files in the directory have been
* encountered.
*/
next: function next() {
if (!this._dir) {
throw StopIteration;
}
for (let entry = UnixFile.readdir(this._dir);
entry != null && !entry.isNull();
entry = UnixFile.readdir(this._dir)) {
let contents = entry.contents;
if (contents.d_type == OS.Constants.libc.DT_DIR) {
let name = contents.d_name.readString();
if (name == "." || name == "..") {
continue;
}
}
return new File.DirectoryIterator.Entry(contents, this._path);
}
this.close();
throw StopIteration;
},
/**
* Close the iterator and recover all resources.
* You should call this once you have finished iterating on a directory.
*/
close: function close() {
if (!this._dir) return;
UnixFile.closedir(this._dir);
this._dir = null;
}
};
/**
* An entry in a directory.
*/
File.DirectoryIterator.Entry = function Entry(unix_entry, parent) {
// Copy the relevant part of |unix_entry| to ensure that
// our data is not overwritten prematurely.
this._d_type = unix_entry.d_type;
this._name = unix_entry.d_name.readString();
this._parent = parent;
};
File.DirectoryIterator.Entry.prototype = {
/**
* |true| if the entry is a directory, |false| otherwise
*/
get isDir() {
return this._d_type == OS.Constants.libc.DT_DIR;
},
/**
* |true| if the entry is a symbolic link, |false| otherwise
*/
get isLink() {
return this._d_type == OS.Constants.libc.DT_LNK;
},
/**
* The name of the entry.
* @type {string}
*/
get name() {
return this._name;
},
/**
* The full path to the entry.
*/
get path() {
delete this.path;
let path = OS.Unix.Path.join(this._parent, this.name);
Object.defineProperty(this, "path", {value: path});
return path;
}
};
/**
* Get/set the current directory.
@ -601,11 +707,10 @@
);
},
get: function() {
let path = UnixFile.getwd(null);
if (path.isNull()) {
throw new File.Error("getwd");
}
return ctypes.CDataFinalizer(path, UnixFile.free);
let path = UnixFile.get_current_dir_name?UnixFile.get_current_dir_name():
UnixFile.getwd_auto(null);
throw_on_null("curDir",path);
return path.readString();
}
}
);
@ -638,6 +743,13 @@
return result;
}
function throw_on_null(operation, result) {
if (result == null || (result.isNull && result.isNull())) {
throw new File.Error(operation);
}
return result;
}
File.POS_START = exports.OS.Constants.libc.SEEK_SET;
File.POS_CURRENT = exports.OS.Constants.libc.SEEK_CUR;
File.POS_END = exports.OS.Constants.libc.SEEK_END;

View File

@ -94,6 +94,24 @@
}
return ctypes.CDataFinalizer(maybe, _CloseHandle);
});
/**
* A C integer holding INVALID_HANDLE_VALUE in case of error or
* a file descriptor in case of success.
*/
Types.maybe_find_HANDLE =
new Type("maybe_find_HANDLE",
Types.HANDLE.implementation,
function (maybe) {
if (ctypes.cast(maybe, ctypes.int).value == invalid_handle) {
// Ensure that API clients can effectively compare against
// Const.INVALID_HANDLE_VALUE. Without this cast,
// == would always return |false|.
return invalid_handle;
}
return ctypes.CDataFinalizer(maybe, _FindClose);
});
let invalid_handle = exports.OS.Constants.Win.INVALID_HANDLE_VALUE;
Types.DWORD = Types.int32_t;
@ -122,6 +140,40 @@
new Type("zero_or_nothing",
Types.bool.implementation);
Types.FILETIME =
new Type("FILETIME",
ctypes.StructType("FILETIME", [
{ lo: Types.DWORD.implementation },
{ hi: Types.DWORD.implementation }]));
Types.FindData =
new Type("FIND_DATA",
ctypes.StructType("FIND_DATA", [
{ dwFileAttributes: ctypes.uint32_t },
{ ftCreationTime: Types.FILETIME.implementation },
{ ftLastAccessTime: Types.FILETIME.implementation },
{ ftLastWriteTime: Types.FILETIME.implementation },
{ nFileSizeHigh: Types.DWORD.implementation },
{ nFileSizeLow: Types.DWORD.implementation },
{ dwReserved0: Types.DWORD.implementation },
{ dwReserved1: Types.DWORD.implementation },
{ cFileName: ctypes.ArrayType(ctypes.jschar, exports.OS.Constants.Win.MAX_PATH) },
{ cAlternateFileName: ctypes.ArrayType(ctypes.jschar, 14) }
]));
Types.SystemTime =
new Type("SystemTime",
ctypes.StructType("SystemTime", [
{ wYear: ctypes.int16_t },
{ wMonth: ctypes.int16_t },
{ wDayOfWeek: ctypes.int16_t },
{ wDay: ctypes.int16_t },
{ wHour: ctypes.int16_t },
{ wMinute: ctypes.int16_t },
{ wSecond: ctypes.int16_t },
{ wMilliSeconds: ctypes.int16_t }
]));
// Special case: these functions are used by the
// finalizer
let _CloseHandle =
@ -133,6 +185,15 @@
return fd.dispose(); // Returns the value of |CloseHandle|.
};
let _FindClose =
libc.declare("CloseHandle", ctypes.winapi_abi,
/*return */ctypes.bool,
/*handle*/ ctypes.voidptr_t);
WinFile.FindClose = function(handle) {
return handle.dispose(); // Returns the value of |CloseHandle|.
};
// Declare libc functions as functions of |OS.Win.File|
WinFile.CopyFile =
@ -158,6 +219,24 @@
/*return*/ Types.zero_or_nothing,
/*path*/ Types.jschar.in_ptr);
WinFile.FileTimeToSystemTime =
declareFFI("FileTimeToSystemTime", ctypes.winapi_abi,
/*return*/ Types.zero_or_nothing,
/*filetime*/Types.FILETIME.in_ptr,
/*systime*/ Types.SystemTime.out_ptr);
WinFile.FindFirstFile =
declareFFI("FindFirstFileW", ctypes.winapi_abi,
/*return*/ Types.maybe_find_HANDLE,
/*pattern*/Types.jschar.in_ptr,
/*data*/ Types.FindData.out_ptr);
WinFile.FindNextFile =
declareFFI("FindNextFileW", ctypes.winapi_abi,
/*return*/ Types.zero_or_nothing,
/*prev*/ Types.HANDLE,
/*data*/ Types.FindData.out_ptr);
WinFile.FormatMessage =
declareFFI("FormatMessageW", ctypes.winapi_abi,
/*return*/ Types.DWORD,
@ -195,6 +274,11 @@
/*overlapped*/Types.void_t.inout_ptr // FIXME: Implement?
);
WinFile.RemoveDirectory =
declareFFI("RemoveDirectoryW", ctypes.winapi_abi,
/*return*/ Types.zero_or_nothing,
/*path*/ Types.jschar.in_ptr);
WinFile.SetCurrentDirectory =
declareFFI("SetCurrentDirectoryW", ctypes.winapi_abi,
/*return*/ Types.zero_or_nothing,

View File

@ -453,12 +453,230 @@
);
};
/**
* A global value used to receive data during a
* |FindFirstFile|/|FindNextFile|.
*/
let gFindData = new OS.Shared.Type.FindData.implementation();
let gFindDataPtr = gFindData.address();
/**
* A global value used to receive data during time conversions.
*/
let gSystemTime = new OS.Shared.Type.SystemTime.implementation();
let gSystemTimePtr = gSystemTime.address();
/**
* Utility function: convert a FILETIME to a JavaScript Date.
*/
let FILETIME_to_Date = function FILETIME_to_Date(fileTime) {
LOG("fileTimeToDate:", fileTime);
if (fileTime == null) {
throw new TypeError("Expecting a non-null filetime");
}
LOG("fileTimeToDate normalized:", fileTime);
throw_on_zero("FILETIME_to_Date", WinFile.FileTimeToSystemTime(fileTime.address(),
gSystemTimePtr));
return new Date(gSystemTime.wYear, gSystemTime.wMonth,
gSystemTime.wDay, gSystemTime.wHour,
gSystemTime.wMinute, gSystemTime.wSecond,
gSystemTime.wMilliSeconds);
};
/**
* Iterate on one directory.
*
* This iterator will not enter subdirectories.
*
* @param {string} path The directory upon which to iterate.
* @param {*=} options Ignored in this implementation.
*
* @throws {File.Error} If |path| does not represent a directory or
* if the directory cannot be iterated.
* @constructor
*/
File.DirectoryIterator = function DirectoryIterator(path, options) {
if (options && options.winPattern) {
this._pattern = path + "\\" + options.winPattern;
} else {
this._pattern = path + "\\*";
}
this._handle = null;
this._path = path;
this._started = false;
};
File.DirectoryIterator.prototype = {
__iterator__: function __iterator__() {
return this;
},
/**
* Fetch the next entry in the directory.
*
* @return null If we have reached the end of the directory.
*/
_next: function _next() {
// Iterator is not fully initialized yet. Finish
// initialization.
if (!this._started) {
this._started = true;
this._handle = WinFile.FindFirstFile(this._pattern, gFindDataPtr);
if (this._handle == null) {
let error = ctypes.winLastError;
if (error == Const.ERROR_FILE_NOT_FOUND) {
this.close();
return null;
} else {
throw new File.Error("iter (FindFirstFile)", error);
}
}
return gFindData;
}
// We have closed this iterator already.
if (!this._handle) {
return null;
}
if (WinFile.FindNextFile(this._handle, gFindDataPtr)) {
return gFindData;
} else {
let error = ctypes.winLastError;
this.close();
if (error == Const.ERROR_NO_MORE_FILES) {
return null;
} else {
throw new File.Error("iter (FindNextFile)", error);
}
}
},
/**
* Return the next entry in the directory, if any such entry is
* available.
*
* Skip special directories "." and "..".
*
* @return {File.Entry} The next entry in the directory.
* @throws {StopIteration} Once all files in the directory have been
* encountered.
*/
next: function next() {
// FIXME: If we start supporting "\\?\"-prefixed paths, do not forget
// that "." and ".." are absolutely normal file names if _path starts
// with such prefix
for (let entry = this._next(); entry != null; entry = this._next()) {
let name = entry.cFileName.readString();
if (name == "." || name == "..") {
continue;
}
return new File.DirectoryIterator.Entry(entry, this._path);
}
throw StopIteration;
},
close: function close() {
if (!this._handle) {
return;
}
WinFile.FindClose(this._handle);
this._handle = null;
}
};
File.DirectoryIterator.Entry = function Entry(win_entry, parent) {
// Copy the relevant part of |win_entry| to ensure that
// our data is not overwritten prematurely.
if (!win_entry.dwFileAttributes) {
throw new TypeError();
}
this._dwFileAttributes = win_entry.dwFileAttributes;
this._name = win_entry.cFileName.readString();
if (!this._name) {
throw new TypeError("Empty name");
}
this._ftCreationTime = win_entry.ftCreationTime;
if (!win_entry.ftCreationTime) {
throw new TypeError();
}
this._ftLastAccessTime = win_entry.ftLastAccessTime;
if (!win_entry.ftLastAccessTime) {
throw new TypeError();
}
this._ftLastWriteTime = win_entry.ftLastWriteTime;
if (!win_entry.ftLastWriteTime) {
throw new TypeError();
}
if (!parent) {
throw new TypeError("Empty parent");
}
this._parent = parent;
};
File.DirectoryIterator.Entry.prototype = {
/**
* |true| if the entry is a directory, |false| otherwise
*/
get isDir() {
return this._dwFileAttributes & Const.FILE_ATTRIBUTE_DIRECTORY;
},
/**
* |true| if the entry is a symbolic link, |false| otherwise
*/
get isLink() {
return this._dwFileAttributes & Const.FILE_ATTRIBUTE_REPARSE_POINT;
},
/**
* The name of the entry.
* @type {string}
*/
get name() {
return this._name;
},
/**
* The creation time of this file.
* @type {Date}
*/
get winCreationTime() {
let date = FILETIME_to_Date(this._ftCreationTime);
delete this.winCreationTime;
Object.defineProperty(this, "winCreationTime", {value: date});
return date;
},
/**
* The last modification time of this file.
* @type {Date}
*/
get winLastWriteTime() {
let date = FILETIME_to_Date(this._ftLastWriteTime);
delete this.winLastWriteTime;
Object.defineProperty(this, "winLastWriteTime", {value: date});
return date;
},
/**
* The last access time of this file.
* @type {Date}
*/
get winLastAccessTime() {
let date = FILETIME_to_Date(this._ftLastAccessTime);
delete this.winLastAccessTime;
Object.defineProperty(this, "winLastAccessTime", {value: date});
return date;
},
/**
* The full path to the entry.
* @type {string}
*/
get path() {
delete this.path;
let path = OS.Win.Path.join(this._parent, this.name);
Object.defineProperty(this, "path", {value: path});
return path;
}
};
/**
* Get/set the current directory.
*/
Object.defineProperty(File, "curDir", {
set: function(path) {
throw_on_zero("set curDir",
throw_on_zero("set curDir",
WinFile.SetCurrentDirectory(path));
},
get: function() {

View File

@ -20,6 +20,7 @@ self.onmessage = function(msg) {
test_copy_existing_file();
test_read_write_file();
test_move_file();
test_iter_dir();
} catch (x) {
log("Catching error: " + x);
log("Stack: " + x.stack);
@ -198,3 +199,63 @@ function test_move_file()
}
function test_iter_dir()
{
ok(true, "test_iter_dir: Starting");
// Create a file, to be sure that it exists
let tmp_file_name = "test_osfile_front.tmp";
let tmp_file = OS.File.open(tmp_file_name, {write: true, trunc:true});
tmp_file.close();
let parent = OS.File.curDir;
ok(true, "test_iter_dir: directory " + parent);
let iterator = new OS.File.DirectoryIterator(parent);
ok(true, "test_iter_dir: iterator created");
let encountered_tmp_file = false;
for (let entry in iterator) {
// Checking that |name| can be decoded properly
ok(true, "test_iter_dir: encountering entry " + entry.name);
if (entry.name == tmp_file_name) {
encountered_tmp_file = true;
isnot(entry.isDir, "test_iter_dir: The temporary file is not a directory");
isnot(entry.isLink, "test_iter_dir: The temporary file is not a link");
}
let file;
let success = true;
try {
file = OS.File.open(entry.path);
} catch (x) {
if (x.becauseNoSuchFile) {
success = false;
}
}
if (file) {
file.close();
}
ok(success, "test_iter_dir: Entry " + entry.path + " exists");
if (OS.Win) {
let year = new Date().getFullYear();
let creation = entry.winCreationTime;
ok(creation, "test_iter_dir: Windows creation date exists: " + creation);
ok(creation.getFullYear() >= year - 1 && creation.getFullYear() <= year, "test_iter_dir: consistent creation date");
let lastWrite = entry.winLastWriteTime;
ok(lastWrite, "test_iter_dir: Windows lastWrite date exists: " + lastWrite);
ok(lastWrite.getFullYear() >= year - 1 && lastWrite.getFullYear() <= year, "test_iter_dir: consistent lastWrite date");
let lastAccess = entry.winLastAccessTime;
ok(lastAccess, "test_iter_dir: Windows lastAccess date exists: " + lastAccess);
ok(lastAccess.getFullYear() >= year - 1 && lastAccess.getFullYear() <= year, "test_iter_dir: consistent lastAccess date");
}
}
ok(encountered_tmp_file, "test_iter_dir: We have found the temporary file");
ok(true, "test_iter_dir: Cleaning up");
iterator.close();
ok(true, "test_iter_dir: Complete");
}

View File

@ -80,8 +80,14 @@ Form History test: form field autocomplete
<button type="submit">Submit</button>
</form>
<!-- normal, basic form (with fieldname='searchbar-history') -->
<!-- form with input type='number' -->
<form id="form12" onsubmit="return false;">
<input type="number" name="field10">
<button type="submit">Submit</button>
</form>
<!-- normal, basic form (with fieldname='searchbar-history') -->
<form id="form13" onsubmit="return false;">
<input type="text" name="searchbar-history">
<button type="submit">Submit</button>
</form>
@ -127,11 +133,12 @@ fh.addEntry("field6", "value");
fh.addEntry("field7", "value");
fh.addEntry("field8", "value");
fh.addEntry("field9", "value");
fh.addEntry("field10", "42");
fh.addEntry("searchbar-history", "blacklist test");
// All these non-implemeted types might need autocomplete tests in the future.
var todoTypes = [ "datetime", "date", "month", "week", "time", "datetime-local",
"number", "range", "color" ];
"range", "color" ];
var todoInput = document.createElement("input");
for each (var type in todoTypes) {
todoInput.type = type;
@ -710,16 +717,28 @@ function runTest(testNum) {
} else if (testNum == 402) {
input = $_(11, "field9");
} else if (testNum == 403) {
// Go to test 500.
fh.addEntry("field1", "value1");
input = $_(1, "field1");
testNum = 499;
input = $_(12, "field10");
}
restoreForm();
doKey("down");
break;
case 404:
checkMenuEntries(["42"]);
doKey("down");
doKey("return");
checkForm("42");
// Go to test 500.
fh.addEntry("field1", "value1");
input = $_(1, "field1");
testNum = 499;
restoreForm();
doKey("down");
break;
// Check that the input event is fired.
case 500:
input.addEventListener("input", function(event) {
@ -738,7 +757,7 @@ function runTest(testNum) {
case 600:
// check we don't show autocomplete for searchbar-history
input = $_(12, "searchbar-history");
input = $_(13, "searchbar-history");
// Trigger autocomplete popup
checkForm("");

View File

@ -18,6 +18,7 @@ XPCOMUtils.defineLazyServiceGetter(this, "gDirService",
var FileUtils = {
MODE_RDONLY : 0x01,
MODE_WRONLY : 0x02,
MODE_RDWR : 0x04,
MODE_CREATE : 0x08,
MODE_APPEND : 0x10,
MODE_TRUNCATE : 0x20,

View File

@ -25,6 +25,10 @@ DEFINES += \
-DMOZ_DEBUG=$(MOZ_DEBUG) \
$(NULL)
ifdef MOZ_MAINTENANCE_SERVICE
DEFINES += -DMOZ_MAINTENANCE_SERVICE=$(MOZ_MAINTENANCE_SERVICE)
endif
# Android doesn't build the updater binary, so it skips the things that test it.
ifneq ($(OS_TARGET),Android)
DIRS = \

View File

@ -288,7 +288,11 @@ var DEBUG_AUS_TEST = true;
#include ../shared.js
#ifdef MOZ_MAINTENANCE_SERVICE
const STATE_APPLIED_PLATFORM = IS_WIN ? STATE_APPLIED_SVC : STATE_APPLIED;
#else
const STATE_APPLIED_PLATFORM = STATE_APPLIED;
#endif
/**
* Nulls out the most commonly used global vars used by tests as appropriate.

View File

@ -247,7 +247,7 @@ function checkUpdateFinished() {
log.append(FILE_UPDATE_LOG);
if (!log.exists()) {
if (gTimeoutRuns > MAX_TIMEOUT_RUNS)
do_throw("Exceeded MAX_TIMEOUT_RUNS whilst waiting for updates log to be created");
do_throw("Exceeded MAX_TIMEOUT_RUNS whilst waiting for updates log to be created at " + log.path);
else
do_timeout(CHECK_TIMEOUT_MILLI, checkUpdateFinished);
return;
@ -257,7 +257,7 @@ function checkUpdateFinished() {
let status = readStatusFile();
if (status == STATE_PENDING || status == STATE_APPLYING) {
if (gTimeoutRuns > MAX_TIMEOUT_RUNS)
do_throw("Exceeded MAX_TIMEOUT_RUNS whilst waiting for updates status to not be pending or applying");
do_throw("Exceeded MAX_TIMEOUT_RUNS whilst waiting for updates status to not be pending or applying, current status is: " + status);
else
do_timeout(CHECK_TIMEOUT_MILLI, checkUpdateFinished);
return;

View File

@ -335,7 +335,7 @@ function checkUpdateApplied() {
// Don't proceed until the update has been applied.
if (gUpdateManager.activeUpdate.state != STATE_APPLIED_PLATFORM) {
if (gTimeoutRuns > MAX_TIMEOUT_RUNS)
do_throw("Exceeded MAX_TIMEOUT_RUNS whilst waiting for update to be applied");
do_throw("Exceeded MAX_TIMEOUT_RUNS whilst waiting for update to be applied, current state is: " + gUpdateManager.activeUpdate.state);
else
do_timeout(CHECK_TIMEOUT_MILLI, checkUpdateApplied);
return;
@ -473,7 +473,7 @@ function checkUpdateFinished() {
let status = readStatusFile();
if (status != STATE_SUCCEEDED) {
if (gTimeoutRuns > MAX_TIMEOUT_RUNS)
do_throw("Exceeded MAX_TIMEOUT_RUNS whilst waiting for succeeded state");
do_throw("Exceeded MAX_TIMEOUT_RUNS whilst waiting for state to change to succeeded, current status: " + status);
else
do_timeout(CHECK_TIMEOUT_MILLI, checkUpdateFinished);
return;

View File

@ -363,7 +363,7 @@ function checkUpdateApplied() {
// Don't proceed until the update has been applied.
if (gUpdateManager.activeUpdate.state != STATE_APPLIED_PLATFORM) {
if (gTimeoutRuns > MAX_TIMEOUT_RUNS)
do_throw("Exceeded whilst waiting for update to be applied");
do_throw("Exceeded MAX_TIMEOUT_RUNS whilst waiting for update to be applied, current state is: " + gUpdateManager.activeUpdate.state);
else
do_timeout(CHECK_TIMEOUT_MILLI, checkUpdateApplied);
return;
@ -501,7 +501,7 @@ function checkUpdateFinished() {
let status = readStatusFile();
if (status != STATE_SUCCEEDED) {
if (gTimeoutRuns > MAX_TIMEOUT_RUNS)
do_throw("Exceeded whilst waiting for succeeded state");
do_throw("Exceeded MAX_TIMEOUT_RUNS whilst waiting for state to change to succeeded, current status: " + status);
else
do_timeout(CHECK_TIMEOUT_MILLI, checkUpdateFinished);
return;

View File

@ -204,7 +204,7 @@ function checkUpdateFinished() {
log.append(FILE_UPDATE_LOG);
if (!log.exists()) {
if (++gTimeoutRuns > MAX_TIMEOUT_RUNS)
do_throw("Exceeded MAX_TIMEOUT_RUNS whilst waiting for updates log to be created");
do_throw("Exceeded MAX_TIMEOUT_RUNS whilst waiting for updates log to be created at " + log.path);
else
do_timeout(CHECK_TIMEOUT_MILLI, checkUpdateFinished);
return;

View File

@ -342,8 +342,8 @@ function checkUpdateApplied() {
gTimeoutRuns++;
// Don't proceed until the update has been applied.
if (gUpdateManager.activeUpdate.state != STATE_APPLIED_PLATFORM) {
if (++gTimeoutRuns > MAX_TIMEOUT_RUNS)
do_throw("Exceeded MAX_TIMEOUT_RUNS whilst waiting for state to be applied to platform");
if (gTimeoutRuns > MAX_TIMEOUT_RUNS)
do_throw("Exceeded MAX_TIMEOUT_RUNS whilst waiting for update to be applied, current state is: " + gUpdateManager.activeUpdate.state);
else
do_timeout(CHECK_TIMEOUT_MILLI, checkUpdateApplied);
return;
@ -360,7 +360,7 @@ function checkUpdateApplied() {
let log = getUpdatesDir();
log.append(FILE_LAST_LOG);
if (!log.exists()) {
if (++gTimeoutRuns > MAX_TIMEOUT_RUNS)
if (gTimeoutRuns > MAX_TIMEOUT_RUNS)
do_throw("Exceeded MAX_TIMEOUT_RUNS whilst waiting for update log to be created");
else
do_timeout(CHECK_TIMEOUT_MILLI, checkUpdateApplied);
@ -455,8 +455,8 @@ function checkUpdateFinished() {
try {
let status = readStatusFile();
if (status != STATE_SUCCEEDED) {
if (++gTimeoutRuns > MAX_TIMEOUT_RUNS)
do_throw("Exceeded MAX_TIMEOUT_RUNS whist waiting for succeeded state");
if (gTimeoutRuns > MAX_TIMEOUT_RUNS)
do_throw("Exceeded MAX_TIMEOUT_RUNS whilst waiting for state to change to succeeded, current status: " + status);
else
do_timeout(CHECK_TIMEOUT_MILLI, checkUpdateFinished);
return;
@ -472,7 +472,7 @@ function checkUpdateFinished() {
if (e.result == Components.results.NS_ERROR_FILE_IS_LOCKED) {
// This might happen on Windows in case the callback application has not
// finished its job yet. So, we'll wait some more.
if (++gTimeoutRuns > MAX_TIMEOUT_RUNS)
if (gTimeoutRuns > MAX_TIMEOUT_RUNS)
do_throw("Exceeded whilst waiting for file to be unlocked");
else
do_timeout(CHECK_TIMEOUT_MILLI, checkUpdateFinished);

View File

@ -372,7 +372,7 @@ function checkUpdateApplied() {
// Don't proceed until the update has been applied.
if (gUpdateManager.activeUpdate.state != STATE_APPLIED_PLATFORM) {
if (gTimeoutRuns > MAX_TIMEOUT_RUNS)
do_throw("Exceeded MAX_TIMEOUT_RUNS whist waiting for update to be applied to the platform");
do_throw("Exceeded MAX_TIMEOUT_RUNS whilst waiting for update to be applied, current state is: " + gUpdateManager.activeUpdate.state);
else
do_timeout(CHECK_TIMEOUT_MILLI, checkUpdateApplied);
return;
@ -485,7 +485,7 @@ function checkUpdateFinished() {
let status = readStatusFile();
if (status != STATE_SUCCEEDED) {
if (gTimeoutRuns > MAX_TIMEOUT_RUNS)
do_throw("Exceeded MAX_TIMEOUT_RUNS whist waiting for success status");
do_throw("Exceeded MAX_TIMEOUT_RUNS whilst waiting for state to change to succeeded, current status: " + status);
else
do_timeout(CHECK_TIMEOUT_MILLI, checkUpdateFinished);
return;

View File

@ -107,4 +107,15 @@ inline NS_HIDDEN_(bool) NS_finite(double d)
#endif
}
/**
* Returns the result of the modulo of x by y using a floored division.
* fmod(x, y) is using a truncated division.
* The main difference is that the result of this method will have the sign of
* y while the result of fmod(x, y) will have the sign of x.
*/
inline NS_HIDDEN_(double) NS_floorModulo(double x, double y)
{
return (x - y * floor(x / y));
}
#endif