mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 05:41:12 +00:00
Merge mozilla-central into mozilla-inbound
This commit is contained in:
commit
4951d76b67
@ -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", "");
|
||||
|
@ -519,7 +519,6 @@
|
||||
autocheck="false"
|
||||
hidden="true"
|
||||
label="&devToolbarMenu.label;"
|
||||
accesskey="&devToolbarMenu.accesskey;"
|
||||
key="key_devToolbar"
|
||||
command="Tools:DevToolbar"/>
|
||||
<menuitem id="webConsole"
|
||||
|
@ -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"
|
||||
|
@ -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' };
|
||||
}
|
||||
|
@ -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
|
||||
|
2
browser/devtools/shared/test/browser_toolbar_tooltip.js
Executable file → Normal file
2
browser/devtools/shared/test/browser_toolbar_tooltip.js
Executable file → Normal 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);
|
||||
}
|
||||
|
@ -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">
|
||||
|
@ -2398,6 +2398,7 @@ html|*#gcli-output-frame {
|
||||
#gcli-tooltip {
|
||||
border-width: 0;
|
||||
background-color: transparent;
|
||||
-moz-appearance: none;
|
||||
margin-bottom: -2px;
|
||||
}
|
||||
|
||||
|
@ -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%);
|
||||
|
@ -3139,6 +3139,7 @@ html|*#gcli-output-frame {
|
||||
#gcli-tooltip {
|
||||
border-width: 0;
|
||||
background-color: transparent;
|
||||
-moz-appearance: none;
|
||||
margin-bottom: -2px;
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -3073,6 +3073,7 @@ html|*#gcli-output-frame {
|
||||
#gcli-tooltip {
|
||||
border-width: 0;
|
||||
background-color: transparent;
|
||||
-moz-appearance: none;
|
||||
margin-bottom: -2px;
|
||||
}
|
||||
|
||||
|
@ -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")
|
||||
|
@ -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 ||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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 :
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
|
@ -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>
|
@ -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>
|
||||
|
168
content/html/content/test/forms/test_max_attribute.html
Normal file
168
content/html/content/test/forms/test_max_attribute.html
Normal 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>
|
168
content/html/content/test/forms/test_min_attribute.html
Normal file
168
content/html/content/test/forms/test_min_attribute.html
Normal 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>
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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);
|
||||
|
259
content/html/content/test/forms/test_step_attribute.html
Normal file
259
content/html/content/test/forms/test_step_attribute.html
Normal 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>
|
353
content/html/content/test/forms/test_stepup_stepdown.html
Normal file
353
content/html/content/test/forms/test_stepup_stepdown.html
Normal 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>
|
@ -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>
|
||||
|
@ -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>
|
@ -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>
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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())
|
||||
|
@ -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()))
|
||||
|
@ -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());
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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 */
|
||||
|
@ -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());
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;)
|
||||
|
@ -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 {
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -60,7 +60,7 @@ class KidsPointer {
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void checkConsistency(const js::Shape *aKid) const;
|
||||
void checkConsistency(js::Shape *aKid) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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; }
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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()))
|
||||
|
@ -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)) {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -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));
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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
|
||||
|
@ -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) },
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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() {
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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("");
|
||||
|
@ -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,
|
||||
|
@ -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 = \
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user